acc_sysC Posted February 22 Report Share Posted February 22 How do I write the below testbench which has non-blocking assignments in systemC? The entire model in systemC is written using SC_METHODs I tried to write the below testbench(stimulus) using SC_THREAD since I could use wait(clk.posedge_event()) in place of @(posedge clk) I am able to see the stimulus correctly same as RTL in the waveforms from VCD file. But will this work same as non-blocking assignment in verilog. I have this question because I know non-blocking assignment in systemC can be done using SC_METHOD(). Please find the systemC code I wrote in the attachment Please advice. module test; reg [8-1 : 0] A; reg [8-1 : 0] B; reg [256-1 : 0] FUNC; reg [8-1 : 0] FUNC_ADDR; reg [9-1 : 0] RUN; reg [9-1 : 0] LOAD_CORE; reg [18-1 : 0] SRC_MODE; reg [18-1 : 0] IN_MODE; reg [36-1 : 0] AIN_ADDR; reg [36-1 : 0] BIN_ADDR; reg [4-1 : 0] Y_ADDR; reg clk; reg reset; wire [8-1 : 0] Y; PIM_Cluster top( .A(A), .B(B), .FUNC(FUNC), .FUNC_ADDR(FUNC_ADDR), .RUN(RUN), .LOAD_CORE(LOAD_CORE), .SRC_MODE(SRC_MODE), .IN_MODE(IN_MODE), .AIN_ADDR(AIN_ADDR), .BIN_ADDR(BIN_ADDR), .Y_ADDR(Y_ADDR), .clk(clk), .reset(reset), .Y(Y) ); integer n = 16; integer index = 0; integer a = 0; integer b = 0; integer kk = 0; integer qq =0; integer ii = 0; integer add = 0; integer mult = 0; reg [2048-1:0] FUNC_MULT; reg [2048-1:0] FUNC_ADD; reg [8-1:0] ADD_tmp; reg [8-1:0] MULT_tmp; reg [16-1:0] ACC; genvar G; initial begin $timeformat(-9,2,"ns", 16); `ifdef SDFSCAN $sdf_annotate("sdf/PIM_Cluster_tsmc18_scan.sdf", test.top); `endif // Initialize Inputs ACC = 16'h0; A = 8'h0; B = 8'h0; FUNC = 256'h0; FUNC_ADDR = 9'h0; RUN = 9'h1FF; LOAD_CORE = 9'h0; SRC_MODE = 18'h0; IN_MODE = 18'h0;//h3ffff AIN_ADDR = 36'h0; BIN_ADDR = 36'h0; Y_ADDR = 4'h0; clk = 0; reset = 0; //Generate Function Words for Multiplication and Addition for (a=0;a<16;a=a+1) begin - - - - - end index = index + 1; end end #5; reset = 1; #5; reset = 0; //LOAD_CORE = 9'h0; for (ii=0;ii<n;ii=ii+1) begin // @(posedge clk) // begin // A <= $random%256; // B <= $random%256; // end @(posedge clk) //#6; A <= $random%256; B <= $random%256; IN_MODE <= 18'h3FC00; SRC_MODE <= 18'h3FC00; AIN_ADDR <= {16'h2233,20'h0}; BIN_ADDR <= {16'h0101,20'h0}; //repeat(2) @(posedge clk); //#6; //A = 0; //B = 0; B[3:0] <= ACC[3:0]; IN_MODE <= 18'h00333; SRC_MODE <=18'h00001; AIN_ADDR <= {16'h0,20'h0B0C00}; BIN_ADDR <= {16'h0,20'h0D0F0E}; RUN <= 9'h1E0; //repeat (3) @(posedge clk); //#6; ACC[3:0] <= Y[3:0]; B[3:0]<= ACC[7:4]; IN_MODE <= 18'h003BB; SRC_MODE <= 18'h00113; AIN_ADDR <= {16'h0,20'h80800}; BIN_ADDR <= {16'h0,20'h87A38}; RUN<= 9'h015; //repeat (4) @(posedge clk);//4 //#6; B[3:0] <=ACC[11:8]; IN_MODE <=18'h00357; SRC_MODE <=18'h00201; AIN_ADDR<= {16'h0,20'h17638}; BIN_ADDR<= {16'h0,20'h00002}; RUN <=9'h015; Y_ADDR <=4'h0000; //repeat (5) @(posedge clk); //#6; ACC[7:4] <=Y[3:0]; B[3:0]<= ACC[15:12]; IN_MODE <=18'h003E3; SRC_MODE<= 18'h00342; AIN_ADDR <= {16'h0,20'h08006}; BIN_ADDR <= {16'h0,20'h89208}; RUN <= 9'h01B; //repeat (6) @(posedge clk); //#6; IN_MODE <= 18'h00333; SRC_MODE <= 18'h00121; AIN_ADDR <= {16'h0,20'h80408}; BIN_ADDR <= {16'h0,20'h10802}; RUN <= 9'h01D; //repeat (7) @(posedge clk); //#6; ACC[11:8] <= Y[3:0]; IN_MODE <= 18'h0000B; SRC_MODE <= 18'h00002; AIN_ADDR<= {16'h0,20'h00006}; BIN_ADDR <={16'h0,20'h00028}; RUN <=9'h015; //repeat (8) @(posedge clk); //#6; IN_MODE <= 18'h00004; SRC_MODE <= 18'h00000; AIN_ADDR <= {16'h0,20'h00000}; BIN_ADDR <= {16'h0,20'h00000}; RUN<= 9'h001; Y_ADDR <= 4'h0001; //repeat (9) @(posedge clk); //#6; ACC[15:12] <= Y[3:0]; IN_MODE <= 18'h00000; RUN <= 9'h002; @(posedge clk); //#6; Y_ADDR <= 4'h0000; IN_MODE <= 18'h00000; RUN <= 9'h000; end $stop; end always #3 clk = ~clk; endmodule PIMC_stimulus (1).h Quote Link to comment Share on other sites More sharing options...
David Black Posted February 22 Report Share Posted February 22 sc_signal<T> is exclusively non-blocking writes. It does NOT depend on SC_THREAD or SC_METHOD. There are two syntaxes (one preferred): //File: example.hpp #include <systemc> SC_MODULE( NbaExample ) { sc_core::sc_trace_file* tracefile{nullptr}; // for waveforms const sc_core::sc_time delay{ 10, sc_core::SC_NS }; sc_core::sc_signal<int> mySignal{"mySignal"}; // ALL sc_signals are non-blocking int var{ 5 }; // always blocking assign explicit NbaExample( const sc_core::sc_module_name& instance ) : sc_module{ instance } { SC_HAS_PROCESS( NbaExample ); SC_THREAD( main_thread ); SC_METHOD( observe_method ); sensitive << mySignal; } void start_of_simulation() override; void end_of_simulation() override; void main_thread(); void observe_method(); }; //-------------------------------------------------------------------------------------- //File: example.cpp #include "example.hpp" #include <string> using namespace std::string_literals; using namespace sc_core; void NbaExample::start_of_simulation() { tracefile = sc_create_vcd_trace_file( "dump" ); sc_trace( tracefile, mySignal, "mySignal" ); mySignal.write( 8 ); //< initial value for t=0; } void NbaExample::end_of_simulation() { sc_close_vcd_trace_file( tracefile ); } void NbaExample::main_thread() { wait( delay ); mySignal.write( 20 ); // Preferred syntax for assignment var = 8; // Blocking assignment -- do not use between processes wait( delay ); mySignal = 30; // Convenience, but looks too much like blocking assignment var = 4; wait( delay ); sc_core::sc_stop(); } void NbaExample::observe_method() { // Using SC_REPORT_* macros allows better control of message reports SC_REPORT_INFO( "/Doulos/NbaExample", ( " At "s + sc_time_stamp().to_string() + " mySignal="s + std::to_string(mySignal.read()) + " var="s + std::to_string(var) ).c_str() ); } //-------------------------------------------------------------------------------------- //File: main.cpp #include "example.hpp" [[maybe_unused]] //< avoid warnings int sc_main( [[maybe_unused]]int argc, [[maybe_unused]]char* argv[] ) { NbaExample top{ "top" }; sc_core::sc_start(); return 0; } Quote Link to comment Share on other sites More sharing options...
acc_sysC Posted February 22 Author Report Share Posted February 22 Thanks David! That helped me understand where I'm going wrong. But I'm a little confused as to how to implement this in the structure of code I'm using. I will used an example which is similar to my situation here: https://edaplayground.com/x/JaQu If I declare everything in my stimulus.h file as sc_signal, it gives error like this when I connect it in my main file(register_main.cpp): register_main.cpp:37:23: error: no match for call to '(sc_core::sc_signal<sc_dt::sc_bv<256> >) (sc_core::sc_signal<sc_dt::sc_bv<256> >&)'stim1.Data_in(DATA_IN); which makes sense because of data type conflicts. So does this mean I should be implementing the syntax you suggested directly in my main file(register_main.cpp)? How do I do this if I want to keep the stimulus in a separate headerfile and then just connect the signals in the main file? Please advice. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.