Compare commits
	
		
			3 Commits
		
	
	
		
			ee6218279e
			...
			2281ec4144
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2281ec4144 | |||
| 11c481cec2 | |||
| a123beb301 | 
| @@ -1,13 +1,13 @@ | |||||||
| import "RV32I.core_desc" | import "ISA/RV32I.core_desc" | ||||||
| import "RVM.core_desc" | import "ISA/RVM.core_desc" | ||||||
| import "RVC.core_desc" | import "ISA/RVC.core_desc" | ||||||
|  |  | ||||||
| Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { | Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { | ||||||
|     architectural_state { |     architectural_state { | ||||||
|         XLEN=32; |         XLEN=32; | ||||||
|         // definitions for the architecture wrapper |         // definitions for the architecture wrapper | ||||||
|         //                    XL    ZYXWVUTSRQPONMLKJIHGFEDCBA |         //                    XL    ZYXWVUTSRQPONMLKJIHGFEDCBA | ||||||
|         unsigned MISA_VAL = 0b01000000000000000001000100000100; |         unsigned int MISA_VAL = 0b01000000000000000001000100000100; | ||||||
|         unsigned MARCHID_VAL = 0x80000003; |         unsigned int MARCHID_VAL = 0x80000003; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,8 +62,8 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { | |||||||
|     reg.PC=address; |     reg.PC=address; | ||||||
|     reg.NEXT_PC=reg.PC; |     reg.NEXT_PC=reg.PC; | ||||||
|     reg.PRIV=0x3; |     reg.PRIV=0x3; | ||||||
|     trap_state=0; |     reg.trap_state=0; | ||||||
|     icount=0; |     reg.icount=0; | ||||||
| } | } | ||||||
|  |  | ||||||
| uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { | 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; |     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; } |     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; } |     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) | #pragma pack(push, 1) | ||||||
| @@ -170,12 +170,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { | |||||||
|         uint32_t last_branch = 0; |         uint32_t last_branch = 0; | ||||||
|     } reg; |     } reg; | ||||||
| #pragma pack(pop) | #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; |     std::array<address_type, 4> addr_mode; | ||||||
|      |      | ||||||
|     uint64_t interrupt_sim=0; |     uint64_t interrupt_sim=0; | ||||||
|   | |||||||
| @@ -13,5 +13,8 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> | |||||||
|   - ${it.instruction.name}: |   - ${it.instruction.name}: | ||||||
|     encoding: ${it.encoding} |     encoding: ${it.encoding} | ||||||
|     mask: ${it.mask}<%if(it.attributes.size) {%> |     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){ |     inline void raise(uint16_t trap_id, uint16_t cause){ | ||||||
|         auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id; |         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(); |         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=start; | ||||||
|     auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); |     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* 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& trap_state = this->core.reg.trap_state; | ||||||
|     auto& icount = this->core.icount; |     auto& icount =  this->core.reg.icount; | ||||||
|     auto& cycle = this->core.cycle; |     auto& cycle =  this->core.reg.cycle; | ||||||
|     auto& instret = this->core.instret; |     auto& instret =  this->core.reg.instret; | ||||||
|     auto& instr = this->core.instruction; |     auto& instr =  this->core.reg.instruction; | ||||||
|     // we fetch at max 4 byte, alignment is 2 |     // we fetch at max 4 byte, alignment is 2 | ||||||
|     auto *const data = reinterpret_cast<uint8_t*>(&instr); |     auto *const data = reinterpret_cast<uint8_t*>(&instr); | ||||||
|  |  | ||||||
|     while(!this->core.should_stop() && |     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){ |         if(fetch_ins(pc, data)!=iss::Ok){ | ||||||
|             this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max()); |             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); |             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' |                     (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||||
|             auto inst_id = decode_inst_id(instr); |             auto inst_id = decode_inst_id(instr); | ||||||
|             // pre execution stuff |             // 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)); |             if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id)); | ||||||
|             switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> |             switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> | ||||||
|             case arch::traits<ARCH>::opcode_e::${instr.name}: { |             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 |             // post execution stuff | ||||||
|             process_spawn_blocks(); |             process_spawn_blocks(); | ||||||
|             if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); |             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 |             // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt | ||||||
|             //    this->core.trap_state = this->core.pending_trap; |             //    this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||||
|             // trap check |             // trap check | ||||||
|             if(trap_state!=0){ |             if(trap_state!=0){ | ||||||
|                 super::core.enter_trap(trap_state, pc.val, instr); |                 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++; |             cycle++; | ||||||
|             pc.val=*NEXT_PC; |             pc.val=*NEXT_PC; | ||||||
|             this->core.reg.PC = this->core.reg.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; |     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 |     // we fetch at max 4 byte, alignment is 2 | ||||||
|     enum {TRAP_ID=1<<16}; |     enum {TRAP_ID=1<<16}; | ||||||
|     code_word_t insn = 0; |     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); |     phys_addr_t paddr(pc); | ||||||
|     auto *const data = (uint8_t *)&insn; |     auto *const data = (uint8_t *)&insn; | ||||||
|     paddr = this->core.v2p(pc); |     paddr = this->core.v2p(pc); | ||||||
|     if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary | //    if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary | ||||||
|         auto res = this->core.read(paddr, 2, data); | //        auto res = this->core.read(paddr, 2, data); | ||||||
|         if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | //        if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | ||||||
|         if ((insn & 0x3) == 0x3) { // this is a 32bit instruction | //        if ((insn & 0x3) == 0x3) { // this is a 32bit instruction | ||||||
|             res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); | //            res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); | ||||||
|         } | //        } | ||||||
|     } else { | //    } else { | ||||||
|         auto res = this->core.read(paddr, 4, data); |         auto res = this->core.read(paddr, 4, data); | ||||||
|         if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); |         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' |     if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||||
|     // curr pc on stack |     // curr pc on stack | ||||||
|     ++inst_cnt; |     ++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 { |     void disass_output(uint64_t pc, const std::string instr) override { | ||||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [s:0x{:x};c:{}]", |         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; } |     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_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; }; |         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; |         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); |             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> | 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)))) { |             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (is_debug(access)) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(!is_debug(access) && (addr&(alignment-1))){ |                 if(!is_debug(access) && (addr&(alignment-1))){ | ||||||
|                     this->trap_state = (1UL << 31) | 4<<16; |                     this->reg.trap_state = (1UL << 31) | 4<<16; | ||||||
|                     fault_data=addr; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     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); |                     res = hart_mem_rd_delegate( phys_addr, length, data); | ||||||
|                 } |                 } | ||||||
|                 if (unlikely(res != iss::Ok)){ |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1UL << 31) | ta.id; |                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 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; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1UL << 31) | ta.id; |         this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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)) { |             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ |                 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; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     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); |                     res = write_mem( phys_addr, length, data); | ||||||
|                 } |                 } | ||||||
|                 if (unlikely(res != iss::Ok)) { |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1UL << 31) | ta.id; |                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 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; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1UL << 31) | ta.id; |         this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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) { | 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) { |     if (addr == mcycle) { | ||||||
|         val = static_cast<reg_t>(cycle_val); |         val = static_cast<reg_t>(cycle_val); | ||||||
|     } else if (addr == mcycleh) { |     } 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); |             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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) { | 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)) { |     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)) { |     } 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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) { | 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) { |     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||||
|         this->instret = static_cast<uint64_t>(val); |         this->reg.instret = static_cast<uint64_t>(val); | ||||||
|     } else { |     } else { | ||||||
|         if ((addr&0xff) == (minstret&0xff)) { |         if ((addr&0xff) == (minstret&0xff)) { | ||||||
|             this->instret = (this->instret & 0xffffffff00000000) + val; |             this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; | ||||||
|         } else  { |         } 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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) { | 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) { |     if (addr == time) { | ||||||
|         val = static_cast<reg_t>(time_val); |         val = static_cast<reg_t>(time_val); | ||||||
|     } else if (addr == timeh) { |     } 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> | 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) { | iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     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: { |     default: { | ||||||
|         for(auto offs=0U; offs<length; ++offs) { |         for(auto offs=0U; offs<length; ++offs) { | ||||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; |             *(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> | 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) { | iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     switch (paddr.val) { | ||||||
|     case 0x10013000: // UART0 base, TXFIFO reg |     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||||
|     case 0x10023000: // UART1 base, TXFIFO reg |  | ||||||
|         uart_buf << (char)data[0]; |  | ||||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { |         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||||
|             LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; |             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||||
|             std::cout << uart_buf.str(); |  | ||||||
|             uart_buf.str(""); |             uart_buf.str(""); | ||||||
|         } |         } else if(((char)data[0]) != '\r') | ||||||
|  |             uart_buf << (char)data[0]; | ||||||
|         break; |         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: { |     default: { | ||||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); |         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); |         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 |                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||||
|                                       << "), stopping simulation"; |                                       << "), 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; |                         this->interrupt_sim=hostvar; | ||||||
|                         break; |                         break; | ||||||
|                         //throw(iss::simulation_stopped(hostvar)); |                         //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; |         	enabled_interrupts >>= 1; | ||||||
|         	res++; |         	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; |         fault_data = 0; | ||||||
|     } else { |     } else { | ||||||
|         csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt |         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; |     csr[mcause] = (trap_id << (traits<BASE>::XLEN-1)) + cause; | ||||||
|     // update mstatus |     // update mstatus | ||||||
| @@ -1305,7 +1277,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e | |||||||
|     } |     } | ||||||
|     // reset trap state |     // reset trap state | ||||||
|     this->reg.PRIV = new_priv; |     this->reg.PRIV = new_priv; | ||||||
|     this->trap_state = 0; |     this->reg.trap_state = 0; | ||||||
|     std::array<char, 32> buffer; |     std::array<char, 32> buffer; | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
|     sprintf(buffer.data(), "0x%016llx", addr); |     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(); |     this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); | ||||||
|     CLOG(INFO, disass) << "Executing xRET"; |     CLOG(INFO, disass) << "Executing xRET"; | ||||||
|     check_interrupt(); |     check_interrupt(); | ||||||
|     this->trap_state = this->pending_trap; |     this->reg.trap_state = this->reg.pending_trap; | ||||||
|     return this->reg.NEXT_PC; |     return this->reg.NEXT_PC; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -307,7 +307,7 @@ public: | |||||||
|  |  | ||||||
|     void disass_output(uint64_t pc, const std::string instr) override { |     void disass_output(uint64_t pc, const std::string instr) override { | ||||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", |         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; } |     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); |             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> | 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)))) { |             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(!is_debug(access)  && (addr&(alignment-1))){ |                 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; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     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(phys_addr_t{access, space, addr}), length, data): | ||||||
|                         read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); |                         read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); | ||||||
|                 if (unlikely(res != iss::Ok)){ |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1 << 31) | ta.id; |                 this->reg.trap_state = (1 << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 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 |             case 3: { // SFENCE:VMA upper | ||||||
|                 auto tvm = state.mstatus.TVM; |                 auto tvm = state.mstatus.TVM; | ||||||
|                 if (this->reg.PRIV == PRIV_S & tvm != 0) { |                 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; |                     this->fault_data = this->reg.PC; | ||||||
|                     return iss::Err; |                     return iss::Err; | ||||||
|                 } |                 } | ||||||
| @@ -673,7 +673,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_ | |||||||
|         } |         } | ||||||
|         return iss::Ok; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1 << 31) | ta.id; |         this->reg.trap_state = (1 << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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)) { |             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             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(phys_addr_t{access, space, addr}, length, data): | ||||||
|                         write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); |                         write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); | ||||||
|                 if (unlikely(res != iss::Ok)) { |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1 << 31) | ta.id; |                 this->reg.trap_state = (1 << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 return iss::Err; | ||||||
|             } |             } | ||||||
| @@ -784,7 +784,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | |||||||
|                 ptw.clear(); |                 ptw.clear(); | ||||||
|                 auto tvm = state.mstatus.TVM; |                 auto tvm = state.mstatus.TVM; | ||||||
|                 if (this->reg.PRIV == PRIV_S & tvm != 0) { |                 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; |                     this->fault_data = this->reg.PC; | ||||||
|                     return iss::Err; |                     return iss::Err; | ||||||
|                 } |                 } | ||||||
| @@ -800,7 +800,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | |||||||
|         } |         } | ||||||
|         return iss::Ok; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1 << 31) | ta.id; |         this->reg.trap_state = (1 << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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) { | 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) { |     if (addr == mcycle) { | ||||||
|         val = static_cast<reg_t>(cycle_val); |         val = static_cast<reg_t>(cycle_val); | ||||||
|     } else if (addr == mcycleh) { |     } 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); |             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; |     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) { | 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) { |     if (addr == time) { | ||||||
|         val = static_cast<reg_t>(time_val); |         val = static_cast<reg_t>(time_val); | ||||||
|     } else if (addr == timeh) { |     } 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) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) { | ||||||
|     reg_t tvm = state.mstatus.TVM; |     reg_t tvm = state.mstatus.TVM; | ||||||
|     if (this->reg.PRIV == PRIV_S & tvm != 0) { |     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; |         this->fault_data = this->reg.PC; | ||||||
|         return iss::Err; |         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) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) { | ||||||
|     reg_t tvm = state.mstatus.TVM; |     reg_t tvm = state.mstatus.TVM; | ||||||
|     if (this->reg.PRIV == PRIV_S & tvm != 0) { |     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; |         this->fault_data = this->reg.PC; | ||||||
|         return iss::Err; |         return iss::Err; | ||||||
|     } |     } | ||||||
| @@ -1024,18 +1024,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne | |||||||
| template <typename BASE> | template <typename BASE> | ||||||
| iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     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: { |     default: { | ||||||
|         for(auto offs=0U; offs<length; ++offs) { |         for(auto offs=0U; offs<length; ++offs) { | ||||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; |             *(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> | template <typename BASE> | ||||||
| iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     switch (paddr.val) { | ||||||
|     case 0x10013000: // UART0 base, TXFIFO reg |     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||||
|     case 0x10023000: // UART1 base, TXFIFO reg |  | ||||||
|         uart_buf << (char)data[0]; |  | ||||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { |         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||||
|             // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send |             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||||
|             // '"<<uart_buf.str()<<"'"; |  | ||||||
|             std::cout << uart_buf.str(); |  | ||||||
|             uart_buf.str(""); |             uart_buf.str(""); | ||||||
|         } |         } else if(((char)data[0]) != '\r') | ||||||
|  |             uart_buf << (char)data[0]; | ||||||
|         break; |         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: { |     default: { | ||||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); |         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); |         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 |                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||||
|                                       << "), stopping simulation"; |                                       << "), 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; |                         this->interrupt_sim=hostvar; | ||||||
|                         break; |                         break; | ||||||
|                         //throw(iss::simulation_stopped(hostvar)); |                         //throw(iss::simulation_stopped(hostvar)); | ||||||
| @@ -1162,7 +1133,7 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() { | |||||||
|     if (enabled_interrupts != 0) { |     if (enabled_interrupts != 0) { | ||||||
|         int res = 0; |         int res = 0; | ||||||
|         while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; |         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) |         if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||||
|             new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; |             new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; | ||||||
|         csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt |         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); |     size_t adr = ucause | (new_priv << 8); | ||||||
|     csr[adr] = (trap_id << 31) + cause; |     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]; |                        << lvl[cur_priv] << " to " << lvl[new_priv]; | ||||||
|     // reset trap state |     // reset trap state | ||||||
|     this->reg.PRIV = new_priv; |     this->reg.PRIV = new_priv; | ||||||
|     this->trap_state = 0; |     this->reg.trap_state = 0; | ||||||
|     update_vm_info(); |     update_vm_info(); | ||||||
|     return this->reg.NEXT_PC; |     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; |     auto tsr = state.mstatus.TSR; | ||||||
|     if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { |     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; |         this->fault_data = this->reg.PC; | ||||||
|         return 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 status = state.mstatus; | ||||||
|     auto tw = status.TW; |     auto tw = status.TW; | ||||||
|     if (this->reg.PRIV == PRIV_S && tw != 0) { |     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; |         this->fault_data = this->reg.PC; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -304,7 +304,7 @@ public: | |||||||
|  |  | ||||||
|     void disass_output(uint64_t pc, const std::string instr) override { |     void disass_output(uint64_t pc, const std::string instr) override { | ||||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", |         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; } |     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); |             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> | 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)) { |                 if(!pmp_check(access, addr, length) && !is_debug(access)) { | ||||||
|                     fault_data = addr; |                     fault_data = addr; | ||||||
|                     if (is_debug(access)) throw trap_access(0, 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; |                     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)))) { |             if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (is_debug(access)) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(!is_debug(access) && (addr&(alignment-1))){ |                 if(!is_debug(access) && (addr&(alignment-1))){ | ||||||
|                     this->trap_state = (1UL << 31) | 4<<16; |                     this->reg.trap_state = (1UL << 31) | 4<<16; | ||||||
|                     fault_data=addr; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     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); |                     res = hart_mem_rd_delegate( phys_addr, length, data); | ||||||
|                 } |                 } | ||||||
|                 if (unlikely(res != iss::Ok)){ |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1UL << 31) | ta.id; |                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 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; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1UL << 31) | ta.id; |         this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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) { |                 if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { | ||||||
|                     fault_data = addr; |                     fault_data = addr; | ||||||
|                     if (access && iss::access_type::DEBUG) throw trap_access(0, 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; |                     return iss::Err; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { |             if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, 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; |                 return iss::Err; | ||||||
|             } |             } | ||||||
|             try { |             try { | ||||||
|                 if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ |                 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; |                     fault_data=addr; | ||||||
|                     return iss::Err; |                     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); |                     res = hart_mem_wr_delegate( phys_addr, length, data); | ||||||
|                 } |                 } | ||||||
|                 if (unlikely(res != iss::Ok)) { |                 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; |                     fault_data=addr; | ||||||
|                 } |                 } | ||||||
|                 return res; |                 return res; | ||||||
|             } catch (trap_access &ta) { |             } catch (trap_access &ta) { | ||||||
|                 this->trap_state = (1UL << 31) | ta.id; |                 this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|                 fault_data=ta.addr; |                 fault_data=ta.addr; | ||||||
|                 return iss::Err; |                 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; |         return iss::Ok; | ||||||
|     } catch (trap_access &ta) { |     } catch (trap_access &ta) { | ||||||
|         this->trap_state = (1UL << 31) | ta.id; |         this->reg.trap_state = (1UL << 31) | ta.id; | ||||||
|         fault_data=ta.addr; |         fault_data=ta.addr; | ||||||
|         return iss::Err; |         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) { | 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) { |     if (addr == mcycle) { | ||||||
|         val = static_cast<reg_t>(cycle_val); |         val = static_cast<reg_t>(cycle_val); | ||||||
|     } else if (addr == mcycleh) { |     } 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); |             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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_instret(unsigned addr, reg_t &val) { | 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)) { |     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)) { |     } 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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) { | 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) { |     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||||
|         this->instret = static_cast<uint64_t>(val); |         this->reg.instret = static_cast<uint64_t>(val); | ||||||
|     } else { |     } else { | ||||||
|         if ((addr&0xff) == (minstret&0xff)) { |         if ((addr&0xff) == (minstret&0xff)) { | ||||||
|             this->instret = (this->instret & 0xffffffff00000000) + val; |             this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; | ||||||
|         } else  { |         } 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; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) { | 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) { |     if (addr == time) { | ||||||
|         val = static_cast<reg_t>(time_val); |         val = static_cast<reg_t>(time_val); | ||||||
|     } else if (addr == timeh) { |     } 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> | 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) { | iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     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: { |     default: { | ||||||
|         for(auto offs=0U; offs<length; ++offs) { |         for(auto offs=0U; offs<length; ++offs) { | ||||||
|             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; |             *(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> | 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) { | iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||||
|     switch (paddr.val) { |     switch (paddr.val) { | ||||||
|     case 0x10013000: // UART0 base, TXFIFO reg |     case 0xFFFF0000: // UART0 base, TXFIFO reg | ||||||
|     case 0x10023000: // UART1 base, TXFIFO reg |  | ||||||
|         uart_buf << (char)data[0]; |  | ||||||
|         if (((char)data[0]) == '\n' || data[0] == 0) { |         if (((char)data[0]) == '\n' || data[0] == 0) { | ||||||
|             LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; |             LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<<uart_buf.str()<<"'"; | ||||||
|             std::cout << uart_buf.str(); |  | ||||||
|             uart_buf.str(""); |             uart_buf.str(""); | ||||||
|         } |         } else if(((char)data[0]) != '\r') | ||||||
|  |             uart_buf << (char)data[0]; | ||||||
|         break; |         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: { |     default: { | ||||||
|         mem_type::page_type &p = mem(paddr.val / mem.page_size); |         mem_type::page_type &p = mem(paddr.val / mem.page_size); | ||||||
|         std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); |         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 |                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||||
|                                       << "), stopping simulation"; |                                       << "), 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; |                         this->interrupt_sim=hostvar; | ||||||
|                         break; |                         break; | ||||||
|                         //throw(iss::simulation_stopped(hostvar)); |                         //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; |         	enabled_interrupts >>= 1; | ||||||
|         	res++; |         	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) { | 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] |     // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] | ||||||
|     // calculate and write mcause val |     // 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 trap_id = bit_sub<0, 16>(flags); | ||||||
|     auto cause = bit_sub<16, 15>(flags); |     auto cause = bit_sub<16, 15>(flags); | ||||||
|     if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause |     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) |         if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||||
|             new_priv = PRIV_U; |             new_priv = PRIV_U; | ||||||
|         csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt |         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); |     size_t adr = ucause | (new_priv << 8); | ||||||
|     csr[adr] = (trap_id << (traits<BASE>::XLEN-1)) + cause; |     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]; |                        << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; | ||||||
|     // reset trap state |     // reset trap state | ||||||
|     this->reg.PRIV = new_priv; |     this->reg.PRIV = new_priv; | ||||||
|     this->trap_state = 0; |     this->reg.trap_state = 0; | ||||||
|     return this->reg.NEXT_PC; |     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; |     auto inst_priv = (flags & 0x3)? 3:0; | ||||||
|     if(inst_priv>cur_priv){ |     if(inst_priv>cur_priv){ | ||||||
|         auto trap_val =  0x80ULL << 24 | (2 << 16); // illegal instruction |         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(); |         this->reg.NEXT_PC = std::numeric_limits<uint32_t>::max(); | ||||||
|     } else { |     } else { | ||||||
|         auto status = state.mstatus; |         auto status = state.mstatus; | ||||||
|   | |||||||
| @@ -55,8 +55,8 @@ void tgc_c::reset(uint64_t address) { | |||||||
|     reg.PC=address; |     reg.PC=address; | ||||||
|     reg.NEXT_PC=reg.PC; |     reg.NEXT_PC=reg.PC; | ||||||
|     reg.PRIV=0x3; |     reg.PRIV=0x3; | ||||||
|     trap_state=0; |     reg.trap_state=0; | ||||||
|     icount=0; |     reg.icount=0; | ||||||
| } | } | ||||||
|  |  | ||||||
| uint8_t *tgc_c::get_regs_base_ptr() { | 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{ |     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"}}; |         {"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; |     constexpr static unsigned FP_REGS_SIZE = 0; | ||||||
|  |  | ||||||
| @@ -189,7 +189,7 @@ struct tgc_c: public arch_if { | |||||||
|  |  | ||||||
|     uint8_t* get_regs_base_ptr() override; |     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; } |     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; } |     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) | #pragma pack(push, 1) | ||||||
| @@ -256,12 +256,6 @@ struct tgc_c: public arch_if { | |||||||
|         uint32_t last_branch = 0; |         uint32_t last_branch = 0; | ||||||
|     } reg; |     } reg; | ||||||
| #pragma pack(pop) | #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; |     std::array<address_type, 4> addr_mode; | ||||||
|      |      | ||||||
|     uint64_t interrupt_sim=0; |     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") |         ("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load") | ||||||
|         ("mem,m", po::value<std::string>(), "the memory input file") |         ("mem,m", po::value<std::string>(), "the memory input file") | ||||||
|         ("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate") |         ("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"); |         ("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation"); | ||||||
|     // clang-format on |     // clang-format on | ||||||
|     auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); |     auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ public: | |||||||
|             std::stringstream s; |             std::stringstream s; | ||||||
|             s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') |             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:" |               << 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: " |             SCCDEBUG(owner->name())<<"disass: " | ||||||
|                 << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) |                 << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) | ||||||
|                 << std::setfill(' ') << std::left << instr << s.str(); |                 << std::setfill(' ') << std::left << instr << s.str(); | ||||||
| @@ -178,7 +178,7 @@ public: | |||||||
|  |  | ||||||
|     void wait_until(uint64_t flags) override { |     void wait_until(uint64_t flags) override { | ||||||
|         SCCDEBUG(owner->name()) << "Sleeping until interrupt"; |         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); |             sc_core::wait(wfi_evt); | ||||||
|         } |         } | ||||||
|         PLAT::wait_until(flags); |         PLAT::wait_until(flags); | ||||||
| @@ -207,7 +207,7 @@ public: | |||||||
|             this->csr[arch::mip] &= ~mask; |             this->csr[arch::mip] &= ~mask; | ||||||
|         this->check_interrupt(); |         this->check_interrupt(); | ||||||
|         if(value) |         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: | private: | ||||||
|   | |||||||
| @@ -115,7 +115,7 @@ protected: | |||||||
|  |  | ||||||
|     inline void raise(uint16_t trap_id, uint16_t cause){ |     inline void raise(uint16_t trap_id, uint16_t cause){ | ||||||
|         auto trap_val =  0x80ULL << 24 | (cause << 16) | trap_id; |         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(); |         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=start; | ||||||
|     auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); |     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* 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& trap_state = this->core.reg.trap_state; | ||||||
|     auto& icount = this->core.icount; |     auto& icount =  this->core.reg.icount; | ||||||
|     auto& cycle = this->core.cycle; |     auto& cycle =  this->core.reg.cycle; | ||||||
|     auto& instret = this->core.instret; |     auto& instret =  this->core.reg.instret; | ||||||
|     auto& instr = this->core.instruction; |     auto& instr =  this->core.reg.instruction; | ||||||
|     // we fetch at max 4 byte, alignment is 2 |     // we fetch at max 4 byte, alignment is 2 | ||||||
|     auto *const data = reinterpret_cast<uint8_t*>(&instr); |     auto *const data = reinterpret_cast<uint8_t*>(&instr); | ||||||
|  |  | ||||||
|     while(!this->core.should_stop() && |     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){ |         if(fetch_ins(pc, data)!=iss::Ok){ | ||||||
|             this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max()); |             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); |             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' |                     (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||||
|             auto inst_id = decode_inst_id(instr); |             auto inst_id = decode_inst_id(instr); | ||||||
|             // pre execution stuff |             // 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)); |             if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id)); | ||||||
|             switch(inst_id){ |             switch(inst_id){ | ||||||
|             case arch::traits<ARCH>::opcode_e::LUI: { |             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; |                                             *(X+rd) = *PC +  4; | ||||||
|                                         } |                                         } | ||||||
|                                         *NEXT_PC = *PC + (int32_t)sext<21>(imm); |                                         *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; |                                             *(X+rd) = *PC +  4; | ||||||
|                                         } |                                         } | ||||||
|                                         *NEXT_PC = new_pc & ~ 0x1; |                                         *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                         else { | ||||||
|                                             *NEXT_PC = *PC + (int16_t)sext<13>(imm); |                                             *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 { |                                 else { | ||||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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); |                                     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; |                                     int8_t res = (int8_t)read_res; | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = (uint32_t)res; |                                         *(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 { |                                 else { | ||||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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); |                                     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; |                                     int16_t res = (int16_t)read_res; | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = (uint32_t)res; |                                         *(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 { |                                 else { | ||||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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); |                                     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; |                                     int32_t res = (int32_t)read_res; | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = (uint32_t)res; |                                         *(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 { |                                 else { | ||||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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); |                                     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; |                                     uint8_t res = (uint8_t)read_res; | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = (uint32_t)res; |                                         *(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 { |                                 else { | ||||||
|                                     uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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); |                                     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; |                                     uint16_t res = (uint16_t)read_res; | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = (uint32_t)res; |                                         *(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 { |                                 else { | ||||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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)); |                                     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; |                 TRAP_SB:break; | ||||||
| @@ -865,7 +865,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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)); |                                     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; |                 TRAP_SH:break; | ||||||
| @@ -892,7 +892,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); |                                     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)); |                                     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; |                 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 |                 // execute instruction | ||||||
|                 { |                 { | ||||||
|                                 super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred <<  4 | succ); |                                 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; |                 TRAP_FENCE:break; | ||||||
|             }// @suppress("No break at end of case") |             }// @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); |                                     uint32_t xrs1 = *(X+rs1); | ||||||
|                                     if(rd !=  0) { |                                     if(rd !=  0) { | ||||||
|                                         uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                         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; |                                         uint32_t xrd = read_res; | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); |                                         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; |                                         *(X+rd) = xrd; | ||||||
|                                     } |                                     } | ||||||
|                                     else { |                                     else { | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); |                                         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 { |                                 else { | ||||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                     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 xrd = read_res; | ||||||
|                                     uint32_t xrs1 = *(X+rs1); |                                     uint32_t xrs1 = *(X+rs1); | ||||||
|                                     if(rs1 !=  0) { |                                     if(rs1 !=  0) { | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1); |                                         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) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = xrd; |                                         *(X+rd) = xrd; | ||||||
| @@ -1577,12 +1577,12 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 } |                                 } | ||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                     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 xrd = read_res; | ||||||
|                                     uint32_t xrs1 = *(X+rs1); |                                     uint32_t xrs1 = *(X+rs1); | ||||||
|                                     if(rs1 !=  0) { |                                     if(rs1 !=  0) { | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1); |                                         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) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = xrd; |                                         *(X+rd) = xrd; | ||||||
| @@ -1612,10 +1612,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 } |                                 } | ||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                     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; |                                     uint32_t xrd = read_res; | ||||||
|                                     super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm); |                                     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) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = xrd; |                                         *(X+rd) = xrd; | ||||||
|                                     } |                                     } | ||||||
| @@ -1644,11 +1644,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 } |                                 } | ||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                     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; |                                     uint32_t xrd = read_res; | ||||||
|                                     if(zimm !=  0) { |                                     if(zimm !=  0) { | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm); |                                         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) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = xrd; |                                         *(X+rd) = xrd; | ||||||
| @@ -1678,11 +1678,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 } |                                 } | ||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); |                                     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; |                                     uint32_t xrd = read_res; | ||||||
|                                     if(zimm !=  0) { |                                     if(zimm !=  0) { | ||||||
|                                         super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); |                                         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) { |                                     if(rd !=  0) { | ||||||
|                                         *(X+rd) = xrd; |                                         *(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 |                 // execute instruction | ||||||
|                 { |                 { | ||||||
|                                 super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm); |                                 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; |                 TRAP_FENCE_I:break; | ||||||
|             }// @suppress("No break at end of case") |             }// @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; |                     uint32_t load_address = *(X+rs1 +  8) + uimm; | ||||||
|                     int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address); |                     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; |                     *(X+rd +  8) = (int32_t)read_res; | ||||||
|                 } |                 } | ||||||
|                 TRAP_CLW:break; |                 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; |                     uint32_t load_address = *(X+rs1 +  8) + uimm; | ||||||
|                     super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 +  8)); |                     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; |                 TRAP_CSW:break; | ||||||
|             }// @suppress("No break at end of case") |             }// @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; |                     *(X+1) = *PC +  2; | ||||||
|                     *NEXT_PC = *PC + (int16_t)sext<12>(imm); |                     *NEXT_PC = *PC + (int16_t)sext<12>(imm); | ||||||
|                     this->core.last_branch = 1; |                     this->core.reg.last_branch = 1; | ||||||
|                 } |                 } | ||||||
|                 TRAP_CJAL:break; |                 TRAP_CJAL:break; | ||||||
|             }// @suppress("No break at end of case") |             }// @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 |                 // execute instruction | ||||||
|                 { |                 { | ||||||
|                                 *NEXT_PC = *PC + (int16_t)sext<12>(imm); |                                 *NEXT_PC = *PC + (int16_t)sext<12>(imm); | ||||||
|                                 this->core.last_branch = 1; |                                 this->core.reg.last_branch = 1; | ||||||
|                             } |                             } | ||||||
|                 TRAP_CJ:break; |                 TRAP_CJ:break; | ||||||
|             }// @suppress("No break at end of case") |             }// @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) { |                                 if(*(X+rs1 +  8) ==  0) { | ||||||
|                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); |                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); | ||||||
|                                     this->core.last_branch = 1; |                                     this->core.reg.last_branch = 1; | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                 TRAP_CBEQZ:break; |                 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) { |                                 if(*(X+rs1 +  8) !=  0) { | ||||||
|                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); |                                     *NEXT_PC = *PC + (int16_t)sext<9>(imm); | ||||||
|                                     this->core.last_branch = 1; |                                     this->core.reg.last_branch = 1; | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                 TRAP_CBNEZ:break; |                 TRAP_CBNEZ:break; | ||||||
| @@ -2436,7 +2436,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                     } |                     } | ||||||
|                     else { |                     else { | ||||||
|                         int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm); |                         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; |                         int32_t res = read_res; | ||||||
|                         *(X+rd) = (int32_t)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) { |                                 if(rs1 && rs1 < traits::RFS) { | ||||||
|                                     *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; |                                     *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; | ||||||
|                                     this->core.last_branch = 1; |                                     this->core.reg.last_branch = 1; | ||||||
|                                 } |                                 } | ||||||
|                                 else { |                                 else { | ||||||
|                                     raise(0, 2); |                                     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); |                                     uint32_t new_pc = *(X+rs1); | ||||||
|                                     *(X+1) = *PC +  2; |                                     *(X+1) = *PC +  2; | ||||||
|                                     *NEXT_PC = new_pc & ~ 0x1; |                                     *NEXT_PC = new_pc & ~ 0x1; | ||||||
|                                     this->core.last_branch = 1; |                                     this->core.reg.last_branch = 1; | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                 TRAP_CJALR:break; |                 TRAP_CJALR:break; | ||||||
| @@ -2592,7 +2592,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|                                 else { |                                 else { | ||||||
|                                     uint32_t offs = *(X+2) + uimm; |                                     uint32_t offs = *(X+2) + uimm; | ||||||
|                                     super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2)); |                                     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; |                 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 |             // post execution stuff | ||||||
|             process_spawn_blocks(); |             process_spawn_blocks(); | ||||||
|             if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); |             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 |             // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt | ||||||
|             //    this->core.trap_state = this->core.pending_trap; |             //    this->core.reg.trap_state =  this->core.reg.pending_trap; | ||||||
|             // trap check |             // trap check | ||||||
|             if(trap_state!=0){ |             if(trap_state!=0){ | ||||||
|                 super::core.enter_trap(trap_state, pc.val, instr); |                 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++; |             cycle++; | ||||||
|             pc.val=*NEXT_PC; |             pc.val=*NEXT_PC; | ||||||
|             this->core.reg.PC = this->core.reg.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; |     return pc; | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user