diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index f808891..bbd2b49 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -613,7 +613,7 @@ std::pair riscv_hart_m_p::load_file(std::str CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } - for(const auto sec : reader.sections) { + for(const auto& sec : reader.sections) { if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 7b3e601..da8fd3f 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -199,7 +199,8 @@ struct core_trace { SC_HAS_PROCESS(core_complex); // NOLINT #ifndef CWR_SYSTEMC -core_complex::core_complex(sc_module_name const& name) +template +core_complex::core_complex(sc_module_name const& name) : sc_module(name) , fetch_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext()) @@ -208,7 +209,8 @@ core_complex::core_complex(sc_module_name const& name) } #endif -void core_complex::init() { +template +void core_complex::init() { trc = new core_trace(); ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void { auto lut_entry = fetch_lut.getEntry(start); @@ -227,6 +229,7 @@ void core_complex::init() { } }); + SC_HAS_PROCESS(core_complex); // NOLINT SC_THREAD(run); SC_METHOD(rst_cb); sensitive << rst_i; @@ -252,16 +255,19 @@ void core_complex::init() { #endif } -core_complex::~core_complex() { +template +core_complex::~core_complex() { delete cpu; delete trc; for(auto* p : plugin_list) delete p; } -void core_complex::trace(sc_trace_file* trf) const {} +template +void core_complex::trace(sc_trace_file* trf) const {} -void core_complex::before_end_of_elaboration() { +template +void core_complex::before_end_of_elaboration() { SCCDEBUG(SCMOD) << "instantiating iss::arch::tgf with " << GET_PROP_VALUE(backend) << " backend"; // cpu = scc::make_unique(this); cpu = new core_wrapper(this); @@ -302,7 +308,8 @@ void core_complex::before_end_of_elaboration() { } } -void core_complex::start_of_simulation() { +template +void core_complex::start_of_simulation() { // quantum_keeper.reset(); if(GET_PROP_VALUE(elf_file).size() > 0) { istringstream is(GET_PROP_VALUE(elf_file)); @@ -325,7 +332,8 @@ void core_complex::start_of_simulation() { } } -bool core_complex::disass_output(uint64_t pc, const std::string instr_str) { +template +bool core_complex::disass_output(uint64_t pc, const std::string instr_str) { if(trc->m_db == nullptr) return false; if(trc->tr_handle.is_active()) @@ -339,7 +347,8 @@ bool core_complex::disass_output(uint64_t pc, const std::string instr_str) { return true; } -void core_complex::forward() { +template +void core_complex::forward() { #ifndef CWR_SYSTEMC set_clock_period(clk_i.read()); #else @@ -348,24 +357,30 @@ void core_complex::forward() { #endif } -void core_complex::set_clock_period(sc_core::sc_time period) { +template +void core_complex::set_clock_period(sc_core::sc_time period) { curr_clk = period; if(period == SC_ZERO_TIME) cpu->set_interrupt_execution(true); } -void core_complex::rst_cb() { +template +void core_complex::rst_cb() { if(rst_i.read()) cpu->set_interrupt_execution(true); } -void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); } +template +void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); } -void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); } +template +void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); } -void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); } +template +void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); } -void core_complex::local_irq_cb() { +template +void core_complex::local_irq_cb() { for(auto i = 0U; i < local_irq_i.size(); ++i) { if(local_irq_i[i].event()) { cpu->local_irq(16 + i, local_irq_i[i].read()); @@ -373,7 +388,8 @@ void core_complex::local_irq_cb() { } } -void core_complex::run() { +template +void core_complex::run() { wait(SC_ZERO_TIME); // separate from elaboration phase do { wait(SC_ZERO_TIME); @@ -391,7 +407,8 @@ void core_complex::run() { sc_stop(); } -bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) { +template +bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) { auto& dmi_lut = is_fetch ? fetch_lut : read_lut; auto lut_entry = dmi_lut.getEntry(addr); if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) { @@ -449,7 +466,8 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data, } } -bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) { +template +bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) { auto lut_entry = write_lut.getEntry(addr); if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) { auto offset = addr - lut_entry.get_start_address(); @@ -497,7 +515,8 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* cons } } -bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) { +template +bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) { tlm::tlm_generic_payload gp; gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); @@ -507,7 +526,8 @@ bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const d return dbus->transport_dbg(gp) == length; } -bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) { +template +bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) { write_buf.resize(length); std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity tlm::tlm_generic_payload gp; @@ -518,5 +538,10 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* gp.set_streaming_width(length); return dbus->transport_dbg(gp) == length; } + +template class core_complex; +template class core_complex<32>; +template class core_complex<64>; + } /* namespace tgfs */ } /* namespace sysc */ diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index 8d1c0c7..a31689a 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #ifdef CWR_SYSTEMC @@ -68,12 +69,35 @@ public: namespace tgfs { class core_wrapper; struct core_trace; +struct core_complex_if { -class core_complex : public sc_core::sc_module, public scc::traceable { + virtual ~core_complex_if() = default; + + virtual bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) =0; + + virtual bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) =0; + + virtual bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) =0; + + virtual bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) =0; + + virtual bool disass_output(uint64_t pc, const std::string instr) =0; + + virtual unsigned get_last_bus_cycles() =0; + + virtual void sync(uint64_t) =0; + + virtual char const* hier_name() = 0; + + scc::sc_in_opt mtime_i{"mtime_i"}; +}; + +template +class core_complex : public sc_core::sc_module, public scc::traceable, public core_complex_if { public: - tlm::scc::initiator_mixin> ibus{"ibus"}; + tlm::scc::initiator_mixin> ibus{"ibus"}; - tlm::scc::initiator_mixin> dbus{"dbus"}; + tlm::scc::initiator_mixin> dbus{"dbus"}; sc_core::sc_in rst_i{"rst_i"}; @@ -88,8 +112,6 @@ public: #ifndef CWR_SYSTEMC sc_core::sc_in clk_i{"clk_i"}; - sc_core::sc_port, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"}; - cci::cci_param elf_file{"elf_file", ""}; cci::cci_param enable_disass{"enable_disass", false}; @@ -115,8 +137,6 @@ public: #else sc_core::sc_in clk_i{"clk_i"}; - sc_core::sc_in mtime_i{"mtime_i"}; - scml_property elf_file{"elf_file", ""}; scml_property enable_disass{"enable_disass", false}; @@ -159,13 +179,13 @@ public: ~core_complex(); - inline unsigned get_last_bus_cycles() { + unsigned get_last_bus_cycles() override { auto mem_incr = std::max(ibus_inc, dbus_inc); ibus_inc = dbus_inc = 0; return mem_incr > 1 ? mem_incr : 1; } - inline void sync(uint64_t cycle) { + void sync(uint64_t cycle) override { auto core_inc = curr_clk * (cycle - last_sync_cycle); quantum_keeper.inc(core_inc); if(quantum_keeper.need_sync()) { @@ -175,20 +195,24 @@ public: last_sync_cycle = cycle; } - bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch); + bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) override; - bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data); + bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) override; - bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data); + bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) override; - bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data); + bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) override; void trace(sc_core::sc_trace_file* trf) const override; - bool disass_output(uint64_t pc, const std::string instr); + bool disass_output(uint64_t pc, const std::string instr) override; void set_clock_period(sc_core::sc_time period); + char const* hier_name() override { + return name(); + } + protected: void before_end_of_elaboration() override; void start_of_simulation() override; diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index 10a1eb8..c140cac 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -21,7 +21,7 @@ public: using reg_t = typename iss::arch::traits::reg_t; using phys_addr_t = typename iss::arch::traits::phys_addr_t; using heart_state_t = typename PLAT::hart_state_type; - sc_core_adapter(sysc::tgfs::core_complex* owner) + sc_core_adapter(sysc::tgfs::core_complex_if* owner) : owner(owner) {} iss::arch_if* get_arch_if() override { return this; } @@ -54,7 +54,7 @@ public: std::stringstream s; s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]"; - SCCDEBUG(owner->name()) << "disass: " + SCCDEBUG(owner->hier_name()) << "disass: " << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << std::setfill(' ') << std::left << instr << s.str(); } @@ -79,10 +79,10 @@ public: switch(hostvar >> 48) { case 0: if(hostvar != 0x1) { - SCCINFO(owner->name()) + SCCINFO(owner->hier_name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } else { - SCCINFO(owner->name()) + SCCINFO(owner->hier_name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } this->reg.trap_state = std::numeric_limits::max(); @@ -112,21 +112,8 @@ public: } iss::status read_csr(unsigned addr, reg_t& val) override { -#ifndef CWR_SYSTEMC - if((addr == iss::arch::time || addr == iss::arch::timeh) && owner->mtime_o.get_interface(0)) { - uint64_t time_val; - bool ret = owner->mtime_o->nb_peek(time_val); - if(addr == iss::arch::time) { - val = static_cast(time_val); - } else if(addr == iss::arch::timeh) { - if(sizeof(reg_t) != 4) - return iss::Err; - val = static_cast(time_val >> 32); - } - return ret ? iss::Ok : iss::Err; -#else if((addr == iss::arch::time || addr == iss::arch::timeh)) { - uint64_t time_val = owner->mtime_i.read(); + uint64_t time_val = owner->mtime_i.get_interface()? owner->mtime_i.read():0; if(addr == iss::arch::time) { val = static_cast(time_val); } else if(addr == iss::arch::timeh) { @@ -135,14 +122,13 @@ public: val = static_cast(time_val >> 32); } return iss::Ok; -#endif } else { return PLAT::read_csr(addr, val); } } void wait_until(uint64_t flags) override { - SCCDEBUG(owner->name()) << "Sleeping until interrupt"; + SCCDEBUG(owner->hier_name()) << "Sleeping until interrupt"; while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) { sc_core::wait(wfi_evt); } @@ -173,11 +159,11 @@ public: this->csr[iss::arch::mip] &= ~mask; this->check_interrupt(); if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; + SCCTRACE(owner->hier_name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; } private: - sysc::tgfs::core_complex* const owner; + sysc::tgfs::core_complex_if* const owner; sc_core::sc_event wfi_evt; uint64_t hostvar{std::numeric_limits::max()}; unsigned to_host_wr_cnt = 0; diff --git a/src/vm/fp_functions.cpp b/src/vm/fp_functions.cpp index 865ee64..de824e5 100644 --- a/src/vm/fp_functions.cpp +++ b/src/vm/fp_functions.cpp @@ -128,7 +128,6 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) { } uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { - float32_t v1f{v1}; softfloat_exceptionFlags = 0; float32_t r;