fixes CSR/CLIC implementation
This commit is contained in:
		| @@ -114,7 +114,7 @@ enum riscv_csr { | ||||
|     mtval = 0x343, | ||||
|     mip = 0x344, | ||||
|     mxnti = 0x345, //CLIC | ||||
|     mintstatus   = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change | ||||
|     mintstatus   = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change | ||||
|     mintthresh   = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change | ||||
|     mscratchcsw  = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) | ||||
|     mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) | ||||
|   | ||||
| @@ -212,9 +212,9 @@ public: | ||||
|         csr[addr & csr.page_addr_mask] = val; | ||||
|     } | ||||
|  | ||||
|     void set_irq_num(unsigned i) { | ||||
|         mcause_max_irq=1<<util::ilog2(i); | ||||
|     } | ||||
| //    void set_irq_num(unsigned i) { | ||||
| //        mcause_max_irq=1<<util::ilog2(i); | ||||
| //    } | ||||
| protected: | ||||
|     struct riscv_instrumentation_if : public iss::instrumentation_if { | ||||
|  | ||||
| @@ -337,7 +337,7 @@ protected: | ||||
|     std::vector<std::function<mem_write_f>> memfn_write; | ||||
|     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); | ||||
|     feature_config cfg; | ||||
|     unsigned mcause_max_irq{16}; | ||||
|     unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; | ||||
|     inline bool debug_mode_active() {return this->reg.PRIV&0x4;} | ||||
| }; | ||||
|  | ||||
| @@ -428,7 +428,6 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg) | ||||
|         clic_int_reg.resize(cfg.clic_num_irq,  clic_int_reg_t{.raw=0}); | ||||
|         clic_cfg_reg=0x20; | ||||
|         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);}); | ||||
| @@ -850,7 +849,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT> | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_tvec(unsigned addr, reg_t &val) { | ||||
|     val = csr[addr] & ~2; | ||||
|     val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| @@ -866,7 +865,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT> | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) { | ||||
|     csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1))| (mcause_max_irq-1)); | ||||
|     csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1)); | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| @@ -1111,7 +1110,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check | ||||
| template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { | ||||
|     // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] | ||||
|     // calculate and write mcause val | ||||
|     auto trap_id = bit_sub<0, 16>(flags); | ||||
|     auto const trap_id = bit_sub<0, 16>(flags); | ||||
|     auto cause = bit_sub<16, 15>(flags); | ||||
|     // calculate effective privilege level | ||||
|     unsigned new_priv = PRIV_M; | ||||
| @@ -1167,11 +1166,19 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e | ||||
|     state.mstatus.MIE = false; | ||||
|  | ||||
|     // get trap vector | ||||
|     auto ivec = csr[mtvec]; | ||||
|     // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE | ||||
|     // bits in mtvec | ||||
|     this->reg.NEXT_PC = ivec & ~0x3UL; | ||||
|     if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; | ||||
|     auto xtvec = csr[mtvec]; | ||||
|     // calculate adds// set NEXT_PC to trap addressess to jump to based on MODE | ||||
|     if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { | ||||
|         reg_t data; | ||||
|         auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&data)); | ||||
|         if(ret == iss::Err) | ||||
|             return this->reg.PC; | ||||
|         this->reg.NEXT_PC = data; | ||||
|     } else { | ||||
|         // bits in mtvec | ||||
|         this->reg.NEXT_PC = xtvec & ~0x3UL; | ||||
|         if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; | ||||
|     } | ||||
|     // reset trap state | ||||
|     this->reg.PRIV = new_priv; | ||||
|     this->trap_state = 0; | ||||
|   | ||||
| @@ -227,9 +227,9 @@ public: | ||||
|         csr[addr & csr.page_addr_mask] = val; | ||||
|     } | ||||
|  | ||||
|     void set_irq_num(unsigned i) { | ||||
|         mcause_max_irq=1<<util::ilog2(i); | ||||
|     } | ||||
| //    void set_irq_num(unsigned i) { | ||||
| //        mcause_max_irq=1<<util::ilog2(i); | ||||
| //    } | ||||
| protected: | ||||
|     struct riscv_instrumentation_if : public iss::instrumentation_if { | ||||
|  | ||||
| @@ -355,7 +355,7 @@ protected: | ||||
|     std::vector<std::function<mem_write_f>> memfn_write; | ||||
|     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); | ||||
|     feature_config cfg; | ||||
|     unsigned mcause_max_irq{16}; | ||||
|     unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; | ||||
|     inline bool debug_mode_active() {return this->reg.PRIV&0x4;} | ||||
| }; | ||||
|  | ||||
| @@ -475,7 +475,6 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg) | ||||
|         clic_int_reg.resize(cfg.clic_num_irq,  clic_int_reg_t{.raw=0}); | ||||
|         clic_cfg_reg=0x20; | ||||
|         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);}); | ||||
| @@ -1001,7 +1000,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_tvec(unsigned addr, reg_t &val) { | ||||
|     val = csr[addr] & ~2; | ||||
|     val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; | ||||
|     return iss::Ok; | ||||
| } | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t &val) { | ||||
| @@ -1350,13 +1349,26 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>:: | ||||
|     } | ||||
|  | ||||
|     // get trap vector | ||||
|     auto ivec = csr[utvec | (new_priv << 8)]; | ||||
|     auto xtvec = csr[utvec | (new_priv << 8)]; | ||||
|     // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE | ||||
|     // bits in mtvec | ||||
|     this->reg.NEXT_PC = ivec & ~0x3UL; | ||||
|     if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; | ||||
|     if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 &&  (xtvec & 0x3UL)==3UL) { | ||||
|         reg_t data; | ||||
|         auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&data)); | ||||
|         if(ret == iss::Err) | ||||
|             return this->reg.PC; | ||||
|         this->reg.NEXT_PC = data; | ||||
|     } else { | ||||
|         this->reg.NEXT_PC = xtvec & ~0x3UL; | ||||
|         if ((xtvec & 0x1) == 1 && trap_id != 0) | ||||
|             this->reg.NEXT_PC += 4 * cause; | ||||
|     } | ||||
|     std::array<char, 32> buffer; | ||||
| #if defined(_MSC_VER) | ||||
|     sprintf(buffer.data(), "0x%016llx", addr); | ||||
| #else | ||||
|     sprintf(buffer.data(), "0x%016lx", addr); | ||||
| #endif | ||||
|     if((flags&0xffffffff) != 0xffffffff) | ||||
|     CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" | ||||
|                        << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user