| // Copyright 2023 Google LLC |
| |
| #ifndef TESTS_VERILATOR_SIM_MATCHA_KELVIN_IF_H_ |
| #define TESTS_VERILATOR_SIM_MATCHA_KELVIN_IF_H_ |
| |
| #include "tests/verilator_sim/kelvin/memory_if.h" |
| #include "tests/verilator_sim/kelvin/kelvin_cfg.h" |
| |
| // [Bus] addr |
| // 1cc [SRAM] addr |
| // 2cc [SRAM] rdata |
| // [Bus] rdata |
| constexpr int kWaitState = 2; |
| constexpr int kBusBits = 256; |
| |
| struct Kelvin_if : Memory_if { |
| sc_in<bool> io_bus_cvalid; |
| sc_out<bool> io_bus_cready; |
| sc_in<bool> io_bus_cwrite; |
| sc_in<sc_bv<7> > io_bus_cid; |
| sc_in<sc_bv<32> > io_bus_caddr; |
| sc_in<sc_bv<kBusBits> > io_bus_wdata; |
| sc_in<sc_bv<32> > io_bus_wmask; |
| |
| sc_out<bool> io_bus_rvalid; |
| sc_out<sc_bv<7> > io_bus_rid; |
| sc_out<sc_bv<kBusBits> > io_bus_rdata; |
| |
| Kelvin_if(sc_module_name n, const char* bin) : Memory_if(n, bin) { |
| for (int i = 0; i < kBusBits / 32; ++i) { |
| runused_.set_word(i, 0); |
| } |
| } |
| |
| void eval() { |
| if (reset) { |
| return; |
| } |
| cycle_++; |
| |
| io_bus_cready = true; |
| |
| // Bus read. |
| if (io_bus_cvalid && io_bus_cready && !io_bus_cwrite) { |
| sc_bv<kBusBits> rdata; |
| uint32_t addr = io_bus_caddr.read().get_word(0); |
| uint32_t words[kBusBits / 32]; |
| Read(addr, kBusBits / 8, (uint8_t*) words); |
| |
| for (int i = 0; i < kBusBits / 32; ++i) { |
| rdata.set_word(i, words[i]); |
| } |
| |
| resp_t resp; |
| resp.cycle = cycle_; |
| resp.id = io_bus_cid.read().get_word(0); |
| for (int i = 0; i < kBusBits / 32; ++i) { |
| resp.data.set_word(i, words[i]); |
| } |
| resp_.write(resp); |
| } |
| |
| // Bus read response. |
| resp_t resp; |
| bool read = resp_.next(resp); |
| if (read && (cycle_ - resp.cycle) >= kWaitState) { |
| assert(resp_.remove()); |
| io_bus_rid = resp.id; |
| io_bus_rdata = resp.data; |
| } else { |
| read = false; |
| io_bus_rid = 0; |
| io_bus_rdata = runused_; |
| } |
| io_bus_rvalid = read; |
| |
| // Bus write. |
| if (io_bus_cvalid && io_bus_cready && io_bus_cwrite) { |
| uint8_t wdata[kBusBits / 8]; |
| uint32_t addr = io_bus_caddr.read().get_word(0); |
| uint32_t* p_wdata = (uint32_t*) wdata; |
| |
| for (int i = 0; i < kBusBits / 32; ++i) { |
| p_wdata[i] = io_bus_wdata.read().get_word(i); |
| } |
| |
| for (int i = 0; i < kBusBits / 8; ++i) { |
| if (io_bus_wmask.read().get_bit(i) != 0) { |
| Write(addr + i, 1, wdata + i); |
| } |
| } |
| } |
| } |
| |
| private: |
| uint32_t cycle_ = 0; |
| |
| struct resp_t { |
| uint32_t cycle; |
| uint32_t id : 7; |
| sc_bv<kBusBits> data; |
| }; |
| |
| fifo_t<resp_t> resp_; |
| sc_bv<kBusBits> runused_; |
| }; |
| |
| #endif // TESTS_VERILATOR_SIM_MATCHA_KELVIN_IF_H_ |