HierarchyFilesModulesSignalsTasksFunctionsHelp
Prev12345678910
        strobe_rsp_f = `true;
        exit_queuing_f = `true;
     end // if

  end
  else begin : loop_queue       //load from command memory
     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;
           end
           else begin
              read_file;  //sets temp_cmd
              if (temp_cmd[fmcode1:fmcode2] !== `null_cmd) begin
                 queue(temp_cmd, end_of_queue);
                 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

                 if (queue_size === max_ctrl_queue_size) begin
                    queue_overflow_f = `true;
                 end // if

                 if (temp_cmd[fmcode1:fmcode2] === `func_end_cmd) begin
                    exe_func_end(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
                 end // if
                 if (temp_cmd[fmcode1:fmcode2] === `call_cmd) begin
                    exe_call(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
                 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);
              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

              if (queue_size === max_ctrl_queue_size) begin
                 queue_overflow_f = `true;
              end // if

              if (temp_cmd[fmcode1:fmcode2] === `func_end_cmd) begin
                 exe_func_end(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
              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
                  exe_call(temp_cmd[fmfunction_name1:fmfunction_name2], curr_mem_addr, cmd_src);
              end // if
           end
           else begin
              curr_mem_addr = 0;
           end // if  //invalid get warnings issued in get_mem_cmd 
        end // if
     end // if
  end // if
 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] = "";
        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
        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
 
// 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
   //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);
  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
   //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;
  
  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

  cmd_src = `cmd_memory;
  push_stack(curr_mem_addr);
  get_addr_tbl_elmnt(function_name, curr_mem_addr, found);
  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
   //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
     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;
           addelement(tmp_cb,load_mem_addr,valid_f);
        end // if
     end
     `func_beg_cmd : begin
       //sets local variables value to approp. tmp_var, and sets status to "passed_val"
       //currently using only global variables, so this command is non-functional

     end
     `func_end_cmd : begin
       //--return value, set status of local vars, return to parent addr
       //--currently using only global variables, so this command only returns toparent addr
       //command is executed when queued
     end

     `sequential_cmd : begin
     end

     `stop_sim_cmd : begin
        $display("======================================================================");
        $display("NOTE at time %t from %m",$time);
        $display("    \" stop_sim command issued, simulation stopped immediately \"");
        $display("======================================================================");
        $finish;
     end

     `wait_on_node_cmd : begin
        wait_on_node_dummy = 1'b0;
        $lmv_wait_on(cmd[fmnode_name1:fmnode_name2],cmd[fmnode_value1:fmnode_value2],cmd[fmnode_mask1:fmnode_mask2],wait_on_node_dummy,ret_stat);

        if (!ret_stat) begin    // Change ret_stat non_zero, no_wait, event already occurred
           wait_on_node_val = 1'b0;
           wait_on_f = `true;
           wait_on_node_f = `true;
        end // if
     end

     default : begin
             if ((!(msg_level < `warnings))) begin
                $display("WARNING at %0t from %m", $time);
                $write("    \"EXE_CTRL_IMMED: Received invalid command,code=%0s",cmd2string(cmd[fmcode1:fmcode2]));
                $display("\"");
             end // if
     end
  endcase
end
endtask // exe_ctrl_immed

//---------------
// CONTROLLER  --
//---------------


 //Operation
   //this procedure performs controller operations other than:
     // get_nxt_cmd, excpt_detected, return_data
 //Side Effects
   //ctrl_init
   //curr_mem_addr
   //rsp_strobe,strobe_rsp_f
   //done_f_rcvd, wait_on_done_f, new_cmd_f

task controller;
begin

  rsp_strobe_set = `false;
  if (ctrl_init) begin
     ctrl_init = `false;
     load_queue(curr_mem_addr, `false);
     if (strobe_rsp_f) begin
        strobe_rsp_f = `false;
        if (rsp_strobe_set != `true) begin
           rsp_strobe_set = `true;
           rsp_strobe = ~rsp_strobe;
           fm_rsp.strobe <= #(0) rsp_strobe;
        end // if
     end // if
  end // if
 

  if (fm_cmd_strobe_event) begin
     load_queue(curr_mem_addr,`true);
     if (strobe_rsp_f) begin
        strobe_rsp_f = `false;
        if (rsp_strobe_set != `true) begin
           rsp_strobe_set = `true;
           rsp_strobe = ~rsp_strobe;
           fm_rsp.strobe <= #(0) rsp_strobe;
        end // if
     end // if
  end // if
 
  if (done_f_rcvd) begin
     done_f_rcvd = `false;
     wait_on_done_f = `false;
     suspend_exe_f = `false;
     new_cmd_f = `true;
  end // if

  chk_for_trigger;

  chk_wait_on_node;

  if ((ctrl_queue_size === 0) && (! wait_on_done_f)) begin // empty and not waiting
     if (exe_nxt_buf_pointer !== 0) begin
        new_cmd_f = `true;
         //only set flag here, queue using exe_nxt_buf data when get_nxt_cmd called
     end // if
  end // if
