diff --git a/.gitignore b/.gitignore index 6eccf7a..bbfda94 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ /my_db* /.settings/ /Debug/ +/*.txlog +/*.vcd diff --git a/CMakeLists.txt b/CMakeLists.txt index c15ef09..e20921d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,16 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/scc/cmake) project(SCC_Test) -set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV") - -set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries") - -set(ENABLE_CLANG_TIDY FALSE CACHE BOOL "Enable clang-tidy checks") +option(FULL_TEST_SUITE "enable also long-running tests" OFF) +option(ENABLE_SCV "Enable use of SCV" OFF) +option(ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF) include(ConanInline) include(GNUInstallDirs) include(BuildType) -#enable_testing() - set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/contrib/axi4_pin_level.gtkw b/contrib/axi4_pin_level.gtkw new file mode 100644 index 0000000..5c02996 --- /dev/null +++ b/contrib/axi4_pin_level.gtkw @@ -0,0 +1,111 @@ +[*] +[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI +[*] Sun Oct 2 10:21:33 2022 +[*] +[dumpfile] "/home/eyck/git/SystemC-Components-Test/axi4_pin_level.vcd" +[dumpfile_mtime] "Sun Oct 2 10:15:49 2022" +[dumpfile_size] 129942 +[savefile] "/home/eyck/git/SystemC-Components-Test/contrib/axi4_pin_level.gtkw" +[timestart] 0 +[size] 1956 1062 +[pos] 1287 112 +*-17.469423 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] SystemC. +[treeopen] SystemC.testbench. +[sst_width] 214 +[signals_width] 254 +[sst_expanded] 1 +[sst_vpaned_height] 314 +@28 +SystemC.testbench.clk +SystemC.testbench.rst +@800200 +-AR +@28 +SystemC.testbench.ar_valid +SystemC.testbench.ar_ready +@22 +SystemC.testbench.ar_addr[31:0] +@28 +SystemC.testbench.ar_burst[1:0] +@22 +SystemC.testbench.ar_cache[3:0] +SystemC.testbench.ar_id[3:0] +SystemC.testbench.ar_len[7:0] +@28 +SystemC.testbench.ar_lock[1:0] +SystemC.testbench.ar_prot[2:0] +@22 +SystemC.testbench.ar_qos[3:0] +SystemC.testbench.ar_region[3:0] +@28 +SystemC.testbench.ar_size[2:0] +SystemC.testbench.ar_user +@1000200 +-AR +@800200 +-R +@28 +SystemC.testbench.r_valid +SystemC.testbench.r_ready +SystemC.testbench.r_last +@22 +SystemC.testbench.r_data[63:0] +SystemC.testbench.r_id[3:0] +@28 +SystemC.testbench.r_resp[1:0] +SystemC.testbench.r_user +@1000200 +-R +@800201 +-AW +@29 +SystemC.testbench.aw_valid +SystemC.testbench.aw_ready +@23 +SystemC.testbench.aw_addr[31:0] +@29 +SystemC.testbench.aw_burst[1:0] +@23 +SystemC.testbench.aw_cache[3:0] +SystemC.testbench.aw_id[3:0] +SystemC.testbench.aw_len[7:0] +@29 +SystemC.testbench.aw_lock[1:0] +SystemC.testbench.aw_prot[2:0] +@23 +SystemC.testbench.aw_qos[3:0] +SystemC.testbench.aw_region[3:0] +@29 +SystemC.testbench.aw_size[2:0] +SystemC.testbench.aw_user +@1000201 +-AW +@800200 +-W +@28 +SystemC.testbench.w_valid +SystemC.testbench.w_ready +SystemC.testbench.w_last +@22 +SystemC.testbench.w_data[63:0] +SystemC.testbench.w_id[3:0] +SystemC.testbench.w_strb[7:0] +@28 +SystemC.testbench.w_user +@1000200 +-W +@c00200 +-B +@28 +SystemC.testbench.b_valid +SystemC.testbench.b_ready +@22 +SystemC.testbench.b_id[3:0] +@28 +SystemC.testbench.b_resp[1:0] +SystemC.testbench.b_user +@1401200 +-B +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/scc b/scc index 74a05b8..74fc861 160000 --- a/scc +++ b/scc @@ -1 +1 @@ -Subproject commit 74a05b818b6e50bcd0ecacbf9ecd4f45ee6b4178 +Subproject commit 74fc861a2da01be614cc4e1f445dbc69d4eb10c7 diff --git a/src/sc_main.cpp b/src/sc_main.cpp index 5af6c4b..9da8eee 100644 --- a/src/sc_main.cpp +++ b/src/sc_main.cpp @@ -11,21 +11,26 @@ #include #include #include +#include using namespace scc; using namespace sc_core; int sc_main(int argc, char* argv[]) { - scc::init_logging(LogConfig().logLevel(log::INFO).logAsync(false)); - auto token = util::split(argv[0], '/'); - auto trc = scc::create_fst_trace_file(token.back().c_str()); - scc::tracer trace(token.back(), scc::tracer::file_type::NONE, trc); - + auto my_name = util::split(argv[0], '/').back(); + scc::init_logging(LogConfig().logLevel(getenv("SCC_TEST_VERBOSE")?log::DEBUG:log::INFO).logAsync(false)); + // create tracer + //auto trc = scc::create_fst_trace_file(my_name.c_str()); + //auto trc = scc::create_vcd_pull_trace_file(my_name.c_str()); + scc::tracer trace(my_name, scc::tracer::file_type::TEXT, true); + // instantiate design(s) factory::get_instance().create(); + // run tests int result = Catch::Session().run( argc, argv ); + // close trace file + //scc::close_fst_trace_file(trc); + //scc::close_vcd_pull_trace_file(trc); + // destroy design(s) factory::get_instance().destroy(); - - scc::close_fst_trace_file(trc); - return result + sc_report_handler::get_count(SC_ERROR) + sc_report_handler::get_count(SC_WARNING); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4310a6b..eeee6f4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,6 @@ add_subdirectory(io-redirector) -add_subdirectory(sim_performance) add_subdirectory(ordered_semaphore) add_subdirectory(axi4_pin_level) +if(FULL_TEST_SUITE) + add_subdirectory(sim_performance) +endif() \ No newline at end of file diff --git a/tests/axi4_pin_level/narrow_burst_test.cpp b/tests/axi4_pin_level/narrow_burst_test.cpp index 5dc2d81..316db58 100644 --- a/tests/axi4_pin_level/narrow_burst_test.cpp +++ b/tests/axi4_pin_level/narrow_burst_test.cpp @@ -3,7 +3,9 @@ #include "testbench.h" #include #include +#undef CHECK #include +#include using namespace sc_core; @@ -16,19 +18,18 @@ bool operator==(tlm::tlm_generic_payload const& a, tlm::tlm_generic_payload cons ret &= a.get_data_length() == b.get_data_length(); for(auto i=0u; i -tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, size_t len, unsigned id_offs = 0, - unsigned addr_offs = 0) { +tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, unsigned len, unsigned width, unsigned id_offs) { static uint8_t id{0}; auto trans = tlm::scc::tlm_mm<>::get().allocate(len); trans->set_address(start_address); @@ -36,15 +37,15 @@ tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, size_t len, unsi auto ext = trans->get_extension(); trans->set_data_length(len); trans->set_streaming_width(len); - ext->set_size(scc::ilog2(4)); + ext->set_size(scc::ilog2(width)); sc_assert(len < (bus_cfg::BUSWIDTH / 8) || len % (bus_cfg::BUSWIDTH / 8) == 0); auto length = (len * 8 - 1) / 32; - if(start_address % (bus_cfg::BUSWIDTH / 8)) + if(width==(bus_cfg::BUSWIDTH / 8) && start_address % (bus_cfg::BUSWIDTH / 8)) length++; ext->set_length(length); // ext->set_burst(len * 8 > bus_cfg::buswidth ? axi::burst_e::INCR : axi::burst_e::FIXED); ext->set_burst(axi::burst_e::INCR); - ext->set_id(id | id_offs); + ext->set_id(id); id = (id + 1) % 8; return trans; } @@ -59,94 +60,121 @@ inline void randomize(tlm::tlm_generic_payload& gp) { req_cnt++; } -TEST_CASE("pin level narrow burst", "[AXI][pin-level]") { - struct { - unsigned int ResetCycles{10}; - unsigned int BurstLengthByte{16}; - unsigned int NumberOfIterations{10}; - std::vector sent_read_tx, sent_write_tx; - std::vector rcv_read_tx, rcv_write_tx; - unsigned resp_cnt{0}; - } state; - +template +void run_scenario(STATE& state){ auto& dut = factory::get(); dut.tgt_pe.set_operation_cb([&state](axi::axi_protocol_types::tlm_payload_type& trans) -> unsigned { - auto addr = trans.get_address(); - uint8_t const* src = reinterpret_cast(&addr); - for(size_t i = 0; i < trans.get_data_length(); ++i) { - *(trans.get_data_ptr() + i) = i % 2 ? i : state.resp_cnt; + auto id = axi::get_axi_id(trans); + if(trans.is_read()) { + for(size_t i = 0; i < trans.get_data_length(); ++i) { + *(trans.get_data_ptr() + i) = i % 2 ? i : (state.resp_cnt+128); + } + state.read_tx[id].second.emplace_back(&trans); } - if(trans.is_read()) state.rcv_read_tx.emplace_back(&trans); - if(trans.is_write()) state.rcv_write_tx.emplace_back(&trans); + if(trans.is_write()) + state.write_tx[id].second.emplace_back(&trans); + SCCDEBUG(__FUNCTION__)<<"RX: "<(StartAddr, state.BurstLengthByte); + tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes, 0); randomize(*trans); trans->set_command(tlm::TLM_READ_COMMAND); + SCCDEBUG(__FUNCTION__)<<"TX: "<<*trans; dut.intor_pe.transport(*trans, false); - state.sent_read_tx.emplace_back(trans); + auto id = axi::get_axi_id(*trans); + state.read_tx[id].first.emplace_back(trans); if(trans->get_response_status() != tlm::TLM_OK_RESPONSE) - SCCERR() << "Invalid response status" << trans->get_response_string(); + SCCERR(__FUNCTION__) << "Invalid response status" << trans->get_response_string(); } - StartAddr += state.BurstLengthByte; { // 2 - tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte); + tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes, 0); trans->set_command(tlm::TLM_WRITE_COMMAND); randomize(*trans); + SCCDEBUG(__FUNCTION__)<<"TX: "<<*trans; dut.intor_pe.transport(*trans, false); - state.sent_read_tx.emplace_back(trans); + auto id = axi::get_axi_id(*trans); + state.write_tx[id].first.emplace_back(trans); if(trans->get_response_status() != tlm::TLM_OK_RESPONSE) - SCCERR() << "Invalid response status" << trans->get_response_string(); + SCCERR(__FUNCTION__) << "Invalid response status" << trans->get_response_string(); } - StartAddr += state.BurstLengthByte; + StartAddr += state.BurstSizeBytes; } }); auto run2 = sc_spawn([&dut, &state](){ - unsigned int StartAddr{0x1020}; + wait(0_ns); + unsigned int StartAddr{0x1000}; for(int i = 0; i < state.NumberOfIterations; ++i) { - SCCDEBUG("test") << "run1 executing transactions in iteration " << i; + SCCDEBUG(__FUNCTION__) << "run1 executing transactions in iteration " << i; { // 1 - tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, 0x8); + tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes, 0x8); randomize(*trans); trans->set_command(tlm::TLM_READ_COMMAND); + SCCDEBUG(__FUNCTION__)<<"TX: "<<*trans; dut.intor_pe.transport(*trans, false); - state.sent_write_tx.emplace_back(trans); + auto id = axi::get_axi_id(*trans); + state.read_tx[id].first.emplace_back(trans); if(trans->get_response_status() != tlm::TLM_OK_RESPONSE) - SCCERR() << "Invalid response status" << trans->get_response_string(); + SCCERR(__FUNCTION__) << "Invalid response status" << trans->get_response_string(); } - StartAddr += state.BurstLengthByte; { // 2 - tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, 0x8); + tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes, 0x8); trans->set_command(tlm::TLM_WRITE_COMMAND); randomize(*trans); + SCCDEBUG(__FUNCTION__)<<"TX: "<<*trans; dut.intor_pe.transport(*trans, false); - state.sent_write_tx.emplace_back(trans); + auto id = axi::get_axi_id(*trans); + state.write_tx[id].first.emplace_back(trans); if(trans->get_response_status() != tlm::TLM_OK_RESPONSE) - SCCERR() << "Invalid response status" << trans->get_response_string(); + SCCERR(__FUNCTION__) << "Invalid response status" << trans->get_response_string(); } - StartAddr += state.BurstLengthByte; + StartAddr += state.BurstSizeBytes; } }); - sc_start(1000 * dut.clk.period()); + sc_start(120 * dut.clk.period()); REQUIRE(run1.terminated()); REQUIRE(run2.terminated()); - REQUIRE(state.resp_cnt==40); - REQUIRE(state.sent_write_tx.size() == state.rcv_write_tx.size()); - for(auto i = 0; i, std::vector>> read_tx; + std::unordered_map, std::vector>> write_tx; + unsigned resp_cnt{0}; + } state; + + run_scenario(state); + + REQUIRE(state.resp_cnt==4*state.NumberOfIterations); + for(auto& e: state.write_tx) { + auto const& send_tx = e.second.first; + auto const& recv_tx = e.second.second; + REQUIRE(send_tx.size() == recv_tx.size()); + for(auto i = 0; i