I am working on a project in SystemC and want to incorporate unit testing. Is it possible to use existing unit test frameworks with SystemC?
I ask this because it seems
I was able to run 2 SystemC tests using the fork system call. I used the tutorial example on doulos.com and the Google Test framework. I was able to run the test twice, but I get an error printed out by the SystemC simulator about starting the test after calling sc_stop. However, regardless of the error, the simulator runs fine the second time around.
SystemC 2.2.0 --- Feb 24 2011 15:01:50
Copyright (c) 1996-2006 by all Contributors
ALL RIGHTS RESERVED
Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from systemc_test
[ RUN ] systemc_test.test1
Time A B F
0 s 0 0 0
0 s 0 0 1
10 ns 0 1 1
20 ns 1 0 1
30 ns 1 1 0
SystemC: simulation stopped by user.
[ OK ] systemc_test.test1 (1 ms)
[ RUN ] systemc_test.test2
Error: (E546) sc_start called after sc_stop has been called
In file: ../../../../src/sysc/kernel/sc_simcontext.cpp:1315
[ OK ] systemc_test.test2 (2 ms)
[----------] 2 tests from systemc_test (3 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (3 ms total)
[ PASSED ] 2 tests.
[ OK ] systemc_test.test1 (3 ms)
[ RUN ] systemc_test.test2
Time A B F
0 s 0 0 0
0 s 0 0 1
10 ns 0 1 1
20 ns 1 0 1
30 ns 1 1 0
SystemC: simulation stopped by user.
[ OK ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (4 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (4 ms total)
[ PASSED ] 2 tests.
[ OK ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (4 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (4 ms total)
[ PASSED ] 2 tests.
UPDATE: Code sample as requested:
// main_1.cxx
#include "systemc.h"
#include "stim.hxx"
#include "exor2.hxx"
#include "mon.hxx"
//#include
#include
#include
void run_1()
{
sc_signal ASig, BSig, FSig;
sc_clock TestClk("TestClock", 10, SC_NS,0.5);
stim* Stim1 = new stim("Stimulus1_1");
Stim1->A(ASig);
Stim1->B(BSig);
Stim1->Clk(TestClk);
exor2* DUT = new exor2("exor2_1");
DUT->A(ASig);
DUT->B(BSig);
DUT->F(FSig);
mon* Monitor1 = new mon("Monitor_1");
Monitor1->A(ASig);
Monitor1->B(BSig);
Monitor1->F(FSig);
Monitor1->Clk(TestClk);
Stim1->run();
delete Stim1;
delete DUT;
delete Monitor1;
}
bool sc_main_1()
{
//int rc;
//pthread_t thread;
//if( (rc = pthread_create( &thread, NULL, &run_1, NULL)) )
//{
// printf("Thread creation failed: %d\n", rc);
//};
//pthread_join(thread, NULL);
int pid = fork();
if(pid == 0)
{
run_1();
};
waitpid(pid, NULL, 0);
return true;
};
// main_2.cxx
#include "systemc.h"
#include "stim.hxx"
#include "exor2.hxx"
#include "mon.hxx"
//#include
#include
#include
void run_2()
{
sc_signal ASig, BSig, FSig;
sc_clock TestClk("TestClock", 10, SC_NS,0.5);
stim* Stim1 = new stim("Stimulus1_2");
Stim1->A(ASig);
Stim1->B(BSig);
Stim1->Clk(TestClk);
exor2* DUT = new exor2("exor2_2");
DUT->A(ASig);
DUT->B(BSig);
DUT->F(FSig);
mon* Monitor1 = new mon("Monitor_2");
Monitor1->A(ASig);
Monitor1->B(BSig);
Monitor1->F(FSig);
Monitor1->Clk(TestClk);
Stim1->run();
delete Stim1;
delete DUT;
delete Monitor1;
}
bool sc_main_2()
{
//int rc;
//pthread_t thread;
//if( (rc = pthread_create( &thread, NULL, &run_1, NULL)) )
//{
// printf("Thread creation failed: %d\n", rc);
//};
//pthread_join(thread, NULL);
int pid = fork();
if(pid == 0)
{
run_2();
};
waitpid(pid, NULL, 0);
return true;
};
// main.cxx
#include "systemc.h"
#include "gtest/gtest.h"
extern bool sc_main_1();
extern bool sc_main_2();
TEST(systemc_test, test1)
{
EXPECT_TRUE(sc_main_1());
};
TEST(systemc_test, test2)
{
EXPECT_TRUE(sc_main_2());
};
int sc_main(int argc, char* argv[])
{
std::cout << "Running main() from gtest_main.cc\n";
testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();
return 0;
}
// stim.hxx
#ifndef stim_hxx
#define stim_hxx
#include "systemc.h"
SC_MODULE(stim)
{
sc_out A, B;
sc_in Clk;
void StimGen()
{
A.write(false);
B.write(false);
wait();
A.write(false);
B.write(true);
wait();
A.write(true);
B.write(false);
wait();
A.write(true);
B.write(true);
wait();
sc_stop();
}
SC_CTOR(stim)
{
SC_THREAD(StimGen);
sensitive << Clk.pos();
}
bool run()
{
sc_start(); // run forever
return true;
};
};
#endif
// exor2.hxx
#ifndef exor_hxx
#define exor_hxx
#include "systemc.h"
#include "nand2.hxx"
SC_MODULE(exor2)
{
sc_in A, B;
sc_out F;
nand2 n1, n2, n3, n4;
sc_signal S1, S2, S3;
SC_CTOR(exor2) : n1("N1"), n2("N2"), n3("N3"), n4("N4")
{
n1.A(A);
n1.B(B);
n1.F(S1);
n2.A(A);
n2.B(S1);
n2.F(S2);
n3.A(S1);
n3.B(B);
n3.F(S3);
n4.A(S2);
n4.B(S3);
n4.F(F);
}
};
#endif
// mon.hxx
#ifndef mon_hxx
#define mon_hxx
#include "systemc.h"
#include
#include
using namespace std;
SC_MODULE(mon)
{
sc_in A,B,F;
sc_in Clk;
void monitor()
{
cout << setw(10) << "Time";
cout << setw(2) << "A" ;
cout << setw(2) << "B";
cout << setw(2) << "F" << endl;
while (true)
{
cout << setw(10) << sc_time_stamp();
cout << setw(2) << A.read();
cout << setw(2) << B.read();
cout << setw(2) << F.read() << endl;
wait(); // wait for 1 clock cycle
}
}
SC_CTOR(mon)
{
SC_THREAD(monitor);
sensitive << Clk.pos();
}
};
#endif