end 
endtask // controller


//The following controller routines are called by the executer
 
//---------------
// GET_NXT_CMD --
//---------------
 //Side Effects
   //cmd_queue, ctrl_queue, num_non_immed_queued, queue_size
   //new_cmd_f
   //curr_cmd

task get_nxt_cmd;
integer i;
reg exit_f;
begin
  exit_f = `false;

  //peforms necessary end-of-command operations
   //dispatches status,return data, and monitor commands
  //removes completed command from queue
  //checks the exe_nxt_buf buffer for a command
  //loads queue as necessary
  //executes next command if it is an immediate command,
   //else exits get_nxt_cmd after updating curr_cmd

  bfm_msg("GET_NXT_CMD" ,`debug_int,msg_level);

  begin : get_nxt
  while (!exit_f) begin    

     if ((!suspend_exe_f) && (ctrl_queue_size !== 0) &&
         (lq_delete_cmd_code !== `null_cmd) && (num_non_immed_queued === 0)) begin
       //time-consuming statements are among burst and queue contains zero-cycle commands
       //which may be incorrectly executed
       //set flag so load_queue can verify/warn
        lq_vfyn_f = `true;
     end // if

     if ((!new_cmd_f) && (!suspend_exe_f) && (ctrl_queue_size !== 0)) begin
       //This section of code is normally entered after execution of each command
         //purpose is to perform end-of-command operations and delete command from queue
         //not new_cmd_f ensures that the first command in the queue has been executed
         //not suspende_exe_f ensures that command execution has not been suspended
         //  this could be due to either a wait_on command,
         //  a remote dispatched with notify_f set true or
         //  wait_on_node command
         //ctrl_queue_size !== 0 ensures that the queue is not empty

       //perform end-of-command operations
        done_chks(ctrl_queue[ctrl_queue_pointer]);
         //dispatches status,return data, and monitor commands
        suspend_exe_f = (wait_on_f | wait_on_done_f);

       //dequeue command(s)
         //current command always deleted
         //modeler may specify additional commands to be deleted through delete_cmd_code variable
           //if delete_cmd_code != `null_cmd, all subsequent delete_cmd's are removed until a different
           //multi-cycle command is reached. Any zero-cycle commands between delete_cmd's are removed

        dequeue(delete_cmd_code);

        if ((num_non_immed_queued === 0) && (delete_cmd_code !== `null_cmd)) begin
          //load_queue should continue to delete incoming delete_cmd's
           if (lq_delete_cmd_code !== `null_cmd) begin
             //modeler has set delete_cmd again before controller reset lq_delete_cmd_code
             //modeler may have called get_nxt_cmd multiple times in same time iteration 
               //(along with setting delete_cmd_code each time)
              bfm_msg("Model has overlapping requests to delete burst sequences;\n      New request only is serviced", `warnings, msg_level);
           end // if
           lq_delete_cmd_code = delete_cmd_code;
           if ((ctrl_queue_size !== 0) && (num_non_immed_queued === 0)) begin
             //time-consuming statement in embedded command sequence
             //residual zero-cycle's in queue will be executed
             //if next multi-cycle received from top is delete_cmd, a warning is issued from load_queue
             //set flag here to notify load_queue of potential illegal condition
              lq_vfyn_f = `true;
           end
           else begin
              lq_vfyn_f = `false; //ensures that for external file mode, flag is reset
           end // if
        end // if
        delete_cmd_code = `null_cmd;
     end // if


    //fill queue if necessary
     load_queue(curr_mem_addr, `false);

    //execute next command if immediate else exit procedure
     ctrl_queue_hold = ctrl_queue[ctrl_queue_pointer];
     if ((ctrl_queue_size !== 0) && (! wait_on_done_f) && (!suspend_exe_f)) begin
        if (new_cmd_f) begin
           new_cmd_f = `false;
        end // if


        if (ctrl_queue_hold[fmcode1:fmcode2] <= `max_ctrl_immed_code) begin
           exe_ctrl_immed(ctrl_queue_hold);                 //in controller section
        end else if (ctrl_queue_hold[fmcode1:fmcode2] <= `max_auto_immed_code) begin
           exe_auto_immed(ctrl_queue_hold[fmfield1:fmfield2]);            //in tool-gen m.s. section
        end else if (ctrl_queue_hold[fmcode1:fmcode2] <= `max_user_immed_code) begin
           exe_user_immed(ctrl_queue_hold[fmfield1:fmfield2]); //in executer section
        end
        else begin
          //load pipeline commands
           temp_cmd_ptr = ctrl_queue_pointer;
           for (i = 0; i <= pipeline_depth-1; i = i + 1) begin
              if (ctrl_queue_size !== 0) begin
                 ctrl_queue_hold = ctrl_queue[temp_cmd_ptr];
                 cmd_queue[i] = ctrl_queue_hold[fmfield1:fmfield2];
                 temp_cmd_ptr = temp_cmd_ptr + 1;
              end
              else begin
                 cmd_queue[i] = timing.fm_data_in_init;
              end // if
           end // loop
          //copy cmd_queue(0) to curr_cmd
           curr_cmd =  cmd_queue[0];
           exit_f = `true;
        end // if
     end
     else begin      //empty
        for (i = 0; i <= pipeline_depth-1; i = i + 1) begin 
            cmd_queue[i] = timing.fm_data_in_init;
        end // loop
        curr_cmd =  cmd_queue[0];
        exit_f = `true;
     end // if
  end // while
  end // get_nxt


  if (strobe_rsp_f) begin
     strobe_rsp_f = `false;
     if (rsp_strobe_set != `true) begin
        rsp_strobe_set = `true;
        rsp_strobe = ~rsp_strobe;
        fm_rsp.strobe <= #(0) rsp_strobe;
     end // if
  end // if
     if ((!(msg_level < `debug_3))) begin
        $display("NOTE at %0t from %m", $time);
        $write("    \"GET_NXT_CMD: Exiting, new command =%0s", cmd2string(curr_cmd[incode1:incode2]));
        $display("\"");
     end // if
end
endtask // get_nxt_cmd
 
//---------------
// RETURN_DATA --
//---------------
//Side Effects
  //ret_data_slv
  //dvalid_f

task return_data_b;
input rdata;
begin
   if ((!(msg_level < `debug_3))) begin
      $display("NOTE at %0t from %m", $time);
      $write("    \"RETURN_DATA: data = %H", rdata);
      $display("\"");
   end // if
  ret_data_mask = 64'hffffffffffffffe;
  ret_data_slv = 64'hxxxxxxxxxxxxxxxx;
  ret_data_slv[0] = rdata;
  dvalid_f = `true;
end
endtask // return_data_b

task return_data_v;
input [63:0] rdata;
begin
   if ((!(msg_level < `debug_3))) begin
      $display("NOTE at %0t from %m", $time);
      $write("    \"RETURN_DATA: data = %H", rdata);
      $display("\"");
   end // if
  ret_data_mask = 64'h0;
  ret_data_slv = rdata;
  dvalid_f = `true;
end
endtask // return_data_v

task return_data_addrb;
input [63:0] addr;
input rdata;
begin
   if ((!(msg_level < `debug_3))) begin
      $display("NOTE at %0t from %m", $time);
      $write("    \"RETURN_DATA:\n");
      $write("         address = %H\n", addr);
      $write("         data    = %H", rdata);
      $display("\"");
   end // if
  ret_addr_slv = addr;
  ret_data_mask = 64'hffffffffffffffe;
  ret_data_slv = 64'hxxxxxxxxxxxxxxxx;
  ret_data_slv[0] = rdata;
  dvalid_f = `true;
end
endtask // return_data_addrb

task return_data_addrv;
input [63:0] addr;
input [63:0] rdata;
begin
   if ((!(msg_level < `debug_3))) begin
      $display("NOTE at %0t from %m", $time);
      $write("    \"RETURN_DATA:\n");
      $write("         address = %H\n", addr);
      $write("         data    = %H", rdata);
      $display("\"");
   end // if
  ret_addr_slv = addr;
  ret_data_mask = 64'h0;
  ret_data_slv = rdata;
  dvalid_f = `true;
end
endtask // return_data_addrv

//====================================--
//       END CONTROLLER SECTION       --
//====================================--
 
//====================================--
//      BEGIN DISPATCHER SECTION      --
//====================================--

//-----------------------------
//Dispatcher Declarations -----
//-----------------------------

reg [cbfield1:cbfield2] dspch_queue [0 : `dspch_queue_page_size-1];        // control_bus_type
reg [cbfield1:cbfield2] dspch_queue_hold;        // control_bus_type

