Compare commits
	
		
			1 Commits
		
	
	
		
			a943dd3bdf
			...
			39b2788b7e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 39b2788b7e | 
| @@ -221,6 +221,7 @@ struct vm_info { | |||||||
|  |  | ||||||
| struct feature_config { | struct feature_config { | ||||||
|     uint64_t clic_base{0xc0000000}; |     uint64_t clic_base{0xc0000000}; | ||||||
|  |     unsigned clic_int_ctl_bits{4}; | ||||||
|     unsigned clic_num_irq{16}; |     unsigned clic_num_irq{16}; | ||||||
|     unsigned clic_num_trigger{0}; |     unsigned clic_num_trigger{0}; | ||||||
|     uint64_t tcm_base{0x10000000}; |     uint64_t tcm_base{0x10000000}; | ||||||
|   | |||||||
| @@ -289,6 +289,8 @@ protected: | |||||||
|         uint32_t raw; |         uint32_t raw; | ||||||
|     }; |     }; | ||||||
|     std::vector<clic_int_reg_t> clic_int_reg; |     std::vector<clic_int_reg_t> clic_int_reg; | ||||||
|  |     uint8_t clic_mprev_lvl{0}; | ||||||
|  |     uint8_t clic_mact_lvl{0}; | ||||||
|  |  | ||||||
|     std::vector<uint8_t> tcm; |     std::vector<uint8_t> tcm; | ||||||
|  |  | ||||||
| @@ -430,6 +432,8 @@ 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_int_reg.resize(cfg.clic_num_irq,  clic_int_reg_t{.raw=0}); | ||||||
|         clic_cfg_reg=0x20; |         clic_cfg_reg=0x20; | ||||||
|         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; |         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; | ||||||
|  |         clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|  |         csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|         insert_mem_range(cfg.clic_base, 0x5000UL, |         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 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);}); |                 [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); | ||||||
| @@ -869,18 +873,26 @@ 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_cause(unsigned addr, reg_t &val) { | template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_cause(unsigned addr, reg_t &val) { | ||||||
|     auto res = csr[addr]; |     auto res = csr[addr]; | ||||||
|     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { |     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { | ||||||
|         res |= state.mstatus.MPIE<<27; |         val = csr[addr] & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); | ||||||
|         res |= state.mstatus.MPP<<28; |         val |= clic_mprev_lvl<<16; | ||||||
|     } |         val |= state.mstatus.MPIE<<27; | ||||||
|     val=res; |         val |= state.mstatus.MPP<<28; | ||||||
|  |     } else | ||||||
|  |         val = csr[addr] & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1)); | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) { | 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)); | ||||||
|     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { |     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { | ||||||
|  |         auto mask = ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); | ||||||
|  |         csr[addr] = (val & mask) | (csr[addr] & ~mask); | ||||||
|  |         clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; | ||||||
|         state.mstatus.MPIE=(val>>27)&0x1; |         state.mstatus.MPIE=(val>>27)&0x1; | ||||||
|         state.mstatus.MPP=(val>>28)&0x3; |         state.mstatus.MPP=(val>>28)&0x3; | ||||||
|  |     } else { | ||||||
|  |         auto mask = ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1)); | ||||||
|  |         csr[addr] = (val & mask) | (csr[addr] & ~mask); | ||||||
|     } |     } | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
| @@ -955,7 +967,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT> | |||||||
|  |  | ||||||
| template<typename BASE, features_e FEAT> | template<typename BASE, features_e FEAT> | ||||||
| iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) { | iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) { | ||||||
|     csr[addr]= val &0xff; |     csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1107,6 +1119,7 @@ template <typename BASE, features_e FEAT> inline void riscv_hart_m_p<BASE, FEAT> | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check_interrupt() { | template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check_interrupt() { | ||||||
|  |     //TODO: Implement CLIC functionality | ||||||
|     //auto ideleg = csr[mideleg]; |     //auto ideleg = csr[mideleg]; | ||||||
|     // Multiple simultaneous interrupts and traps at the same privilege level are |     // Multiple simultaneous interrupts and traps at the same privilege level are | ||||||
|     // handled in the following decreasing priority order: |     // handled in the following decreasing priority order: | ||||||
|   | |||||||
| @@ -304,6 +304,8 @@ protected: | |||||||
|         uint32_t raw; |         uint32_t raw; | ||||||
|     }; |     }; | ||||||
|     std::vector<clic_int_reg_t> clic_int_reg; |     std::vector<clic_int_reg_t> clic_int_reg; | ||||||
|  |     uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0}; | ||||||
|  |     uint8_t clic_mact_lvl{0}, clic_uact_lvl{0}; | ||||||
|  |  | ||||||
|     std::vector<uint8_t> tcm; |     std::vector<uint8_t> tcm; | ||||||
|  |  | ||||||
| @@ -486,6 +488,10 @@ 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_int_reg.resize(cfg.clic_num_irq,  clic_int_reg_t{.raw=0}); | ||||||
|         clic_cfg_reg=0x30; |         clic_cfg_reg=0x30; | ||||||
|         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; |         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; | ||||||
|  |         clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|  |         clic_uact_lvl = clic_uprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|  |         csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|  |         csr[uintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|         insert_mem_range(cfg.clic_base, 0x5000UL, |         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 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);}); |                 [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); | ||||||
| @@ -715,7 +721,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | |||||||
|                 return iss::Err; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(!is_debug(access)  && (addr&(alignment-1))){ |                 if(!is_debug(access) && (addr&(alignment-1))){ | ||||||
|                     this->trap_state = (1UL << 31) | 4<<16; |                     this->trap_state = (1UL << 31) | 4<<16; | ||||||
|                     fault_data=addr; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     return iss::Err; | ||||||
| @@ -1026,36 +1032,44 @@ 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_cause(unsigned addr, reg_t &val) { | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cause(unsigned addr, reg_t &val) { | ||||||
|     auto res = csr[addr]; |  | ||||||
|     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { |     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { | ||||||
|  |         val = csr[addr] & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); | ||||||
|         auto mode = (addr >> 8) & 0x3; |         auto mode = (addr >> 8) & 0x3; | ||||||
|         switch(mode) { |         switch(mode) { | ||||||
|         case 0: |         case 0: | ||||||
|             res |= state.mstatus.UPIE<<27; |             val |= clic_uprev_lvl<<16; | ||||||
|  |             val |= state.mstatus.UPIE<<27; | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             res |= state.mstatus.MPIE<<27; |             val |= clic_mprev_lvl<<16; | ||||||
|             res |= state.mstatus.MPP<<28; |             val |= state.mstatus.MPIE<<27; | ||||||
|  |             val |= state.mstatus.MPP<<28; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } else | ||||||
|     val=res; |         val = csr[addr] & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1)); | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) { | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) { | ||||||
|     csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1))|(mcause_max_irq-1)); |  | ||||||
|     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { |     if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { | ||||||
|  |         auto mask = ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); | ||||||
|  |         csr[addr] = (val & mask) | (csr[addr] & ~mask); | ||||||
|         auto mode = (addr >> 8) & 0x3; |         auto mode = (addr >> 8) & 0x3; | ||||||
|         switch(mode) { |         switch(mode) { | ||||||
|         case 0: |         case 0: | ||||||
|  |             clic_uprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; | ||||||
|             state.mstatus.UPIE=(val>>27)&0x1; |             state.mstatus.UPIE=(val>>27)&0x1; | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|  |             clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; | ||||||
|             state.mstatus.MPIE=(val>>27)&0x1; |             state.mstatus.MPIE=(val>>27)&0x1; | ||||||
|             state.mstatus.MPP=(val>>28)&0x3; |             state.mstatus.MPP=(val>>28)&0x3; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |     } else { | ||||||
|  |         auto mask = ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1)); | ||||||
|  |         csr[addr] = (val & mask) | (csr[addr] & ~mask); | ||||||
|     } |     } | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
| @@ -1146,7 +1160,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT | |||||||
|  |  | ||||||
| template<typename BASE, features_e FEAT> | template<typename BASE, features_e FEAT> | ||||||
| iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) { | iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) { | ||||||
|     csr[addr]= val &0xff; |     csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1298,6 +1312,7 @@ template <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::check_interrupt() { | template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::check_interrupt() { | ||||||
|  |     //TODO: Implement CLIC functionality | ||||||
|     auto ideleg = csr[mideleg]; |     auto ideleg = csr[mideleg]; | ||||||
|     // Multiple simultaneous interrupts and traps at the same privilege level are |     // Multiple simultaneous interrupts and traps at the same privilege level are | ||||||
|     // handled in the following decreasing priority order: |     // handled in the following decreasing priority order: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user