diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a61b9c3..f955608 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(${PROJECT_NAME} CLIParser.cpp tgc_vp/tb.cpp tgc_vp/system.cpp + tgc_vp/Flash.cpp ) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc_sc) diff --git a/src/tgc_vp/Flash.cpp b/src/tgc_vp/Flash.cpp new file mode 100644 index 0000000..37ea418 --- /dev/null +++ b/src/tgc_vp/Flash.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include + +template class flash : public scc::memory { + +public: + flash(const sc_core::sc_module_name& nm); + cci::cci_param FB_BUFFER_COUNT{"FB_BUFFER_COUNT", 2, "number of flash buffers"}; + cci::cci_param FB_SIZE{"FB_SIZE", 2, "represents the flash line size normalized to the bus data width"}; + cci::cci_param FR_DELAY{ + "FR_DELAY", 0, + "When a read is requested to the flash, it takes FR_DELAY cycles longer to respond in case of a buffer miss"}; + cci::cci_param FR_DELAY_TIME{"FR_DELAY_TIME", sc_core::SC_ZERO_TIME, + "When a read is requested to the flash, it takes FR_DELAY_TIME " + "duration longer to respond in case of a buffer miss"}; + +private: + std::vector buffers; + std::vector timestamps; + unsigned counter{0}; + int handle_operation(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay); + bool buffer_hit(uint64_t addr); +}; + +template +flash::flash(const sc_core::sc_module_name& nm) +: scc::memory(nm) +, buffers(FB_BUFFER_COUNT, std::numeric_limits::max()) +, timestamps(FB_BUFFER_COUNT, 0) { + this->set_operation_callback( + [this](scc::memory& mem, tlm::tlm_generic_payload& gp, sc_core::sc_time& delay) -> int { + tlm::tlm_command cmd = gp.get_command(); + auto res = 0; + if(cmd == tlm::TLM_READ_COMMAND) { + ::sc_dt::uint64 adr = gp.get_address(); + unsigned len = gp.get_data_length(); + delay += buffer_hit(adr) ? sc_core::SC_ZERO_TIME + : this->clk_i.get_interface() ? this->clk_i->read() * FR_DELAY + : FR_DELAY_TIME; + res = mem.handle_operation(gp, delay); + } else if(!sc_core::sc_time_stamp().value()) { + res = mem.handle_operation(gp, delay); + } + gp.set_dmi_allowed(false); + return res; + }); +} +template bool flash::buffer_hit(uint64_t addr) { + auto current_cache_start = addr - addr % (BUSWIDTH / 8 * FB_SIZE); + auto it = std::find(buffers.begin(), buffers.end(), current_cache_start); + if(it != buffers.end()) { + size_t index = std::distance(buffers.begin(), it); + timestamps[index] = ++counter; + return true; + } else { + auto it = std::min_element(timestamps.begin(), timestamps.end()); + size_t lru_index = std::distance(timestamps.begin(), it); + buffers[lru_index] = current_cache_start; + timestamps[lru_index] = ++counter; + return false; + } +} \ No newline at end of file diff --git a/src/tgc_vp/system.cpp b/src/tgc_vp/system.cpp index 126261b..796d768 100644 --- a/src/tgc_vp/system.cpp +++ b/src/tgc_vp/system.cpp @@ -16,7 +16,7 @@ using namespace sysc::tgfs; system::system(sc_core::sc_module_name nm) : sc_core::sc_module(nm) -, NAMED(ahb_router, 3, 2) +, NAMED(ahb_router, 4, 2) , NAMED(apbBridge, PipelinedMemoryBusToApbBridge_map.size(), 1) { core_complex.ibus(ahb_router.target[0]); core_complex.dbus(ahb_router.target[1]); @@ -27,6 +27,8 @@ system::system(sc_core::sc_module_name nm) ahb_router.set_target_range(1, 0x80000000, 32_kB); ahb_router.initiator.at(2)(apbBridge.target[0]); ahb_router.set_target_range(2, 0xF0000000, 256_MB); + ahb_router.initiator.at(3)(flash_mem.target); + ahb_router.set_target_range(3, 0xD0000000, 8_kB); size_t i = 0; for(const auto& e : PipelinedMemoryBusToApbBridge_map) { @@ -44,6 +46,7 @@ system::system(sc_core::sc_module_name nm) boot_rom.clk_i(clk_i); core_complex.clk_i(clk_i); main_ram.clk_i(clk_i); + flash_mem.clk_i(clk_i); gpio0.rst_i(rst_s); uart0.rst_i(rst_s); diff --git a/src/tgc_vp/system.h b/src/tgc_vp/system.h index e4ff3d2..6e3caf4 100644 --- a/src/tgc_vp/system.h +++ b/src/tgc_vp/system.h @@ -27,6 +27,7 @@ #include #include +#include "Flash.cpp" namespace tgc_vp { class system : public sc_core::sc_module { @@ -63,6 +64,7 @@ private: scc::memory<1_kB, scc::LT> boot_rom{"boot_rom"}; scc::memory<32_kB, scc::LT> main_ram{"main_ram"}; + flash<8_kB, 32> flash_mem{"flash_mem"}; sc_core::sc_signal rst_s{"rst_s"}, mtime_int_s{"mtime_int_s"}, msip_int_s{"msip_int_s"};