Using existing unit test frameworks with SystemC

后端 未结 4 751
野的像风
野的像风 2021-02-05 17:28

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

4条回答
  •  失恋的感觉
    2021-02-05 17:44

    Very often SystemC Device-under-test (DUT) can be resetted to initial state by asserting some signal. You can utilize this fact and enable any C++ unit testing framework you want. Just reset you DUT before running each test, so you don't need to elaborate it twice.

    Here is an example with Google Test, and a simple "Accumulator" DUT

    1. Initialize GTest (::testing::InitGoogleTest(&argc, argv);) from sc_main
    2. Elaborate your model
    3. Run tests from some thread inside sc_module by calling RUN_ALL_TESTS()
    4. You will need somehow to pass pointer to SystemC DUT interface to your tests. I've used global variable for that purpose

    Source:

    #include 
    #include "gtest/gtest.h"
    
    struct test_driver;
    
    test_driver *test_driver_p = nullptr;
    
    void register_test_driver(test_driver *td) {
        test_driver_p = td;
    }
    
    test_driver* get_test_driver() {
        assert(test_driver_p);
        return test_driver_p;
    }
    
    
    SC_MODULE(dut_accum) {
        sc_in_clk   clk{"clk"};
        sc_in reset{"reset"};
    
        sc_in en{"en"};
        sc_in  din{"din"};
        sc_out dout{"dout"};
    
        SC_CTOR(dut_accum) {
            SC_METHOD(accum_method);
            sensitive << clk.pos();
        };
    
        void accum_method() {
            if (reset)
                dout = 0;
            else if (en)
                dout = dout + din;
        }
    };
    
    SC_MODULE(test_driver) {
    
        sc_signal reset{"reset",1};
        sc_signal en{"en",0};
        sc_signal din{"din",0};
        sc_signal dout{"dout"};
    
        SC_CTOR(test_driver) {
            dut_inst.clk(clk);
            dut_inst.reset(reset);
            dut_inst.en(en);
            dut_inst.din(din);
            dut_inst.dout(dout);
            SC_THREAD(test_thread);
            sensitive << clk.posedge_event();
            register_test_driver(this);
        }
    
    private:
        void test_thread() {
            if (RUN_ALL_TESTS())
                SC_REPORT_ERROR("Gtest", "Some test FAILED");
            sc_stop();
        }
    
        dut_accum dut_inst{"dut_inst"};
        sc_clock clk{"clk", 10, SC_NS};
    };
    
    
    
    namespace {
        // The fixture for testing dut_accum
        class accum_test: public ::testing::Test {
        protected:
    
            test_driver & td;
    
            accum_test(): td(*get_test_driver()){
                reset_dut();
            }
    
            virtual ~accum_test() {}
    
            void reset_dut(){
                td.reset = 1;
                wait();
                td.reset = 0;
            }
        };
    
        TEST_F(accum_test, test0) {
            td.din = 10;
            td.en = 1;
            wait();
            wait();
            EXPECT_EQ(td.dout.read(), 10);
        }
    
        TEST_F(accum_test, test1_no_en) {
            td.din = 10;
            td.en = 0;
            wait();
            wait();
            EXPECT_EQ(td.dout.read(), 10); // this test will fail, since en is 0
        }
    
        TEST_F(accum_test, test2_reset_asserted) {
            td.din = 10;
            td.en = 1;
            td.reset = 1;
            wait();
            wait();
            EXPECT_EQ(td.dout.read(), 0);
        }
    }
    
    int sc_main(int argc, char **argv) {
        ::testing::InitGoogleTest(&argc, argv);
        test_driver td{"td"};
        sc_start();
    }
    

    CMakeLists.txt (requires installed SystemC 2.3.2 )

    cmake_minimum_required(VERSION 3.8)
    project(systemc_gtest)
    
    find_package(SystemCLanguage CONFIG REQUIRED)
    
    set (CMAKE_CXX_STANDARD ${SystemC_CXX_STANDARD})
    
    find_package(GTest REQUIRED)
    
    enable_testing()
    
    add_executable(systemc_gtest main.cpp)
    target_link_libraries(systemc_gtest ${GTEST_LIBRARIES} SystemC::systemc )
    target_include_directories(systemc_gtest PRIVATE ${GTEST_INCLUDE_DIRS})
    add_test(AllTestsInSystemCGtest systemc_gtest)
    

提交回复
热议问题