add ace_pin_level testcase and update scc
This commit is contained in:
		
							
								
								
									
										2
									
								
								scc
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								scc
									
									
									
									
									
								
							 Submodule scc updated: 3d5f733ed4...a21316a97f
									
								
							| @@ -1,6 +1,7 @@ | ||||
| add_subdirectory(io-redirector) | ||||
| add_subdirectory(ordered_semaphore) | ||||
| add_subdirectory(axi4_pin_level) | ||||
| add_subdirectory(ace_pin_level) | ||||
| add_subdirectory(configuration) | ||||
| if(FULL_TEST_SUITE) | ||||
| 	add_subdirectory(sim_performance) | ||||
|   | ||||
							
								
								
									
										9
									
								
								tests/ace_pin_level/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/ace_pin_level/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| project (ace_pin_level) | ||||
|  | ||||
| add_executable(${PROJECT_NAME}  | ||||
| 	ace_narrow_burst_test.cpp | ||||
| 	${test_util_SOURCE_DIR}/sc_main.cpp | ||||
| ) | ||||
| target_link_libraries (${PROJECT_NAME} PUBLIC test_util) | ||||
|  | ||||
| catch_discover_tests(${PROJECT_NAME}) | ||||
							
								
								
									
										242
									
								
								tests/ace_pin_level/ace_narrow_burst_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								tests/ace_pin_level/ace_narrow_burst_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | ||||
