Skip to content

Commit 0edd11e

Browse files
authored
Add unratified Smclic, Ssclic, Smclicshv extensions
Spec: https://github.com/riscv/riscv-fast-interrupt Tests: riscv-non-isa/riscv-arch-test#436
1 parent 0224391 commit 0edd11e

12 files changed

+1090
-63
lines changed

model/riscv_clic_control.sail

Lines changed: 528 additions & 0 deletions
Large diffs are not rendered by default.

model/riscv_clic_mem.sail

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*=======================================================================================*/
2+
/* This Sail RISC-V architecture model, comprising all files and */
3+
/* directories except where otherwise noted is subject the BSD */
4+
/* two-clause license in the LICENSE file. */
5+
/* */
6+
/* SPDX-License-Identifier: BSD-2-Clause */
7+
/*=======================================================================================*/
8+
9+
val vector_table_fetch : xlenbits -> VectorTableFetchResult
10+
function vector_table_fetch(table_addr) -> VectorTableFetchResult =
11+
if sizeof(xlen) == 32 then {
12+
match mem_read(Execute(), table_addr, 4, false, false, false) {
13+
MemException(e) => F_TableError(e, table_addr),
14+
MemValue(table_entry) => F_TableEntry(table_entry)
15+
}
16+
} else { /* xlen == 64 */
17+
match mem_read(Execute(), table_addr, 8, false, false, false) {
18+
MemException(e) => F_TableError(e, table_addr),
19+
MemValue(table_entry) => F_TableEntry(table_entry)
20+
}
21+
}

model/riscv_clic_regs.sail

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*=======================================================================================*/
2+
/* This Sail RISC-V architecture model, comprising all files and */
3+
/* directories except where otherwise noted is subject the BSD */
4+
/* two-clause license in the LICENSE file. */
5+
/* */
6+
/* SPDX-License-Identifier: BSD-2-Clause */
7+
/*=======================================================================================*/
8+
9+
/* Architectural state for the 'Smclic' fast interrupts extension. */
10+
11+
/* Smclic csrs */
12+
mapping clause csr_name_map = 0x307 <-> "mtvt"
13+
mapping clause csr_name_map = 0x345 <-> "mnxti"
14+
mapping clause csr_name_map = 0xFB1 <-> "mintstatus"
15+
mapping clause csr_name_map = 0x347 <-> "mintthresh"
16+
mapping clause csr_name_map = 0x348 <-> "mscratchcsw"
17+
mapping clause csr_name_map = 0x349 <-> "mscratchcswl"
18+
/* Ssclic csrs */
19+
mapping clause csr_name_map = 0x107 <-> "stvt"
20+
mapping clause csr_name_map = 0x145 <-> "snxti"
21+
mapping clause csr_name_map = 0xDB1 <-> "sintstatus"
22+
mapping clause csr_name_map = 0x147 <-> "sintthresh"
23+
mapping clause csr_name_map = 0x148 <-> "sscratchcsw"
24+
mapping clause csr_name_map = 0x149 <-> "sscratchcswl"
25+
/* Suclic csrs */
26+
mapping clause csr_name_map = 0x107 <-> "utvt"
27+
mapping clause csr_name_map = 0x145 <-> "unxti"
28+
mapping clause csr_name_map = 0xDB1 <-> "uintstatus"
29+
mapping clause csr_name_map = 0x147 <-> "uintthresh"
30+
mapping clause csr_name_map = 0x148 <-> "sscratchcsw"
31+
mapping clause csr_name_map = 0x149 <-> "sscratchcswl"
32+
33+
register inhv : bits(1) /* internal state of accessing vector table, exception handler will decide which xinhv to set */
34+
35+
register mtvt : xlenbits
36+
register mintthresh : ilbits
37+
register mil : ilbits
38+
register mpil : ilbits
39+
register minhv : bits(1)
40+
41+
register stvt : xlenbits
42+
register sintthresh : ilbits
43+
register sil : ilbits
44+
register spil : ilbits
45+
register sinhv : bits(1)
46+
47+
register utvt : xlenbits
48+
register uintthresh : ilbits
49+
register uil : ilbits
50+
register upil : ilbits
51+
register uinhv : bits(1)
52+
53+
register clicintip_raw : vector(4096, dec, bits(1))
54+
register clicintip_raw_prev : vector(4096, dec, bits(1))
55+
register clicintip : vector(4096, dec, bits(1))
56+
register clicintie : vector(4096, dec, bits(1))
57+
register clicintctl : vector(4096, dec, ilbits)
58+
register clicintattr : vector(4096, dec, clicintattr_layout)
59+
60+
bitfield ClicMcause : xlenbits = {
61+
IsInterrupt : xlen - 1,
62+
Minhv : 30,
63+
ClicMcauseMpp : 29 .. 28,
64+
ClicMcauseMpie: 27,
65+
Mpil : 23 .. 16,
66+
Exccode : 11 .. 0
67+
}
68+
register clicmcause : ClicMcause
69+
register clicmstatus : Mstatus
70+
71+
bitfield ClicScause : xlenbits = {
72+
IsInterrupt : xlen - 1,
73+
Sinhv : 30,
74+
ClicScauseSpp : 28,
75+
ClicScauseSpie: 27,
76+
Spil : 23 .. 16,
77+
Exccode : 11 .. 0
78+
}
79+
register clicscause : ClicScause
80+
81+
bitfield ClicUcause : xlenbits = {
82+
IsInterrupt : xlen - 1,
83+
Uinhv : 30,
84+
ClicUcauseUpie: 27,
85+
Upil : 23 .. 16,
86+
Exccode : 11 .. 0
87+
}
88+
register clicucause : ClicUcause
89+
90+
bitfield Mintstatus : xlenbits = {
91+
mil : 31 .. 24,
92+
sil : 15 .. 8,
93+
uil : 7 .. 0
94+
}
95+
register mintstatus : Mintstatus

