|
|
|
@ -27,7 +27,7 @@ processor_t::processor_t(const char* isa, const char* priv, const char* varch, |
|
|
|
: debug(false), halt_request(HR_NONE), sim(sim), ext(NULL), id(id), xlen(0), |
|
|
|
histogram_enabled(false), log_commits_enabled(false), |
|
|
|
log_file(log_file), halt_on_reset(halt_on_reset), |
|
|
|
extension_table(256, false), last_pc(1), executions(1) |
|
|
|
extension_table(256, false), impl_table(256, false), last_pc(1), executions(1) |
|
|
|
{ |
|
|
|
VU.p = this; |
|
|
|
|
|
|
|
@ -45,6 +45,12 @@ processor_t::processor_t(const char* isa, const char* priv, const char* varch, |
|
|
|
|
|
|
|
set_pmp_granularity(1 << PMP_SHIFT); |
|
|
|
set_pmp_num(state.max_pmp); |
|
|
|
|
|
|
|
if (max_xlen == 32) |
|
|
|
set_mmu_capability(IMPL_MMU_SV32); |
|
|
|
else if (max_xlen == 64) |
|
|
|
set_mmu_capability(IMPL_MMU_SV48); |
|
|
|
|
|
|
|
reset(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -502,6 +508,31 @@ void processor_t::set_pmp_granularity(reg_t gran) { |
|
|
|
lg_pmp_granularity = ctz(gran); |
|
|
|
} |
|
|
|
|
|
|
|
void processor_t::set_mmu_capability(int cap) |
|
|
|
{ |
|
|
|
switch (cap) { |
|
|
|
case IMPL_MMU_SV32: |
|
|
|
set_impl(cap, true); |
|
|
|
set_impl(IMPL_MMU, true); |
|
|
|
break; |
|
|
|
case IMPL_MMU_SV39: |
|
|
|
set_impl(cap, true); |
|
|
|
set_impl(IMPL_MMU, true); |
|
|
|
break; |
|
|
|
case IMPL_MMU_SV48: |
|
|
|
set_impl(cap, true); |
|
|
|
set_impl(IMPL_MMU_SV39, true); |
|
|
|
set_impl(IMPL_MMU, true); |
|
|
|
break; |
|
|
|
default: |
|
|
|
set_impl(IMPL_MMU_SV32, false); |
|
|
|
set_impl(IMPL_MMU_SV39, false); |
|
|
|
set_impl(IMPL_MMU_SV48, false); |
|
|
|
set_impl(IMPL_MMU, false); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void processor_t::take_interrupt(reg_t pending_interrupts) |
|
|
|
{ |
|
|
|
reg_t enabled_interrupts, deleg, status, mie, m_enabled; |
|
|
|
@ -774,6 +805,39 @@ int processor_t::paddr_bits() |
|
|
|
return max_xlen == 64 ? 50 : 34; |
|
|
|
} |
|
|
|
|
|
|
|
reg_t processor_t::cal_satp(reg_t val) const |
|
|
|
{ |
|
|
|
reg_t reg_val = 0; |
|
|
|
reg_t rv64_ppn_mask = (reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1; |
|
|
|
mmu->flush_tlb(); |
|
|
|
if (max_xlen == 32) { |
|
|
|
reg_val = val & (SATP32_PPN | |
|
|
|
(supports_impl(IMPL_MMU_SV32) ? SATP32_MODE : 0)); |
|
|
|
} |
|
|
|
|
|
|
|
if (max_xlen == 64 && (get_field(val, SATP64_MODE) == SATP_MODE_OFF || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV39 || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV48)) { |
|
|
|
reg_val = val & (SATP64_PPN | rv64_ppn_mask); |
|
|
|
reg_t mode = get_field(val, SATP64_MODE); |
|
|
|
|
|
|
|
switch(mode) { |
|
|
|
case SATP_MODE_OFF: |
|
|
|
default: |
|
|
|
mode = SATP_MODE_OFF; |
|
|
|
break; |
|
|
|
case SATP_MODE_SV39: |
|
|
|
mode = supports_impl(IMPL_MMU_SV39) ? SATP_MODE_SV39 : SATP_MODE_OFF; |
|
|
|
break; |
|
|
|
case SATP_MODE_SV48: |
|
|
|
mode = supports_impl(IMPL_MMU_SV48) ? SATP_MODE_SV48 : SATP_MODE_OFF; |
|
|
|
break; |
|
|
|
} |
|
|
|
reg_val = set_field(reg_val, SATP64_MODE, mode); |
|
|
|
} |
|
|
|
|
|
|
|
return reg_val; |
|
|
|
} |
|
|
|
void processor_t::set_csr(int which, reg_t val) |
|
|
|
{ |
|
|
|
#if defined(RISCV_ENABLE_COMMITLOG) |
|
|
|
@ -847,8 +911,11 @@ void processor_t::set_csr(int which, reg_t val) |
|
|
|
VU.vxrm = (val & VCSR_VXRM) >> VCSR_VXRM_SHIFT; |
|
|
|
break; |
|
|
|
case CSR_MSTATUS: { |
|
|
|
bool has_page = supports_extension('S') && supports_impl(IMPL_MMU); |
|
|
|
if ((val ^ state.mstatus) & |
|
|
|
(MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR)) |
|
|
|
(MSTATUS_MPP | MSTATUS_MPRV |
|
|
|
| (has_page ? (MSTATUS_MXR | MSTATUS_SUM) : 0) |
|
|
|
| MSTATUS_MXR)) |
|
|
|
mmu->flush_tlb(); |
|
|
|
|
|
|
|
bool has_fs = supports_extension('S') || supports_extension('F') |
|
|
|
@ -858,8 +925,9 @@ void processor_t::set_csr(int which, reg_t val) |
|
|
|
bool has_gva = has_mpv; |
|
|
|
|
|
|
|
reg_t mask = MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPRV |
|
|
|
| (supports_extension('S') ? (MSTATUS_SUM | MSTATUS_SIE | MSTATUS_SPIE) : 0) |
|
|
|
| MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM | MSTATUS_TSR |
|
|
|
| (supports_extension('S') ? (MSTATUS_SIE | MSTATUS_SPIE) : 0) |
|
|
|
| MSTATUS_TW | MSTATUS_TSR |
|
|
|
| (has_page ? (MSTATUS_MXR | MSTATUS_SUM | MSTATUS_TVM) : 0) |
|
|
|
| (has_fs ? MSTATUS_FS : 0) |
|
|
|
| (has_vs ? MSTATUS_VS : 0) |
|
|
|
| (ext ? MSTATUS_XS : 0) |
|
|
|
@ -970,22 +1038,15 @@ void processor_t::set_csr(int which, reg_t val) |
|
|
|
state.mie = (state.mie & ~mask) | (val & mask); |
|
|
|
break; |
|
|
|
} |
|
|
|
case CSR_SATP: { |
|
|
|
reg_t reg_val = 0; |
|
|
|
reg_t rv64_ppn_mask = (reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1; |
|
|
|
mmu->flush_tlb(); |
|
|
|
if (max_xlen == 32) |
|
|
|
reg_val = val & (SATP32_PPN | SATP32_MODE); |
|
|
|
if (max_xlen == 64 && (get_field(val, SATP64_MODE) == SATP_MODE_OFF || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV39 || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV48)) |
|
|
|
reg_val = val & (SATP64_MODE | (SATP64_PPN & rv64_ppn_mask)); |
|
|
|
case CSR_SATP: |
|
|
|
if (!supports_impl(IMPL_MMU)) |
|
|
|
val = 0; |
|
|
|
|
|
|
|
if (state.v) |
|
|
|
state.vsatp = reg_val; |
|
|
|
state.vsatp = cal_satp(val); |
|
|
|
else |
|
|
|
state.satp = reg_val; |
|
|
|
state.satp = cal_satp(val); |
|
|
|
break; |
|
|
|
} |
|
|
|
case CSR_SEPC: |
|
|
|
if (state.v) |
|
|
|
state.vsepc = val & ~(reg_t)1; |
|
|
|
@ -1052,8 +1113,9 @@ void processor_t::set_csr(int which, reg_t val) |
|
|
|
break; |
|
|
|
} |
|
|
|
case CSR_HSTATUS: { |
|
|
|
reg_t mask = HSTATUS_VTSR | HSTATUS_VTW | HSTATUS_VTVM | |
|
|
|
HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; |
|
|
|
reg_t mask = HSTATUS_VTSR | HSTATUS_VTW |
|
|
|
| (supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0) |
|
|
|
| HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; |
|
|
|
state.hstatus = (state.hstatus & ~mask) | (val & mask); |
|
|
|
break; |
|
|
|
} |
|
|
|
@ -1140,19 +1202,12 @@ void processor_t::set_csr(int which, reg_t val) |
|
|
|
state.mip = (state.mip & ~mask) | ((val << 1) & mask); |
|
|
|
break; |
|
|
|
} |
|
|
|
case CSR_VSATP: { |
|
|
|
reg_t reg_val = 0; |
|
|
|
reg_t rv64_ppn_mask = (reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1; |
|
|
|
mmu->flush_tlb(); |
|
|
|
if (max_xlen == 32) |
|
|
|
reg_val = val & (SATP32_PPN | SATP32_MODE); |
|
|
|
if (max_xlen == 64 && (get_field(val, SATP64_MODE) == SATP_MODE_OFF || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV39 || |
|
|
|
get_field(val, SATP64_MODE) == SATP_MODE_SV48)) |
|
|
|
reg_val = val & (SATP64_MODE | (SATP64_PPN & rv64_ppn_mask)); |
|
|
|
state.vsatp = reg_val; |
|
|
|
case CSR_VSATP: |
|
|
|
if (!supports_impl(IMPL_MMU)) |
|
|
|
val = 0; |
|
|
|
|
|
|
|
state.vsatp = cal_satp(val); |
|
|
|
break; |
|
|
|
} |
|
|
|
case CSR_TSELECT: |
|
|
|
if (val < state.num_triggers) { |
|
|
|
state.tselect = val; |
|
|
|
|