fix detailed behavior of TGC_C

This commit is contained in:
Eyck Jentzsch 2021-07-06 21:19:36 +02:00
parent 23b9741adf
commit 2f4b5bd9b2
6 changed files with 76 additions and 43 deletions

@ -1 +1 @@
Subproject commit 0c70a41376fb3a529e4f56a9b9d7167c9613958e
Subproject commit 98cddb2999bfc05862a796b157500f7cd0f36ca4

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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