model/riscv_clic_type.sail

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*=======================================================================================*/
2+
/* This Sail RISC-V architecture model, comprising all files and */
3+
/* directories except where otherwise noted is subject the BSD */
4+
/* two-clause license in the LICENSE file. */
5+
/* */
6+
/* SPDX-License-Identifier: BSD-2-Clause */
7+
/*=======================================================================================*/
8+
9+
/* Definitions for fast interrupt (Smclic extensions) */
10+
11+
/* default register type */
12+
type ilbits = bits(8)
13+
14+
bitfield clicintattr_layout : bits(8) = {
15+
MODE : 7 .. 6, /* privilege mode */
16+
TRIG : 2 .. 1, /* 11 - negedge triggered */
17+
/* 10 - active low */
18+
/* 01 - posedge triggered */
19+
/* 00 - active high */
20+
SHV : 0 /* hardware vectored interrupt */
21+
}
22+
23+
val is_shv : bitvector(1) -> bool
24+
function is_shv (shv) =
25+
match (shv) {
26+
0b0 => false,
27+
0b1 => true
28+
}
29+
30+
let CLIC_MTI = 7
31+
let CLIC_MSI = 3
32+
33+
union VectorTableFetchResult = {
34+
F_TableEntry : xlenbits, /* Entry in vector table */
35+
F_TableError : (ExceptionType, xlenbits) /* standard exception and table entry addr */
36+
}

