Skip to content

Commit 0eb41dc

Browse files
committed
fixes pmp and clic implementation to match HW
1 parent c28db29 commit 0eb41dc

File tree

6 files changed

+96
-29
lines changed

6 files changed

+96
-29
lines changed

src/iss/arch/riscv_hart_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ template <typename WORD_TYPE> struct priv_if {
295295

296296
std::function<iss::status(unsigned, WORD_TYPE&)> read_csr;
297297
std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
298+
std::function<WORD_TYPE(unsigned)> get_csr;
299+
std::function<void(unsigned, WORD_TYPE)> set_csr;
298300
std::function<iss::status(uint8_t const*, unsigned)> exec_htif;
299301
std::function<void(uint16_t, uint16_t, WORD_TYPE)> raise_trap; // trap_id, cause, fault_data
300302
std::unordered_map<unsigned, rd_csr_f>& csr_rd_cb;
@@ -941,6 +943,8 @@ template <typename BASE = logging::disass> struct riscv_hart_common : public BAS
941943
return priv_if<reg_t>{
942944
.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); },
943945
.write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); },
946+
.get_csr = [this](unsigned addr) -> reg_t { return csr.at(addr); },
947+
.set_csr = [this](unsigned addr, reg_t val) -> void { csr.at(addr)=val;},
944948
.exec_htif = [this](uint8_t const* data, unsigned length) -> iss::status { return execute_htif(data, length); },
945949
.raise_trap =
946950
[this](uint16_t trap_id, uint16_t cause, reg_t fault_data) {

src/iss/arch/riscv_hart_m_p.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const addr_t& a, const unsigned len
151151
case traits<BASE>::fence:
152152
case traits<BASE>::fencei:
153153
break;
154-
case traits<BASE>::fencevma: {
155-
this->reg.trap_state = (1UL << 31) | traits<BASE>::RV_CAUSE_ILLEGAL_INSTRUCTION << 16;
156-
}
157154
default:
158155
return iss::Ok;
159156
}
@@ -250,9 +247,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const addr_t& a, const unsigned le
250247
case traits<BASE>::fence:
251248
case traits<BASE>::fencei:
252249
break;
253-
case traits<BASE>::fencevma: {
254-
this->reg.trap_state = (1UL << 31) | traits<BASE>::RV_CAUSE_ILLEGAL_INSTRUCTION << 16;
255-
}
256250
default:
257251
return iss::Ok;
258252
}

src/iss/arch/riscv_hart_msu_vp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
100100
uint64_t leave_trap(uint64_t flags) override;
101101
void wait_until(uint64_t flags) override;
102102

103-
void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; }
103+
void set_csr(unsigned addr, reg_t val) { this->csr[addr] = val; }
104104

105105
protected:
106106
using mem_read_f = iss::status(iss::phys_addr_t addr, unsigned, uint8_t* const);

src/iss/arch/riscv_hart_mu_p.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : pu
9090
uint64_t leave_trap(uint64_t flags) override;
9191
void wait_until(uint64_t flags) override;
9292

93-
void set_csr(unsigned addr, reg_t val) { this->csr[addr & this->csr.page_addr_mask] = val; }
93+
void set_csr(unsigned addr, reg_t val) { this->csr[addr] = val; }
9494

9595
protected:
9696
using mem_read_f = iss::status(iss::phys_addr_t addr, unsigned, uint8_t* const);
@@ -103,6 +103,9 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : pu
103103
iss::status read_ie(unsigned addr, reg_t& val);
104104
iss::status write_ie(unsigned addr, reg_t val);
105105
iss::status read_ip(unsigned addr, reg_t& val);
106+
iss::status write_ideleg(unsigned addr, reg_t val);
107+
iss::status write_edeleg(unsigned addr, uint32_t val);
108+
iss::status write_edeleg(unsigned addr, uint64_t val);
106109

