diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 8365a5d..59b16f9 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -182,7 +182,7 @@ public: return traits::MISA_VAL&0b0100?~1:~3; } - riscv_hart_m_p(); + riscv_hart_m_p(feature_config cfg = feature_config{}); virtual ~riscv_hart_m_p() = default; void reset(uint64_t address) override; @@ -194,9 +194,9 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - virtual uint64_t leave_trap(uint64_t flags) override; + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; const reg_t& get_mhartid() const { return mhartid_reg; } void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; @@ -208,14 +208,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -337,8 +329,6 @@ protected: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); @@ -346,23 +336,22 @@ protected: std::vector> memfn_read; std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); - uint64_t clic_base_addr{0}; - unsigned clic_num_irq{0}; - unsigned clic_num_trigger{0}; + feature_config cfg; unsigned mcause_max_irq{16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; template -riscv_hart_m_p::riscv_hart_m_p() +riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) : state() -, instr_if(*this) { +, instr_if(*this) +, cfg(cfg) { // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; - csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file + csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ @@ -385,7 +374,10 @@ riscv_hart_m_p::riscv_hart_m_p() //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; + const std::array addrs{{ + misa, mvendorid, marchid, mimpid, + mepc, mtvec, mscratch, mcause, mtval + }}; for(auto addr: addrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; @@ -416,6 +408,8 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; + csr_rd_cb[mcounteren] = &this_class::read_null; + csr_wr_cb[mcounteren] = &this_class::write_null; csr_wr_cb[misa] = &this_class::write_null; csr_wr_cb[mvendorid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null; @@ -436,29 +430,27 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mclicbase] = &this_class::read_csr_reg; csr_wr_cb[mclicbase] = &this_class::write_null; - clic_base_addr=0xC0000000; - clic_num_irq=16; - clic_int_reg.resize(clic_num_irq); + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; - mcause_max_irq=clic_num_irq+16; - insert_mem_range(clic_base_addr, 0x5000UL, + clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + mcause_max_irq=cfg.clic_num_irq+16; + insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); } if(FEAT & FEAT_TCM) { - tcm.resize(0x8000); + tcm.resize(cfg.tcm_size); std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-0x10000000; + auto offset=addr.val-this->cfg.tcm_base; std::copy(tcm.data() + offset, tcm.data() + offset + length, data); return iss::Ok; }; std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-0x10000000; + auto offset=addr.val-this->cfg.tcm_base; std::copy(data, data + length, tcm.data() + offset); return iss::Ok; }; - insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); + insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); } if(FEAT & FEAT_DEBUG){ csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; @@ -582,7 +574,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if(!is_fetch(access) && memfn_range.size()){ + if(access != access_type::FETCH && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; }); @@ -863,7 +855,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[mtvec] & ~2; + val = csr[addr] & ~2; return iss::Ok; } @@ -879,7 +871,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[mcause] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); + csr[addr] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); return iss::Ok; } @@ -959,7 +951,6 @@ iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -984,14 +975,12 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned len template iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg uart_buf << (char)data[0]; if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<>16)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned le template iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg *data=clic_cfg_reg; for(auto i=1; i=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo + } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo read_reg_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } else { @@ -1081,17 +1070,18 @@ iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length template iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg clic_cfg_reg = *data; clic_cfg_reg&= 0x7e; -// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo +// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo // write_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 } return iss::Ok; } @@ -1109,8 +1099,8 @@ template void riscv_hart_m_p::check // any synchronous traps. auto ena_irq = csr[mip] & csr[mie]; - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq : 0; if (enabled_interrupts != 0) { diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index a742d08..54e93fd 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -312,14 +312,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -422,8 +414,6 @@ private: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; protected: void check_interrupt(); @@ -1031,7 +1021,6 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -1056,7 +1045,6 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length template iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 55c8f0c..eb05618 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -223,14 +223,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -250,26 +242,24 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - virtual uint64_t get_pc() { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; }; - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_instr_count() { return arch.icount; } + uint64_t get_instr_count() override { return arch.icount; } uint64_t get_pendig_traps() override { return arch.trap_state; } uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; + void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; riscv_hart_mu_p &arch; }; friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); @@ -357,8 +347,6 @@ protected: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); @@ -1020,14 +1008,12 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); + val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3); return iss::Ok; } template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - state.write_mstatus(val, req_priv_lvl); + state.write_mstatus(val, (addr >> 8) & 0x3); check_interrupt(); return iss::Ok; } @@ -1129,7 +1115,6 @@ iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t va template iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -1154,7 +1139,6 @@ iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned le template iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg @@ -1279,8 +1263,8 @@ template void riscv_hart_mu_p::chec // any synchronous traps. auto ena_irq = csr[mip] & csr[mie]; - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || mie; + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; if (enabled_interrupts != 0) {