end
else begin
bfm_msg("Attempted read of empty location in Command Memory, return to embedded mode" ,`warnings,msg_level);
end // if
end
else begin
if ((!(msg_level < `warnings))) begin
$display("WARNING at %0t from %m", $time);
$write(" \"Command Memory Address Out of Range, returning to embedded mode:\n");
$write(" Last Valid Address = %0d\n",max_cmd_mem_size);
$write(" Attempted Address = %0d", cmd_addr);
$display("\"");
end // if
end // if
end
endtask // get_mem_cmd
function exit_cond;
input [31:0] exit_val;
input [31:0] step_val;
input [31:0] curr_loop_val;
begin
if (step_val >= 0) begin
if (curr_loop_val > exit_val) exit_cond = `true;
else exit_cond = `false;
end else begin
if (curr_loop_val < exit_val) exit_cond = `true;
else exit_cond = `false;
end // if
end
endfunction // exit_cond
//-------------
// READ_FILE --
//-------------
//Side effects
//cmd_mem, load_mem_addr
//temp_cmd, tmp_str, curr_func_name
task read_file;
integer linen;
reg [1:`token_size*8] inline;
reg [1:`token_size*8] tmp_inline;
reg [(`token_size-1)*8:0] token_1;
reg status_f;
reg error_f;
integer plitype;
integer plisize;
reg found;
reg valid_f;
begin
linen = 0;
inline = "";
valid_f = `false;
found = `false;
if (!endfile) begin
begin : preload
while (!endfile) begin
inline = "";
tmp_inline = "";
$lmv_fgetcmd(fh, inline, error_f);
linen = linen + 1;
tmp_inline = (inline >> 4);
tmp_cb[cbmsg1:cbmsg2] = "";
tmp_cb[cbmsg1:cbmsg2] = (inline >> 4);
plitype = 3;
plisize = 0;
token_1 = "";
$lmv_tokenize(tmp_inline, 3, 0, token_1, status_f);
if (token_1 !== "") begin
if (nest_level === 0) begin
if (token_1 === "{") begin
nest_level = nest_level + 1;
end else begin
//build FUNC_BEGIN command
build_cmd(tmp_cb[cbmsg1:cbmsg2],"func_beg",token_1);
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
disable preload; //exit preload
end // if
set_addr_tbl_elmnt(token_1,load_mem_addr,found);
if (found) begin
bfm_msg("Duplicate function names in command file:\nOnly the last declared will be used", `warnings, msg_level);
end // if
curr_func_name = token_1;
end // if
end
else if (nest_level > 0 || sequential_f) begin
if (token_1 === "{") begin
nest_level = nest_level + 1;
end else if (token_1 === "}") begin
nest_level = nest_level - 1;
if (nest_level === 0) begin
build_cmd(tmp_cb[cbmsg1:cbmsg2],"func_end",curr_func_name);
if (! sequential_f) begin
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
disable preload; //exit preload
end // if
end
else begin
timing.to_fm_data_in(tmp_cb[cbmsg1:cbmsg2], msg_level);
temp_cmd[fmfield1:fmfield2] = timing.wk_cmd;
end // if
end // if
end else if (timing.is_command(token_1)) begin
timing.to_fm_data_in(tmp_cb[cbmsg1:cbmsg2], msg_level);
temp_cmd[fmfield1:fmfield2] = timing.wk_cmd;
if (! sequential_f) begin
if (temp_cmd[fmcode1:fmcode2] !== `null_cmd) begin //syntax okay
//store string
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
disable preload; //exit preload
end // if
if (temp_cmd[fmcode1:fmcode2] === `sequential_cmd) begin
disable preload; //exit preload;
end // if
end // if
end // if
end else begin
build_cmd(tmp_cb[cbmsg1:cbmsg2],"call",token_1);
if (! sequential_f) begin
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
disable preload; //exit preload
end // if
end
else begin
timing.to_fm_data_in(tmp_cb[cbmsg1:cbmsg2], msg_level);
temp_cmd[fmfield1:fmfield2] = timing.wk_cmd;
end // if
end // if
end // if
end // if
if (sequential_f) begin
disable preload; //exit preload;
end // if
$lmv_endfile(fh,endfile);
end // while
end // preload
if (nest_level !== 0) begin
if (! (sequential_f || (temp_cmd[fmcode1:fmcode2] === `sequential_cmd))) begin
bfm_msg("Syntax error in command file: Unmatched `{': Attempting to recover", `warnings, msg_level);
//attempt to recover by adding func_end command so sim won't blow up
max_cmd_mem_size = max_cmd_mem_size + 1;
//build FUNC_END command
build_cmd( tmp_cb[cbmsg1:cbmsg2],"func_end",curr_func_name);
addelement(tmp_cb,load_mem_addr,valid_f);
end // if
end // if
end // if
if (! (sequential_f || temp_cmd[fmcode1:fmcode2] === `sequential_cmd)) begin
if (msg_level >= `debug_cmd_mem) begin
bfm_msg("Command Memory Loaded, Contents = ", `debug_cmd_mem, msg_level);
begin: print_mem
integer i;
for (i=0; i<=cmd_mem_counter; i=i+1) begin
cmd_mem_hold = cmd_mem[i];
$display("%0s", cmd_mem_hold[cbmsg1:cbmsg2]);
end // loop
end // print_mem
end // if
end // if
end
endtask // read_file
// End Read File Declarations --
//=========================
// DEALLOCATE_CTRL_QUEUE ==
//=========================
task deallocate_ctrl_queue;
input [31:0] pointer;
input [31:0] size;
integer i;
begin
for (i = pointer; i <= size; i = i +1) begin
ctrl_queue[i] = ctrl_queue[i+1];
end // loop
ctrl_queue_size = ctrl_queue_size - 1;
end
endtask // deallocate_ctrl_queue
//---------
// QUEUE --
//---------
//Side effects
//queue_size, ctrl_queue_end
//new_cmd_f
task queue;
input [ctrl_store1:ctrl_store2] cmd; // ctrl_store_data
input [31:0] which_end; // default = end_of_queue
integer i;
begin
if (ctrl_queue_size == 0) begin //empty queue
new_cmd_f = `true;
ctrl_queue[ctrl_queue_size + 1] = cmd; // ctrl_queue[1]
ctrl_queue_size = ctrl_queue_size + 1; // ctrl_queue_size = 1
end
else begin //neither _end or _beg is null
if (which_end == end_of_queue) begin
ctrl_queue[ctrl_queue_size + 1] = cmd;
ctrl_queue_size = ctrl_queue_size + 1;
end
else begin
for (i = ctrl_queue_size; i >= 1; i = i - 1) begin // shift queue one location down
ctrl_queue[i+1] = ctrl_queue[i];
end // loop
ctrl_queue_size = ctrl_queue_size + 1;
ctrl_queue[1] = cmd;
end // if
end // if
if (cmd[fmcode1:fmcode2] > `max_user_immed_code) begin //must be "user_cycle" command
//!!8.0.burst remove condition around statement
//!! if ((cmd[fmcode1:fmcode2] !== `read_continue_cmd) && (cmd[fmcode1:fmcode2] !== `write_continue_cmd)) begin
// special for pci
num_non_immed_queued = num_non_immed_queued + 1;
//!! end // if
end // if
queue_size = queue_size + 1;
if ((!(msg_level < `debug_int))) begin
$display("NOTE at %0t from %m", $time);
$display(" \"QUEUE: cmd =%0s", cmd2string(cmd[fmcode1:fmcode2]));
//!!8.0 change ($write -->> $display)
$write(" QUEUE: queue_size = %0d", queue_size);
$display("\"");
end // if
end
endtask // queue
//!!8.0.burst begin - add procedure
task dequeue;
input [31:0] delete_cmd_code;
//Always dequeues at least the first command in queue
//Additionally, if delete_cmd_code /= null_cmd
//count number of occurances of delete_cmd in ctrl_queue,
//stop counting if a multi-cycle command (which is not delete_cmd) is reached
//if first location in queue has multi-cycle, ignore it to ensure its deletion
//this is for case where delete_cmd_code is set to read_continue during a read_cycle
//both the read_cycle and subsequent read_continue's should be deleted
//then loop through dequeue loop until this number of delete_cmd's are removed
//any zero-cycle commands between delete_cmd's will be removed
//At this point, three conditions may exist;
//if the queue contained only delete_cmd's and zero-cycle commands,
//the queue will be empty except for zero-cycle commands following the last delete_cmd
//if the queue contained a multi-cycle command (non-delete_cmd)
//the queue will maintain zero-cycle commands between the last delete_cmd
//and the multi-cycle command
reg [ctrl_store1:ctrl_store2] cmd_reg; //ctrl_queue_ptr
integer num_delete_cmds;
reg first_f;
integer tmp_queue_size;
integer tmp_ptr;
reg exit_search_f, exit_remove_cmd_f;
begin
num_delete_cmds = 0;
first_f = `true;
tmp_queue_size = ctrl_queue_size;
tmp_ptr = ctrl_queue_pointer;
exit_search_f = `false;
exit_remove_cmd_f = `false;
if (delete_cmd_code !== `null_cmd) begin
cmd_reg = ctrl_queue[tmp_ptr]; // ctrl_queue[1]
num_delete_cmds = 0;
begin: search
while (!exit_search_f) begin
if (tmp_queue_size === 0) begin
exit_search_f = `true; //exit search
end
else if (cmd_reg[fmcode1:fmcode2] > `max_user_immed_code) begin
if (cmd_reg[fmcode1:fmcode2] === delete_cmd_code) begin
num_delete_cmds = num_delete_cmds + 1;
end
else if (! first_f) begin
exit_search_f = `true; //exit search
end // if
end // if
cmd_reg = ctrl_queue[tmp_ptr+1];
first_f = `false;
tmp_ptr = tmp_ptr + 1;
tmp_queue_size = tmp_queue_size - 1;
end // while
end // search
end // if
begin: remove_cmd
while (!exit_remove_cmd_f) begin
ctrl_queue_hold = ctrl_queue[ctrl_queue_pointer];
if (ctrl_queue_hold[fmcode1:fmcode2] > `max_user_immed_code) begin //must be "user_cycle" command
num_non_immed_queued = num_non_immed_queued - 1;
if (ctrl_queue_hold[fmcode1:fmcode2] === delete_cmd_code) begin
num_delete_cmds = num_delete_cmds - 1;
end // if
end // if
if (ctrl_queue_size !== 0) begin //queue has at least 1 more command
deallocate_ctrl_queue(ctrl_queue_pointer, ctrl_queue_size);
end
else begin //no more commands
deallocate_ctrl_queue(ctrl_queue_pointer, ctrl_queue_size); //also deallocates _end "dangling"
end // if
queue_size = queue_size - 1;
if ((queue_size < max_ctrl_queue_size/2) && queue_overflow_f) begin
queue_overflow_f = `false;
end // if
if ((!(msg_level < `debug_int))) begin
$display("NOTE at %0t from %m", $time);
$write(" \"DEQUEUE: removing command, queue_size = %0d", queue_size);
$display("\"");
end // if
if ((ctrl_queue_size === 0) || (num_delete_cmds <= 0))
exit_remove_cmd_f = `true; //exit remove_cmd when ctrl_queue_beg = null
// or num_delete_cmds <= 0;
//loop will execute once if delete_cmd = null_cmd, because num_delete_cmds will be 0
end // while
end // remove_cmd
end
endtask // dequeue
//!!8.0.burst end - add procedure
//----------------
// CLEAR_BUSY_F --
//----------------
//Side effects
//dspch_data, dspch_data_f,
//issued_busy_f
task clear_busy_f;
begin
if (issued_busy_f) begin
issued_busy_f = `false;
//signal dispatcher to broadcast ready message
dspch_data[cbinitiator_id1:cbinitiator_id2] = id_number;
dspch_data[cbtarget_id1:cbtarget_id2] = `cb_brdcst_id;
dspch_data[cbtransaction1:cbtransaction2] = `status_trans;
dspch_data[cbdone_f] = `false;
dspch_data[cbdvalid_f] = `false;
dspch_data[cbbuffer_avail_f] = `true;
dspch_data[cbmsg1:cbmsg2] = "";
dspch_data[cbtag1:cbtag2] = 0; //0 since broadcasting
//call dispatcher to queue dspch_data for dispatching
dspch_data_f = `true;
dispatcher;
end // if
end
endtask // clear_busy_f
//-------------------
// CHK_FOR_TRIGGER --
//-------------------
//Side effects
//exe_nxt_buf
//dspch_data, dspch_data_f,
//wait_on_f,suspend_exe_f,new_cmd_f
task chk_for_trigger;
begin
if (exe_nxt_buf_pointer !== 0) begin
exe_nxt_buf_hold = exe_nxt_buf[exe_nxt_buf_pointer];
if (wait_on_f) begin
if (exe_nxt_buf_hold[fmcode1:fmcode2] ===`trigger_cmd) begin
if ((exe_nxt_buf_hold[fmtvalue1:fmtvalue2] === wait_on_val) || (exe_nxt_buf_hold[fmtvalue1:fmtvalue2] === `blanket_tvalue)) begin
wait_on_f = `false;
suspend_exe_f = `false;
new_cmd_f = `true;
end else begin
if ((!(msg_level < `debug_3))) begin
$display("NOTE at %0t from %m", $time);
$display(" \"TRIGGER with incorrect TVALUE received during WAIT_ON execution,");
$display(" deleting command from exe_nxt_buf to avoid locking model\"");
cb2string(exe_nxt_buf_hold[cbfield1:cbfield2]);
end // if
end // if
end else begin
if ((!(msg_level < `debug_3))) begin
$display("NOTE at %0t from %m", $time);
$display(" \"non-TRIGGER command received during WAIT_ON execution");
$display(" deleting command from exe_nxt_buf to avoid locking model\"");
cb2string(exe_nxt_buf_hold[cbfield1:cbfield2]);
end // if
end //if
exe_nxt_buf_pointer = 0;
clear_busy_f;
end else begin
if (exe_nxt_buf_hold[fmcode1:fmcode2] === `trigger_cmd) begin
exe_nxt_buf_pointer = 0;
clear_busy_f;
bfm_msg("Model not waiting: Deleting TRIGGER from exe_nxt_buf buffer",`debug_3,msg_level);
end // if
end // if
end // if
end
endtask // chk_for_trigger
//-------------------
// CHK_EXE_NXT_BUF --
//-------------------
//Side effects
//exe_nxt_buf, ctrl_queue
//dspch_data, dspch_data_f,
//issued_busy_f, stop_queuing_f
task chk_exe_nxt_buf;
begin
if (exe_nxt_buf_pointer !== 0) begin
queue(exe_nxt_buf[exe_nxt_buf_pointer], beg_of_queue);
exe_nxt_buf_pointer = 0;
end // if
clear_busy_f;
end
endtask // chk_exe_nxt_buf
//-------------------
// CHK_WAIT_ON_NODE --
//-------------------
//Side effects
//wait_on_node_f,wait_on_node_val
//wait_on_f,suspend_exe_f,new_cmd_f
task chk_wait_on_node;
begin
if (wait_on_node_f) begin
if (wait_on_node_val === 1'b1) begin
wait_on_node_f = `false;
wait_on_f = `false;
suspend_exe_f = `false;
new_cmd_f = `true;
end // if
end // if
end
endtask // chk_wait_on_node
//---------------
// LOAD_QUEUE --
//---------------
//Side effects
//!!8.0.burst remove comment
//!! //stop_queuing_f
//fm_rsp, rsp_strobe, strobe_rsp_f
//!!8.0.burst remove ", temp_cmd" from comment
//!! //cmd_mem, temp_cmd
//cmd_mem
task load_queue;
inout [31:0] curr_mem_addr;
//!!8.0.burst - change new_top_cmd_f to top_cmd_f (one line only)
//!!input new_top_cmd_f; // default = `false
input top_cmd_f; // default = `false
reg valid_get_f;
reg found;
//!!8.0.burst - add vars
reg new_top_cmd_f;
reg [ctrl_store1:ctrl_store2] lq_temp_cmd; // ctrl_store_data
reg exit_queuing_f;
begin
valid_get_f = `false;
found = `false;
new_top_cmd_f = top_cmd_f;
exit_queuing_f = `false;
bfm_msg("LOAD QUEUE" ,`debug_int,msg_level);
if ((!new_top_cmd_f) && (!wait_on_done_f) && (!wait_on_f)) begin
chk_exe_nxt_buf;
//!!8.0.burst - remove "if" condition ( not body )
//!! if (! stop_queuing_f) begin
chk_excpt_detected(curr_mem_addr);
//!! end // if
end // if
//!!8.0.burst - add loop around rest of code
begin: queuing
while (!exit_queuing_f) begin
//!!8.0.burst - add "or new_top_cmd_f"
//!! if (curr_mem_addr === 0) begin //load commands from embedded (top-level entity)
if (curr_mem_addr === 0 || new_top_cmd_f) begin //load commands from embedded (top-level entity)
if (new_top_cmd_f) begin
//!!8.0.burst - add line
new_top_cmd_f = `false;
//!!8.0.burst - change condition of "if"
//!! if (stop_queuing_f) begin
if (curr_mem_addr !== 0) begin
bfm_msg("Controller not expecting command from embedded" ,`warnings,msg_level);
end // if
//top is sending cmd - always accept,
//load_queue was called when fm_cmd.strobe'event
bfm_msg("LOAD QUEUE: Receiving command from top-level" ,`debug_int,msg_level);
lq_temp_cmd[cbfield1:cbfield2] = cb_field_local_cmd;
lq_temp_cmd[fmfield1:fmfield2] = fm_cmd;
queue(lq_temp_cmd, end_of_queue);
//!!8.0.burst begin - add block
if (lq_delete_cmd_code !== `null_cmd) begin
if (lq_temp_cmd[fmcode1:fmcode2] > `max_user_immed_code) begin
if (lq_temp_cmd[fmcode1:fmcode2] === lq_delete_cmd_code) begin
//check for illegal condition signalled by get_nxt_cmd
if (lq_vfyn_f) begin
lq_vfyn_f = `false;
bfm_msg("LOAD_QUEUE: Illegal command sequence: Time-consuming statements within burst sequence;\n Some zero-cycle commands may have been incorrectly executed", `warnings, msg_level);
end // if
//command that was just queued should be deleted,
//command was queued prior to checking so that
//num_delete_cmds is counted properly in dequeue();
dequeue(lq_delete_cmd_code); //also deletes any previously queued zero-cycle commands
end
else begin
lq_delete_cmd_code = `null_cmd;
lq_vfyn_f = `false;
end // if
end // if
end // if
//!!8.0.burst end - add block
if (lq_temp_cmd[fmcode1:fmcode2] === `call_cmd) begin
//!!8.0.burst begin - change body of "if"
//!! stop_queuing_f = `true;
exe_call(lq_temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
//if successful, changes curr_mem_addr, so signal not ready to top-level
//!!8.0.burst end - change body of "if"
end // if
end // if
//!!8.0.burst - remove "and not stop_queuing_f"
//!! if ((num_non_immed_queued < (pipeline_depth + 1)) && (! stop_queuing_f) && (queue_size < max_ctrl_queue_size)) begin
if ((num_non_immed_queued < (pipeline_depth + 1)) && (queue_size < max_ctrl_queue_size)) begin
//!!8.0.burst begin - change section - add if/else condition, existing code + more in body
if (curr_mem_addr === 0) begin
//request next command from top
fm_rsp.ready <= #(0) `true;
bfm_msg("LOAD QUEUE: Signalling ready to top-level" ,`debug_int,msg_level);
strobe_rsp_f = `true;
exit_queuing_f = `true;
end
else begin
fm_rsp.ready <= #(0) `false;
bfm_msg("LOAD QUEUE: Signalling NOT ready to top-level" ,`debug_int,msg_level);
strobe_rsp_f = `true;
//(no exit, load from command memory)
end // if
end
//!!8.0.burst end - change section
else begin
fm_rsp.ready <= #(0) `false;
bfm_msg("LOAD QUEUE: Signalling NOT ready to top-level" ,`debug_int,msg_level);
//!!8.0.burst add two lines
strobe_rsp_f = `true;
exit_queuing_f = `true;
end // if
//!!8.0.burst - remove line
//!! strobe_rsp_f = `true;
end
else begin : loop_queue //load from command memory
//!!8.0.burst - replace while statement with exit statement
//!! while ((num_non_immed_queued < (pipeline_depth+1)) && (! stop_queuing_f) && (!queue_overflow_f)) begin
if ((num_non_immed_queued >= (pipeline_depth+1)) || (queue_overflow_f)) begin
exit_queuing_f = `true;
end
else begin
if (sequential_f) begin
//get next command from command file
bfm_msg("LOAD QUEUE: Reading command from command file; Sequential mode" ,`debug_int,msg_level);
$lmv_endfile(fh,endfile);
if (endfile) begin
bfm_msg("Syntax error in command file during sequential mode:\n The end of the command file was reached without properly terminating the program.\n Returning to embedded mode ",`warnings, msg_level);
curr_mem_addr = 0;
//!!8.0.burst - remove exit
//!! disable loop_queue; //exit;
end
else begin
read_file; //sets temp_cmd
if (temp_cmd[fmcode1:fmcode2] !== `null_cmd) begin
queue(temp_cmd, end_of_queue);
//!!8.0.burst begin - add block
if (lq_delete_cmd_code !== `null_cmd) begin
if (temp_cmd[fmcode1:fmcode2] > `max_user_immed_code) begin
if (temp_cmd[fmcode1:fmcode2] === lq_delete_cmd_code) begin
//must have first queued the command in question, so that
//num_delete_cmds is counted properly in dequeue();
dequeue(lq_delete_cmd_code); //also deletes any previously queued zero-cycle commands
end
else begin
lq_delete_cmd_code = `null_cmd;
end // if
end // if
end // if
//!!8.0.burst end - add block
//!!8.0 add condition - begin
if (queue_size === max_ctrl_queue_size) begin
queue_overflow_f = `true;
end // if
//!!8.0 add condition - end
if (temp_cmd[fmcode1:fmcode2] === `func_end_cmd) begin
//!!8.0.burst begin - change "if" body
//!! stop_queuing_f = `true;
exe_func_end(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
//!!8.0.burst end - change "if" body
end // if
if (temp_cmd[fmcode1:fmcode2] === `call_cmd) begin
//!!8.0.burst begin - change "if" body
//!! stop_queuing_f = `true;
exe_call(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
//!!8.0.burst end - change "if" body
end // if
end // if
end // if
end
else begin
//get next command from command memory
bfm_msg("LOAD QUEUE: Retreiving command from command memory" ,`debug_int,msg_level);
get_mem_cmd(temp_cmd, curr_mem_addr, valid_get_f);
if (valid_get_f) begin
queue(temp_cmd, end_of_queue);
//!!8.0.burst begin - add block
if (lq_delete_cmd_code !== `null_cmd) begin
if (temp_cmd[fmcode1:fmcode2] > `max_user_immed_code) begin
if (temp_cmd[fmcode1:fmcode2] === lq_delete_cmd_code) begin
//must have first queued the command in question, so that
//num_delete_cmds is counted properly in dequeue();
dequeue(lq_delete_cmd_code); //also deletes any previously queued zero-cycle commands
end
else begin
lq_delete_cmd_code = `null_cmd;
end // if
end // if
end // if
//!!8.0.burst end - add block
//!!8.0 add condition - begin
if (queue_size === max_ctrl_queue_size) begin
queue_overflow_f = `true;
end // if
//!!8.0 add condition - end
if (temp_cmd[fmcode1:fmcode2] === `func_end_cmd) begin
//!!8.0.burst begin - change "if" body
//!! stop_queuing_f = `true;
exe_func_end(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
//!!8.0.burst end - change "if" body
end
else if (temp_cmd[fmcode1:fmcode2] === `sequential_cmd) begin
sequential_f = `true;
end
else begin
curr_mem_addr = curr_mem_addr + 1;
end // if
if (temp_cmd[fmcode1:fmcode2] === `call_cmd) begin
//!!8.0.burst begin - change "if" body
//!! stop_queuing_f = `true;
exe_call(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
//!!8.0.burst end - change "if" body
end // if
end
else begin
curr_mem_addr = 0;
//!!8.0.burst - remove exit
//!! disable loop_queue;
end // if //invalid get warnings issued in get_mem_cmd
end // if
//!!8.0.burst - remove end loop
//!! end // loop_queue
end // if
end // if
//!!8.0.burst - add end loop queuing
end // while
end // queuing
end
endtask // load_queue
//-------------
// DONE_CHKS --
//-------------
//Side effects
//dspch_data, dspch_data_f, temp_cmd
//dvalid_f, ret_data_ary, ret_data_ptr, ret_data_t, ret_val
task done_chks;
input [ctrl_store1:ctrl_store2] cmd;
reg [1:`slv_size] data_str;
reg [1:`slv_size] addr_str;
begin
// Status / Return Data
if (cmd[cbinitiator_id1:cbinitiator_id2] !== id_number) begin //command was received via Control Bus
//return status/data (if appl.)
if (cmd[cbnotify_f] || (dvalid_f && cmd[cbreturn_data_f])) begin
dspch_data[cbinitiator_id1:cbinitiator_id2] = id_number;
dspch_data[cbtarget_id1:cbtarget_id2] = cmd[cbinitiator_id1:cbinitiator_id2];
dspch_data[cbtransaction1:cbtransaction2] = `status_trans;
dspch_data[cbdone_f] = cmd[cbnotify_f];
if (dvalid_f && (cmd[cbreturn_data_f] == `true)) begin
dspch_data[cbdvalid_f] = `true;
data_str = ret_data_slv;
addr_str = ret_addr_slv;
dspch_data[cbmsg1:1126] = addr_str;
dspch_data[1127:cbmsg2] = data_str;
end
else begin
dspch_data[cbdvalid_f] = `false;
dspch_data[cbmsg1:cbmsg2] = ""; // (others => NUL);
end // if
dspch_data[cbtag1:cbtag2] = cmd[cbtag1:cbtag2]; //return original tag
//call dispatcher to queue dspch_data for dispatching
dspch_data_f = `true;
dispatcher;
end // if
end
else begin //command was local command
if (dvalid_f) begin
//return data to top-level via ret_val
//!!8.0.burst - remove "if" (not body)
//!! if (cmd_src === `embedded) begin
if (ret_data_t === $time) begin
//multiple return datum in same tick
//data always returned in same tick or different absolute time
if (ret_data_ptr < `ret_ary_len) begin
ret_data_ary_hold = ret_data_ary[ret_data_ptr];
ret_data_ary_hold[127:64] = ret_addr_slv;
ret_data_ary_hold[63:0] = ret_data_slv;
ret_data_ary[ret_data_ptr] = ret_data_ary_hold;
ret_data_ptr = ret_data_ptr + 1; //start appending at 1 (0 is for preceding non-immed)
end
else begin
ret_data_ptr = 0;
bfm_msg("Maximum number of elements in RET_VAL array has been exceeded.\n Remaining data to be returned will overwrite data already loaded ",`warnings, msg_level);
end
end
else begin
ret_data_t = $time;
ret_data_ary_hold = ret_data_ary[0];
ret_data_ary_hold[127:64] = ret_addr_slv;
ret_data_ary_hold[63:0] = ret_data_slv;
ret_data_ary[0] = ret_data_ary_hold;
ret_data_ptr = 1;
end // if
//pass data to top-level
if (ret_data_ptr === 0)
ret_val <= #(0) ret_data_ary[0];
else
ret_val <= #(0) ret_data_ary[ret_data_ptr-1];
//!! end // if
end // if
end // if
// Compare Data (checks for "x" signifying no comparison)
if (dvalid_f) begin
if (cmd[fmcode1:fmcode2] !== `remote_cmd) begin //else return data was received via control bus
compare_data(cmd[fmexpected_data1:fmexpected_data2], ret_data_slv, ret_addr_slv);
end // if
end // if
// Generate Monitor Command
if (monitor_id !== 0) begin // 0 indicates no monitor model
dspch_data[cbinitiator_id1:cbinitiator_id2] = id_number;
dspch_data[cbtarget_id1:cbtarget_id2] = monitor_id;
dspch_data[cbtransaction1:cbtransaction2] = `cmd_trans;
dspch_data[cbbuffer_f] = `false;
dspch_data[cbnotify_f] = `false;
dspch_data[cbreturn_data_f] = `false;
dspch_data[cbmsg1:cbmsg2] = cmd[cbmsg1:cbmsg2]; //return original msg
if (dvalid_f) begin
end // if
dspch_data[cbtag1:cbtag2] = cmd[cbtag1:cbtag2]; //return original tag
//call dispatcher to queue dspch_data for dispatching
dspch_data_f = `true;
dispatcher;
end // if
dvalid_f = `false;
end
endtask // done_chks
//----------------
// EXE_FUNC_END --
//----------------
//Side effects
//!!8.0.burst - remove ", stop_queuing_f"
//!! //returnto_stk, stop_queuing_f
//returnto_stk
task exe_func_end;
input [1:`token_size*8] function_name;
inout [31:0] curr_mem_addr;
inout [31:0] cmd_src;
begin
pop_stack(curr_mem_addr);
//!!8.0.burst - remove line
//!! stop_queuing_f = `false;
if (curr_mem_addr == 0) begin
cmd_src = `embedded;
end // if
if (sequential_f) begin //function which contained sequential cmd has completed
//functions called while in seq mode reset this flag during exec. of function
sequential_f = `false;
end // if
if (function_name === seq_halt_func_name) begin
sequential_f = `true;
end // if
end
endtask // exe_func_end
//------------------------
// EXE_CALL DECLARATION --
//------------------------
//Side effects
//!!8.0.burst - remove ", stop_queuing_f"
//!! //returnto_stk, stop_queuing_f
//returnto_stk
task exe_call;
input [1:`token_size*8] function_name; // string
inout [31:0] curr_mem_addr;
inout [31:0] cmd_src;
reg found;
begin
found = `false;
//!!8.0.burst begin - add "if" and body - comes from exe_ctrl_immed/when call_cmd
if (first_call_f) begin
first_call_f = `false;
$lmv_openr(cmd_file, fh);
if (fh == 0) begin
if ((!(msg_level < `warnings))) begin
$display("WARNING at time %t from %m",$time);
$display(" \"Cannot open COMMAND file %0s. No commands are preloaded!\"",cmd_file);
end // if
end
else begin
$lmv_endfile(fh,endfile);
read_file;
end // if
end // if
//!!8.0.burst end - add "if" and body
cmd_src = `cmd_memory;
push_stack(curr_mem_addr);
get_addr_tbl_elmnt(function_name, curr_mem_addr, found);
//!!8.0.burst - remove line
//!! stop_queuing_f = `false;
if (sequential_f) begin
seq_halt_func_name = function_name;
sequential_f = `false;
end // if
if (!found) begin
//return to previous addr
exe_func_end(function_name, curr_mem_addr,cmd_src);
if ((!(msg_level < `warnings))) begin
$display("WARNING at %0t from %m", $time);
$write(" \"Illegal function call, function %0s not declared", function_name);
$display("\"");
end // if
end // if
end
endtask // exe_call
//------------------
// EXE_CTRL_IMMED --
//------------------
//Side effects
//dspch_data, dspch_data_f,
//excpt_f_ary
//msg_level
//wait_on_f, wait_on_val
//!!8.0.burst - remove ", stop_queuing_f
//!! //curr_mem_addr, load_mem_addr, cmd_src, stop_queuing_f, tmp_str
//curr_mem_addr, load_mem_addr, cmd_src, tmp_str
task exe_ctrl_immed;
input [ctrl_store1:ctrl_store2] cmd;
reg tmp, ret_stat;
reg found;
reg valid_f;
begin
if ((!(msg_level < `debug_3))) begin
$display("NOTE at %0t from %m", $time);
$write(" \"EXE_CTRL_IMMED: Executing = %0s", cmd2string(cmd[fmcode1:fmcode2]));
$display("\"");
end // if
valid_f = `false;
found = `false;
case (cmd[fmcode1:fmcode2])
`remote_cmd : begin
dspch_data[cbinitiator_id1:cbinitiator_id2] = id_number;
dspch_data[cbtarget_id1:cbtarget_id2] = cmd[fmtarget_id1:fmtarget_id2];
dspch_data[cbtransaction1:cbtransaction2] = `cmd_trans;
dspch_data[cbbuffer_f] = cmd[fmbuffer_f];
dspch_data[cbnotify_f] = cmd[fmnotify_f];
dspch_data[cbreturn_data_f] = cmd[fmreturn_data_f];
dspch_data[cbmsg1:cbmsg2] = cmd[fmmsg1:fmmsg2];
dspch_data[cbtag1:cbtag2] = cmd[cbtag1:cbtag2];
//holds orig tag if forwarding
//initialized to zero if not forwarding(dispatcher will assign)
//call dispatcher to queue dspch_data for dispatching
dspch_data_f = `true;
dispatcher;
if (cmd[fmnotify_f]) begin
wait_on_done_f = `true;
wait_on_done_tag = dspch_data[cbtag1:cbtag2]; //this is the value the dispatcher assigned to tag
end // if
end
`restart_cmd : begin
bfm_msg("Restart command not yet implemented" ,`warnings,msg_level);
end
`trigger_cmd : begin
if ((cmd[cbinitiator_id1:cbinitiator_id2] === id_number) && (cmd[cbtarget_id1:cbtarget_id2] === id_number)) begin //trigger originates in this model, broadcast trigger to others
dspch_data[cbinitiator_id1:cbinitiator_id2] = id_number;
dspch_data[cbtarget_id1:cbtarget_id2] = `cb_brdcst_id;
dspch_data[cbtransaction1:cbtransaction2] = `cmd_trans;
dspch_data[cbbuffer_f] = `false;
dspch_data[cbnotify_f] = `false;
dspch_data[cbreturn_data_f] = `false;
dspch_data[cbmsg1:cbmsg2] = {"trigger","(",cmd[fmtvalue1:fmtvalue2],")",";"};
dspch_data[cbtag1:cbtag2] = 0;
//holds orig tag if forwarding
//initialized to zero if not forwarding(dispatcher will assign)
//call dispatcher to queue dspch_data for dispatching
dspch_data_f = `true;
dispatcher;
end // if
end
`wait_on_cmd : begin
wait_on_f = `true;
wait_on_val = cmd[fmtvalue1:fmtvalue2]; //wait_on_f set when wait_on is dequeued
end
`print_msg_cmd : $display($time,,"%0s", cmd[fmmessage1:fmmessage2]);
`set_msg_level_cmd : msg_level = cmd[fmmlevel1:fmmlevel2];
`call_cmd : begin
//!!8.0.burst - remove "when" body
//!! //store parent addr, chaddr to function, set status of local variables, set tmp_vars to vars being passed
//!! //currently using only global variables, so this command only stores parent addr and changes addr
//!!
//!! if (first_call_f) begin
//!! first_call_f = `false;
//!!
//!! $lmv_openr(cmd_file, fh);
//!! if (fh ==0) begin
//!! if ((!(msg_level < `warnings))) begin
//!! $display("WARNING at time %t from %m",$time);
//!! $display(" \"Cannot open COMMAND file %0s. No commands are preloaded!\"",cmd_file);
//!! end //if
//!! end // if
//!! $lmv_endfile(fh,endfile);
//!!
//!! read_file;
//!! end // if
//!!
//!! exe_call(cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
end
`open_buffer_cmd : begin
//write func_beg_cmd, declare func_beg addr = load_mem_addr
build_cmd(tmp_cb[cbmsg1:cbmsg2],"func_beg",cmd[fmfunction_name1:fmfunction_name2]);
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
bfm_msg("Command memory FULL, New buffer can not be opened", `warnings, msg_level);
end // if
set_addr_tbl_elmnt(cmd[fmfunction_name1:fmfunction_name2],load_mem_addr,found); // addr_tbl
if (found) begin
bfm_msg("Duplicate function name already in command file:\nNewly declared buffer will be used for subsequent calls", `warnings, msg_level);
end // if
curr_func_name =cmd[fmfunction_name1:fmfunction_name2];
end
`close_buffer_cmd : begin
build_cmd(tmp_cb[cbmsg1:cbmsg2],"func_end",curr_func_name);
addelement(tmp_cb,load_mem_addr,valid_f);
if (!valid_f) begin
max_cmd_mem_size = max_cmd_mem_size + 1;
This page: |
Created: | Thu Aug 19 11:57:05 1999 |
| From: |
../../../sparc_v8/system/lmc/rtl/pcimaster_fm.v
|