107110
void check_interrupt();
108111
mem::neumann_memory_with_htif<BASE> default_mem;
@@ -131,13 +134,17 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p()
131134
this->csr_wr_cb[ustatus] = MK_CSR_WR_CB(write_status);
132135
this->csr_rd_cb[ucause] = MK_CSR_RD_CB(read_cause);
133136
this->csr_wr_cb[ucause] = MK_CSR_WR_CB(write_cause);
134-
this->csr_rd_cb[utvec] = MK_CSR_RD_CB(read_plain);
135137
this->csr_rd_cb[utvec] = MK_CSR_RD_CB(read_tvec);
138+
this->csr_wr_cb[utvec] = MK_CSR_WR_CB(write_plain);
136139
this->csr_rd_cb[uscratch] = MK_CSR_RD_CB(read_plain);
137140
this->csr_wr_cb[uscratch] = MK_CSR_WR_CB(write_plain);
138141
this->csr_rd_cb[utval] = MK_CSR_RD_CB(read_plain);
139142
this->csr_wr_cb[utval] = MK_CSR_WR_CB(write_plain);
140143
this->csr[misa] |= extension_encoding::N;
144+
this->csr_rd_cb[mideleg] = MK_CSR_RD_CB(read_plain);
145+
this->csr_wr_cb[mideleg] = MK_CSR_WR_CB(write_ideleg);
146+
this->csr_rd_cb[medeleg] = MK_CSR_RD_CB(read_plain);
147+
this->csr_wr_cb[medeleg] = MK_CSR_WR_CB(write_edeleg);
141148
}
142149
if(FEAT & FEAT_DEBUG)
143150
this->add_debug_csrs();
@@ -180,9 +187,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const addr_t& a, const unsigned le
180187
case traits<BASE>::fence:
181188
case traits<BASE>::fencei:
182189
break;
183-
case traits<BASE>::fencevma: {
184-
this->reg.trap_state = (1UL << 31) | traits<BASE>::RV_CAUSE_ILLEGAL_INSTRUCTION << 16;
185-
}
186190
default:
187191
return iss::Ok;
188192
}
@@ -279,9 +283,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const addr_t& a, const unsigned l
279283
case traits<BASE>::fence:
280284
case traits<BASE>::fencei:
281285
break;
282-
case traits<BASE>::fencevma: {
283-
this->reg.trap_state = (1UL << 31) | traits<BASE>::RV_CAUSE_ILLEGAL_INSTRUCTION << 16;
284-
}
285286
default:
286287
return iss::Ok;
287288
}
@@ -358,6 +359,27 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
358359
return iss::Ok;
359360
}
360361

