Compare commits
	
		
			1 Commits
		
	
	
		
			b0cb997009
			...
			6ea7721961
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6ea7721961 | 
| @@ -43,7 +43,7 @@ namespace arch { | ||||
|  | ||||
| enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; | ||||
|  | ||||
| enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8}; | ||||
| enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16}; | ||||
|  | ||||
| enum riscv_csr { | ||||
|     /* user-level CSR */ | ||||
| @@ -239,6 +239,49 @@ public: | ||||
|     trap_store_page_fault(uint64_t badaddr) | ||||
|     : trap_access(15 << 16, badaddr) {} | ||||
| }; | ||||
|  | ||||
| inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { | ||||
|     auto reg_ptr = reinterpret_cast<uint8_t*>(®); | ||||
|     switch (offs & 0x3) { | ||||
|     case 0: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + i); | ||||
|     break; | ||||
|     case 1: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + 1 + i); | ||||
|     break; | ||||
|     case 2: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + 2 + i); | ||||
|     break; | ||||
|     case 3: | ||||
|         *data = *(reg_ptr + 3); | ||||
|     break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { | ||||
|     auto reg_ptr = reinterpret_cast<uint8_t*>(®); | ||||
|     switch (offs & 0x3) { | ||||
|     case 0: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + i) = *(data + i); | ||||
|     break; | ||||
|     case 1: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + 1 + i) = *(data + i); | ||||
|     break; | ||||
|     case 2: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + 2 + i) = *(data + i); | ||||
|     break; | ||||
|     case 3: | ||||
|         *(reg_ptr + 3) = *data ; | ||||
|     break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -97,8 +97,10 @@ public: | ||||
|     using reg_t = typename core::reg_t; | ||||
|     using addr_t = typename core::addr_t; | ||||
|  | ||||
|     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||
|     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); | ||||
|     using rd_csr_f    = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||
|     using wr_csr_f    = iss::status (this_class::*)(unsigned addr, reg_t); | ||||
|     using mem_read_f  = iss::status(phys_addr_t addr, unsigned, uint8_t *const); | ||||
|     using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); | ||||
|  | ||||
|     // primary template | ||||
|     template <class T, class Enable = void> struct hart_state {}; | ||||
| @@ -294,6 +296,8 @@ protected: | ||||
|     }; | ||||
|     std::vector<clic_int_reg_t> clic_int_reg; | ||||
|  | ||||
|     std::vector<uint8_t> tcm; | ||||
|  | ||||
|     iss::status read_csr_reg(unsigned addr, reg_t &val); | ||||
|     iss::status write_csr_reg(unsigned addr, reg_t val); | ||||
|     iss::status read_null(unsigned addr, reg_t &val); | ||||
| @@ -337,6 +341,10 @@ protected: | ||||
|  | ||||
|     void check_interrupt(); | ||||
|     bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); | ||||
|     std::vector<std::tuple<uint64_t, uint64_t>> memfn_range; | ||||
|     std::vector<std::function<mem_read_f>> memfn_read; | ||||
|     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>); | ||||
|     uint64_t clic_base_addr{0}; | ||||
|     unsigned clic_num_irq{0}; | ||||
|     unsigned clic_num_trigger{0}; | ||||
| @@ -407,10 +415,52 @@ riscv_hart_m_p<BASE, FEAT>::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; | ||||
|     csr_wr_cb[mimpid] = &this_class::write_null; | ||||
|     if(FEAT & FEAT_CLIC) { | ||||
|         csr_rd_cb[mtvt] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mtvt] = &this_class::write_csr_reg; | ||||
|         csr_rd_cb[mxnti] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mxnti] = &this_class::write_csr_reg; | ||||
|         csr_rd_cb[mintstatus] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mintstatus] = &this_class::write_null; | ||||
|         csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; | ||||
|         csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; | ||||
|         csr_rd_cb[mintthresh] = &this_class::read_csr_reg; | ||||
|         csr_wr_cb[mintthresh] = &this_class::write_intthresh; | ||||
|         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_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, | ||||
|                 [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); | ||||
|         std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { | ||||
|             auto offset=addr.val-0x10000000; | ||||
|             std::copy(tcm.data() + offset, tcm.data() + offset + length, data); | ||||
|             return iss::Ok; | ||||
|         }; | ||||
|         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; | ||||
|             std::copy(data, data + length, tcm.data() + offset); | ||||
|             return iss::Ok; | ||||
|         }; | ||||
|         insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); | ||||
|     } | ||||
|     if(FEAT & FEAT_DEBUG){ | ||||
|         csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; | ||||
|         csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; | ||||
| @@ -489,6 +539,20 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m | ||||
|     throw std::runtime_error("memory load file not found"); | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f, | ||||
|         std::function<mem_write_f> wr_fn) { | ||||
|     std::tuple<uint64_t, uint64_t> entry{base, size}; | ||||
|     auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, | ||||
|             [](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){ | ||||
|         return std::get<0>(a)<std::get<0>(b); | ||||
|     }); | ||||
|     auto idx = std::distance(memfn_range.begin(), it); | ||||
|     memfn_range.insert(it, entry); | ||||
|     memfn_read.insert(std::begin(memfn_read)+idx, rd_f); | ||||
|     memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, | ||||
|         const uint64_t addr, const unsigned length, uint8_t *const data) { | ||||
| @@ -517,9 +581,20 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
|                 auto res = type==iss::address_type::PHYSICAL? | ||||
|                         read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): | ||||
|                         read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); | ||||
|                 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(access != access_type::FETCH && memfn_range.size()){ | ||||
|                     auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ | ||||
|                         return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; | ||||
|                     }); | ||||
|                     if(it!=std::end(memfn_range)) { | ||||
|                         auto idx = std::distance(std::begin(memfn_range), it); | ||||
|                         res = memfn_read[idx](phys_addr, length, data); | ||||
|                     } else | ||||
|                         res = read_mem( phys_addr, length, data); | ||||
|                 } else { | ||||
|                     res = read_mem( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)){ | ||||
|                     this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     fault_data=addr; | ||||
| @@ -594,14 +669,25 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(!(access && iss::access_type::DEBUG) &&  length>1 && (addr&(length-1))){ | ||||
|                 if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ | ||||
|                     this->reg.trap_state = 1<<31 | 6<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
|                 auto res = type==iss::address_type::PHYSICAL? | ||||
|                         write_mem(phys_addr_t{access, space, addr}, length, data): | ||||
|                         write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); | ||||
|                 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(access != access_type::FETCH && memfn_range.size()){ | ||||
|                     auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){ | ||||
|                         return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; | ||||
|                     }); | ||||
|                     if(it!=std::end(memfn_range)) { | ||||
|                         auto idx = std::distance(std::begin(memfn_range), it); | ||||
|                         res = memfn_write[idx]( phys_addr, length, data); | ||||
|                     } else | ||||
|                         res = write_mem( phys_addr, length, data); | ||||
|                 } else { | ||||
|                     res = write_mem( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)) { | ||||
|                     this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     fault_data=addr; | ||||
| @@ -874,6 +960,12 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT> | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) { | ||||
|     csr[addr]= val &0xff; | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||
|     if(mem_read_cb) return mem_read_cb(paddr, length, data); | ||||
| @@ -977,6 +1069,42 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { | ||||
|     if(addr==clic_base_addr) { // cliccfg | ||||
|         *data=clic_cfg_reg; | ||||
|         for(auto i=1; i<length; ++i) *(data+i)=0; | ||||
|     } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+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 | ||||
|         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 | ||||
|         auto offset = ((addr&0x7fff)-0x1000)/4; | ||||
|         read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|     } else { | ||||
|         for(auto i = 0U; i<length; ++i) *(data+i)=0; | ||||
|     } | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { | ||||
|     if(addr==clic_base_addr) { // cliccfg | ||||
|         clic_cfg_reg = *data; | ||||
|         clic_cfg_reg&= 0x7e; | ||||
| //    } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo | ||||
| //        write_uint32(addr, clic_info_reg, data, length); | ||||
|     } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // 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 | ||||
|         auto offset = ((addr&0x7fff)-0x1000)/4; | ||||
|         write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|     } | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> inline void riscv_hart_m_p<BASE, FEAT>::reset(uint64_t address) { | ||||
|     BASE::reset(address); | ||||
|     state.mstatus = hart_state_type::mstatus_reset_val; | ||||
|   | ||||
| @@ -97,8 +97,10 @@ public: | ||||
|     using reg_t = typename core::reg_t; | ||||
|     using addr_t = typename core::addr_t; | ||||
|  | ||||
|     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||
|     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); | ||||
|     using rd_csr_f    = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||
|     using wr_csr_f    = iss::status (this_class::*)(unsigned addr, reg_t); | ||||
|     using mem_read_f  = iss::status(phys_addr_t addr, unsigned, uint8_t *const); | ||||
|     using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); | ||||
|  | ||||
|     // primary template | ||||
|     template <class T, class Enable = void> struct hart_state {}; | ||||
| @@ -309,6 +311,8 @@ protected: | ||||
|     }; | ||||
|     std::vector<clic_int_reg_t> clic_int_reg; | ||||
|  | ||||
|     std::vector<uint8_t> tcm; | ||||
|  | ||||
|     iss::status read_csr_reg(unsigned addr, reg_t &val); | ||||
|     iss::status write_csr_reg(unsigned addr, reg_t val); | ||||
|     iss::status read_null(unsigned addr, reg_t &val); | ||||
| @@ -355,6 +359,10 @@ protected: | ||||
|  | ||||
|     void check_interrupt(); | ||||
|     bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); | ||||
|     std::vector<std::tuple<uint64_t, uint64_t>> memfn_range; | ||||
|     std::vector<std::function<mem_read_f>> memfn_read; | ||||
|     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>); | ||||
|     uint64_t clic_base_addr{0}; | ||||
|     unsigned clic_num_irq{0}; | ||||
|     unsigned clic_num_trigger{0}; | ||||
| @@ -483,6 +491,23 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | ||||
|         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, | ||||
|                 [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); | ||||
|         std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { | ||||
|             auto offset=addr.val-0x10000000; | ||||
|             std::copy(tcm.data() + offset, tcm.data() + offset + length, data); | ||||
|             return iss::Ok; | ||||
|         }; | ||||
|         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; | ||||
|             std::copy(data, data + length, tcm.data() + offset); | ||||
|             return iss::Ok; | ||||
|         }; | ||||
|         insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); | ||||
|     } | ||||
|     if(FEAT & FEAT_DEBUG){ | ||||
|         csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; | ||||
| @@ -562,6 +587,20 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m | ||||
|     throw std::runtime_error("memory load file not found"); | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f, | ||||
|         std::function<mem_write_f> wr_fn) { | ||||
|     std::tuple<uint64_t, uint64_t> entry{base, size}; | ||||
|     auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, | ||||
|             [](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){ | ||||
|         return std::get<0>(a)<std::get<0>(b); | ||||
|     }); | ||||
|     auto idx = std::distance(memfn_range.begin(), it); | ||||
|     memfn_range.insert(it, entry); | ||||
|     memfn_read.insert(std::begin(memfn_read)+idx, rd_f); | ||||
|     memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) { | ||||
|     csr[addr] = val & 0x9f9f9f9f; | ||||
| @@ -688,8 +727,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | ||||
|                 } | ||||
|                 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((FEAT & FEAT_CLIC) && access != access_type::FETCH && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000)){ //TODO: should be a constant | ||||
|                     res = read_clic(phys_addr.val, length, data); | ||||
|                 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<uint64_t, uint64_t> const& a){ | ||||
|                         return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; | ||||
|                     }); | ||||
|                     if(it!=std::end(memfn_range)) { | ||||
|                         auto idx = std::distance(std::begin(memfn_range), it); | ||||
|                         res = memfn_read[idx](phys_addr, length, data); | ||||
|                     } else | ||||
|                         res = read_mem( phys_addr, length, data); | ||||
|                 } else { | ||||
|                     res = read_mem( phys_addr, length, data); | ||||
|                 } | ||||
| @@ -781,8 +827,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | ||||
|                     return iss::Err; | ||||
|                 } | ||||
|                 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 = ((FEAT & FEAT_CLIC) && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000))? //TODO: should be a constant | ||||
|                         write_clic(phys_addr.val, length, data) : write_mem( phys_addr, length, data); | ||||
|                 auto res = iss::Err; | ||||
|                 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<uint64_t, uint64_t> const& a){ | ||||
|                         return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; | ||||
|                     }); | ||||
|                     if(it!=std::end(memfn_range)) { | ||||
|                         auto idx = std::distance(std::begin(memfn_range), it); | ||||
|                         res = memfn_write[idx]( phys_addr, length, data); | ||||
|                     } else | ||||
|                         res = write_mem( phys_addr, length, data); | ||||
|                 } else { | ||||
|                     res = write_mem( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)) { | ||||
|                     this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     fault_data=addr; | ||||
| @@ -1111,8 +1168,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l | ||||
|     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 | ||||
|             // '"<<uart_buf.str()<<"'"; | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             std::cout << uart_buf.str(); | ||||
|             uart_buf.str(""); | ||||
|         } | ||||
| @@ -1181,61 +1237,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| void read_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { | ||||
|     auto reg_ptr = reinterpret_cast<uint8_t*>(®); | ||||
|     switch (offs & 0x3) { | ||||
|     case 0: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + i); | ||||
|     break; | ||||
|     case 1: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + 1 + i); | ||||
|     break; | ||||
|     case 2: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(data + i) = *(reg_ptr + 2 + i); | ||||
|     break; | ||||
|     case 3: | ||||
|         *data = *(reg_ptr + 3); | ||||
|     break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void write_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { | ||||
|     auto reg_ptr = reinterpret_cast<uint8_t*>(®); | ||||
|     switch (offs & 0x3) { | ||||
|     case 0: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + i) = *(data + i); | ||||
|     break; | ||||
|     case 1: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + 1 + i) = *(data + i); | ||||
|     break; | ||||
|     case 2: | ||||
|         for (auto i = 0U; i < length; ++i) | ||||
|             *(reg_ptr + 2 + i) = *(data + i); | ||||
|     break; | ||||
|     case 3: | ||||
|         *(reg_ptr + 3) = *data ; | ||||
|     break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|     if(addr==clic_base_addr) { // cliccfg | ||||
|         *data=clic_cfg_reg; | ||||
|         for(auto i=1; i<length; ++i) *(data+i)=0; | ||||
|     } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo | ||||
|         read_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 | ||||
|         auto offset = ((addr&0x7fff)-0x40)/4; | ||||
|         read_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 | ||||
|         auto offset = ((addr&0x7fff)-0x1000)/4; | ||||
|         read_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|         read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|     } else { | ||||
|         for(auto i = 0U; i<length; ++i) *(data+i)=0; | ||||
|     } | ||||
| @@ -1251,10 +1265,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng | ||||
| //        write_uint32(addr, clic_info_reg, data, length); | ||||
|     } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig | ||||
|         auto offset = ((addr&0x7fff)-0x40)/4; | ||||
|         write_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 | ||||
|         auto offset = ((addr&0x7fff)-0x1000)/4; | ||||
|         write_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|         write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); | ||||
|     } | ||||
|     return iss::Ok; | ||||
| } | ||||
|   | ||||
| @@ -37,7 +37,7 @@ using tgc_e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_e, (iss::arch: | ||||
| #ifdef CORE_TGC_X | ||||
| #include "riscv_hart_mu_p.h" | ||||
| #include "tgc_x.h" | ||||
| using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>; | ||||
| using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>; | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user