diff --git a/.cproject b/.cproject index fea828d..bc9079e 100644 --- a/.cproject +++ b/.cproject @@ -28,8 +28,8 @@ - - + + diff --git a/scc b/scc index dc097db..eadb928 160000 --- a/scc +++ b/scc @@ -1 +1 @@ -Subproject commit dc097db73a29488e1aa11b823e423a55809fb843 +Subproject commit eadb9285757d639ce1acd854551c115ef84fc903 diff --git a/src/factory.h b/src/factory.h index 2c57fce..09e8cb3 100644 --- a/src/factory.h +++ b/src/factory.h @@ -25,7 +25,7 @@ public: add(const std::string& name, Args&&... args); }; - template static T& get(const std::string& name = ""); + template static T& get(const std::string& name = typeid(T).name()); void create(); @@ -50,7 +50,7 @@ private: std::map m_objects; }; -template factory::add::add(Args&&... args) { add("", args...); } +template factory::add::add(Args&&... args) { add(typeid(T).name(), args...); } template factory::add::add(const std::string& name, Args&&... args) { factory::get_instance().add_object(name, [args...]() -> object { diff --git a/src/sc_main.cpp b/src/sc_main.cpp index 6ff5088..eced2bc 100644 --- a/src/sc_main.cpp +++ b/src/sc_main.cpp @@ -27,8 +27,9 @@ int sc_main(int argc, char* argv[]) { scc::init_logging(LogConfig().logLevel(getenv("SCC_TEST_VERBOSE") ? log::TRACE : log::FATAL).logAsync(false).msgTypeFieldWidth(35)); // create tracer if environment variable SCC_TEST_TRACE is defined std::unique_ptr tracer; - if(getenv("SCC_TEST_TRACE")) - tracer = std::make_unique(my_name, scc::tracer::NONE, scc::tracer::ENABLE); + if(auto* test_trace = getenv("SCC_TEST_TRACE")) { + tracer = std::make_unique(my_name, scc::tracer::ENABLE, scc::tracer::ENABLE); + } int result = -1; if(setjmp(abrt) == 0) { // instantiate design(s) @@ -37,6 +38,7 @@ int sc_main(int argc, char* argv[]) { result = Catch::Session().run(argc, argv); // destroy design(s) sc_stop(); + SCCTRACE()<<"Test sequence finished"; factory::get_instance().destroy(); } return result; diff --git a/tests/cxs_tlm/CMakeLists.txt b/tests/cxs_tlm/CMakeLists.txt index 1a68c5b..ede8eff 100644 --- a/tests/cxs_tlm/CMakeLists.txt +++ b/tests/cxs_tlm/CMakeLists.txt @@ -1,3 +1,8 @@ -add_executable (cxs_tlm sc_main.cpp) -target_link_libraries (cxs_tlm LINK_PUBLIC busses scc-sysc) -add_test(NAME cxs_tlm COMMAND cxs_tlm ) \ No newline at end of file +project (cxs_tlm) +add_executable(${PROJECT_NAME} + csx_packet_test.cpp + ${test_util_SOURCE_DIR}/sc_main.cpp +) +target_link_libraries (${PROJECT_NAME} PUBLIC scc::busses test_util) + +catch_discover_tests(${PROJECT_NAME}) diff --git a/tests/cxs_tlm/csx_packet_test.cpp b/tests/cxs_tlm/csx_packet_test.cpp new file mode 100644 index 0000000..98f531b --- /dev/null +++ b/tests/cxs_tlm/csx_packet_test.cpp @@ -0,0 +1,115 @@ + +#include "testbench.h" +#include +#include +#undef CHECK +#include +#include + +using namespace sc_core; + +factory::add> tb8; +factory::add> tb9; +factory::add> tb10; + +template unsigned run_scenario(STATE& state) { + auto& dut = factory::get>(); + + dut.rst.write(true); + sc_start(state.reset_cycles * dut.clk.period()); + dut.rst.write(false); + sc_start(dut.clk.period()); + + auto run1 = sc_spawn([&dut, &state]() { + auto burst_cnt{0}; + for(auto size:state.packet_sizes) { + cxs_pkt_shared_ptr tx_pkt = cxs_pkt_mm::get().allocate(); + tx_pkt->get_data().resize(size); + auto phase{tlm::nw::REQUEST}; + sc_core::sc_time t = sc_core::SC_ZERO_TIME; + auto status = dut.isck->nb_transport_fw(*tx_pkt, phase, t); + REQUIRE(status == tlm::TLM_UPDATED); + REQUIRE(phase == tlm::nw::CONFIRM); + if(++burst_cnt==state.granularity) { + wait(dut.recv.data_written_event()); + while(!dut.recv.empty()) { + auto recv_pkt = dut.recv.front(); + dut.recv.pop_front(); + REQUIRE(tx_pkt==recv_pkt); + REQUIRE(recv_pkt->get_data().size()==state.packet_sizes[state.resp_cnt]); + state.resp_cnt++; + } + burst_cnt=0; + } + } + }); + + unsigned cycles{0}; + while(cycles < state.max_cycles && !(run1.terminated())) { + // while(cycles<1000 && !(run5.terminated())){ + sc_start(10 * dut.clk.period()); + cycles += 10; + } + return cycles; +} + +template +unsigned run_scenario(int width, STATE &state) +{ + switch (width) { + case 8: + case 256: + return run_scenario<256>(state); + case 9: + case 512: + return run_scenario<512>(state); + case 10: + case 1024: + return run_scenario<1024>(state); + } + return 0; +} + +TEST_CASE("single-packet", "[CXS][tlm-level]") { + struct { + unsigned int reset_cycles{4}; + unsigned int max_cycles = 5000; + std::vector packet_sizes; + unsigned granularity{1}; + unsigned resp_cnt{0}; + } state; + + + state.packet_sizes.assign({4, 8, 16, 32, 64, 128, 256, 1024}); + for(auto width=8; width<11; ++width) { + state.resp_cnt = 0; + auto cycles = run_scenario(width, state); + + REQUIRE(cycles < state.max_cycles); + REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0); + REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0); + + REQUIRE(state.resp_cnt == state.packet_sizes.size()); + } +} +/* +TEST_CASE("flit-alignment", "[CXS][tlm-level]") { + struct { + unsigned int reset_cycles{4}; + std::vector packet_sizes; + unsigned granularity{2}; + unsigned resp_cnt{0}; + } state; + + state.packet_sizes.assign({4, 32, 32, 8, 64, 128}); + state.resp_cnt = 0; + auto cycles = run_scenario(8, state); + + REQUIRE(cycles < 1000); + REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0); + REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0); + + REQUIRE(state.resp_cnt == state.packet_sizes.size()); +} + +*/ diff --git a/tests/cxs_tlm/sc_main.cpp b/tests/cxs_tlm/sc_main.cpp deleted file mode 100644 index 4d50866..0000000 --- a/tests/cxs_tlm/sc_main.cpp +++ /dev/null @@ -1,108 +0,0 @@ - -#define SC_INCLUDE_FX -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace sc_dt; -using namespace std; -using namespace cxs; -/* - * to be tested: - * PHITSIZE: 256, messages: 4*12bytes, 4*16bytes, 4x20bytes, 2x32bytes, 2x48bytes, 2x64bytes - */ -enum { PHIT_WIDTH = 256 }; -struct testbench : public sc_core::sc_module, - public tlm::nw::tlm_network_fw_transport_if, - public tlm::nw::tlm_network_bw_transport_if { - - using transaction_type = cxs_packet_types::tlm_payload_type; - using phase_type = cxs_packet_types::tlm_phase_type; - - sc_core::sc_clock clk{"clk", 1_ns}; - sc_core::sc_signal rst{"rst"}; - cxs_pkt_initiator_socket<> isck{"isck"}; - cxs_transmitter tx{"tx"}; - cxs_channel cxs_chan{"cxs_chan"}; - cxs_receiver rx{"rx"}; - cxs_pkt_target_socket<> tsck{"tsck"}; - - testbench(sc_core::sc_module_name const& nm) - : sc_module(nm) { - isck(*this); - tsck(*this); - isck(tx.tsck); - tx.clk_i(clk); - tx.isck(cxs_chan.tsck); - cxs_chan.isck(rx.tsck); - rx.clk_i(clk); - rx.rst_i(rst); - rx.isck(tsck); - SC_HAS_PROCESS(testbench); - SC_THREAD(run); - cxs_chan.channel_delay.set_value(100_ns); - rx.max_credit.set_value(15); - } - - void run() { - rst = true; - for(auto i = 0u; i < 11u; ++i) - wait(clk.posedge_event()); - rst = false; - cxs::cxs_packet_payload trans; - sc_core::sc_time t = sc_core::SC_ZERO_TIME; - isck->b_transport(trans, t); - wait(t); - cxs_pkt_shared_ptr trans_ptr = cxs_pkt_mm::get().allocate(); - trans_ptr->get_data().resize(16); - auto phase{tlm::nw::REQUEST}; - auto status = isck->nb_transport_fw(*trans_ptr, phase, t); - sc_assert(phase == tlm::nw::CONFIRM); - wait(target_received_evt); - wait(1_us); - sc_core::sc_stop(); - } - - void b_transport(transaction_type& trans, sc_core::sc_time& t) override { - SCCINFO(SCMOD) << "Received blocking transaction at local time " << (sc_core::sc_time_stamp() + t); - } - - tlm::tlm_sync_enum nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) override { - if(phase == tlm::nw::REQUEST) { - SCCINFO(SCMOD) << "Received non-blocking transaction with phase " << phase.get_name(); - target_received_evt.notify(sc_core::SC_ZERO_TIME); - phase = tlm::nw::CONFIRM; - return tlm::TLM_UPDATED; - } - throw std::runtime_error("illegal request in forward path"); - } - - tlm::tlm_sync_enum nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) override { - if(phase == tlm::nw::CONFIRM) { - confirmation_evt.notify(sc_core::SC_ZERO_TIME); - return tlm::TLM_ACCEPTED; - } - throw std::runtime_error("illegal response in backward path"); - } - - unsigned int transport_dbg(transaction_type& trans) override { return 0; } - - sc_core::sc_event confirmation_evt; - sc_core::sc_event target_received_evt; -}; - -int sc_main(int sc_argc, char* sc_argv[]) { - scc::init_logging(scc::log::DEBUG); - scc::configurer cfg(""); - scc::tracer trc("cxs_tlm"); - testbench tb("tb"); - sc_core::sc_start(); - SCCINFO("sc_main") << "End Simulation."; - - return sc_core::sc_report_handler::get_count(sc_core::SC_ERROR) + sc_core::sc_report_handler::get_count(sc_core::SC_WARNING); -} // End of 'sc_main' diff --git a/tests/cxs_tlm/testbench.h b/tests/cxs_tlm/testbench.h new file mode 100644 index 0000000..368a88a --- /dev/null +++ b/tests/cxs_tlm/testbench.h @@ -0,0 +1,79 @@ +#ifndef _TESTBENCH_H_ +#define _TESTBENCH_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sc_core; +using namespace sc_dt; +using namespace std; +using namespace cxs; + +const char* sc_gen_unique_name( const char*, bool preserve_first ); +template +struct testbench : public sc_core::sc_module { + + using transaction_type = cxs_packet_types::tlm_payload_type; + using phase_type = cxs_packet_types::tlm_phase_type; + + sc_core::sc_clock clk{"clk", 1_ns}; + sc_core::sc_signal rst{"rst"}; + tlm::nw::initiator_mixin, cxs_packet_types> isck{"isck"}; + cxs_transmitter tx{"tx"}; + cxs_channel cxs_chan{"cxs_chan"}; + cxs_receiver rx{"rx"}; + tlm::nw::target_mixin,cxs_packet_types> tsck{"tsck"}; + + testbench() + : testbench(sc_core::sc_gen_unique_name("testbench", false)) {} + + testbench(sc_core::sc_module_name const& nm) + : sc_module(nm) { + isck.register_nb_transport_bw([this](transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { + return this->nb_transport_fw(trans, phase, t); + }); + tsck.register_nb_transport_fw([this](transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { + return this->nb_transport_fw(trans, phase, t); + }); + isck(tx.tsck); + tx.clk_i(clk); + tx.isck(cxs_chan.tsck); + cxs_chan.isck(rx.tsck); + rx.clk_i(clk); + rx.rst_i(rst); + rx.isck(tsck); + cxs_chan.channel_delay.set_value(100_ns); + rx.max_credit.set_value(15); + } + + tlm::tlm_sync_enum nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { + if(phase == tlm::nw::REQUEST) { + SCCINFO(SCMOD) << "Received non-blocking transaction with phase " << phase.get_name(); + recv.push_back(&trans); + phase = tlm::nw::CONFIRM; + return tlm::TLM_UPDATED; + } + throw std::runtime_error("illegal request in forward path"); + } + + tlm::tlm_sync_enum nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { + if(phase == tlm::nw::CONFIRM) { + confirmation_evt.notify(sc_core::SC_ZERO_TIME); + return tlm::TLM_ACCEPTED; + } + throw std::runtime_error("illegal response in backward path"); + } + + sc_core::sc_event confirmation_evt; + scc::fifo_w_cb recv; +}; + +#endif // _TESTBENCH_H_