362+
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_ideleg(unsigned addr, reg_t val) {
363+
// only U and S mode interrupts can be delegated
364+
auto mask = 0b0001'0001'0001;
365+
this->csr[mideleg] = (this->csr[mideleg] & ~mask) | (val & mask);
366+
return iss::Ok;
367+
}
368+
369+
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_edeleg(unsigned addr, uint32_t val) {
370+
// we mask according to privilege spec: bit 3 (break), bit 10 (reserved), bit 11 (Ecall from M) bit 14 (reserved)
371+
uint32_t mask = 0b0000'0000'0000'0000'1011'0011'1111'0111;
372+
this->csr[arch::riscv_csr::medeleg] = (this->csr[arch::riscv_csr::medeleg] & ~mask) | (val & mask);
373+
return iss::Ok;
374+
}
375+
376+
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_edeleg(unsigned addr, uint64_t val) {
377+
// we mask according to privilege spec: bit 3 (break), bit 10 (reserved), bit 11 (Ecall from M) bit 14 (reserved)
378+
uint64_t mask = 0b0000'0000'0000'0000'1011'0011'1111'0111;
379+
this->csr[arch::riscv_csr::medeleg] = (this->csr[arch::riscv_csr::medeleg] & ~mask) | (val & mask);
380+
return iss::Ok;
381+
}
382+
361383
template <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT>::reset(uint64_t address) {
362384
BASE::reset(address);
363385
this->state.mstatus = hart_state<reg_t>::mstatus_reset_val;

src/iss/mem/clic.h

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,21 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
102102
clic_cfg_reg = 0x30;
103103
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
104104
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
105-
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_xtvt); // 0x307
105+
hart_if.csr_rd_cb[arch::mcause] = MK_CSR_RD_CB(read_cause);
106+
hart_if.csr_wr_cb[arch::mcause] = MK_CSR_WR_CB(write_cause);
107+
hart_if.csr_rd_cb[arch::mtvec] = MK_CSR_RD_CB(read_xtvec);
108+
hart_if.csr_wr_cb[arch::mtvec] = MK_CSR_WR_CB(write_xtvec);
109+
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_xtvt);
106110
hart_if.csr_wr_cb[arch::mtvt] = MK_CSR_WR_CB(write_xtvt);
107-
// hart_if.csr_rd_cb[mxnti] = MK_CSR_RD_CB(read_plain(a,r);};
108-
// hart_if.csr_wr_cb[mxnti] = MK_CSR_WR_CB(write_plain(a,r);};
109111
hart_if.csr_rd_cb[arch::mintstatus] = MK_CSR_RD_CB(read_intstatus);
110112
hart_if.csr_wr_cb[arch::mintstatus] = MK_CSR_WR_CB(write_null);
111-
// hart_if.csr_rd_cb[mscratchcsw] = MK_CSR_RD_CB(read_plain(a,r);};
112-
// hart_if.csr_wr_cb[mscratchcsw] = MK_CSR_WR_CB(write_plain(a,r);};
113-
// hart_if.csr_rd_cb[mscratchcswl] = MK_CSR_RD_CB(read_plain(a,r);};
114-
// hart_if.csr_wr_cb[mscratchcswl] = MK_CSR_WR_CB(write_plain(a,r);};
115113
hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_intthresh);
116114
hart_if.csr_wr_cb[arch::mintthresh] = MK_CSR_WR_CB(write_intthresh);
117115
if(cfg.nmode) {
118-
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_xtvt); // 0x007
116+
hart_if.csr_rd_cb[arch::ucause] = MK_CSR_RD_CB(read_cause);
117+
hart_if.csr_wr_cb[arch::ucause] = MK_CSR_WR_CB(write_cause);
118+
hart_if.csr_rd_cb[arch::utvec] = MK_CSR_RD_CB(read_xtvec);
119+
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_xtvt);
119120
hart_if.csr_wr_cb[arch::utvt] = MK_CSR_WR_CB(write_xtvt);
120121
hart_if.csr_rd_cb[arch::uintstatus] = MK_CSR_RD_CB(read_intstatus);
121122
hart_if.csr_wr_cb[arch::uintstatus] = MK_CSR_WR_CB(write_null);
@@ -139,13 +140,15 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
139140

140141
private:
141142
iss::status read_mem(addr_t const& addr, unsigned length, uint8_t* data) {
142-
if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000))
143+
auto end_addr = addr.val - 1 + length;
144+
if(addr.space == 0 && addr.val<=end_addr && addr.val >= cfg.clic_base && end_addr <= (cfg.clic_base + 0x7fff))
143145
return read_clic(addr.val, length, data);
144146
return down_stream_mem.rd_mem(addr, length, data);
145147
}
146148

147149
iss::status write_mem(addr_t const& addr, unsigned length, uint8_t const* data) {
148-
if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000))
150+
auto end_addr = addr.val - 1 + length;
151+
if(addr.space == 0 && addr.val<=end_addr && addr.val >= cfg.clic_base && end_addr <= (cfg.clic_base + 0x7fff))
149152
return write_clic(addr.val, length, data);
150153
return down_stream_mem.wr_mem(addr, length, data);
151154
}
@@ -184,6 +187,50 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
184187
return iss::Ok;
185188
}
186189

