I'm trying to simulate in SystemC a module with a CABA (Cycle Accurate / Bit Accurate) model which adds two numbers. It has the following signals:
Module addition_CABA
a
: Input number for the addition.b
: Input number for the addition.clk
: Clock input.valid
: Input signal which changes to 1 when the inputs a
and b
are available.result
: Output signal containing the result of a
+ b
.ready
: Output signal which changes to 1 when result
is ready.In order to test if the result from this module is right I have created a testbench
module which has the following signals:
Module testbench
result_tb
: Input signal which receives the result signal from addition_CABA
module.ready_tb
: Input signal which receives the ready signal from addition_CABA
module.clk_tb
: Clock input signal. It's the same for both modules.rst_tb
: Reset input signal. It's the same for both modules.a_tb
: Output signal which sends the number a to addition_CABA
module.b_tb
: Output signal which sends the number b to addition_CABA
module.valid_tb
: Output signal which sends the valid signal to addition_CABA
module.The test I'm doing is as follows:
testbench
a pair of random numbers is generated to give values to a
and b
.The problem I'm having is that when I run the simulation testbench
gives the right result, and addition_CABA
shows the result but some clock cycles later, so the comparison is between two different numbers. In addition, when the program ends I have a Segmentation fault (core dumped)
message. What I'm trying to figure it out is how to indicate testbench
to wait until the result is ready (with signal ready_tb
) so it can do the comparison with the right number. I have tried with a while(!ready_tb.read()) wait();
condition just before starting the test, but when doing this the program ends and the simulation never starts.
In the main.cpp
file I'm just doing the connections between modules, generating the clock and setting the rst
signal to 0
. Below is my code:
addition_CABA.h
#include <systemc.h>
//Module which adds two numbers
SC_MODULE(addition_CABA){
sc_in< sc_uint<8> > a;
sc_in< sc_uint<8> > b;
sc_in<bool> clk;
sc_in<bool> valid;
sc_in<bool> rst;
sc_out<bool> ready;
sc_out< sc_uint<8> > result;
int addcaba(int a, int b){
int c;
c = a+b;
wait(3);
return c;
}
void loop();
SC_CTOR(addition_CABA){
SC_CTHREAD(loop, clk.pos());
async_reset_signal_is(rst, true);
}
};
addition_CABA.cpp
void addition_CABA::loop(){
ready.write(0);
result.write(0);
if(rst){
ready.write(0);
result.write(0);
}
else{
while(1){
while (!valid.read()) wait();
result.write(addcaba(a.read(),b.read()));
ready.write(1);
wait();
ready.write(0);
}
}
}
testbench.h
#include <systemc.h>
SC_MODULE(testbench){
sc_in< sc_uint<8> > result_tb;
sc_in<bool> ready_tb;
sc_in<bool> clk_tb;
sc_in<bool> rst_tb;
sc_out< sc_uint<8> > a_tb;
sc_out< sc_uint<8> > b_tb;
sc_out<bool> valid_tb;
void test();
SC_CTOR(testbench){
SC_CTHREAD(test, clk_tb.pos());
async_reset_signal_is(rst_tb, true);
}
};
testbench.cpp
void testbench::test(){
uint8_t c = 0;
int k = 0;
if (rst_tb){
c = 0;
k = 0;
cout << "\nReset on!\n" << endl;
}
else{
//while(!ready_tb.read()) wait(); //when using this condition the simulation never starts
while(k < 5){
a_tb.write( (1 + rand() % (128-1)) );
b_tb.write( (1 + rand() % (128-1)) );
valid_tb.write(1);
sc_start(10, SC_NS);
valid_tb.write(0);
sc_start(10, SC_NS);
cout << "\nTest number " << k+1 << endl;
cout << "\ta = " << a_tb.read() << " and b = " << b_tb.read() << endl;
cout << "\tAddition of " << a_tb.read() << " and " << b_tb.read();
cout << " = " << result_tb.read() << endl;
c = a_tb.read() + b_tb.read();
if ( result_tb.read() != c ){
cout << "Real result = " << a_tb.read() + b_tb.read();
cout << " and result with module = " << result_tb.read() << endl;
cout << "Wrong result\n" << endl;
// exit(1);
}
else cout << "Result OK\n" << endl;
k++;
}
}
}
The root causes of the problem were the following ones:
main.cpp
function was too short (10 ns, I modified to 500 ns).SC_CTHREAD
, it must be within an infinite loop. The previous implementation was completely wrong and I think this was also the root cause of the Segmentation fault (core dumped)
message.In addition, the loop which repeats the test five times is not necessary as the number of iterations is related to the simulation time (set in the main.cpp
function). Below is the code for testbench.cpp
corrected:
void testbench::test(){
uint8_t c = 0;
int k = 0;
if (rst_tb){
c = 0;
k = 0;
cout << "\nReset on!\n" << endl;
}
else{
while(1){
a_tb.write( (1 + rand() % (128-1)) );
b_tb.write( (1 + rand() % (128-1)) );
valid_tb.write(1);
wait();
valid_tb.write(0);
wait();
while(!ready_tb.read()) wait();//This condition waits until ready_tb = true to continue the simulation
cout << "\nTest number " << k+1 << endl;
cout << "\ta = " << a_tb.read() << " and b = " << b_tb.read() << endl;
cout << "\tAddition of " << a_tb.read() << " and " << b_tb.read();
cout << " = " << result_tb.read() << endl;
c = a_tb.read() + b_tb.read();
if ( result_tb.read() != c ){
cout << "Real result = " << a_tb.read() + b_tb.read();
cout << " and result with module = " << result_tb.read() << endl;
cout << "Wrong result\n" << endl;
exit(1);
}
else cout << "Result OK\n" << endl;
k++;
}
}
}