SV DPI; accessing a task within a module in the C code

In reply to dave_59:

Dave, great, thanks. You’ll probably see the issue quickly.

The module with the c code context import is here:


module axi4lite_mst_c_skel
#(
    parameter module_id     = "AXI4-Lite DPI Master",
    parameter drive_edge    = "rise", 
    parameter datawidth     = 32,     
    parameter addrwidth     = 32,
    parameter drive_dly     = 0      
)
(
    input 			   aclk,
    input 			   aresetn,

    // write addr channel
    input 			   awready,
    output reg 			   awvalid,
    output reg [addrwidth-1:0] 	   awaddr,
    output reg [2:0] 		   awprot,
    // write data channel
    input 			   wready,
    output reg 			   wvalid,
    output reg [datawidth-1:0] 	   wdata,
    output reg [(datawidth/8)-1:0] wstrb,
    // write response
    input 			   bvalid, // valid bresp
    input [1:0] 		   bresp,
    output reg 			   bready,
    // read address channel
    input 			   arready,
    output reg 			   arvalid,
    output reg [addrwidth-1:0] 	   araddr,
    output reg [2:0] 		   arprot,
    // read data channel
    input 			   rvalid,
    input [datawidth-1:0] 	   rdata,
    input [1:0] 		   rresp,
    output reg 			   rready
);

   //---------------------------------------------------------------------------
   // Declarations  
   //---------------------------------------------------------------------------

  
   //---------------------------------------------------------------------------
   // events
   //---------------------------------------------------------------------------
   event           mst_write_req_evt;
   event           mst_write_done_evt;
   event           mst_read_req_evt;
   event           mst_read_done_evt;
   event           slv_write_rdy_evt;
   event           slv_write_ack_evt;
   event           slv_write_resp_evt;
   event           slv_read_rdy_evt;
   event           slv_read_resp_evt;

   //clock events
   event           aclk_rise;
   event           aclk_fall;
   event           aresetn_rise;
   event           aresetn_fall;


   //---------------------------------------------------------------------------
   //
   // This section sets all events
   // ... and has other tasks
   //
   //---------------------------------------------------------------------------
   
   
   export "DPI-C" task axi_rd;

   import "DPI-C" context task read_register();

   // where vsim now crashes, to maintain context at the same level.  This now maintains 
   // import and export in the same BFM.
   // So this is now context imported task calling exported task.  However it's wrapped
   // in a simple rreg task (which is now used in the test sequencer at the top lvl tb.
   task rreg;
   begin
      read_register();
   end
   endtask // read_register
   

   
    //---------------------------------------------------------------------------
    // ISSUE READ TRANSACTION  
    //---------------------------------------------------------------------------
    task axi_rd;
    input  int useraddr;
    output int userdata;
    begin
       if(enable)
       begin
          wait(pending_rd_tx == 0);
             read_addr_t = useraddr;
             @(aclk_rise);
             -> mst_read_req_evt;
             @(mst_read_done_evt);
             userdata = read_data_t; 
             if(debug)  $display("@%10t : [%s] Read Done  [ADDR = %08X, DATA = %8X]", $time, 
                                module_id, useraddr, userdata);
       end
       else // !enable
       begin
          if(debug) $display("@%10t : [%s] Module disabled. Read Transaction NOT done. ", $time, 
                                       module_id);
       end
    end
    endtask


endmodule

And the C code (per original post):


#include <stdio.h>
#include "svdpi.h"

extern void axi_rd(int, int); // the SV function

void read_register(void)
{
  int axidata;
  axi_rd(0x0, axidata);
  printf("Data from C code: 0x%8X\r\n", (axidata >> 16) & 0xFFFE);
}

Finally the top level tb task simply calls bus_mstr_c.rreg. bus_mstr_c is the instance name of
the axi4lite_mst_c_skel module shown above.
bus_mstr is the instance name of the existing sv bfm I’ve used for some time. I am transitioning to c simulation for better SW/HW integration.

I am running the SV BFM (bus_mstr) side by side with the DPI-based system (bus_mstr_c) for functional comparison. Really trivial as I am reading one register once in a long while.


   always @(posedge busclk)
   begin
      if (init_done)
      begin
         bus_mstr.rd(`TEMP_REG, userdata32[0]);
	 bus_mstr_c.rreg;
	 $display("done");
	 
         if (userdata32[0] & 1'b1) begin	     
            $display("[%10t]: New reading: Temp: %04X", $time, userdata32[0][31:16] & 16'hFFFE);
         end
	 else begin
	    $display("[%10t]: Old reading: Temp: %04X", $time, userdata32[0][31:16] & 16'hFFFE);
	 end
	
         #50000000; // read every 50 us
      end
   end

Thanks,
Jerry