190+
iss::status read_xtvec(unsigned addr, reg_t& val) {
191+
val = hart_if.get_csr(addr);
192+
return iss::Ok;
193+
}
194+
195+
iss::status write_xtvec(unsigned addr, reg_t val) {
196+
hart_if.set_csr(addr, val);
197+
if((val & 0x3) != 0x3) {
198+
clic_mprev_lvl = 0xff>>cfg.clic_int_ctl_bits;
199+
clic_uprev_lvl = 0xff>>cfg.clic_int_ctl_bits;
200+
}
201+
return iss::Ok;
202+
}
203+
204+
iss::status read_cause(unsigned addr, reg_t& val) {
205+
val = hart_if.get_csr(addr) & ((1UL << (WORD_LEN - 1)) | (hart_if.max_irq - 1));
206+
auto xtvec = hart_if.get_csr(arch::mtvec);
207+
if((xtvec& 0x3) == 0x3) {
208+
if(addr == arch::mcause) { //mcause access
209+
val |= hart_if.state.mstatus.MPP<<28 | hart_if.state.mstatus.MPIE<<27 |clic_mprev_lvl<<16;
210+
} else if(addr ==arch::ucause) {
211+
val |= hart_if.state.mstatus.UPIE<<27 | clic_uprev_lvl<<16;
212+
}
213+
}
214+
return iss::Ok;
215+
}
216+
217+
iss::status write_cause(unsigned addr, reg_t val) {
218+
auto mask = ((1UL << (WORD_LEN - 1)) | (hart_if.max_irq - 1));
219+
hart_if.set_csr(addr,(val & mask) | (hart_if.get_csr(addr) & ~mask));
220+
auto xtvec = hart_if.get_csr(arch::mtvec);
221+
if((xtvec & 0x3) == 0x3) {
222+
if(addr == arch::mcause){ //mcause access
223+
hart_if.state.mstatus.MPIE = (val>>27)&1;
224+
clic_mprev_lvl = ((val >> 16) & 0xff) | 0xff>>cfg.clic_int_ctl_bits;
225+
hart_if.state.mstatus.MPP = (val <<28)&0x3;
226+
} else if(addr ==arch::ucause) {
227+
hart_if.state.mstatus.UPIE = (val>>27)&1;
228+
clic_uprev_lvl = ((val >> 16) & 0xff) | 0xff>>cfg.clic_int_ctl_bits;
229+
}
230+
}
231+
return iss::Ok;
232+
}
233+
187234
protected:
188235
arch::priv_if<WORD_TYPE> hart_if;
189236
memory_if down_stream_mem;
@@ -202,8 +249,8 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
202249
std::vector<clic_int_reg_t> clic_int_reg;
203250
uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0};
204251
uint8_t clic_mact_lvl{0}, clic_uact_lvl{0};
205-
std::array<reg_t, 4> clic_intthresh;
206-
std::array<reg_t, 4> clic_xtvt;
252+
std::array<reg_t, 4> clic_intthresh{0};
253+
std::array<reg_t, 4> clic_xtvt{0};
207254
};
208255

209256
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {

src/iss/mem/pmp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ template <typename PLAT> struct pmp : public memory_elem {
7777
void set_next(memory_if mem) override { down_stream_mem = mem; }
7878

7979
private:
80-
std::array<reg_t, 16> pmpaddr;
81-
std::array<reg_t, 16 / sizeof(reg_t)> pmpcfg;
80+
std::array<reg_t, 16> pmpaddr{0};
81+
std::array<reg_t, 16 / sizeof(reg_t)> pmpcfg{0};
8282

8383
iss::status read_mem(const addr_t& addr, unsigned length, uint8_t* data) {
8484
assert((addr.type == iss::address_type::PHYSICAL || is_debug(addr.access)) && "Only physical addresses are expected in pmp");

0 commit comments

Comments
 (0)