diff --git a/.gitignore b/.gitignore
index e6d0854..5bae3aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,5 @@
/*.vcd
/.venv/
/.pydevproject
+/*.fst
+/*.gtkw
diff --git a/.project b/.project
index e7ad514..781e2b6 100644
--- a/.project
+++ b/.project
@@ -28,6 +28,5 @@
org.eclipse.cdt.core.ccnature
org.eclipse.cdt.managedbuilder.core.managedBuildNature
org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
- org.python.pydev.pythonNature
diff --git a/scc b/scc
index 77a9f22..94569ea 160000
--- a/scc
+++ b/scc
@@ -1 +1 @@
-Subproject commit 77a9f223d7dc8cf838d95155f6023385bd6fdd03
+Subproject commit 94569eac10c4b8b5e3be6f8bcea7412b6e91396b
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f50c669..f2f005e 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(io-redirector)
add_subdirectory(ordered_semaphore)
+add_subdirectory(ahb_pin_level)
add_subdirectory(axi4_pin_level)
add_subdirectory(ace_pin_level)
add_subdirectory(configuration)
diff --git a/tests/ace_pin_level/ace_narrow_burst_test.cpp b/tests/ace_pin_level/ace_narrow_burst_test.cpp
index 8202712..425ecd1 100644
--- a/tests/ace_pin_level/ace_narrow_burst_test.cpp
+++ b/tests/ace_pin_level/ace_narrow_burst_test.cpp
@@ -10,20 +10,6 @@ using namespace sc_core;
factory::add tb;
-struct {
- unsigned int ResetCycles{4};
- unsigned int BurstLengthByte{16};
-// unsigned int BurstLengthByte{32};
- unsigned int BurstSizeBytes{8};
- // unsigned int NumberOfIterations{8};
- unsigned int NumberOfIterations{2};
- unsigned int CachelineSizeBytes={64}; //
- std::unordered_map, std::vector>> read_tx;
- std::unordered_map, std::vector>> write_tx;
- std::unordered_map, std::vector>> snoop_tx;
- unsigned resp_cnt{0};
-} state;
-
int snoop_id=0;
bool operator==(tlm::tlm_generic_payload const& a, tlm::tlm_generic_payload const& b){
@@ -77,31 +63,6 @@ inline void randomize(tlm::tlm_generic_payload& gp) {
req_cnt++;
}
-unsigned testbench::transport(tlm::tlm_generic_payload& trans) {
- SCCDEBUG(__FUNCTION__)<<" update snoop trans, with snoop_id = " << snoop_id;
- // SCCDEBUG(__FUNCTION__)<<" in transport with trans " << trans;
- // extracting address and snoop_e from ac_trans and pack them into cache data trans
- auto ac_address = trans.get_address();
- auto ext = trans.get_extension();
- auto ac_snoop=ext->get_snoop();
-
- for(size_t i = 0; i < trans.get_data_length(); ++i) {
- *(trans.get_data_ptr() + i) = i % 2 ? i : 128;
- }
- //SCCDEBUG(__FUNCTION__)<<" vector size " <set_snoop_data_transfer(true);
- ext->set_snoop_error(false);
- ext->set_pass_dirty(false);
- ext->set_shared(false);
- ext->set_snoop_was_unique(false);
- */
- return 1;
-
-}
-
template
unsigned run_scenario(STATE& state){
auto& dut = factory::get();
@@ -120,6 +81,18 @@ unsigned run_scenario(STATE& state){
state.resp_cnt++;
return 0;
});
+ dut.transport_cb = [&state](tlm::tlm_generic_payload& trans) -> unsigned {
+ SCCDEBUG(__FUNCTION__)<<" update snoop trans, with snoop_id = " << snoop_id;
+ // extracting address and snoop_e from ac_trans and pack them into cache data trans
+ auto ac_address = trans.get_address();
+ auto ext = trans.get_extension();
+ auto ac_snoop=ext->get_snoop();
+ for(size_t i = 0; i < trans.get_data_length(); ++i) {
+ *(trans.get_data_ptr() + i) = i % 2 ? i : 128;
+ }
+ state.snoop_tx[snoop_id].second.emplace_back(&trans);
+ return 1;
+ };
dut.rst.write(false);
sc_start(state.ResetCycles*dut.clk.period());
@@ -201,6 +174,17 @@ unsigned run_scenario(STATE& state){
}
TEST_CASE("ace_burst_alignment", "[AXI][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{16};
+ unsigned int BurstSizeBytes{8};
+ unsigned int NumberOfIterations{2};
+ unsigned int CachelineSizeBytes={64}; //
+ std::unordered_map, std::vector>> read_tx;
+ std::unordered_map, std::vector>> write_tx;
+ std::unordered_map, std::vector>> snoop_tx;
+ unsigned resp_cnt{0};
+ } state;
state.resp_cnt=0;
auto cycles = run_scenario(state);
@@ -250,7 +234,19 @@ TEST_CASE("ace_burst_alignment", "[AXI][pin-level]") {
}
-TEST_CASE("axi4_narrow_burst", "[AXI][pin-level]") {
+TEST_CASE("ace_narrow_burst", "[AXI][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{16};
+ unsigned int BurstSizeBytes{8};
+ unsigned int NumberOfIterations{2};
+ unsigned int CachelineSizeBytes={64}; //
+ std::unordered_map, std::vector>> read_tx;
+ std::unordered_map, std::vector>> write_tx;
+ std::unordered_map, std::vector>> snoop_tx;
+ unsigned resp_cnt{0};
+ } state;
+
state.resp_cnt=0;
auto cycles = run_scenario(state);
diff --git a/tests/ace_pin_level/testbench.h b/tests/ace_pin_level/testbench.h
index c0e23cf..93181c6 100644
--- a/tests/ace_pin_level/testbench.h
+++ b/tests/ace_pin_level/testbench.h
@@ -27,14 +27,14 @@ public:
axi::ace_initiator_socket intor{"ace_intor"};
axi::pin::ace_initiator intor_bfm{"ace_intor_bfm"};
// signal accurate bus
- axi::aw_ch_ace aw;
- axi::wdata_ch_ace wdata;
- axi::b_ch_ace b;
- axi::ar_ch_ace ar;
- axi::rresp_ch_ace rresp;
- axi::ac_ch_ace ac;
- axi::cr_ch_ace cr;
- axi::cd_ch_ace cd;
+ axi::aw_ace aw;
+ axi::wdata_ace wdata;
+ axi::b_ace b;
+ axi::ar_ace ar;
+ axi::rresp_ace rresp;
+ axi::ac_ace ac;
+ axi::cr_ace cr;
+ axi::cd_ace cd;
axi::pin::ace_target tgt_bfm{"ace_tgt_bfm"};
// target side
@@ -93,9 +93,8 @@ public:
}
- unsigned transport(tlm::tlm_generic_payload& trans) override ;
- void run1() {
- }
+ unsigned transport(tlm::tlm_generic_payload& trans) override { if(transport_cb) return transport_cb(trans); else return 0;}
+ std::function transport_cb;
};
#endif // _TESTBENCH_H_
diff --git a/tests/ahb_pin_level/CMakeLists.txt b/tests/ahb_pin_level/CMakeLists.txt
new file mode 100644
index 0000000..621893d
--- /dev/null
+++ b/tests/ahb_pin_level/CMakeLists.txt
@@ -0,0 +1,9 @@
+project (ahb_pin_level)
+
+add_executable(${PROJECT_NAME}
+ bus_test.cpp
+ ${test_util_SOURCE_DIR}/sc_main.cpp
+)
+target_link_libraries (${PROJECT_NAME} PUBLIC test_util)
+
+catch_discover_tests(${PROJECT_NAME})
diff --git a/tests/ahb_pin_level/bus_test.cpp b/tests/ahb_pin_level/bus_test.cpp
new file mode 100644
index 0000000..3b8129c
--- /dev/null
+++ b/tests/ahb_pin_level/bus_test.cpp
@@ -0,0 +1,260 @@
+
+#include "testbench.h"
+#include
+#include
+#undef CHECK
+#include
+#include
+
+using namespace sc_core;
+using namespace ahb;
+
+factory::add tb;
+
+bool operator==(tlm::tlm_generic_payload const& a, tlm::tlm_generic_payload const& b){
+ auto ret = true;
+ ret &= a.get_command() == b.get_command();
+ ret &= a.get_address() == b.get_address();
+ ret &= a.get_data_length() == b.get_data_length();
+ for(auto i=0u; i
+tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, unsigned len, unsigned width) {
+ static unsigned id{0};
+ auto trans = tlm::scc::tlm_mm<>::get().allocate(len);
+ trans->set_address(start_address);
+ tlm::scc::setId(*trans, ++id);
+ auto ext = trans->get_extension();
+ trans->set_data_length(len);
+ trans->set_streaming_width(len);
+ ext->set_burst(ahb::burst_e::INCR);
+ return trans;
+}
+
+inline void randomize(tlm::tlm_generic_payload& gp) {
+ static uint8_t req_cnt{0};
+ auto addr = gp.get_address();
+ uint8_t const* src = reinterpret_cast(&addr);
+ for(size_t i = 0; i < gp.get_data_length(); ++i) {
+ *(gp.get_data_ptr() + i) = i % 2 ? i : req_cnt;
+ }
+ req_cnt++;
+}
+
+template
+unsigned run_scenario(STATE& state, unsigned wait_states = 0){
+ auto& dut = factory::get();
+ dut.tsck.register_b_transport([&state, wait_states](tlm::tlm_base_protocol_types::tlm_payload_type& trans, sc_core::sc_time& d) {
+ 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.second.emplace_back(&trans);
+ }
+ if(trans.is_write())
+ state.write_tx.second.emplace_back(&trans);
+ SCCDEBUG(__FUNCTION__)<<"RX: "<().clk.posedge_event());
+ state.resp_cnt++;
+ return 0;
+ });
+
+ dut.rst_n.write(false);
+ sc_start(state.ResetCycles*dut.clk.period());
+ dut.rst_n.write(true);
+ sc_start(dut.clk.period());
+ dut.HSEL.write(true);
+ sc_start(dut.clk.period());
+
+ auto run1 = sc_spawn([&dut, &state](){
+ unsigned int StartAddr{0x0};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_READ_COMMAND);
+ SCCDEBUG(__FUNCTION__) << "task run1, iteration " << i <<" TX: "<<*trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.read_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run1 finished";
+ });
+ auto run2 = sc_spawn([&dut, &state](){
+ unsigned int StartAddr{0x2000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_WRITE_COMMAND);
+ randomize(*trans);
+ SCCDEBUG(__FUNCTION__) << "task run2, iteration " << i <<" TX: "<<*trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.write_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run2 finished";
+ });
+ auto run3 = sc_spawn([&dut, &state](){
+ unsigned int StartAddr{0x1000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_READ_COMMAND);
+ SCCDEBUG(__FUNCTION__) << "task run3, iteration " << i <<" TX: "<<*trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.read_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run3 finished";
+ });
+ auto run4 = sc_spawn([&dut, &state](){
+ unsigned int StartAddr{0x3000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans = prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_WRITE_COMMAND);
+ randomize(*trans);
+ SCCDEBUG(__FUNCTION__) << "task run4, iteration " << i <<" TX: "<<*trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.write_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run4 finished";
+ });
+
+ unsigned cycles{0};
+ while(cycles<1000 && !(run1.terminated() && run2.terminated() && run3.terminated() && run4.terminated())){
+ sc_start(10 * dut.clk.period());
+ cycles+=10;
+ }
+ return cycles;
+}
+
+TEST_CASE("ahb_read_write", "[AHB][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{4};
+ unsigned int BurstSizeBytes{4};
+ unsigned int NumberOfIterations{1};
+ std::pair, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(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==4*state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; iget_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(*send_tx[i] == *recv_tx[i]);
+ }
+ }
+ {
+ auto& e = state.read_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; iget_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(*send_tx[i] == *recv_tx[i]);
+ }
+ }
+}
+
+TEST_CASE("ahb_narrow_read_write", "[AHB][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{1};
+ unsigned int BurstSizeBytes{1};
+ unsigned int NumberOfIterations{8};
+ std::pair, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(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==4*state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(state, 1);
+
+ 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==4*state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; iget_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(*send_tx[i] == *recv_tx[i]);
+ }
+ }
+ {
+ auto& e = state.read_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; iget_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(*send_tx[i] == *recv_tx[i]);
+ }
+ }
+}
+
diff --git a/tests/ahb_pin_level/testbench.h b/tests/ahb_pin_level/testbench.h
new file mode 100644
index 0000000..bb57d9f
--- /dev/null
+++ b/tests/ahb_pin_level/testbench.h
@@ -0,0 +1,79 @@
+#ifndef _TESTBENCH_H_
+#define _TESTBENCH_H_
+
+#include
+#include
+#include
+
+using namespace sc_core;
+
+class testbench : public sc_core::sc_module {
+public:
+ enum { DWIDTH = 32};
+ sc_core::sc_time clk_period{10, sc_core::SC_NS};
+ sc_core::sc_clock clk{"clk", clk_period, 0.5, sc_core::SC_ZERO_TIME, true};
+ sc_core::sc_signal rst_n{"rst_n"};
+ // initiator side
+ tlm::scc::initiator_mixin> isck{"isck"};
+ ahb::pin::initiator intor_bfm{"intor_bfm"};
+ // signal accurate bus
+ sc_core::sc_signal> HADDR{"HADDR"};
+ sc_core::sc_signal> HBURST{"HBURST"};
+ sc_core::sc_signal HMASTLOCK{"HMASTLOCK"};
+ sc_core::sc_signal> HPROT{"HPROT"};
+ sc_core::sc_signal> HSIZE{"HSIZE"};
+ sc_core::sc_signal> HTRANS{"HTRANS"};
+ sc_core::sc_signal> HWDATA{"HWDATA"};
+ sc_core::sc_signal HWRITE{"HWRITE"};
+ sc_core::sc_signal> HRDATA{"HRDATA"};
+ sc_core::sc_signal HREADY{"HREADY"};
+ sc_core::sc_signal HRESP{"HRESP"};
+ sc_core::sc_signal HSEL{"HSEL"};
+ // target side
+ ahb::pin::target tgt_bfm{"tgt_bfm"};
+ tlm::scc::target_mixin> tsck{"tsck"};
+
+public:
+ SC_HAS_PROCESS(testbench);
+ testbench(): testbench("testbench") {}
+ testbench(sc_core::sc_module_name nm)
+ : sc_core::sc_module(nm) {
+ intor_bfm.HCLK_i(clk);
+ tgt_bfm.HCLK_i(clk);
+ // bfm to signals
+ isck(intor_bfm.tsckt);
+ intor_bfm.HRESETn_i(rst_n);
+ intor_bfm.HADDR_o(HADDR);
+ intor_bfm.HBURST_o(HBURST);
+ intor_bfm.HMASTLOCK_o(HMASTLOCK);
+ intor_bfm.HPROT_o(HPROT);
+ intor_bfm.HSIZE_o(HSIZE);
+ intor_bfm.HTRANS_o(HTRANS);
+ intor_bfm.HWDATA_o(HWDATA);
+ intor_bfm.HWRITE_o(HWRITE);
+ intor_bfm.HRDATA_i(HRDATA);
+ intor_bfm.HREADY_i(HREADY);
+ intor_bfm.HRESP_i(HRESP);
+ // signals to bfm
+ tgt_bfm.HRESETn_i(rst_n);
+ tgt_bfm.HADDR_i(HADDR);
+ tgt_bfm.HBURST_i(HBURST);
+ tgt_bfm.HMASTLOCK_i(HMASTLOCK);
+ tgt_bfm.HPROT_i(HPROT);
+ tgt_bfm.HSIZE_i(HSIZE);
+ tgt_bfm.HTRANS_i(HTRANS);
+ tgt_bfm.HWDATA_i(HWDATA);
+ tgt_bfm.HWRITE_i(HWRITE);
+ tgt_bfm.HSEL_i(HSEL);
+ tgt_bfm.HRDATA_o(HRDATA);
+ tgt_bfm.HREADY_o(HREADY);
+ tgt_bfm.HRESP_o(HRESP);
+ tgt_bfm.isckt(tsck);
+ }
+
+
+ void run1() {
+ }
+};
+
+#endif // _TESTBENCH_H_
diff --git a/tests/axi4_pin_level/testbench.h b/tests/axi4_pin_level/testbench.h
index bfad95b..db748bf 100644
--- a/tests/axi4_pin_level/testbench.h
+++ b/tests/axi4_pin_level/testbench.h
@@ -24,11 +24,11 @@ public:
axi::scv::axi_recorder_module intor_rec{"intor_rec"};
axi::pin::axi4_initiator intor_bfm{"intor_bfm"};
// signal accurate bus
- axi::aw_ch aw;
- axi::wdata_ch wdata;
- axi::b_ch b;
- axi::ar_ch ar;
- axi::rresp_ch rresp;
+ axi::aw_axi aw;
+ axi::wdata_axi wdata;
+ axi::b_axi b;
+ axi::ar_axi ar;
+ axi::rresp_axi rresp;
axi::pin::axi4_target tgt_bfm{"tgt_bfm"};
// target side
axi::scv::axi_recorder_module tgt_rec{"tgt_rec"};