integer in_dspch_q_ptr; initial in_dspch_q_ptr = 0;  // first empty location
integer out_dspch_q_ptr; initial out_dspch_q_ptr = 0; // location to be output
reg dspch_q_empty; initial dspch_q_empty = `true;
integer dspch_tag; initial dspch_tag = 0;

integer active_target_id; initial active_target_id = 0;
integer ack_srch_ct; initial ack_srch_ct = 0; //num.of attempts to find cb_ack
reg check_cb_ack_f; initial check_cb_ack_f = `false;
reg wait_on_ack_f; initial wait_on_ack_f = `true;
reg released_cb_f; initial released_cb_f = `true;
integer wait_on_avail_t; initial wait_on_avail_t = 0 * `time_scale_multiplier;
reg driving_cb_f; initial driving_cb_f = `false;


reg check_cb_ack_event;
always @(check_cb_ack) begin
  check_cb_ack_event = `true;
  check_cb_ack_event <= #(0) `false;
end

//---------------------------
// Dispatcher Procedures ----
//---------------------------

task queue_dspch;
input [cbfield1:cbfield2] dspch_data;   // control_bus_type
begin : dspch_loop
  if (in_dspch_q_ptr >= `dspch_queue_page_size) begin
     if (out_dspch_q_ptr !== 0) begin
        in_dspch_q_ptr = 0;
     end
     else begin
         bfm_msg("Dispatcher Queue Overflow: Dispatch data not queued for output" ,`warnings,msg_level);
        disable dspch_loop;      // return
     end // if
  end // if

  if ((!(msg_level < `debug_3))) begin
     $display("NOTE at %0t from %m", $time);
     $write("    \"QUEUE_DSPCH: Initiator %0d", id_number);
     $write(" : Storing data to be dispatched, location = %0d", in_dspch_q_ptr);
     $display("\"");
  end // if
  dspch_queue[in_dspch_q_ptr] = dspch_data;
  in_dspch_q_ptr = in_dspch_q_ptr + 1;

end // dspch_loop
endtask // queue_dspch

task dequeue_dspch;
begin
  if (out_dspch_q_ptr !== in_dspch_q_ptr) begin
     out_dspch_q_ptr = out_dspch_q_ptr + 1;
     if (out_dspch_q_ptr === `dspch_queue_page_size) begin
        out_dspch_q_ptr = 0;
        if (in_dspch_q_ptr === `dspch_queue_page_size) begin
          //in ptr hasn't been reset, but queue is empty
           in_dspch_q_ptr = 0;
        end // if
     end // if
  end 
  else begin
       bfm_msg("DEQUEUE_DSPCH: Error in dispatcher's queue" ,`warnings,msg_level);
  end // if
end
endtask // dequeue_dspch

//---------------
// Dispatcher  --
//---------------

task dispatcher;
integer temp_time;
reg [cbfield1:cbfield2] t_dspch_queue;
begin

 begin : loop_dispatcher
 //queue dispatch data if necessary
  if (dspch_data_f) begin
     dspch_data_f = `false;
     if ((dspch_data[cbtransaction1:cbtransaction2] === `cmd_trans) && (dspch_data[cbtag1:cbtag2] === 0)) begin
        dspch_data[cbtag1:cbtag2] = dspch_tag;
        dspch_tag = dspch_tag + 1;
     end // if
     queue_dspch(dspch_data);
     disable loop_dispatcher;      // return
  end // if

 //monitor Control Bus activity
  if (cb_initiator_id_event) begin
     if ((lmcver.cb[cbinitiator_id1:cbinitiator_id2] === id_number) && (driving_cb_f)) begin
       //this model just became owner of Control Bus, release now so message is valid for 1 tick
        driving_cb_f = `false;
        lmcver.free_bus(id_number);
        lmcver.cb[cbinitiator_id1:cbinitiator_id2] <= #(0) `cb_release_id;
        check_cb_ack_f = `true;
        active_target_id = lmcver.cb[cbtarget_id1:cbtarget_id2];
        check_cb_ack <= #(0) ~check_cb_ack;
         if ((!(msg_level < `debug_cb))) begin
            $display("NOTE at %0t from %m", $time);
            $write("    \"DISPATCHER: Initiator %0d: Message on CB, Release CB",id_number);
            $display("\"");
         end // if
     end // if
  end // if

  if ((check_cb_ack_event) && (check_cb_ack_f)) begin
      t_dspch_queue = dspch_queue[out_dspch_q_ptr];
      if ((!(msg_level < `debug_cb))) begin
         $display("NOTE at %0t from %m", $time);
         $write("    \"DISPATCHER: Initiator %0d: Check # %0d", id_number, (ack_srch_ct+1));
         $write("  for response to message w/ TAG = %0d\n", t_dspch_queue[cbtag1:cbtag2]);
         $display("      initiator_id = %0d", lmcver.cb_ack[ackinitiator_id1:ackinitiator_id2]);
         $display("      target_id    = %0d", lmcver.cb_ack[acktarget_id1:acktarget_id2]);
         $write("      ack_val      = %0s", cbackval2string(lmcver.cb_ack[ackack_val1:ackack_val2]));
         $display("\"");
      end // if
    //check response
     if (((lmcver.cb_ack[ackinitiator_id1:ackinitiator_id2] === id_number) && (lmcver.cb_ack[acktarget_id1:acktarget_id2] === active_target_id))
       || (active_target_id === `cb_brdcst_id)) begin
        check_cb_ack_f = `false;
        ack_srch_ct = 0;
       //valid response (assumed for broadcast)
        if ((lmcver.cb_ack[ackack_val1:ackack_val2] === `ack_rsp) || (active_target_id === `cb_brdcst_id)) begin
          //message accepted (assumed for broadcast)
          dequeue_dspch;
           bfm_msg("Message was received by Target(s)" ,`debug_cb,msg_level);
        end else if (lmcver.cb_ack[ackack_val1:ackack_val2] === `busy_rsp) begin
            //save message for resending
           wait_on_avail_f = `true;
           dspch_queue_hold = dspch_queue[out_dspch_q_ptr];
           wait_on_avail_id = dspch_queue_hold[cbtarget_id1:cbtarget_id2];
           wait_on_avail_t = $time;
             bfm_msg("Target responded with BUSY" ,`debug_cb,msg_level);
        end else if (lmcver.cb_ack[ackack_val1:ackack_val2] === `unknown) begin
          //error, for bus conflict, resolution outputs id's = 0, so target must have output `unknown'
             if ((!(msg_level < `debug_cb))) begin
                $display("WARNING at %0t from %m", $time);
                $write("    \"DISPATCHER: Initiator %0d :Received UNKNOWN acknowledge",id_number);
                $display("\"");
             end // if
        end else if (lmcver.cb_ack[ackack_val1:ackack_val2] === `Release) begin
          //not a possible comb. due to resolution (if ack_val = release, id's = 0)
             if ((!(msg_level < `debug_cb))) begin
                $display("WARNING at %0t from %m", $time);
                $write("    \"DISPATCHER: Initiator %0d :Received RELEASE acknowledge",id_number);
                $display("\"");
             end // if
        end // if
     end
     else begin
       //improper response, ignore and keep looking for ack upto max_ack_srch
        if (ack_srch_ct >= (`max_ack_srch-1)) begin
            if ((!(msg_level < `debug_cb))) begin
               $display("WARNING at %0t from %m", $time);
               $write("    \"DISPATCHER: CB_ACK check timeout expired, No valid response to message:\n");
               $write("                Message deleted from dispatch queue");
               $display("\"");
            end // if
           check_cb_ack_f = `false;
           ack_srch_ct = 0;
           dequeue_dspch;
        end else begin
           ack_srch_ct = ack_srch_ct + 1;
           check_cb_ack <= #(0) ~check_cb_ack;
        end // if
     end // if
  end // if

  temp_time = ($time - wait_on_avail_t);

  if ((wait_on_avail_f) && (temp_time >= `max_wait_on_avail_t)) begin
       if ((!(msg_level < `debug_cb))) begin
          $display("WARNING at %0t from %m", $time);
          $write("    \"DISPATCHER: Wait_on_avail timeout expired, Target not available for message:\n");
          $write("                Message deleted from dispatch queue");
          $display("\"");
       end // if
     wait_on_avail_f = `false; 
     dequeue_dspch;
  end // if

  if (in_dspch_q_ptr === out_dspch_q_ptr) dspch_q_empty = `true;
  else dspch_q_empty = `false;

  if (ack_srch_ct !== 0) wait_on_ack_f = `true;
  else wait_on_ack_f = `false;


 //output dispatch data if possible
  if ((!dspch_q_empty) && (lmcver.cb[cbinitiator_id1:cbinitiator_id2] === `cb_release_id) && (!driving_cb_f)
     && (!wait_on_avail_f) && (!wait_on_ack_f) && (!check_cb_ack_f)) begin
    //attempt dispatch
     driving_cb_f = `true;
     lmcver.request_bus(id_number);
     lmcver.cb[cbinitiator_id1:cbinitiator_id2] = lmcver.winner_id;
     if (lmcver.cb[cbinitiator_id1:cbinitiator_id2] === id_number) begin
//??        lmcver.cb <= #(0) dspch_queue[out_dspch_q_ptr];    
        lmcver.cb = dspch_queue[out_dspch_q_ptr];    
     end else begin
        driving_cb_f = `false;
     end // if


     if ((!(msg_level < `debug_cb))) begin
        $display("WARNING at %0t from %m", $time);
        $write("    \"Initiator %0d: Driving cb with dispatch queue location %0d",id_number,out_dspch_q_ptr);
        $display("\"");
        cb2string(dspch_queue[out_dspch_q_ptr]);
     end // if
  end // if
 
 end // loop_dispatcher
end
endtask // dispatcher


//====================================--
//       END DISPATCHER SECTION       --
//====================================--

//====================================--
//       BEGIN EXECUTER SECTION       --
//====================================--

parameter cmd_queue_depth = pipeline_depth;

reg init; initial init = `true;

 //**--**--**--**--**--**--**--**--  Executer Declarations USER CODE BEGIN

 //-------------------------------
 //-------------------------------
 // Enter user variables here   --
 //-------------------------------
 //-------------------------------

parameter max_commands = 30;
reg [31:0] new_cmd_buffer[max_commands*5-1:0];
integer    buffer_ptr ; initial buffer_ptr =  0;
integer    buffer_cnt ; initial buffer_cnt =  0;


//        type tm_event cmd_states  
parameter sready = 0;
parameter terminate = 1;
parameter terminate_first = 2;
parameter d_delay = 3;
parameter ready_first = 4;
                            
parameter ddelay_first = 5;
parameter abort = 6;
parameter abort_first = 7;

//        type abort_state_type  
//parameter abort = 0; 
parameter waiting = 1;

//        type snoop_states  
parameter snp_standby = 0; 
parameter snp_busy = 1; 
parameter snp_clean = 2; 
parameter snp_hit_mod = 3; 

//        type req_space_type  
parameter io_space = 0; 
parameter mem_space = 1; 
parameter cfg_space = 2; 
parameter iack_space = 3; 
parameter spc_space = 4;
parameter no_space = 5;

//        type dir_type  
parameter write = 0; 
parameter read = 1;

//        type delay_cnt_type  is array (`max_burst_len : 1) of integer range 0 : 15;

//        type termination_style  
parameter with_data = 0; 
parameter without_data = 1;

//        type slave_states  
parameter sidle = 0; 
Next12345678910
HierarchyFilesModulesSignalsTasksFunctionsHelp

This page: Created:Thu Aug 19 12:02:00 1999
From: ../../../sparc_v8/system/lmc/rtl/pcislave_fm.v

Verilog converted to html by v2html 5.0 (written by Costas Calamvokis).Help