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