|  |  | @@ -197,7 +197,7 @@ public: | 
			
		
	
		
		
			
				
					
					|  |  |  |         return traits<BASE>::MISA_VAL&0b0100?~1:~3; |  |  |  |         return traits<BASE>::MISA_VAL&0b0100?~1:~3; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     riscv_hart_mu_p(); |  |  |  |     riscv_hart_mu_p(feature_config cfg = feature_config{}); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     virtual ~riscv_hart_mu_p() = default; |  |  |  |     virtual ~riscv_hart_mu_p() = default; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     void reset(uint64_t address) override; |  |  |  |     void reset(uint64_t address) override; | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -363,23 +363,22 @@ protected: | 
			
		
	
		
		
			
				
					
					|  |  |  |     std::vector<std::function<mem_read_f>> memfn_read; |  |  |  |     std::vector<std::function<mem_read_f>> memfn_read; | 
			
		
	
		
		
			
				
					
					|  |  |  |     std::vector<std::function<mem_write_f>> memfn_write; |  |  |  |     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>); |  |  |  |     void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>); | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint64_t clic_base_addr{0}; |  |  |  |     feature_config cfg; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned clic_num_irq{0}; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned clic_num_trigger{0}; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     unsigned mcause_max_irq{16}; |  |  |  |     unsigned mcause_max_irq{16}; | 
			
		
	
		
		
			
				
					
					|  |  |  |     inline bool debug_mode_active() {return this->reg.PRIV&0x4;} |  |  |  |     inline bool debug_mode_active() {return this->reg.PRIV&0x4;} | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | template <typename BASE, features_e FEAT> |  |  |  | template <typename BASE, features_e FEAT> | 
			
		
	
		
		
			
				
					
					|  |  |  | riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() |  |  |  | riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | : state() |  |  |  | : state() | 
			
		
	
		
		
			
				
					
					|  |  |  | , instr_if(*this) { |  |  |  | , instr_if(*this) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | , cfg(cfg) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     // reset values |  |  |  |     // reset values | 
			
		
	
		
		
			
				
					
					|  |  |  |     csr[misa] = traits<BASE>::MISA_VAL; |  |  |  |     csr[misa] = traits<BASE>::MISA_VAL; | 
			
		
	
		
		
			
				
					
					|  |  |  |     csr[mvendorid] = 0x669; |  |  |  |     csr[mvendorid] = 0x669; | 
			
		
	
		
		
			
				
					
					|  |  |  |     csr[marchid] = traits<BASE>::MARCHID_VAL; |  |  |  |     csr[marchid] = traits<BASE>::MARCHID_VAL; | 
			
		
	
		
		
			
				
					
					|  |  |  |     csr[mimpid] = 1; |  |  |  |     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(""); |  |  |  |     uart_buf.str(""); | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ |  |  |  |     for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -485,29 +484,27 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | 
			
		
	
		
		
			
				
					
					|  |  |  |         csr_rd_cb[mclicbase] = &this_class::read_csr_reg; |  |  |  |         csr_rd_cb[mclicbase] = &this_class::read_csr_reg; | 
			
		
	
		
		
			
				
					
					|  |  |  |         csr_wr_cb[mclicbase] = &this_class::write_null; |  |  |  |         csr_wr_cb[mclicbase] = &this_class::write_null; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         clic_base_addr=0xC0000000; |  |  |  |         clic_int_reg.resize(cfg.clic_num_irq); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         clic_num_irq=16; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         clic_int_reg.resize(clic_num_irq); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         clic_cfg_reg=0x20; |  |  |  |         clic_cfg_reg=0x20; | 
			
		
	
		
		
			
				
					
					|  |  |  |         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; |  |  |  |         clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         mcause_max_irq=clic_num_irq+16; |  |  |  |         mcause_max_irq=cfg.clic_num_irq+16; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         insert_mem_range(clic_base_addr, 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);}); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if(FEAT & FEAT_TCM) { |  |  |  |     if(FEAT & FEAT_TCM) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         tcm.resize(0x8000); |  |  |  |         tcm.resize(cfg.tcm_size); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { |  |  |  |         std::function<mem_read_f> 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); |  |  |  |             std::copy(tcm.data() + offset, tcm.data() + offset + length, data); | 
			
		
	
		
		
			
				
					
					|  |  |  |             return iss::Ok; |  |  |  |             return iss::Ok; | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  |         std::function<mem_write_f> write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { |  |  |  |         std::function<mem_write_f> 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); |  |  |  |             std::copy(data, data + length, tcm.data() + offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |             return iss::Ok; |  |  |  |             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){ |  |  |  |     if(FEAT & FEAT_DEBUG){ | 
			
		
	
		
		
			
				
					
					|  |  |  |         csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; |  |  |  |         csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -1239,15 +1236,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | template<typename BASE, features_e FEAT> |  |  |  | template<typename BASE, features_e FEAT> | 
			
		
	
		
		
			
				
					
					|  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { |  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::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; |  |  |  |         *data=clic_cfg_reg; | 
			
		
	
		
		
			
				
					
					|  |  |  |         for(auto i=1; i<length; ++i) *(data+i)=0; |  |  |  |         for(auto i=1; i<length; ++i) *(data+i)=0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else if(addr>=(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); |  |  |  |         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; |  |  |  |         auto offset = ((addr&0x7fff)-0x40)/4; | 
			
		
	
		
		
			
				
					
					|  |  |  |         read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); |  |  |  |         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+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         auto offset = ((addr&0x7fff)-0x1000)/4; |  |  |  |         auto offset = ((addr&0x7fff)-0x1000)/4; | 
			
		
	
		
		
			
				
					
					|  |  |  |         read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); |  |  |  |         read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } else { | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -1258,15 +1255,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned lengt | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | template<typename BASE, features_e FEAT> |  |  |  | template<typename BASE, features_e FEAT> | 
			
		
	
		
		
			
				
					
					|  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { |  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::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 = *data; | 
			
		
	
		
		
			
				
					
					|  |  |  |         clic_cfg_reg&= 0x7e; |  |  |  |         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); |  |  |  | //        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+0xC0)){ // clicinttrig | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         auto offset = ((addr&0x7fff)-0x40)/4; |  |  |  |         auto offset = ((addr&0x7fff)-0x40)/4; | 
			
		
	
		
		
			
				
					
					|  |  |  |         write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); |  |  |  |         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+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         auto offset = ((addr&0x7fff)-0x1000)/4; |  |  |  |         auto offset = ((addr&0x7fff)-0x1000)/4; | 
			
		
	
		
		
			
				
					
					|  |  |  |         write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); |  |  |  |         write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					
					|  |  |   |