|  | ||||
| #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> 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<a.get_data_length(); ++i) | ||||
|         ret &= a.get_data_ptr()[i] == b.get_data_ptr()[i]; | ||||
|     //    if(a.get_byte_enable_ptr() && b.get_byte_enable_ptr()) { | ||||
|     //        ret &= a.get_byte_enable_length() == b.get_byte_enable_length(); | ||||
|     //        for(auto i=0u; i<a.get_byte_enable_length(); ++i) | ||||
|     //            ret &= a.get_byte_enable_ptr()[i] == b.get_byte_enable_ptr()[i]; | ||||
|     //    } | ||||
|     ret &= a.get_command() == b.get_command(); | ||||
|     //if(!ret) SCCWARN()<<"Comparison failed: "<<a<<" and "<<b; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| template<typename bus_cfg> | ||||
| tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, unsigned addr_incr, unsigned len, unsigned width, unsigned id) { | ||||
|     auto trans = tlm::scc::tlm_mm<>::get().allocate<axi::axi4_extension>(len); | ||||
|     trans->set_address(start_address); | ||||
|     tlm::scc::setId(*trans, id); | ||||
|     auto ext = trans->get_extension<axi::axi4_extension>(); | ||||
|     trans->set_data_length(len); | ||||
|     trans->set_streaming_width(len); | ||||
|     ext->set_size(scc::ilog2(width)); | ||||
|     sc_assert(len < (bus_cfg::BUSWIDTH / 8) || len % (bus_cfg::BUSWIDTH / 8) == 0); | ||||
|     auto length = (len * 8 - 1) / (8*width); | ||||
|     if(width==(bus_cfg::BUSWIDTH / 8) && start_address % (bus_cfg::BUSWIDTH / 8)) | ||||
|         length++; | ||||
|     ext->set_length(length); | ||||
|     // ext->set_burst(len * 8 > bus_cfg::buswidth ? axi::burst_e::INCR : axi::burst_e::FIXED); | ||||
|     ext->set_burst(axi::burst_e::INCR); | ||||
|     ext->set_id(id); | ||||
|     return trans; | ||||
| } | ||||
|  | ||||
| template<typename bus_cfg> | ||||
| tlm::tlm_generic_payload* prepare_trans_ace(uint64_t start_address, unsigned addr_incr, unsigned len, unsigned width, unsigned id) { | ||||
|     auto trans = tlm::scc::tlm_mm<>::get().allocate<axi::ace_extension>(len); | ||||
|     trans->set_address(start_address); | ||||
|     tlm::scc::setId(*trans, id); | ||||
|     auto ext = trans->get_extension<axi::ace_extension>(); | ||||
|     trans->set_data_length(len); | ||||
|     trans->set_streaming_width(len); | ||||
|     ext->set_size(scc::ilog2(width)); | ||||
|     sc_assert(len < (bus_cfg::BUSWIDTH / 8) || len % (bus_cfg::BUSWIDTH / 8) == 0); | ||||
|     auto length = (len * 8 - 1) / (8*width); | ||||
|     if(width==(bus_cfg::BUSWIDTH / 8) && start_address % (bus_cfg::BUSWIDTH / 8)) | ||||
|         length++; | ||||
|     ext->set_length(length); | ||||
|     // ext->set_burst(len * 8 > bus_cfg::buswidth ? axi::burst_e::INCR : axi::burst_e::FIXED); | ||||
|     ext->set_burst(axi::burst_e::INCR); | ||||
|     ext->set_id(id); | ||||
|     ext->set_snoop(axi::snoop_e::READ_SHARED); // set it so that is_data_less return true??? | ||||
|     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<uint8_t const*>(&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<typename STATE> | ||||
| unsigned run_scenario(STATE& state){ | ||||
|     auto& dut = factory::get<testbench>(); | ||||
|  | ||||
|     dut.axi_tgt_pe.set_operation_cb([&state](axi::axi_protocol_types::tlm_payload_type& trans) -> unsigned { | ||||
|         auto id = axi::get_axi_id(trans); | ||||
|         if(trans.is_read()) { | ||||
|             for(size_t i = 0; i < trans.get_data_length(); ++i) { | ||||
|                 *(trans.get_data_ptr() + i) = i % 2 ? 123 : (state.resp_cnt+128); | ||||
|             } | ||||
|             state.read_tx[id].second.emplace_back(&trans); | ||||
|         } | ||||
|         if(trans.is_write()) | ||||
|             state.write_tx[id].second.emplace_back(&trans); | ||||
|         SCCDEBUG(__FUNCTION__)<<"RX: "<<trans; | ||||
|         state.resp_cnt++; | ||||
|         return 0; | ||||
|     }); | ||||
|  | ||||
|  | ||||
|  | ||||
|     dut.rst.write(false); | ||||
|     sc_start(state.ResetCycles*dut.clk.period()); | ||||
|     dut.rst.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<testbench::bus_cfg>(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 1); | ||||
|             tlm::scc::tlm_gp_shared_ptr trans = prepare_trans_ace<testbench::bus_cfg>(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 1); | ||||
|             trans->set_command(tlm::TLM_READ_COMMAND); | ||||
|             SCCDEBUG(__FUNCTION__) << "run1, iteration " << i <<" TX: "<<*trans; | ||||
|             dut.intor_pe.transport(*trans, false); | ||||
|             state.read_tx[axi::get_axi_id(*trans)].first.emplace_back(trans); | ||||
|             StartAddr += state.BurstSizeBytes; | ||||
|         } | ||||
|     }); | ||||
| /* | ||||
|     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_ace<testbench::bus_cfg>(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 2); | ||||
|             trans->set_command(tlm::TLM_WRITE_COMMAND); | ||||
|             randomize(*trans); | ||||
|             SCCDEBUG(__FUNCTION__) << "run2, iteration " << i <<" TX: "<<*trans; | ||||
|             dut.intor_pe.transport(*trans, false); | ||||
|             state.write_tx[axi::get_axi_id(*trans)].first.emplace_back(trans); | ||||
|             StartAddr += state.BurstSizeBytes; | ||||
|         } | ||||
|     }); | ||||
|     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_ace<testbench::bus_cfg>(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 3); | ||||
|             trans->set_command(tlm::TLM_READ_COMMAND); | ||||
|             SCCDEBUG(__FUNCTION__) << "run3, iteration " << i <<" TX: "<<*trans; | ||||
|             dut.intor_pe.transport(*trans, false); | ||||
|             state.read_tx[axi::get_axi_id(*trans)].first.emplace_back(trans); | ||||
|             StartAddr += state.BurstSizeBytes; | ||||
|         } | ||||
|     }); | ||||
|     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_ace<testbench::bus_cfg>(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 4); | ||||
|             trans->set_command(tlm::TLM_WRITE_COMMAND); | ||||
|             randomize(*trans); | ||||
|             SCCDEBUG(__FUNCTION__) << "run4, iteration " << i <<" TX: "<<*trans; | ||||
|             dut.intor_pe.transport(*trans, false); | ||||
|             state.write_tx[axi::get_axi_id(*trans)].first.emplace_back(trans); | ||||
|             StartAddr += state.BurstSizeBytes; | ||||
|         } | ||||
|     }); | ||||
| */ | ||||
|     unsigned cycles{0}; | ||||
|  //   while(cycles<1000 && !(run1.terminated() && run2.terminated() && run3.terminated() && run4.terminated())){ | ||||
|    while(cycles<1000 && !(run1.terminated())){ | ||||
|         sc_start(10 * dut.clk.period()); | ||||
|         cycles+=10; | ||||
|     } | ||||
|     return cycles; | ||||
| } | ||||
|  | ||||
| TEST_CASE("ace_burst_alignment", "[AXI][pin-level]") { | ||||
|     struct { | ||||
|         unsigned int ResetCycles{4}; | ||||
|  //       unsigned int BurstLengthByte{16}; | ||||
|         unsigned int BurstLengthByte{32}; | ||||
|         unsigned int BurstSizeBytes{8}; | ||||
| //        unsigned int NumberOfIterations{8}; | ||||
|         unsigned int NumberOfIterations{1}; | ||||
|         std::unordered_map<unsigned, std::pair<std::vector<tlm::scc::tlm_gp_shared_ptr>, std::vector<tlm::scc::tlm_gp_shared_ptr>>> read_tx; | ||||
|         std::unordered_map<unsigned, std::pair<std::vector<tlm::scc::tlm_gp_shared_ptr>, std::vector<tlm::scc::tlm_gp_shared_ptr>>> 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); | ||||
|     for(auto& e: state.write_tx) { | ||||
|         auto const& send_tx = e.second.first; | ||||
|         auto const& recv_tx = e.second.second; | ||||
|         REQUIRE(send_tx.size() == recv_tx.size()); | ||||
|         for(auto i = 0; i<send_tx.size(); ++i) { | ||||
|             REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE); | ||||
|             CHECK(*send_tx[i] == *recv_tx[i]); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|     for(auto& e: state.read_tx) { | ||||
|         auto const& send_tx = e.second.first; | ||||
|         auto const& recv_tx = e.second.second; | ||||
|         REQUIRE(send_tx.size() == recv_tx.size()); | ||||
|         for(auto i = 0; i<send_tx.size(); ++i){ | ||||
|             REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE); | ||||
|             CHECK(*send_tx[i] == *recv_tx[i]); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("axi4_narrow_burst", "[AXI][pin-level]") { | ||||
|     struct { | ||||
|         unsigned int ResetCycles{4}; | ||||
|         unsigned int BurstLengthByte{32}; | ||||
|   //      unsigned int BurstLengthByte{16}; | ||||
|         unsigned int BurstSizeBytes{4}; | ||||
|  //       unsigned int NumberOfIterations{8}; | ||||
|         unsigned int NumberOfIterations{1}; | ||||
|         std::unordered_map<unsigned, std::pair<std::vector<tlm::scc::tlm_gp_shared_ptr>, std::vector<tlm::scc::tlm_gp_shared_ptr>>> read_tx; | ||||
|         std::unordered_map<unsigned, std::pair<std::vector<tlm::scc::tlm_gp_shared_ptr>, std::vector<tlm::scc::tlm_gp_shared_ptr>>> 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); | ||||
|     for(auto& e: state.write_tx) { | ||||
|         auto const& send_tx = e.second.first; | ||||
|         auto const& recv_tx = e.second.second; | ||||
|         REQUIRE(send_tx.size() == recv_tx.size()); | ||||
|         for(auto i = 0; i<send_tx.size(); ++i) | ||||
|             CHECK(*send_tx[i] == *recv_tx[i]); | ||||
|  | ||||
|     } | ||||
|     for(auto& e: state.read_tx) { | ||||
|         auto const& send_tx = e.second.first; | ||||
|         auto const& recv_tx = e.second.second; | ||||
|         REQUIRE(send_tx.size() == recv_tx.size()); | ||||
|         for(auto i = 0; i<send_tx.size(); ++i) | ||||
|             CHECK(*send_tx[i] == *recv_tx[i]); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								tests/ace_pin_level/testbench.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								tests/ace_pin_level/testbench.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #ifndef _TESTBENCH_H_ | ||||
| #define _TESTBENCH_H_ | ||||
|  | ||||
| #include <axi/pe/axi_initiator.h> | ||||
| #include <axi/pe/simple_target.h> | ||||
| #include <axi/pe/simple_ace_target.h> | ||||
| #include <axi/pin/ace_initiator.h> | ||||
| #include <axi/pin/ace_target.h> | ||||
| #include <axi/scv/recorder_modules.h> | ||||
| #include <scc.h> | ||||
|  | ||||
| using namespace sc_core; | ||||
| using namespace axi; | ||||
| using namespace axi::pe; | ||||
|  | ||||
| class testbench : public sc_core::sc_module { | ||||
| public: | ||||
|     using bus_cfg = axi::ace_cfg</*BUSWIDTH=*/64, /*ADDRWIDTH=*/32, /*IDWIDTH=*/4, /*USERWIDTH=*/1>; | ||||
|  | ||||
|     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<bool> rst{"rst"}; | ||||
|     // initiator side | ||||
|     axi::ace_initiator_socket<bus_cfg::BUSWIDTH> intor{"ace_intor"}; | ||||
|  | ||||
|     axi::pin::ace_initiator<bus_cfg> intor_bfm{"ace_intor_bfm"}; | ||||
|     // signal accurate bus | ||||
|     axi::aw_ch_ace<bus_cfg, axi::signal_types> aw; | ||||
|     axi::wdata_ch_ace<bus_cfg, axi::signal_types> wdata; | ||||
|     axi::b_ch_ace<bus_cfg, axi::signal_types> b; | ||||
|     axi::ar_ch_ace<bus_cfg, axi::signal_types> ar; | ||||
|     axi::rresp_ch_ace<bus_cfg, axi::signal_types> rresp; | ||||
|  | ||||
|     axi::pin::ace_target<bus_cfg> tgt_bfm{"ace_tgt_bfm"}; | ||||
|     // target side | ||||
|     axi::ace_target_socket<bus_cfg::BUSWIDTH> tgt_ace{"tgt_ace"}; | ||||
|     axi::axi_target_socket<bus_cfg::BUSWIDTH> tgt_axi{"tgt_axi"}; | ||||
|     // engines | ||||
|     axi::pe::ace_initiator<bus_cfg::BUSWIDTH> intor_pe; | ||||
|     axi::pe::simple_target<bus_cfg::BUSWIDTH> axi_tgt_pe; | ||||
|     axi::pe::simple_ace_target<bus_cfg::BUSWIDTH> ace_tgt_pe; | ||||
|  | ||||
| public: | ||||
|     SC_HAS_PROCESS(testbench); | ||||
|     testbench(): testbench("testbench") {} | ||||
|     testbench(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm) | ||||
|     , intor_pe("ace_intor_pe", intor) | ||||
|     , ace_tgt_pe("ace_tgt_pe", tgt_ace) | ||||
|     , axi_tgt_pe("axi_tgt_pe", tgt_axi) { | ||||
|         intor_pe.clk_i(clk); | ||||
|         intor_bfm.clk_i(clk); | ||||
|         tgt_bfm.clk_i(clk); | ||||
|         axi_tgt_pe.clk_i(clk); | ||||
|         ace_tgt_pe.clk_i(clk); | ||||
|         // pe socket to recorder | ||||
|         intor(intor_bfm.tsckt); | ||||
|  | ||||
|         // bfm to signals | ||||
|         intor_bfm.bind_aw(aw); | ||||
|         intor_bfm.bind_w(wdata); | ||||
|         intor_bfm.bind_b(b); | ||||
|         intor_bfm.bind_ar(ar); | ||||
|         intor_bfm.bind_r(rresp); | ||||
|         // signals to bfm | ||||
|         tgt_bfm.bind_aw(aw); | ||||
|         tgt_bfm.bind_w(wdata); | ||||
|         tgt_bfm.bind_b(b); | ||||
|         tgt_bfm.bind_ar(ar); | ||||
|         tgt_bfm.bind_r(rresp); | ||||
|         // bfm to recorder | ||||
|         tgt_bfm.isckt(tgt_ace); | ||||
|  | ||||
|         ace_tgt_pe.isckt_axi(tgt_axi); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     void run1() { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif // _TESTBENCH_H_ | ||||
		Reference in New Issue
	
	Block a user