adds some more CXS channel testing
This commit is contained in:
parent
89920683e9
commit
a0bd767bc9
@ -28,8 +28,8 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||||
<storageModule buildDir="build/${ConfigName}" dirtyTs="1733906038982" moduleId="de.marw.cmake4eclipse.mbs.settings">
|
<storageModule buildDir="build/${ConfigName}" dirtyTs="1733906014591" moduleId="de.marw.cmake4eclipse.mbs.settings">
|
||||||
<options otherArguments="--preset RelWithDebInfo"/>
|
<options otherArguments="--preset Debug"/>
|
||||||
<defs>
|
<defs>
|
||||||
<def name="BUILD_SCC_DOCUMENTATION" type="BOOL" val="OFF"/>
|
<def name="BUILD_SCC_DOCUMENTATION" type="BOOL" val="OFF"/>
|
||||||
<def name="ENABLE_CLANG_TIDY" type="STRING" val="OFF"/>
|
<def name="ENABLE_CLANG_TIDY" type="STRING" val="OFF"/>
|
||||||
|
2
scc
2
scc
@ -1 +1 @@
|
|||||||
Subproject commit dc097db73a29488e1aa11b823e423a55809fb843
|
Subproject commit eadb9285757d639ce1acd854551c115ef84fc903
|
@ -25,7 +25,7 @@ public:
|
|||||||
add(const std::string& name, Args&&... args);
|
add(const std::string& name, Args&&... args);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> static T& get(const std::string& name = "");
|
template <typename T> static T& get(const std::string& name = typeid(T).name());
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ private:
|
|||||||
std::map<std::string, object> m_objects;
|
std::map<std::string, object> m_objects;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Args> factory::add<T, Args...>::add(Args&&... args) { add("", args...); }
|
template <typename T, typename... Args> factory::add<T, Args...>::add(Args&&... args) { add(typeid(T).name(), args...); }
|
||||||
|
|
||||||
template <typename T, typename... Args> factory::add<T, Args...>::add(const std::string& name, Args&&... args) {
|
template <typename T, typename... Args> factory::add<T, Args...>::add(const std::string& name, Args&&... args) {
|
||||||
factory::get_instance().add_object(name, [args...]() -> object {
|
factory::get_instance().add_object(name, [args...]() -> object {
|
||||||
|
@ -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));
|
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
|
// create tracer if environment variable SCC_TEST_TRACE is defined
|
||||||
std::unique_ptr<scc::tracer> tracer;
|
std::unique_ptr<scc::tracer> tracer;
|
||||||
if(getenv("SCC_TEST_TRACE"))
|
if(auto* test_trace = getenv("SCC_TEST_TRACE")) {
|
||||||
tracer = std::make_unique<scc::tracer>(my_name, scc::tracer::NONE, scc::tracer::ENABLE);
|
tracer = std::make_unique<scc::tracer>(my_name, scc::tracer::ENABLE, scc::tracer::ENABLE);
|
||||||
|
}
|
||||||
int result = -1;
|
int result = -1;
|
||||||
if(setjmp(abrt) == 0) {
|
if(setjmp(abrt) == 0) {
|
||||||
// instantiate design(s)
|
// instantiate design(s)
|
||||||
@ -37,6 +38,7 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
result = Catch::Session().run(argc, argv);
|
result = Catch::Session().run(argc, argv);
|
||||||
// destroy design(s)
|
// destroy design(s)
|
||||||
sc_stop();
|
sc_stop();
|
||||||
|
SCCTRACE()<<"Test sequence finished";
|
||||||
factory::get_instance().destroy();
|
factory::get_instance().destroy();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
add_executable (cxs_tlm sc_main.cpp)
|
project (cxs_tlm)
|
||||||
target_link_libraries (cxs_tlm LINK_PUBLIC busses scc-sysc)
|
add_executable(${PROJECT_NAME}
|
||||||
add_test(NAME cxs_tlm COMMAND cxs_tlm )
|
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})
|
||||||
|
115
tests/cxs_tlm/csx_packet_test.cpp
Normal file
115
tests/cxs_tlm/csx_packet_test.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
#include "testbench.h"
|
||||||
|
#include <factory.h>
|
||||||
|
#include <tlm/scc/tlm_gp_shared.h>
|
||||||
|
#undef CHECK
|
||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
|
||||||
|
factory::add<testbench<256>> tb8;
|
||||||
|
factory::add<testbench<512>> tb9;
|
||||||
|
factory::add<testbench<1024>> tb10;
|
||||||
|
|
||||||
|
template <unsigned WIDTH, typename STATE> unsigned run_scenario(STATE& state) {
|
||||||
|
auto& dut = factory::get<testbench<WIDTH>>();
|
||||||
|
|
||||||
|
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 <typename STATE>
|
||||||
|
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<unsigned int> 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<unsigned int> 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
@ -1,108 +0,0 @@
|
|||||||
|
|
||||||
#define SC_INCLUDE_FX
|
|
||||||
#include <cxs/cxs_tlm.h>
|
|
||||||
#include <scc/cci_util.h>
|
|
||||||
#include <scc/configurer.h>
|
|
||||||
#include <scc/observer.h>
|
|
||||||
#include <scc/sc_variable.h>
|
|
||||||
#include <scc/tracer.h>
|
|
||||||
#include <string>
|
|
||||||
#include <systemc>
|
|
||||||
|
|
||||||
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<cxs_packet_types>,
|
|
||||||
public tlm::nw::tlm_network_bw_transport_if<cxs_packet_types> {
|
|
||||||
|
|
||||||
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<bool> rst{"rst"};
|
|
||||||
cxs_pkt_initiator_socket<> isck{"isck"};
|
|
||||||
cxs_transmitter<PHIT_WIDTH> tx{"tx"};
|
|
||||||
cxs_channel<PHIT_WIDTH> cxs_chan{"cxs_chan"};
|
|
||||||
cxs_receiver<PHIT_WIDTH> 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'
|
|
79
tests/cxs_tlm/testbench.h
Normal file
79
tests/cxs_tlm/testbench.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef _TESTBENCH_H_
|
||||||
|
#define _TESTBENCH_H_
|
||||||
|
|
||||||
|
#include <cxs/cxs_tlm.h>
|
||||||
|
#include <scc/cci_util.h>
|
||||||
|
#include <scc/configurer.h>
|
||||||
|
#include <scc/observer.h>
|
||||||
|
#include <scc/sc_variable.h>
|
||||||
|
#include <scc/tracer.h>
|
||||||
|
#include <tlm/nw/initiator_mixin.h>
|
||||||
|
#include <tlm/nw/target_mixin.h>
|
||||||
|
#include <string>
|
||||||
|
#include <systemc>
|
||||||
|
|
||||||
|
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<unsigned PHIT_WIDTH>
|
||||||
|
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<bool> rst{"rst"};
|
||||||
|
tlm::nw::initiator_mixin<cxs_pkt_initiator_socket<>, cxs_packet_types> isck{"isck"};
|
||||||
|
cxs_transmitter<PHIT_WIDTH> tx{"tx"};
|
||||||
|
cxs_channel<PHIT_WIDTH> cxs_chan{"cxs_chan"};
|
||||||
|
cxs_receiver<PHIT_WIDTH> rx{"rx"};
|
||||||
|
tlm::nw::target_mixin<cxs_pkt_target_socket<>,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<cxs_pkt_shared_ptr> recv;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _TESTBENCH_H_
|
Loading…
Reference in New Issue
Block a user