Skip to content

Commit

Permalink
fix(dbltrp): align logic of sdt with xiangshan
Browse files Browse the repository at this point in the history
  * align vsstatus.sdt/henvcfg.DTE interaction logic with xiangshan
    * as vsstatus is not aliase of otther CSR fields and SDT is controlled
      by henvcfg.DTE. According to the manual, when the read/write property
      of **sdt** changes from **RO** to **RW**, its immediate value becomes
      **UNSPECIFIED** but valid. XiangShan adopts the simplest hardware
      implementation, allowing **vsstatus.sdt** to be written when **DTE**
      is disabled, while reads are masked by **DTE**. In contrast, Spike
      employs a design where both reads and writes are masked. To align the
      behavior of **vsstatus.sdt** in Spike with XiangShan during comparison,
      we adjust Spike's write behavior under **DTE**-disabled conditions to match XiangShan's.
  * add mstatus.sdt/sie, mstatus.mdt/mie missing interatcion logic.
    when sdt/mdt write 1, sie/mie will clear.
  • Loading branch information
lewislzh authored and huxuan0307 committed Nov 28, 2024
1 parent 5c1faa6 commit ad9bf36
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions riscv/csrs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,21 @@ vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):

bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
const reg_t hDTE = (state->henvcfg->read() & HENVCFG_DTE);
const reg_t adj_write_mask = sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT);
const reg_t adj_write_mask =
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
sstatus_write_mask;
#else
sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT);
#endif
reg_t newval = (this->val & ~adj_write_mask) | (val & adj_write_mask);
bool write_sdt =
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
newval & SSTATUS_SDT && hDTE;
#else
(newval & SSTATUS_SDT);
#endif

newval = (newval & SSTATUS_SDT) ? (newval & ~SSTATUS_SIE) : newval;
newval = (write_sdt) ? (newval & ~SSTATUS_SIE) : newval;

if (state->v) maybe_flush_tlb(newval);
this->val = adjust_sd(newval);
Expand All @@ -527,9 +538,7 @@ bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
const reg_t mDTE = (state->menvcfg->read() & MENVCFG_DTE);
const reg_t adj_write_mask = sstatus_write_mask & ~(mDTE ? 0 : SSTATUS_SDT);
reg_t new_mstatus = (mstatus->read() & ~adj_write_mask) | (val & adj_write_mask);

new_mstatus = (new_mstatus & SSTATUS_SDT) ? (new_mstatus & ~SSTATUS_SIE) : new_mstatus;

// On RV32 this will only log the low 32 bits, so make sure we're
// not modifying anything in the upper 32 bits.
assert((adj_write_mask & 0xffffffffU) == adj_write_mask);
Expand Down Expand Up @@ -580,9 +589,8 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
new_mstatus ^= new_mstatus & (0x3 << 13); // FS is always zero
#else
reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
if (new_mstatus & MSTATUS_MDT) {
new_mstatus = new_mstatus & ~MSTATUS_MIE;
}
new_mstatus = (new_mstatus & MSTATUS_MDT) ? (new_mstatus & ~MSTATUS_MIE) : new_mstatus;
new_mstatus = (new_mstatus & MSTATUS_SDT) ? (new_mstatus & ~MSTATUS_SIE) : new_mstatus;
#endif
maybe_flush_tlb(new_mstatus);
this->val = adjust_sd(new_mstatus);
Expand Down

0 comments on commit ad9bf36

Please sign in to comment.