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"};