Compare commits
	
		
			3 Commits
		
	
	
		
			ee6218279e
			...
			2281ec4144
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2281ec4144 | |||
| 11c481cec2 | |||
| a123beb301 | 
| @@ -1,13 +1,13 @@ | ||||
| import "RV32I.core_desc" | ||||
| import "RVM.core_desc" | ||||
| import "RVC.core_desc" | ||||
| import "ISA/RV32I.core_desc" | ||||
| import "ISA/RVM.core_desc" | ||||
| import "ISA/RVC.core_desc" | ||||
|  | ||||
| Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { | ||||
|     architectural_state { | ||||
|         XLEN=32; | ||||
|         // definitions for the architecture wrapper | ||||
|         //                    XL    ZYXWVUTSRQPONMLKJIHGFEDCBA | ||||
|         unsigned MISA_VAL = 0b01000000000000000001000100000100; | ||||
|         unsigned MARCHID_VAL = 0x80000003; | ||||
|         unsigned int MISA_VAL = 0b01000000000000000001000100000100; | ||||
|         unsigned int MARCHID_VAL = 0x80000003; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -62,8 +62,8 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { | ||||
|     reg.PC=address; | ||||
|     reg.NEXT_PC=reg.PC; | ||||
|     reg.PRIV=0x3; | ||||
|     trap_state=0; | ||||
|     icount=0; | ||||
|     reg.trap_state=0; | ||||
|     reg.icount=0; | ||||
| } | ||||
|  | ||||
| uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { | ||||
|   | ||||
| @@ -136,7 +136,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|  | ||||
|     uint8_t* get_regs_base_ptr() override; | ||||
|  | ||||
|     inline uint64_t get_icount() { return icount; } | ||||
|     inline uint64_t get_icount() { return reg.icount; } | ||||
|  | ||||
|     inline bool should_stop() { return interrupt_sim; } | ||||
|  | ||||
| @@ -154,7 +154,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|  | ||||
|     virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } | ||||
|  | ||||
|     inline uint32_t get_last_branch() { return last_branch; } | ||||
|     inline uint32_t get_last_branch() { return reg.last_branch; } | ||||
|  | ||||
|  | ||||
| #pragma pack(push, 1) | ||||
| @@ -170,12 +170,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|         uint32_t last_branch = 0; | ||||
|     } reg; | ||||
| #pragma pack(pop) | ||||
|     uint32_t trap_state = 0, pending_trap = 0; | ||||
|     uint64_t icount = 0; | ||||
|     uint64_t cycle = 0; | ||||
|     uint64_t instret = 0; | ||||
|     uint32_t instruction = 0; | ||||
|     uint32_t last_branch = 0; | ||||
|     std::array<address_type, 4> addr_mode; | ||||
|      | ||||
|     uint64_t interrupt_sim=0; | ||||
|   | ||||
| @@ -13,5 +13,8 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> | ||||
|   - ${it.instruction.name}: | ||||
|     encoding: ${it.encoding} | ||||
|     mask: ${it.mask}<%if(it.attributes.size) {%> | ||||
|     attributes: ${it.attributes}<%}}}%> | ||||
|     attributes: ${it.attributes}<%}%> | ||||
| 	size:   ${it.length} | ||||
| 	branch:   ${it.modifiesPC} | ||||
| 	delay:   ${it.isConditional?"[1,1]":"1"}<%}}%> | ||||
|  | ||||
|   | ||||
| @@ -121,7 +121,7 @@ protected: | ||||
|  | ||||
|     inline void raise(uint16_t trap_id, uint16_t cause){ | ||||
|         auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id; | ||||
|         this->core.trap_state = trap_val; | ||||
|         this->core.reg.trap_state = trap_val; | ||||
|         this->template get_reg<uint${addrDataWidth}_t>(traits::NEXT_PC) = std::numeric_limits<uint${addrDataWidth}_t>::max(); | ||||
|     } | ||||
|  | ||||
| @@ -244,16 +244,16 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|     auto pc=start; | ||||
|     auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); | ||||
|     auto* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]); | ||||
|     auto& trap_state = this->core.trap_state; | ||||
|     auto& icount = this->core.icount; | ||||
|     auto& cycle = this->core.cycle; | ||||
|     auto& instret = this->core.instret; | ||||
|     auto& instr = this->core.instruction; | ||||
|     auto& trap_state = this->core.reg.trap_state; | ||||
|     auto& icount =  this->core.reg.icount; | ||||
|     auto& cycle =  this->core.reg.cycle; | ||||
|     auto& instret =  this->core.reg.instret; | ||||
|     auto& instr =  this->core.reg.instruction; | ||||
|     // we fetch at max 4 byte, alignment is 2 | ||||
|     auto *const data = reinterpret_cast<uint8_t*>(&instr); | ||||
|  | ||||
|     while(!this->core.should_stop() && | ||||
|             !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ | ||||
|             !(is_count_limit_enabled(cond) && icount >= icount_limit)){ | ||||
|         if(fetch_ins(pc, data)!=iss::Ok){ | ||||
|             this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max()); | ||||
|             pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0); | ||||
| @@ -262,7 +262,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                     (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||
|             auto inst_id = decode_inst_id(instr); | ||||
|             // pre execution stuff | ||||
|             this->core.last_branch = 0; | ||||
|              this->core.reg.last_branch = 0; | ||||
|             if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id)); | ||||
|             switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> | ||||
|             case arch::traits<ARCH>::opcode_e::${instr.name}: { | ||||
| @@ -289,8 +289,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|             // post execution stuff | ||||
|             process_spawn_blocks(); | ||||
|             if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); | ||||
|             // if(!this->core.trap_state) // update trap state if there is a pending interrupt | ||||
|             //    this->core.trap_state = this->core.pending_trap; | ||||
|             // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt | ||||
|             //    this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||
|             // trap check | ||||
|             if(trap_state!=0){ | ||||
|                 super::core.enter_trap(trap_state, pc.val, instr); | ||||
| @@ -301,7 +301,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|             cycle++; | ||||
|             pc.val=*NEXT_PC; | ||||
|             this->core.reg.PC = this->core.reg.NEXT_PC; | ||||
|             this->core.trap_state = this->core.pending_trap; | ||||
|             this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||
|         } | ||||
|     } | ||||
|     return pc; | ||||
|   | ||||
| @@ -256,20 +256,20 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, | ||||
|     // we fetch at max 4 byte, alignment is 2 | ||||
|     enum {TRAP_ID=1<<16}; | ||||
|     code_word_t insn = 0; | ||||
|     const typename traits::addr_t upper_bits = ~traits::PGMASK; | ||||
|     // const typename traits::addr_t upper_bits = ~traits::PGMASK; | ||||
|     phys_addr_t paddr(pc); | ||||
|     auto *const data = (uint8_t *)&insn; | ||||
|     paddr = this->core.v2p(pc); | ||||
|     if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary | ||||
|         auto res = this->core.read(paddr, 2, data); | ||||
|         if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | ||||
|         if ((insn & 0x3) == 0x3) { // this is a 32bit instruction | ||||
|             res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); | ||||
|         } | ||||
|     } else { | ||||
| //    if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary | ||||
| //        auto res = this->core.read(paddr, 2, data); | ||||
| //        if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | ||||
| //        if ((insn & 0x3) == 0x3) { // this is a 32bit instruction | ||||
| //            res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); | ||||
| //        } | ||||
| //    } else { | ||||
|         auto res = this->core.read(paddr, 4, data); | ||||
|         if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | ||||
|     } | ||||
| //    } | ||||
|     if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||
|     // curr pc on stack | ||||
|     ++inst_cnt; | ||||
| @@ -1,9 +0,0 @@ | ||||
| {  | ||||
| 	"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} | ||||
| 		{ | ||||
| 			"name"  : "${instr.name}", | ||||
| 			"size"  : ${instr.length}, | ||||
| 			"delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} | ||||
| 		}<%}%> | ||||
| 	] | ||||
| } | ||||
| @@ -1,223 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (C) 2017, 2018 MINRES Technologies GmbH | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer in the documentation | ||||
|  *    and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * 3. Neither the name of the copyright holder nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||||
|  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
|  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||
|  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||
|  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
|  * POSSIBILITY OF SUCH DAMAGE. | ||||
|  * | ||||
|  *******************************************************************************/ | ||||
|  | ||||
| <%  | ||||
| import com.minres.coredsl.coreDsl.Register | ||||
| import com.minres.coredsl.coreDsl.RegisterFile | ||||
| import com.minres.coredsl.coreDsl.RegisterAlias | ||||
| def getTypeSize(size){ | ||||
| 	if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 | ||||
| } | ||||
| def getOriginalName(reg){ | ||||
|     if( reg.original instanceof RegisterFile) { | ||||
|     	if( reg.index != null ) { | ||||
|         	return reg.original.name+generator.generateHostCode(reg.index) | ||||
|         } else { | ||||
|         	return reg.original.name | ||||
|         } | ||||
|     } else if(reg.original instanceof Register){ | ||||
|         return reg.original.name | ||||
|     } | ||||
| } | ||||
| def getRegisterNames(){ | ||||
| 	def regNames = [] | ||||
|  	allRegs.each { reg ->  | ||||
| 		if( reg instanceof RegisterFile) { | ||||
| 			(reg.range.right..reg.range.left).each{ | ||||
|     			regNames+=reg.name.toLowerCase()+it | ||||
|             } | ||||
|         } else if(reg instanceof Register){ | ||||
|     		regNames+=reg.name.toLowerCase() | ||||
|         } | ||||
|     } | ||||
|     return regNames | ||||
| } | ||||
| def getRegisterAliasNames(){ | ||||
| 	def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} | ||||
|  	return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> | ||||
| 		if( reg instanceof RegisterFile) { | ||||
| 			return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } | ||||
|         } else if(reg instanceof Register){ | ||||
|     		regMap[reg.name]?:reg.name.toLowerCase() | ||||
|         } | ||||
|  	}.flatten() | ||||
| } | ||||
| %> | ||||
| #ifndef _${coreDef.name.toUpperCase()}_H_ | ||||
| #define _${coreDef.name.toUpperCase()}_H_ | ||||
|  | ||||
| #include <array> | ||||
| #include <iss/arch/traits.h> | ||||
| #include <iss/arch_if.h> | ||||
| #include <iss/vm_if.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace arch { | ||||
|  | ||||
| struct ${coreDef.name.toLowerCase()}; | ||||
|  | ||||
| template <> struct traits<${coreDef.name.toLowerCase()}> { | ||||
|  | ||||
| 	constexpr static char const* const core_type = "${coreDef.name}"; | ||||
|      | ||||
|   	static constexpr std::array<const char*, ${getRegisterNames().size}> reg_names{ | ||||
|  		{"${getRegisterNames().join("\", \"")}"}}; | ||||
|   | ||||
|   	static constexpr std::array<const char*, ${getRegisterAliasNames().size}> reg_aliases{ | ||||
|  		{"${getRegisterAliasNames().join("\", \"")}"}}; | ||||
|  | ||||
|     enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; | ||||
|  | ||||
|     enum reg_e {<% | ||||
|      	allRegs.each { reg ->  | ||||
|     		if( reg instanceof RegisterFile) { | ||||
|     			(reg.range.right..reg.range.left).each{%> | ||||
|         ${reg.name}${it},<% | ||||
|                 } | ||||
|             } else if(reg instanceof Register){ %> | ||||
|         ${reg.name},<%   | ||||
|             } | ||||
|         }%> | ||||
|         NUM_REGS, | ||||
|         NEXT_${pc.name}=NUM_REGS, | ||||
|         TRAP_STATE, | ||||
|         PENDING_TRAP, | ||||
|         MACHINE_STATE, | ||||
|         LAST_BRANCH, | ||||
|         ICOUNT<%  | ||||
|      	allRegs.each { reg ->  | ||||
|     		if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, | ||||
|         ${reg.name} = ${aliasname}<% | ||||
|             } | ||||
|         }%> | ||||
|     }; | ||||
|  | ||||
|     using reg_t = uint${regDataWidth}_t; | ||||
|  | ||||
|     using addr_t = uint${addrDataWidth}_t; | ||||
|  | ||||
|     using code_word_t = uint${addrDataWidth}_t; //TODO: check removal | ||||
|  | ||||
|     using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>; | ||||
|  | ||||
|     using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; | ||||
|  | ||||
|  	static constexpr std::array<const uint32_t, ${regSizes.size}> reg_bit_widths{ | ||||
|  		{${regSizes.join(",")}}}; | ||||
|  | ||||
|     static constexpr std::array<const uint32_t, ${regOffsets.size}> reg_byte_offsets{ | ||||
|     	{${regOffsets.join(",")}}}; | ||||
|  | ||||
|     static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); | ||||
|  | ||||
|     enum sreg_flag_e { FLAGS }; | ||||
|  | ||||
|     enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; | ||||
| }; | ||||
|  | ||||
| struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|  | ||||
|     using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t; | ||||
|     using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t; | ||||
|     using reg_t =  typename traits<${coreDef.name.toLowerCase()}>::reg_t; | ||||
|     using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t; | ||||
|  | ||||
|     ${coreDef.name.toLowerCase()}(); | ||||
|     ~${coreDef.name.toLowerCase()}(); | ||||
|  | ||||
|     void reset(uint64_t address=0) override; | ||||
|  | ||||
|     uint8_t* get_regs_base_ptr() override; | ||||
|     /// deprecated | ||||
|     void get_reg(short idx, std::vector<uint8_t>& value) override {} | ||||
|     void set_reg(short idx, const std::vector<uint8_t>& value) override {} | ||||
|     /// deprecated | ||||
|     bool get_flag(int flag) override {return false;} | ||||
|     void set_flag(int, bool value) override {}; | ||||
|     /// deprecated | ||||
|     void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; | ||||
|  | ||||
|     inline uint64_t get_icount() { return reg.icount; } | ||||
|  | ||||
|     inline bool should_stop() { return interrupt_sim; } | ||||
|  | ||||
|     inline uint64_t stop_code() { return interrupt_sim; } | ||||
|  | ||||
|     inline phys_addr_t v2p(const iss::addr_t& addr){ | ||||
|         if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || | ||||
|                 addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) { | ||||
|             return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); | ||||
|         } else | ||||
|             return virt2phys(addr); | ||||
|     } | ||||
|  | ||||
|     virtual phys_addr_t virt2phys(const iss::addr_t& addr); | ||||
|  | ||||
|     virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } | ||||
|  | ||||
|     inline uint32_t get_last_branch() { return reg.last_branch; } | ||||
|  | ||||
| protected: | ||||
|     struct ${coreDef.name}_regs {<% | ||||
|      	allRegs.each { reg ->  | ||||
|     		if( reg instanceof RegisterFile) { | ||||
|     			(reg.range.right..reg.range.left).each{%> | ||||
|         uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<% | ||||
|                 } | ||||
|             } else if(reg instanceof Register){ %> | ||||
|         uint${generator.getSize(reg)}_t ${reg.name} = 0;<% | ||||
|             } | ||||
|         }%> | ||||
|         uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0; | ||||
|         uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; | ||||
|         uint64_t icount = 0; | ||||
|     } reg; | ||||
|  | ||||
|     std::array<address_type, 4> addr_mode; | ||||
|      | ||||
|     uint64_t interrupt_sim=0; | ||||
| <% | ||||
| def fcsr = allRegs.find {it.name=='FCSR'} | ||||
| if(fcsr != null) {%> | ||||
| 	uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;} | ||||
| 	void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;}		 | ||||
| <%} else { %> | ||||
| 	uint32_t get_fcsr(){return 0;} | ||||
| 	void set_fcsr(uint32_t val){} | ||||
| <%}%> | ||||
| }; | ||||
|  | ||||
| } | ||||
| }             | ||||
| #endif /* _${coreDef.name.toUpperCase()}_H_ */ | ||||
| @@ -1,107 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (C) 2017, 2018 MINRES Technologies GmbH | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|  *    this list of conditions and the following disclaimer in the documentation | ||||
|  *    and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * 3. Neither the name of the copyright holder nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||||
|  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
|  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||
|  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||
|  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
|  * POSSIBILITY OF SUCH DAMAGE. | ||||
|  * | ||||
|  *******************************************************************************/ | ||||
|  <%  | ||||
| import com.minres.coredsl.coreDsl.Register | ||||
| import com.minres.coredsl.coreDsl.RegisterFile | ||||
| import com.minres.coredsl.coreDsl.RegisterAlias | ||||
| def getOriginalName(reg){ | ||||
|     if( reg.original instanceof RegisterFile) { | ||||
|     	if( reg.index != null ) { | ||||
|         	return reg.original.name+generator.generateHostCode(reg.index) | ||||
|         } else { | ||||
|         	return reg.original.name | ||||
|         } | ||||
|     } else if(reg.original instanceof Register){ | ||||
|         return reg.original.name | ||||
|     } | ||||
| } | ||||
| def getRegisterNames(){ | ||||
| 	def regNames = [] | ||||
|  	allRegs.each { reg ->  | ||||
| 		if( reg instanceof RegisterFile) { | ||||
| 			(reg.range.right..reg.range.left).each{ | ||||
|     			regNames+=reg.name.toLowerCase()+it | ||||
|             } | ||||
|         } else if(reg instanceof Register){ | ||||
|     		regNames+=reg.name.toLowerCase() | ||||
|         } | ||||
|     } | ||||
|     return regNames | ||||
| } | ||||
| def getRegisterAliasNames(){ | ||||
| 	def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} | ||||
|  	return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> | ||||
| 		if( reg instanceof RegisterFile) { | ||||
| 			return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } | ||||
|         } else if(reg instanceof Register){ | ||||
|     		regMap[reg.name]?:reg.name.toLowerCase() | ||||
|         } | ||||
|  	}.flatten() | ||||
| } | ||||
| %> | ||||
| #include "util/ities.h" | ||||
| #include <util/logging.h> | ||||
| #include <iss/arch/${coreDef.name.toLowerCase()}.h> | ||||
| #include <cstdio> | ||||
| #include <cstring> | ||||
| #include <fstream> | ||||
|  | ||||
| using namespace iss::arch; | ||||
|  | ||||
| constexpr std::array<const char*, ${getRegisterNames().size}>    iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names; | ||||
| constexpr std::array<const char*, ${getRegisterAliasNames().size}>    iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases; | ||||
| constexpr std::array<const uint32_t, ${regSizes.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths; | ||||
| constexpr std::array<const uint32_t, ${regOffsets.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets; | ||||
|  | ||||
| ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { | ||||
|     reg.icount = 0; | ||||
| } | ||||
|  | ||||
| ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; | ||||
|  | ||||
| void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { | ||||
|     for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); | ||||
|     reg.PC=address; | ||||
|     reg.NEXT_PC=reg.PC; | ||||
|     reg.trap_state=0; | ||||
|     reg.machine_state=0x3; | ||||
|     reg.icount=0; | ||||
| } | ||||
|  | ||||
| uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { | ||||
| 	return reinterpret_cast<uint8_t*>(®); | ||||
| } | ||||
|  | ||||
| ${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { | ||||
|     return phys_addr_t(pc); // change logical address to physical address | ||||
| } | ||||
|  | ||||
| @@ -280,7 +280,7 @@ public: | ||||
|  | ||||
|     void disass_output(uint64_t pc, const std::string instr) override { | ||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [s:0x{:x};c:{}]", | ||||
|                 pc, instr, (reg_t)state.mstatus, this->icount + cycle_offset); | ||||
|                 pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); | ||||
|     }; | ||||
|  | ||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||
| @@ -308,17 +308,17 @@ protected: | ||||
|  | ||||
|         uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; | ||||
|  | ||||
|         uint64_t get_instr_word() override { return arch.instruction; } | ||||
|         uint64_t get_instr_word() override { return arch.reg.instruction; } | ||||
|  | ||||
|         uint64_t get_instr_count() override { return arch.icount; } | ||||
|         uint64_t get_instr_count() override { return arch.reg.icount; } | ||||
|  | ||||
|         uint64_t get_pendig_traps() override { return arch.trap_state; } | ||||
|         uint64_t get_pendig_traps() override { return arch.reg.trap_state; } | ||||
|  | ||||
|         uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } | ||||
|         uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } | ||||
|  | ||||
|         void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; | ||||
|  | ||||
|         bool is_branch_taken() override { return arch.last_branch; }; | ||||
|         bool is_branch_taken() override { return arch.reg.last_branch; }; | ||||
|  | ||||
|         riscv_hart_m_p<BASE, FEAT> &arch; | ||||
|     }; | ||||
| @@ -619,9 +619,9 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m | ||||
|             } | ||||
|             return std::make_pair(entry, true); | ||||
|         } | ||||
|         throw std::runtime_error("memory load file is not a valid elf file"); | ||||
|         throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); | ||||
|     } | ||||
|     throw std::runtime_error("memory load file not found"); | ||||
|     throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| @@ -657,12 +657,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce | ||||
|             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||
|                 fault_data = addr; | ||||
|                 if (is_debug(access)) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1UL << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1UL << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(!is_debug(access) && (addr&(alignment-1))){ | ||||
|                     this->trap_state = (1UL << 31) | 4<<16; | ||||
|                     this->reg.trap_state = (1UL << 31) | 4<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -681,12 +681,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce | ||||
|                     res = hart_mem_rd_delegate( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)){ | ||||
|                     this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1UL << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -712,7 +712,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1UL << 31) | ta.id; | ||||
|         this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -750,12 +750,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc | ||||
|             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { | ||||
|                 fault_data = addr; | ||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1UL << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1UL << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ | ||||
|                     this->trap_state = (1UL << 31) | 6<<16; | ||||
|                     this->reg.trap_state = (1UL << 31) | 6<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -774,12 +774,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc | ||||
|                     res = write_mem( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)) { | ||||
|                     this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1UL << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -839,7 +839,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1UL << 31) | ta.id; | ||||
|         this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -885,7 +885,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_cycle(unsigned addr, reg_t &val) { | ||||
|     auto cycle_val = this->icount + cycle_offset; | ||||
|     auto cycle_val = this->reg.icount + cycle_offset; | ||||
|     if (addr == mcycle) { | ||||
|         val = static_cast<reg_t>(cycle_val); | ||||
|     } else if (addr == mcycleh) { | ||||
| @@ -904,35 +904,35 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT> | ||||
|             mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff); | ||||
|         } | ||||
|     } | ||||
|     cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around | ||||
|     cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) { | ||||
|     if ((addr&0xff) == (minstret&0xff)) { | ||||
|         val = static_cast<reg_t>(this->instret); | ||||
|         val = static_cast<reg_t>(this->reg.instret); | ||||
|     } else if ((addr&0xff) == (minstreth&0xff)) { | ||||
|         val = static_cast<reg_t>(this->instret >> 32); | ||||
|         val = static_cast<reg_t>(this->reg.instret >> 32); | ||||
|     } | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) { | ||||
|     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||
|         this->instret = static_cast<uint64_t>(val); | ||||
|         this->reg.instret = static_cast<uint64_t>(val); | ||||
|     } else { | ||||
|         if ((addr&0xff) == (minstret&0xff)) { | ||||
|             this->instret = (this->instret & 0xffffffff00000000) + val; | ||||
|             this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; | ||||
|         } else  { | ||||
|             this->instret = (static_cast<uint64_t>(val)<<32) + (this->instret & 0xffffffff); | ||||
|             this->reg.instret = (static_cast<uint64_t>(val)<<32) + (this->reg.instret & 0xffffffff); | ||||
|         } | ||||
|     } | ||||
|     this->instret--; | ||||
|     this->reg.instret--; | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) { | ||||
|     uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     if (addr == time) { | ||||
|         val = static_cast<reg_t>(time_val); | ||||
|     } else if (addr == timeh) { | ||||
| @@ -1074,18 +1074,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) { | ||||
| 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) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x0200BFF8: { // CLINT base, mtime reg | ||||
|         if (sizeof(reg_t) < length) return iss::Err; | ||||
|         reg_t time_val; | ||||
|         this->read_csr(time, time_val); | ||||
|         std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); | ||||
|     } break; | ||||
|     case 0x10008000: { | ||||
|         const mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         uint64_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(p.data() + offs, p.data() + offs + length, data); | ||||
|         if (this->icount > 30000) data[3] |= 0x80; | ||||
|     } break; | ||||
|     default: { | ||||
|         for(auto offs=0U; offs<length; ++offs) { | ||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; | ||||
| @@ -1098,29 +1086,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len | ||||
| template <typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x10013000: // UART0 base, TXFIFO reg | ||||
|     case 0x10023000: // UART1 base, TXFIFO reg | ||||
|         uart_buf << (char)data[0]; | ||||
|     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             std::cout << uart_buf.str(); | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             uart_buf.str(""); | ||||
|         } | ||||
|         } else if(((char)data[0]) != '\r') | ||||
|             uart_buf << (char)data[0]; | ||||
|         break; | ||||
|     case 0x10008000: { // HFROSC base, hfrosccfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 | ||||
|     } break; | ||||
|     case 0x10008008: { // HFROSC base, pllcfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         x |= 0x80; // set pll lock upon writing | ||||
|     } break; | ||||
|     default: { | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); | ||||
| @@ -1142,7 +1114,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le | ||||
|                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||
|                                       << "), stopping simulation"; | ||||
|                         } | ||||
|                         this->trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->reg.trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->interrupt_sim=hostvar; | ||||
|                         break; | ||||
|                         //throw(iss::simulation_stopped(hostvar)); | ||||
| @@ -1227,7 +1199,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check | ||||
|         	enabled_interrupts >>= 1; | ||||
|         	res++; | ||||
|         } | ||||
|         this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|         this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1275,7 +1247,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e | ||||
|         fault_data = 0; | ||||
|     } else { | ||||
|         csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt | ||||
|         this->pending_trap = 0; | ||||
|         this->reg.pending_trap = 0; | ||||
|     } | ||||
|     csr[mcause] = (trap_id << (traits<BASE>::XLEN-1)) + cause; | ||||
|     // update mstatus | ||||
| @@ -1305,7 +1277,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e | ||||
|     } | ||||
|     // reset trap state | ||||
|     this->reg.PRIV = new_priv; | ||||
|     this->trap_state = 0; | ||||
|     this->reg.trap_state = 0; | ||||
|     std::array<char, 32> buffer; | ||||
| #if defined(_MSC_VER) | ||||
|     sprintf(buffer.data(), "0x%016llx", addr); | ||||
| @@ -1326,7 +1298,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::l | ||||
|     this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); | ||||
|     CLOG(INFO, disass) << "Executing xRET"; | ||||
|     check_interrupt(); | ||||
|     this->trap_state = this->pending_trap; | ||||
|     this->reg.trap_state = this->reg.pending_trap; | ||||
|     return this->reg.NEXT_PC; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -307,7 +307,7 @@ public: | ||||
|  | ||||
|     void disass_output(uint64_t pc, const std::string instr) override { | ||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", | ||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); | ||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); | ||||
|     }; | ||||
|  | ||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||
| @@ -583,9 +583,9 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load | ||||
|             } | ||||
|             return std::make_pair(entry, true); | ||||
|         } | ||||
|         throw std::runtime_error("memory load file is not a valid elf file"); | ||||
|         throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); | ||||
|     } | ||||
|     throw std::runtime_error("memory load file not found"); | ||||
|     throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); | ||||
| } | ||||
|  | ||||
| template <typename BASE> | ||||
| @@ -607,12 +607,12 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_ | ||||
|             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||
|                 fault_data = addr; | ||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1 << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1 << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(!is_debug(access)  && (addr&(alignment-1))){ | ||||
|                     this->trap_state = 1<<31 | 4<<16; | ||||
|                     this->reg.trap_state = 1<<31 | 4<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -631,12 +631,12 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_ | ||||
|                         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); | ||||
|                 if (unlikely(res != iss::Ok)){ | ||||
|                 	this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                 	this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1 << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1 << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -652,7 +652,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_ | ||||
|             case 3: { // SFENCE:VMA upper | ||||
|                 auto tvm = state.mstatus.TVM; | ||||
|                 if (this->reg.PRIV == PRIV_S & tvm != 0) { | ||||
|                     this->trap_state = (1 << 31) | (2 << 16); | ||||
|                     this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|                     this->fault_data = this->reg.PC; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -673,7 +673,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_ | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1 << 31) | ta.id; | ||||
|         this->reg.trap_state = (1 << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -711,7 +711,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | ||||
|             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { | ||||
|                 fault_data = addr; | ||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1 << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1 << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
| @@ -730,12 +730,12 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | ||||
|                         write_mem(phys_addr_t{access, space, addr}, length, data): | ||||
|                         write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); | ||||
|                 if (unlikely(res != iss::Ok)) { | ||||
|                     this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1 << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1 << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -784,7 +784,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | ||||
|                 ptw.clear(); | ||||
|                 auto tvm = state.mstatus.TVM; | ||||
|                 if (this->reg.PRIV == PRIV_S & tvm != 0) { | ||||
|                     this->trap_state = (1 << 31) | (2 << 16); | ||||
|                     this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|                     this->fault_data = this->reg.PC; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -800,7 +800,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1 << 31) | ta.id; | ||||
|         this->reg.trap_state = (1 << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -846,7 +846,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned | ||||
| } | ||||
|  | ||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) { | ||||
|     auto cycle_val = this->icount + cycle_offset; | ||||
|     auto cycle_val = this->reg.icount + cycle_offset; | ||||
|     if (addr == mcycle) { | ||||
|         val = static_cast<reg_t>(cycle_val); | ||||
|     } else if (addr == mcycleh) { | ||||
| @@ -868,7 +868,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cycle(unsign | ||||
|             mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff); | ||||
|         } | ||||
|     } | ||||
|     cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around | ||||
|     cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| @@ -899,7 +899,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_instret(unsi | ||||
| } | ||||
|  | ||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) { | ||||
|     uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     if (addr == time) { | ||||
|         val = static_cast<reg_t>(time_val); | ||||
|     } else if (addr == timeh) { | ||||
| @@ -968,7 +968,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_epc(unsigned | ||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) { | ||||
|     reg_t tvm = state.mstatus.TVM; | ||||
|     if (this->reg.PRIV == PRIV_S & tvm != 0) { | ||||
|         this->trap_state = (1 << 31) | (2 << 16); | ||||
|         this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|         this->fault_data = this->reg.PC; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -979,7 +979,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned | ||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) { | ||||
|     reg_t tvm = state.mstatus.TVM; | ||||
|     if (this->reg.PRIV == PRIV_S & tvm != 0) { | ||||
|         this->trap_state = (1 << 31) | (2 << 16); | ||||
|         this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|         this->fault_data = this->reg.PC; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -1024,18 +1024,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne | ||||
| template <typename BASE> | ||||
| iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x0200BFF8: { // CLINT base, mtime reg | ||||
|         if (sizeof(reg_t) < length) return iss::Err; | ||||
|         reg_t time_val; | ||||
|         this->read_csr(time, time_val); | ||||
|         std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); | ||||
|     } break; | ||||
|     case 0x10008000: { | ||||
|         const mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         uint64_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(p.data() + offs, p.data() + offs + length, data); | ||||
|         if (this->icount > 30000) data[3] |= 0x80; | ||||
|     } break; | ||||
|     default: { | ||||
|         for(auto offs=0U; offs<length; ++offs) { | ||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; | ||||
| @@ -1048,30 +1036,13 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length | ||||
| template <typename BASE> | ||||
| iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x10013000: // UART0 base, TXFIFO reg | ||||
|     case 0x10023000: // UART1 base, TXFIFO reg | ||||
|         uart_buf << (char)data[0]; | ||||
|     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||
|             // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send | ||||
|             // '"<<uart_buf.str()<<"'"; | ||||
|             std::cout << uart_buf.str(); | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             uart_buf.str(""); | ||||
|         } | ||||
|         } else if(((char)data[0]) != '\r') | ||||
|             uart_buf << (char)data[0]; | ||||
|         break; | ||||
|     case 0x10008000: { // HFROSC base, hfrosccfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 | ||||
|     } break; | ||||
|     case 0x10008008: { // HFROSC base, pllcfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         x |= 0x80; // set pll lock upon writing | ||||
|     } break; | ||||
|     default: { | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); | ||||
| @@ -1093,7 +1064,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt | ||||
|                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||
|                                       << "), stopping simulation"; | ||||
|                         } | ||||
|                         this->trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->reg.trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->interrupt_sim=hostvar; | ||||
|                         break; | ||||
|                         //throw(iss::simulation_stopped(hostvar)); | ||||
| @@ -1162,7 +1133,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() { | ||||
|     if (enabled_interrupts != 0) { | ||||
|         int res = 0; | ||||
|         while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; | ||||
|         this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|         this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1306,7 +1277,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f | ||||
|         if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||
|             new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; | ||||
|         csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt | ||||
|         this->pending_trap = 0; | ||||
|         this->reg.pending_trap = 0; | ||||
|     } | ||||
|     size_t adr = ucause | (new_priv << 8); | ||||
|     csr[adr] = (trap_id << 31) + cause; | ||||
| @@ -1351,7 +1322,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f | ||||
|                        << lvl[cur_priv] << " to " << lvl[new_priv]; | ||||
|     // reset trap state | ||||
|     this->reg.PRIV = new_priv; | ||||
|     this->trap_state = 0; | ||||
|     this->reg.trap_state = 0; | ||||
|     update_vm_info(); | ||||
|     return this->reg.NEXT_PC; | ||||
| } | ||||
| @@ -1363,7 +1334,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f | ||||
|  | ||||
|     auto tsr = state.mstatus.TSR; | ||||
|     if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { | ||||
|         this->trap_state = (1 << 31) | (2 << 16); | ||||
|         this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|         this->fault_data = this->reg.PC; | ||||
|         return this->reg.PC; | ||||
|     } | ||||
| @@ -1402,7 +1373,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags | ||||
|     auto status = state.mstatus; | ||||
|     auto tw = status.TW; | ||||
|     if (this->reg.PRIV == PRIV_S && tw != 0) { | ||||
|         this->trap_state = (1 << 31) | (2 << 16); | ||||
|         this->reg.trap_state = (1 << 31) | (2 << 16); | ||||
|         this->fault_data = this->reg.PC; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -304,7 +304,7 @@ public: | ||||
|  | ||||
|     void disass_output(uint64_t pc, const std::string instr) override { | ||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", | ||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); | ||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); | ||||
|     }; | ||||
|  | ||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||
| @@ -689,9 +689,9 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m | ||||
|             } | ||||
|             return std::make_pair(entry, true); | ||||
|         } | ||||
|         throw std::runtime_error("memory load file is not a valid elf file"); | ||||
|         throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); | ||||
|     } | ||||
|     throw std::runtime_error("memory load file not found"); | ||||
|     throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); | ||||
| } | ||||
|  | ||||
| template<typename BASE, features_e FEAT> | ||||
| @@ -816,7 +816,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | ||||
|                 if(!pmp_check(access, addr, length) && !is_debug(access)) { | ||||
|                     fault_data = addr; | ||||
|                     if (is_debug(access)) throw trap_access(0, addr); | ||||
|                     this->trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 | ||||
|                     this->reg.trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 | ||||
|                     return iss::Err; | ||||
|                 } | ||||
|             } | ||||
| @@ -824,12 +824,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | ||||
|             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||
|                 fault_data = addr; | ||||
|                 if (is_debug(access)) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1UL << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1UL << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(!is_debug(access) && (addr&(alignment-1))){ | ||||
|                     this->trap_state = (1UL << 31) | 4<<16; | ||||
|                     this->reg.trap_state = (1UL << 31) | 4<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -848,12 +848,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | ||||
|                     res = hart_mem_rd_delegate( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)){ | ||||
|                     this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1UL << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -879,7 +879,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1UL << 31) | ta.id; | ||||
|         this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -918,19 +918,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | ||||
|                 if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { | ||||
|                     fault_data = addr; | ||||
|                     if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||
|                     this->trap_state = (1UL << 31) | (7 << 16); // issue trap 1 | ||||
|                     this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 | ||||
|                     return iss::Err; | ||||
|                 } | ||||
|             } | ||||
|             if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { | ||||
|                 fault_data = addr; | ||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||
|                 this->trap_state = (1UL << 31); // issue trap 0 | ||||
|                 this->reg.trap_state = (1UL << 31); // issue trap 0 | ||||
|                 return iss::Err; | ||||
|             } | ||||
|             try { | ||||
|                 if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ | ||||
|                     this->trap_state = (1UL << 31) | 6<<16; | ||||
|                     this->reg.trap_state = (1UL << 31) | 6<<16; | ||||
|                     fault_data=addr; | ||||
|                     return iss::Err; | ||||
|                 } | ||||
| @@ -949,12 +949,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | ||||
|                     res = hart_mem_wr_delegate( phys_addr, length, data); | ||||
|                 } | ||||
|                 if (unlikely(res != iss::Ok)) { | ||||
|                     this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) | ||||
|                     fault_data=addr; | ||||
|                 } | ||||
|                 return res; | ||||
|             } catch (trap_access &ta) { | ||||
|                 this->trap_state = (1UL << 31) | ta.id; | ||||
|                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|                 fault_data=ta.addr; | ||||
|                 return iss::Err; | ||||
|             } | ||||
| @@ -1014,7 +1014,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | ||||
|         } | ||||
|         return iss::Ok; | ||||
|     } catch (trap_access &ta) { | ||||
|         this->trap_state = (1UL << 31) | ta.id; | ||||
|         this->reg.trap_state = (1UL << 31) | ta.id; | ||||
|         fault_data=ta.addr; | ||||
|         return iss::Err; | ||||
|     } | ||||
| @@ -1060,7 +1060,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_cycle(unsigned addr, reg_t &val) { | ||||
|     auto cycle_val = this->icount + cycle_offset; | ||||
|     auto cycle_val = this->reg.icount + cycle_offset; | ||||
|     if (addr == mcycle) { | ||||
|         val = static_cast<reg_t>(cycle_val); | ||||
|     } else if (addr == mcycleh) { | ||||
| @@ -1079,35 +1079,35 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT | ||||
|             mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff); | ||||
|         } | ||||
|     } | ||||
|     cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around | ||||
|     cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) { | ||||
|     if ((addr&0xff) == (minstret&0xff)) { | ||||
|         val = static_cast<reg_t>(this->instret); | ||||
|         val = static_cast<reg_t>(this->reg.instret); | ||||
|     } else if ((addr&0xff) == (minstreth&0xff)) { | ||||
|         val = static_cast<reg_t>(this->instret >> 32); | ||||
|         val = static_cast<reg_t>(this->reg.instret >> 32); | ||||
|     } | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) { | ||||
|     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||
|         this->instret = static_cast<uint64_t>(val); | ||||
|         this->reg.instret = static_cast<uint64_t>(val); | ||||
|     } else { | ||||
|         if ((addr&0xff) == (minstret&0xff)) { | ||||
|             this->instret = (this->instret & 0xffffffff00000000) + val; | ||||
|             this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; | ||||
|         } else  { | ||||
|             this->instret = (static_cast<uint64_t>(val)<<32) + (this->instret & 0xffffffff); | ||||
|             this->reg.instret = (static_cast<uint64_t>(val)<<32) + (this->reg.instret & 0xffffffff); | ||||
|         } | ||||
|     } | ||||
|     this->instret--; | ||||
|     this->reg.instret--; | ||||
|     return iss::Ok; | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) { | ||||
|     uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; | ||||
|     if (addr == time) { | ||||
|         val = static_cast<reg_t>(time_val); | ||||
|     } else if (addr == timeh) { | ||||
| @@ -1283,18 +1283,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) { | ||||
| template <typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x0200BFF8: { // CLINT base, mtime reg | ||||
|         if (sizeof(reg_t) < length) return iss::Err; | ||||
|         reg_t time_val; | ||||
|         this->read_csr(time, time_val); | ||||
|         std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); | ||||
|     } break; | ||||
|     case 0x10008000: { | ||||
|         const mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         uint64_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(p.data() + offs, p.data() + offs + length, data); | ||||
|         if (this->icount > 30000) data[3] |= 0x80; | ||||
|     } break; | ||||
|     default: { | ||||
|         for(auto offs=0U; offs<length; ++offs) { | ||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; | ||||
| @@ -1307,29 +1295,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le | ||||
| template <typename BASE, features_e FEAT> | ||||
| iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||
|     switch (paddr.val) { | ||||
|     case 0x10013000: // UART0 base, TXFIFO reg | ||||
|     case 0x10023000: // UART1 base, TXFIFO reg | ||||
|         uart_buf << (char)data[0]; | ||||
|     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             std::cout << uart_buf.str(); | ||||
|             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||
|             uart_buf.str(""); | ||||
|         } | ||||
|         } else if(((char)data[0]) != '\r') | ||||
|             uart_buf << (char)data[0]; | ||||
|         break; | ||||
|     case 0x10008000: { // HFROSC base, hfrosccfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 | ||||
|     } break; | ||||
|     case 0x10008008: { // HFROSC base, pllcfg reg | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         size_t offs = paddr.val & mem.page_addr_mask; | ||||
|         std::copy(data, data + length, p.data() + offs); | ||||
|         uint8_t &x = *(p.data() + offs + 3); | ||||
|         x |= 0x80; // set pll lock upon writing | ||||
|     } break; | ||||
|     default: { | ||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); | ||||
| @@ -1351,7 +1323,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l | ||||
|                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||
|                                       << "), stopping simulation"; | ||||
|                         } | ||||
|                         this->trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->reg.trap_state=std::numeric_limits<uint32_t>::max(); | ||||
|                         this->interrupt_sim=hostvar; | ||||
|                         break; | ||||
|                         //throw(iss::simulation_stopped(hostvar)); | ||||
| @@ -1436,14 +1408,14 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec | ||||
|         	enabled_interrupts >>= 1; | ||||
|         	res++; | ||||
|         } | ||||
|         this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|         this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id | ||||
|     } | ||||
| } | ||||
|  | ||||
| template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_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 | ||||
|     if(flags==std::numeric_limits<uint64_t>::max()) flags=this->trap_state; | ||||
|     if(flags==std::numeric_limits<uint64_t>::max()) flags=this->reg.trap_state; | ||||
|     auto trap_id = bit_sub<0, 16>(flags); | ||||
|     auto cause = bit_sub<16, 15>(flags); | ||||
|     if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause | ||||
| @@ -1490,7 +1462,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>:: | ||||
|         if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||
|             new_priv = PRIV_U; | ||||
|         csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt | ||||
|         this->pending_trap = 0; | ||||
|         this->reg.pending_trap = 0; | ||||
|     } | ||||
|     size_t adr = ucause | (new_priv << 8); | ||||
|     csr[adr] = (trap_id << (traits<BASE>::XLEN-1)) + cause; | ||||
| @@ -1543,7 +1515,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>:: | ||||
|                        << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; | ||||
|     // reset trap state | ||||
|     this->reg.PRIV = new_priv; | ||||
|     this->trap_state = 0; | ||||
|     this->reg.trap_state = 0; | ||||
|     return this->reg.NEXT_PC; | ||||
| } | ||||
|  | ||||
| @@ -1552,7 +1524,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>:: | ||||
|     auto inst_priv = (flags & 0x3)? 3:0; | ||||
|     if(inst_priv>cur_priv){ | ||||
|         auto trap_val =  0x80ULL << 24 | (2 << 16); // illegal instruction | ||||
|         this->trap_state = trap_val; | ||||
|         this->reg.trap_state = trap_val; | ||||
|         this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max(); | ||||
|     } else { | ||||
|         auto status = state.mstatus; | ||||
|   | ||||
| @@ -55,8 +55,8 @@ void tgc_c::reset(uint64_t address) { | ||||
|     reg.PC=address; | ||||
|     reg.NEXT_PC=reg.PC; | ||||
|     reg.PRIV=0x3; | ||||
|     trap_state=0; | ||||
|     icount=0; | ||||
|     reg.trap_state=0; | ||||
|     reg.icount=0; | ||||
| } | ||||
|  | ||||
| uint8_t *tgc_c::get_regs_base_ptr() { | ||||
|   | ||||
| @@ -53,7 +53,7 @@ template <> struct traits<tgc_c> { | ||||
|     static constexpr std::array<const char*, 36> reg_aliases{ | ||||
|         {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; | ||||
|  | ||||
|     enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; | ||||
|     enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 0; | ||||
|  | ||||
| @@ -189,7 +189,7 @@ struct tgc_c: public arch_if { | ||||
|  | ||||
|     uint8_t* get_regs_base_ptr() override; | ||||
|  | ||||
|     inline uint64_t get_icount() { return icount; } | ||||
|     inline uint64_t get_icount() { return reg.icount; } | ||||
|  | ||||
|     inline bool should_stop() { return interrupt_sim; } | ||||
|  | ||||
| @@ -207,7 +207,7 @@ struct tgc_c: public arch_if { | ||||
|  | ||||
|     virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } | ||||
|  | ||||
|     inline uint32_t get_last_branch() { return last_branch; } | ||||
|     inline uint32_t get_last_branch() { return reg.last_branch; } | ||||
|  | ||||
|  | ||||
| #pragma pack(push, 1) | ||||
| @@ -256,12 +256,6 @@ struct tgc_c: public arch_if { | ||||
|         uint32_t last_branch = 0; | ||||
|     } reg; | ||||
| #pragma pack(pop) | ||||
|     uint32_t trap_state = 0, pending_trap = 0; | ||||
|     uint64_t icount = 0; | ||||
|     uint64_t cycle = 0; | ||||
|     uint64_t instret = 0; | ||||
|     uint32_t instruction = 0; | ||||
|     uint32_t last_branch = 0; | ||||
|     std::array<address_type, 4> addr_mode; | ||||
|      | ||||
|     uint64_t interrupt_sim=0; | ||||
|   | ||||
| @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { | ||||
|         ("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load") | ||||
|         ("mem,m", po::value<std::string>(), "the memory input file") | ||||
|         ("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate") | ||||
|         ("backend", po::value<std::string>()->default_value("interp"), "the memory input file") | ||||
|         ("backend", po::value<std::string>()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") | ||||
|         ("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation"); | ||||
|     // clang-format on | ||||
|     auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); | ||||
|   | ||||
| @@ -118,7 +118,7 @@ public: | ||||
|             std::stringstream s; | ||||
|             s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') | ||||
|               << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" | ||||
|               << this->icount + this->cycle_offset << "]"; | ||||
|               << this->reg.icount + this->cycle_offset << "]"; | ||||
|             SCCDEBUG(owner->name())<<"disass: " | ||||
|                 << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) | ||||
|                 << std::setfill(' ') << std::left << instr << s.str(); | ||||
| @@ -178,7 +178,7 @@ public: | ||||
|  | ||||
|     void wait_until(uint64_t flags) override { | ||||
|         SCCDEBUG(owner->name()) << "Sleeping until interrupt"; | ||||
|         while(this->pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { | ||||
|         while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { | ||||
|             sc_core::wait(wfi_evt); | ||||
|         } | ||||
|         PLAT::wait_until(flags); | ||||
| @@ -207,7 +207,7 @@ public: | ||||
|             this->csr[arch::mip] &= ~mask; | ||||
|         this->check_interrupt(); | ||||
|         if(value) | ||||
|             SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->pending_trap; | ||||
|             SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|   | ||||
| @@ -115,7 +115,7 @@ protected: | ||||
|  | ||||
|     inline void raise(uint16_t trap_id, uint16_t cause){ | ||||
|         auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id; | ||||
|         this->core.trap_state = trap_val; | ||||
|         this->core.reg.trap_state = trap_val; | ||||
|         this->template get_reg<uint32_t>(traits::NEXT_PC) = std::numeric_limits<uint32_t>::max(); | ||||
|     } | ||||
|  | ||||
| @@ -322,16 +322,16 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|     auto pc=start; | ||||
|     auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); | ||||
|     auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]); | ||||
|     auto& trap_state = this->core.trap_state; | ||||
|     auto& icount = this->core.icount; | ||||
|     auto& cycle = this->core.cycle; | ||||
|     auto& instret = this->core.instret; | ||||
|     auto& instr = this->core.instruction; | ||||
|     auto& trap_state = this->core.reg.trap_state; | ||||
|     auto& icount =  this->core.reg.icount; | ||||
|     auto& cycle =  this->core.reg.cycle; | ||||
|     auto& instret =  this->core.reg.instret; | ||||
|     auto& instr =  this->core.reg.instruction; | ||||
|     // we fetch at max 4 byte, alignment is 2 | ||||
|     auto *const data = reinterpret_cast<uint8_t*>(&instr); | ||||
|  | ||||
|     while(!this->core.should_stop() && | ||||
|             !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ | ||||
|             !(is_count_limit_enabled(cond) && icount >= icount_limit)){ | ||||
|         if(fetch_ins(pc, data)!=iss::Ok){ | ||||
|             this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max()); | ||||
|             pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0); | ||||
| @@ -340,7 +340,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                     (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||
|             auto inst_id = decode_inst_id(instr); | ||||
|             // pre execution stuff | ||||
|             this->core.last_branch = 0; | ||||
|              this->core.reg.last_branch = 0; | ||||
|             if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id)); | ||||
|             switch(inst_id){ | ||||
|             case arch::traits<ARCH>::opcode_e::LUI: { | ||||
| @@ -422,7 +422,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                             *(X+rd) = *PC +  4; | ||||
|                                         } | ||||
|                                         *NEXT_PC = *PC + (int32_t)sext<21>(imm); | ||||
|                                         this->core.last_branch = 1; | ||||
|                                         this->core.reg.last_branch = 1; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
| @@ -457,7 +457,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                             *(X+rd) = *PC +  4; | ||||
|                                         } | ||||
|                                         *NEXT_PC = new_pc & ~ 0x1; | ||||
|                                         this->core.last_branch = 1; | ||||
|                                         this->core.reg.last_branch = 1; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
| @@ -489,7 +489,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -522,7 +522,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -555,7 +555,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -588,7 +588,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -621,7 +621,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -654,7 +654,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); | ||||
|                                             this->core.last_branch = 1; | ||||
|                                             this->core.reg.last_branch = 1; | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
| @@ -683,7 +683,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     int8_t read_res = super::template read_mem<int8_t>(traits::MEM, load_address); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB; | ||||
|                                     int8_t res = (int8_t)read_res; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = (uint32_t)res; | ||||
| @@ -714,7 +714,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     int16_t read_res = super::template read_mem<int16_t>(traits::MEM, load_address); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH; | ||||
|                                     int16_t res = (int16_t)read_res; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = (uint32_t)res; | ||||
| @@ -745,7 +745,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW; | ||||
|                                     int32_t res = (int32_t)read_res; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = (uint32_t)res; | ||||
| @@ -776,7 +776,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     uint8_t read_res = super::template read_mem<uint8_t>(traits::MEM, load_address); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU; | ||||
|                                     uint8_t res = (uint8_t)read_res; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = (uint32_t)res; | ||||
| @@ -807,7 +807,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     uint16_t read_res = super::template read_mem<uint16_t>(traits::MEM, load_address); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU; | ||||
|                                     uint16_t res = (uint16_t)read_res; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = (uint32_t)res; | ||||
| @@ -838,7 +838,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     super::template write_mem<uint8_t>(traits::MEM, store_address, (int8_t)*(X+rs2)); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_SB:break; | ||||
| @@ -865,7 +865,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     super::template write_mem<uint16_t>(traits::MEM, store_address, (int16_t)*(X+rs2)); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_SH:break; | ||||
| @@ -892,7 +892,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); | ||||
|                                     super::template write_mem<uint32_t>(traits::MEM, store_address, (int32_t)*(X+rs2)); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_SW:break; | ||||
| @@ -1428,7 +1428,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 // execute instruction | ||||
|                 { | ||||
|                                 super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred <<  4 | succ); | ||||
|                                 if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE; | ||||
|                                 if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE; | ||||
|                             } | ||||
|                 TRAP_FENCE:break; | ||||
|             }// @suppress("No break at end of case") | ||||
| @@ -1507,15 +1507,15 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                     uint32_t xrs1 = *(X+rs1); | ||||
|                                     if(rd !=  0) { | ||||
|                                         uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                         uint32_t xrd = read_res; | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                         *(X+rd) = xrd; | ||||
|                                     } | ||||
|                                     else { | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
| @@ -1542,12 +1542,12 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; | ||||
|                                     uint32_t xrd = read_res; | ||||
|                                     uint32_t xrs1 = *(X+rs1); | ||||
|                                     if(rs1 !=  0) { | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; | ||||
|                                     } | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = xrd; | ||||
| @@ -1577,12 +1577,12 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; | ||||
|                                     uint32_t xrd = read_res; | ||||
|                                     uint32_t xrs1 = *(X+rs1); | ||||
|                                     if(rs1 !=  0) { | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; | ||||
|                                     } | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = xrd; | ||||
| @@ -1612,10 +1612,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; | ||||
|                                     uint32_t xrd = read_res; | ||||
|                                     super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = xrd; | ||||
|                                     } | ||||
| @@ -1644,11 +1644,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; | ||||
|                                     uint32_t xrd = read_res; | ||||
|                                     if(zimm !=  0) { | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; | ||||
|                                     } | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = xrd; | ||||
| @@ -1678,11 +1678,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; | ||||
|                                     uint32_t xrd = read_res; | ||||
|                                     if(zimm !=  0) { | ||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); | ||||
|                                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; | ||||
|                                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; | ||||
|                                     } | ||||
|                                     if(rd !=  0) { | ||||
|                                         *(X+rd) = xrd; | ||||
| @@ -1707,7 +1707,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 // execute instruction | ||||
|                 { | ||||
|                                 super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm); | ||||
|                                 if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE_I; | ||||
|                                 if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I; | ||||
|                             } | ||||
|                 TRAP_FENCE_I:break; | ||||
|             }// @suppress("No break at end of case") | ||||
| @@ -2015,7 +2015,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                     uint32_t load_address = *(X+rs1 +  8) + uimm; | ||||
|                     int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address); | ||||
|                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CLW; | ||||
|                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; | ||||
|                     *(X+rd +  8) = (int32_t)read_res; | ||||
|                 } | ||||
|                 TRAP_CLW:break; | ||||
| @@ -2038,7 +2038,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                     uint32_t load_address = *(X+rs1 +  8) + uimm; | ||||
|                     super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 +  8)); | ||||
|                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSW; | ||||
|                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; | ||||
|                 } | ||||
|                 TRAP_CSW:break; | ||||
|             }// @suppress("No break at end of case") | ||||
| @@ -2097,7 +2097,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                     *(X+1) = *PC +  2; | ||||
|                     *NEXT_PC = *PC + (int16_t)sext<12>(imm); | ||||
|                     this->core.last_branch = 1; | ||||
|                     this->core.reg.last_branch = 1; | ||||
|                 } | ||||
|                 TRAP_CJAL:break; | ||||
|             }// @suppress("No break at end of case") | ||||
| @@ -2342,7 +2342,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 // execute instruction | ||||
|                 { | ||||
|                                 *NEXT_PC = *PC + (int16_t)sext<12>(imm); | ||||
|                                 this->core.last_branch = 1; | ||||
|                                 this->core.reg.last_branch = 1; | ||||
|                             } | ||||
|                 TRAP_CJ:break; | ||||
|             }// @suppress("No break at end of case") | ||||
| @@ -2363,7 +2363,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                                 if(*(X+rs1 +  8) ==  0) { | ||||
|                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); | ||||
|                                     this->core.last_branch = 1; | ||||
|                                     this->core.reg.last_branch = 1; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_CBEQZ:break; | ||||
| @@ -2385,7 +2385,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                                 if(*(X+rs1 +  8) !=  0) { | ||||
|                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); | ||||
|                                     this->core.last_branch = 1; | ||||
|                                     this->core.reg.last_branch = 1; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_CBNEZ:break; | ||||
| @@ -2436,7 +2436,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                     } | ||||
|                     else { | ||||
|                         int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm); | ||||
|                         if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP; | ||||
|                         if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; | ||||
|                         int32_t res = read_res; | ||||
|                         *(X+rd) = (int32_t)res; | ||||
|                     } | ||||
| @@ -2485,7 +2485,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                 { | ||||
|                                 if(rs1 && rs1 < traits::RFS) { | ||||
|                                     *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; | ||||
|                                     this->core.last_branch = 1; | ||||
|                                     this->core.reg.last_branch = 1; | ||||
|                                 } | ||||
|                                 else { | ||||
|                                     raise(0, 2); | ||||
| @@ -2553,7 +2553,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                     uint32_t new_pc = *(X+rs1); | ||||
|                                     *(X+1) = *PC +  2; | ||||
|                                     *NEXT_PC = new_pc & ~ 0x1; | ||||
|                                     this->core.last_branch = 1; | ||||
|                                     this->core.reg.last_branch = 1; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_CJALR:break; | ||||
| @@ -2592,7 +2592,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|                                 else { | ||||
|                                     uint32_t offs = *(X+2) + uimm; | ||||
|                                     super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2)); | ||||
|                                     if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP; | ||||
|                                     if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP; | ||||
|                                 } | ||||
|                             } | ||||
|                 TRAP_CSWSP:break; | ||||
| @@ -2618,8 +2618,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|             // post execution stuff | ||||
|             process_spawn_blocks(); | ||||
|             if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); | ||||
|             // if(!this->core.trap_state) // update trap state if there is a pending interrupt | ||||
|             //    this->core.trap_state = this->core.pending_trap; | ||||
|             // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt | ||||
|             //    this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||
|             // trap check | ||||
|             if(trap_state!=0){ | ||||
|                 super::core.enter_trap(trap_state, pc.val, instr); | ||||
| @@ -2630,7 +2630,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | ||||
|             cycle++; | ||||
|             pc.val=*NEXT_PC; | ||||
|             this->core.reg.PC = this->core.reg.NEXT_PC; | ||||
|             this->core.trap_state = this->core.pending_trap; | ||||
|             this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||
|         } | ||||
|     } | ||||
|     return pc; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user