model/riscv_insts_zicsr.sail

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function readCSR csr : csreg -> xlenbits = {
3333
(0x301, _) => misa.bits,
3434
(0x302, _) => medeleg.bits,
3535
(0x303, _) => mideleg.bits,
36-
(0x304, _) => mie.bits,
36+
(0x304, _) => if haveSmclic() then { zero_extend(0b0) } else mie.bits,
3737
(0x305, _) => get_mtvec(),
3838
(0x306, _) => zero_extend(mcounteren.bits),
3939
(0x30A, _) => menvcfg.bits[sizeof(xlen) - 1 .. 0],
@@ -43,9 +43,17 @@ function readCSR csr : csreg -> xlenbits = {
4343

4444
(0x340, _) => mscratch,
4545
(0x341, _) => get_xret_target(Machine) & pc_alignment_mask(),
46-
(0x342, _) => mcause.bits,
46+
(0x342, _) => if haveSmclic() then {
47+
clicmcause.bits = mcause.bits;
48+
clicmcause[Minhv] = minhv;
49+
clicmcause[ClicMcauseMpp] = mstatus[MPP];
50+
clicmcause[ClicMcauseMpie] = mstatus[MPIE];
51+
clicmcause[Mpil] = mpil;
52+
clicmcause.bits
53+
} else
54+
mcause.bits,
4755
(0x343, _) => mtval,
48-
(0x344, _) => mip.bits,
56+
(0x344, _) => if haveSmclic() then { zero_extend(0b0) } else mip.bits,
4957

5058
// pmpcfgN
5159
(0x3A @ idx : bits(4), _) if idx[0] == bitzero | sizeof(xlen) == 32 => pmpReadCfgReg(unsigned(idx)),
@@ -77,15 +85,23 @@ function readCSR csr : csreg -> xlenbits = {
7785
(0x100, _) => lower_mstatus(mstatus).bits,
7886
(0x102, _) => sedeleg.bits,
7987
(0x103, _) => sideleg.bits,
80-
(0x104, _) => lower_mie(mie, mideleg).bits,
88+
(0x104, _) => if haveSmclic() then { zero_extend(0b0) } else lower_mie(mie, mideleg).bits,
8189
(0x105, _) => get_stvec(),
8290
(0x106, _) => zero_extend(scounteren.bits),
8391
(0x10A, _) => senvcfg.bits[sizeof(xlen) - 1 .. 0],
8492
(0x140, _) => sscratch,
8593
(0x141, _) => get_xret_target(Supervisor) & pc_alignment_mask(),
86-
(0x142, _) => scause.bits,
94+
(0x142, _) => if haveSmclic() then {
95+
clicscause.bits = scause.bits;
96+
clicscause[Sinhv] = sinhv;
97+
clicscause[ClicScauseSpp] = mstatus[SPP];
98+
clicscause[ClicScauseSpie] = mstatus[SPIE];
99+
clicscause[Spil] = mpil;
100+
clicscause.bits
101+
} else
102+
scause.bits,
87103
(0x143, _) => stval,
88-
(0x144, _) => lower_mip(mip, mideleg).bits,
104+
(0x144, _) => if haveSmclic() then { zero_extend(0b0) } else lower_mip(mip, mideleg).bits,
89105
(0x180, _) => satp,
90106

91107
/* user mode counters */
@@ -119,7 +135,7 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
119135
(0x301, _) => { misa = legalize_misa(misa, value); Some(misa.bits) },
120136
(0x302, _) => { medeleg = legalize_medeleg(medeleg, value); Some(medeleg.bits) },
121137
(0x303, _) => { mideleg = legalize_mideleg(mideleg, value); Some(mideleg.bits) },
122-
(0x304, _) => { mie = legalize_mie(mie, value); Some(mie.bits) },
138+
(0x304, _) => { if haveSmclic() then { mie = mie; Some(mie.bits) } else { mie = legalize_mie(mie, value); Some(mie.bits) } },
123139
(0x305, _) => { Some(set_mtvec(value)) },
124140
(0x306, _) => { mcounteren = legalize_mcounteren(mcounteren, value); Some(zero_extend(mcounteren.bits)) },
125141
(0x30A, 32) => { menvcfg = legalize_envcfg(menvcfg, menvcfg.bits[63 .. 32] @ value); Some(menvcfg.bits[31 .. 0]) },
@@ -129,9 +145,19 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
129145
(0x320, _) => { mcountinhibit = legalize_mcountinhibit(mcountinhibit, value); Some(zero_extend(mcountinhibit.bits)) },
130146
(0x340, _) => { mscratch = value; Some(mscratch) },
131147
(0x341, _) => { Some(set_xret_target(Machine, value)) },
132-
(0x342, _) => { mcause.bits = value; Some(mcause.bits) },
148+
(0x342, _) => { if haveSmclic() then {
149+
clicmcause.bits = value;
150+
minhv = clicmcause[Minhv];
151+
mstatus[MPP] = clicmcause[ClicMcauseMpp];
152+
mstatus[MPIE] = clicmcause[ClicMcauseMpie];
153+
mpil = clicmcause[Mpil];
154+
Some(clicmcause.bits)
155+
} else {
156+
mcause.bits = value; Some(mcause.bits)
157+
}
158+
},
133159
(0x343, _) => { mtval = value; Some(mtval) },
134-
(0x344, _) => { mip = legalize_mip(mip, value); Some(mip.bits) },
160+
(0x344, _) => { if haveSmclic() then { mip = mip; Some(mip.bits) } else { mip = legalize_mip(mip, value); Some(mip.bits) } },
135161

136162
// pmpcfgN
137163
(0x3A @ idx : bits(4), _) if idx[0] == bitzero | sizeof(xlen) == 32 => {
@@ -158,15 +184,25 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
158184
(0x100, _) => { mstatus = legalize_sstatus(mstatus, value); Some(mstatus.bits) },
159185
(0x102, _) => { sedeleg = legalize_sedeleg(sedeleg, value); Some(sedeleg.bits) },
160186
(0x103, _) => { sideleg.bits = value; Some(sideleg.bits) }, /* TODO: does this need legalization? */
161-
(0x104, _) => { mie = legalize_sie(mie, mideleg, value); Some(mie.bits) },
187+
(0x104, _) => { if haveSmclic() then { mie = mie; Some(mie.bits) } else { mie = legalize_sie(mie, mideleg, value); Some(mie.bits) } },
162188
(0x105, _) => { Some(set_stvec(value)) },
163189
(0x106, _) => { scounteren = legalize_scounteren(scounteren, value); Some(zero_extend(scounteren.bits)) },
164190
(0x10A, _) => { senvcfg = legalize_envcfg(senvcfg, zero_extend(value)); Some(senvcfg.bits[sizeof(xlen) - 1 .. 0]) },
165191
(0x140, _) => { sscratch = value; Some(sscratch) },
166192
(0x141, _) => { Some(set_xret_target(Supervisor, value)) },
167-
(0x142, _) => { scause.bits = value; Some(scause.bits) },
193+
(0x142, _) => { if haveSmclic() then {
194+
clicscause.bits = value;
195+
sinhv = clicscause[Sinhv];
196+
mstatus[SPP] = clicscause[ClicScauseSpp];
197+
mstatus[SPIE] = clicscause[ClicScauseSpie];
198+
spil = clicscause[Spil];
199+
Some(clicscause.bits)
200+
} else {
201+
scause.bits = value; Some(scause.bits)
202+
}
203+
},
168204
(0x143, _) => { stval = value; Some(stval) },
169-
(0x144, _) => { mip = legalize_sip(mip, mideleg, value); Some(mip.bits) },
205+
(0x144, _) => { if haveSmclic() then { mip = mip; Some(mip.bits) } else { mip = legalize_sip(mip, mideleg, value); Some(mip.bits) } },
170206
(0x180, _) => { satp = legalize_satp(cur_Architecture(), satp, value); Some(satp) },
171207

172208
/* user mode: seed (entropy source). writes are ignored */
@@ -201,17 +237,32 @@ function clause execute CSR(csr, rs1, rd, is_imm, op) = {
201237
else if not(ext_check_CSR(csr, cur_privilege, isWrite))
202238
then { ext_check_CSR_fail(); RETIRE_FAIL }
203239
else {
204-
let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */
205-
if isWrite then {
206-
let new_val : xlenbits = match op {
207-
CSRRW => rs1_val,
208-
CSRRS => csr_val | rs1_val,
209-
CSRRC => csr_val & ~(rs1_val)
210-
};
211-
writeCSR(csr, new_val)
212-
};
213-
X(rd) = csr_val;
214-
RETIRE_SUCCESS
240+
let cond_writeCSR : bool = isWrite & (op == CSRRW) & is_imm == false;
241+
match (csr, sizeof(xlen)) {
242+
/* special conditional write CSRs, CSRRS/C/I/read behavior reserved */
243+
(0x348, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
244+
(0x349, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
245+
(0x148, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
246+
(0x149, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
247+
(0x049, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
248+
/* special Smclic nxti CSRs */
249+
(0x345, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, Machine) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
250+
(0x145, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, Supervisor) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
251+
(0x045, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, User) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
252+
_ => { /* standard CSRs */
253+
let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */
254+
if isWrite then {
255+
let new_val : xlenbits = match op {
256+
CSRRW => rs1_val,
257+
CSRRS => csr_val | rs1_val,
258+
CSRRC => csr_val & ~(rs1_val)
259+
};
260+
writeCSR(csr, new_val)
261+
};
262+
X(rd) = csr_val;
263+
RETIRE_SUCCESS
264+
}
265+
}
215266
}
216267
}
217268

model/riscv_next_control.sail

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,21 @@ function clause ext_is_CSR_defined(0x043, _) = haveUsrMode() & haveNExt() // utv
1818
function clause ext_is_CSR_defined(0x044, _) = haveUsrMode() & haveNExt() // uip
1919

2020
function clause ext_read_CSR(0x000) = Some(lower_sstatus(lower_mstatus(mstatus)).bits)
21-
function clause ext_read_CSR(0x004) = Some(lower_sie(lower_mie(mie, mideleg), sideleg).bits)
21+
function clause ext_read_CSR(0x004) = if haveSmclic() then { Some(zero_extend(0b0)) } else Some(lower_sie(lower_mie(mie, mideleg), sideleg).bits)
2222
function clause ext_read_CSR(0x005) = Some(get_utvec())
2323
function clause ext_read_CSR(0x040) = Some(uscratch)
2424
function clause ext_read_CSR(0x041) = Some(get_xret_target(User) & pc_alignment_mask())
25-
function clause ext_read_CSR(0x042) = Some(ucause.bits)
25+
function clause ext_read_CSR(0x042) = if haveSmclic() then {
26+
clicucause.bits = ucause.bits;
27+
clicucause[Uinhv] = uinhv;
28+
clicucause[ClicUcauseUpie] = mstatus[UPIE];
29+
clicucause[Upil] = upil;
30+
Some(clicucause.bits)
31+
} else
32+
Some(ucause.bits)
33+
2634
function clause ext_read_CSR(0x043) = Some(utval)
27-
function clause ext_read_CSR(0x044) = Some(lower_sip(lower_mip(mip, mideleg), sideleg).bits)
35+
function clause ext_read_CSR(0x044) = if haveSmclic() then { Some(zero_extend(0b0)) } else Some(lower_sip(lower_mip(mip, mideleg), sideleg).bits)
2836

2937
function clause ext_write_CSR(0x000, value) = { mstatus = legalize_ustatus(mstatus, value); Some(mstatus.bits) }
3038
function clause ext_write_CSR(0x004, value) = { let sie = legalize_uie(lower_mie(mie, mideleg), sideleg, value);
@@ -33,7 +41,17 @@ function clause ext_write_CSR(0x004, value) = { let sie = legalize_uie(lower_mie
3341
function clause ext_write_CSR(0x005, value) = { Some(set_utvec(value)) }
3442
function clause ext_write_CSR(0x040, value) = { uscratch = value; Some(uscratch) }
3543
function clause ext_write_CSR(0x041, value) = { Some(set_xret_target(User, value)) }
36-
function clause ext_write_CSR(0x042, value) = { ucause.bits = value; Some(ucause.bits) }
44+
function clause ext_write_CSR(0x042, value) = { if haveSmclic() then {
45+
clicucause.bits = value;
46+
uinhv = clicucause[Uinhv];
47+
mstatus[UPIE] = clicucause[ClicUcauseUpie];
48+
upil = clicucause[Upil];
49+
Some(clicucause.bits)
50+
} else {
51+
ucause.bits = value; Some(ucause.bits)
52+
}
53+
}
54+
3755
function clause ext_write_CSR(0x043, value) = { utval = value; Some(utval) }
3856
function clause ext_write_CSR(0x044, value) = { let sip = legalize_uip(lower_mip(mip, mideleg), sideleg, value);
3957
mip = lift_sip(mip, mideleg, sip);

0 commit comments

Comments
 (0)