fix detailed behavior of TGC_C
This commit is contained in:
parent
23b9741adf
commit
2f4b5bd9b2
@ -1 +1 @@
|
||||
Subproject commit 0c70a41376fb3a529e4f56a9b9d7167c9613958e
|
||||
Subproject commit 98cddb2999bfc05862a796b157500f7cd0f36ca4
|
@ -152,16 +152,28 @@ public:
|
||||
mstatus = new_val;
|
||||
}
|
||||
|
||||
T satp;
|
||||
|
||||
static constexpr uint32_t get_mask() {
|
||||
return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 // only machine mode is supported
|
||||
//return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported
|
||||
// +-SD
|
||||
// | +-TSR
|
||||
// | |+-TW
|
||||
// | ||+-TVM
|
||||
// | |||+-MXR
|
||||
// | ||||+-SUM
|
||||
// | |||||+-MPRV
|
||||
// | |||||| +-XS
|
||||
// | |||||| | +-FS
|
||||
// | |||||| | | +-MPP
|
||||
// | |||||| | | | +-SPP
|
||||
// | |||||| | | | |+-MPIE
|
||||
// | ||||||/|/|/| || +-MIE
|
||||
return 0b00000000000000000001100010001000;
|
||||
}
|
||||
};
|
||||
using hart_state_type = hart_state<reg_t>;
|
||||
|
||||
constexpr reg_t get_irq_mask() {
|
||||
return 0b101110111011; // only machine mode is supported
|
||||
return 0b100010001000; // only machine mode is supported
|
||||
}
|
||||
|
||||
riscv_hart_m_p();
|
||||
@ -286,7 +298,12 @@ template <typename BASE>
|
||||
riscv_hart_m_p<BASE>::riscv_hart_m_p()
|
||||
: state()
|
||||
, instr_if(*this) {
|
||||
// reset values
|
||||
csr[misa] = traits<BASE>::MISA_VAL;
|
||||
csr[mvendorid] = 0x669;
|
||||
csr[marchid] = 0x80000003;
|
||||
csr[mimpid] = 1;
|
||||
|
||||
uart_buf.str("");
|
||||
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){
|
||||
csr_rd_cb[addr] = &this_class::read_null;
|
||||
@ -309,7 +326,7 @@ riscv_hart_m_p<BASE>::riscv_hart_m_p()
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
}
|
||||
// common regs
|
||||
const std::array<unsigned, 7> addrs{{misa, mepc, mtvec, mscratch, mcause, mtval, mscratch}};
|
||||
const std::array<unsigned, 10> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}};
|
||||
for(auto addr: addrs) {
|
||||
csr_rd_cb[addr] = &this_class::read_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_reg;
|
||||
@ -338,6 +355,9 @@ riscv_hart_m_p<BASE>::riscv_hart_m_p()
|
||||
csr_wr_cb[mcounteren] = &this_class::write_null;
|
||||
csr_rd_cb[mtvec] = &this_class::read_mtvec;
|
||||
csr_wr_cb[misa] = &this_class::write_null;
|
||||
csr_wr_cb[mvendorid] = &this_class::write_null;
|
||||
csr_wr_cb[marchid] = &this_class::write_null;
|
||||
csr_wr_cb[mimpid] = &this_class::write_null;
|
||||
}
|
||||
|
||||
template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_file(std::string name, int type) {
|
||||
@ -406,13 +426,23 @@ iss::status riscv_hart_m_p<BASE>::read(const address_type type, const access_typ
|
||||
return iss::Err;
|
||||
}
|
||||
try {
|
||||
auto alignment = access == iss::access_type::FETCH? (traits<BASE>::MISA_VAL&0x100? 2 : 4) : length;
|
||||
if(alignment>1 && (addr&(alignment-1))){
|
||||
this->reg.trap_state = 1<<31 | 4<<16;
|
||||
fault_data=addr;
|
||||
return iss::Err;
|
||||
}
|
||||
auto res = type==iss::address_type::PHYSICAL?
|
||||
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
|
||||
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||
if (unlikely(res != iss::Ok)) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
if (unlikely(res != iss::Ok)){
|
||||
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
fault_data=addr;
|
||||
}
|
||||
return res;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
fault_data=ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
} break;
|
||||
@ -438,6 +468,7 @@ iss::status riscv_hart_m_p<BASE>::read(const address_type type, const access_typ
|
||||
return iss::Ok;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
fault_data=ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
}
|
||||
@ -478,14 +509,22 @@ iss::status riscv_hart_m_p<BASE>::write(const address_type type, const access_ty
|
||||
return iss::Err;
|
||||
}
|
||||
try {
|
||||
if(length>1 && (addr&(length-1))){
|
||||
this->reg.trap_state = 1<<31 | 6<<16;
|
||||
fault_data=addr;
|
||||
return iss::Err;
|
||||
}
|
||||
auto res = type==iss::address_type::PHYSICAL?
|
||||
write_mem(phys_addr_t{access, space, addr}, length, data):
|
||||
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
|
||||
if (unlikely(res != iss::Ok))
|
||||
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
|
||||
if (unlikely(res != iss::Ok)) {
|
||||
this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||
fault_data=addr;
|
||||
}
|
||||
return res;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
fault_data=ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
|
||||
@ -545,6 +584,7 @@ iss::status riscv_hart_m_p<BASE>::write(const address_type type, const access_ty
|
||||
return iss::Ok;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
fault_data=ta.addr;
|
||||
return iss::Err;
|
||||
}
|
||||
}
|
||||
@ -670,7 +710,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_status(unsigned
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_ie(unsigned addr, reg_t &val) {
|
||||
val = csr[mie];
|
||||
val &= csr[mideleg];
|
||||
//val &= csr[mideleg];
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
@ -688,7 +728,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_ie(unsigned add
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_ip(unsigned addr, reg_t &val) {
|
||||
val = csr[mip];
|
||||
val &= csr[mideleg];
|
||||
//val &= csr[mideleg];
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
@ -727,7 +767,6 @@ iss::status riscv_hart_m_p<BASE>::read_mem(phys_addr_t paddr, unsigned length, u
|
||||
|
||||
template <typename BASE>
|
||||
iss::status riscv_hart_m_p<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||
if ((paddr.val + length) > mem.size()) return iss::Err;
|
||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
||||
switch (paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
@ -808,7 +847,7 @@ template <typename BASE> inline void riscv_hart_m_p<BASE>::reset(uint64_t addres
|
||||
}
|
||||
|
||||
template <typename BASE> void riscv_hart_m_p<BASE>::check_interrupt() {
|
||||
auto ideleg = csr[mideleg];
|
||||
//auto ideleg = csr[mideleg];
|
||||
// Multiple simultaneous interrupts and traps at the same privilege level are
|
||||
// handled in the following decreasing priority order:
|
||||
// external interrupts, software interrupts, timer interrupts, then finally
|
||||
@ -817,7 +856,7 @@ template <typename BASE> void riscv_hart_m_p<BASE>::check_interrupt() {
|
||||
|
||||
bool mie = state.mstatus.MIE;
|
||||
auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie);
|
||||
auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
|
||||
auto enabled_interrupts = m_enabled ? ena_irq /*& ~ideleg*/ : 0;
|
||||
|
||||
if (enabled_interrupts != 0) {
|
||||
int res = 0;
|
||||
@ -839,7 +878,7 @@ template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flag
|
||||
if (trap_id == 0) { // exception
|
||||
// store ret addr in xepc register
|
||||
csr[mepc] = static_cast<reg_t>(addr); // store actual address instruction of exception
|
||||
csr[mtval] = cause==2?instr:fault_data;
|
||||
csr[mtval] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data;
|
||||
fault_data = 0;
|
||||
} else {
|
||||
csr[mepc] = this->reg.NEXT_PC; // store next address if interrupt
|
||||
@ -877,9 +916,11 @@ template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flag
|
||||
|
||||
template <typename BASE> uint64_t riscv_hart_m_p<BASE>::leave_trap(uint64_t flags) {
|
||||
state.mstatus.MIE = state.mstatus.MPIE;
|
||||
state.mstatus.MPIE = 1;
|
||||
// sets the pc to the value stored in the x epc register.
|
||||
this->reg.NEXT_PC = csr[mepc];
|
||||
CLOG(INFO, disass) << "Executing xRET";
|
||||
check_interrupt();
|
||||
return this->reg.NEXT_PC;
|
||||
}
|
||||
|
||||
|
@ -1228,15 +1228,18 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
|
||||
this->reg.PRIV = state.mstatus.MPP;
|
||||
state.mstatus.MPP = 0; // clear mpp to U mode
|
||||
state.mstatus.MIE = state.mstatus.MPIE;
|
||||
state.mstatus.MPIE = 1;
|
||||
break;
|
||||
case PRIV_S:
|
||||
this->reg.PRIV = state.mstatus.SPP;
|
||||
state.mstatus.SPP = 0; // clear spp to U mode
|
||||
state.mstatus.SIE = state.mstatus.SPIE;
|
||||
state.mstatus.SPIE = 1;
|
||||
break;
|
||||
case PRIV_U:
|
||||
this->reg.PRIV = 0;
|
||||
state.mstatus.UIE = state.mstatus.UPIE;
|
||||
state.mstatus.UPIE = 1;
|
||||
break;
|
||||
}
|
||||
// sets the pc to the value stored in the x epc register.
|
||||
@ -1244,6 +1247,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t f
|
||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
|
||||
<< lvl[this->reg.PRIV];
|
||||
update_vm_info();
|
||||
check_interrupt();
|
||||
return this->reg.NEXT_PC;
|
||||
}
|
||||
|
||||
|
@ -870,16 +870,19 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||
this->reg.PRIV = state.mstatus.MPP;
|
||||
state.mstatus.MPP = 0; // clear mpp to U mode
|
||||
state.mstatus.MIE = state.mstatus.MPIE;
|
||||
state.mstatus.MPIE = 1;
|
||||
break;
|
||||
case PRIV_U:
|
||||
this->reg.PRIV = 0;
|
||||
state.mstatus.UIE = state.mstatus.UPIE;
|
||||
state.mstatus.UPIE = 1;
|
||||
break;
|
||||
}
|
||||
// sets the pc to the value stored in the x epc register.
|
||||
this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
|
||||
CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to "
|
||||
<< lvl[this->reg.PRIV];
|
||||
check_interrupt();
|
||||
return this->reg.NEXT_PC;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ template <> struct traits<tgc_c> {
|
||||
static constexpr std::array<const char*, 35> reg_aliases{
|
||||
{"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV"}};
|
||||
|
||||
enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b01000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, eei_aligned_addresses=1, MUL_LEN=64};
|
||||
enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b01000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64};
|
||||
|
||||
constexpr static unsigned FP_REGS_SIZE = 0;
|
||||
|
||||
|
@ -875,11 +875,8 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||
if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4);
|
||||
else {
|
||||
int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = res;
|
||||
}
|
||||
int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = res;
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -923,11 +920,8 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4);
|
||||
else {
|
||||
int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = (uint32_t)res;
|
||||
}
|
||||
int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = (uint32_t)res;
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -1015,11 +1009,8 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||
if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4);
|
||||
else {
|
||||
uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = res;
|
||||
}
|
||||
uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm));
|
||||
if(rd != 0) *(X+rd) = res;
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -1104,8 +1095,7 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||
if(traits::eei_aligned_addresses && (store_address & 0x1)) raise(0, 6);
|
||||
else writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2));
|
||||
writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2));
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -1149,8 +1139,7 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm);
|
||||
if(traits::eei_aligned_addresses && (store_address & 0x3)) raise(0, 6);
|
||||
else writeSpace4(traits::MEM, store_address, *(X+rs2));
|
||||
writeSpace4(traits::MEM, store_address, *(X+rs2));
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -2929,8 +2918,7 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t load_address = *(X+(rs1 + 8)) + uimm;
|
||||
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4);
|
||||
else *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address);
|
||||
*(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address);
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -2974,8 +2962,7 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t load_address = *(X+(rs1 + 8)) + uimm;
|
||||
if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 6);
|
||||
else writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8)));
|
||||
writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8)));
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
@ -3759,8 +3746,7 @@ private:
|
||||
try {
|
||||
if(rd) {
|
||||
uint32_t offs = *(X+2) + uimm;
|
||||
if(traits::eei_aligned_addresses && (offs & 0x3)) raise(0, 4);
|
||||
else *(X+rd) = (int32_t)readSpace4(traits::MEM, offs);
|
||||
*(X+rd) = (int32_t)readSpace4(traits::MEM, offs);
|
||||
}
|
||||
else raise(0, 2);
|
||||
} catch(...){}
|
||||
@ -4035,8 +4021,7 @@ private:
|
||||
try {
|
||||
{
|
||||
uint32_t offs = *(X+2) + uimm;
|
||||
if(traits::eei_aligned_addresses && (offs & 0x3)) raise(0, 4);
|
||||
else writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2));
|
||||
writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2));
|
||||
}
|
||||
} catch(...){}
|
||||
// post execution stuff
|
||||
|
Loading…
Reference in New Issue
Block a user