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_