From 90cc3e161ad93d0f14a311045009fe86b7364e0d Mon Sep 17 00:00:00 2001 From: Damien Pretet Date: Sat, 9 Sep 2023 21:17:08 +0200 Subject: [PATCH] New: Put in place SUPERVISOR, HYPERVISOR and USER mode enable parameters New: Add documentation on privilege modes, description and design Change: Rework MSTATUS, aligning it with latest privilege spec and create a function to format it --- doc/ios_params.md | 15 ++ doc/monodraw.monopic | Bin 0 -> 2155 bytes doc/privilege.md | 90 ++++++++ rtl/friscv_control.sv | 12 +- rtl/friscv_csr.sv | 350 ++++++++++++++++++++++---------- rtl/friscv_rv32i_core.sv | 48 +++-- rtl/friscv_rv32i_platform.sv | 59 +++--- test/common/friscv_testbench.sv | 12 ++ 8 files changed, 430 insertions(+), 156 deletions(-) create mode 100644 doc/monodraw.monopic create mode 100644 doc/privilege.md diff --git a/doc/ios_params.md b/doc/ios_params.md index d3de16f..994dab2 100644 --- a/doc/ios_params.md +++ b/doc/ios_params.md @@ -50,6 +50,21 @@ - 0 or 1 - default: 0, no multiply/divide support +- USER_MODE + - activate user mode support + - 0 or 1 + - default: 0, not supported + +- SUPERVISOR_MODE + - activate supervisor mode support + - 0 or 1 + - default: 0, not supported + +- HYPERVISOR_MODE + - activate hypervisor mode support + - 0 or 1 + - default: 0, not supported + - PROCESSING_BUS_PIPELINE - insert a pipeline at processing unit input bus - 0 or 1 diff --git a/doc/monodraw.monopic b/doc/monodraw.monopic new file mode 100644 index 0000000000000000000000000000000000000000..2e139287a7f54217708d0da718c3810a2384b9dd GIT binary patch literal 2155 zcmV-x2$c8#O;1iwP)S1pABzY8000000u$|A-IJR(5dT+hc;==^LIT}eCUc!;CT%m9 zrhQ0nJlM!KjSsHCU6N+}zgGfQfIlwApx9&kzw%Nt}x~w{AY(+vT0dB#ITy zkN3-^UA~445hhGMzD_EP(oD!#9otIf0Ogxmlt)P{Kh5k0AK13wU!&b>m{sN8E9Ic`H~%v-qJ9 zoh0y(Jd5&&{!$vv=K6OOiqSYpLm{c;>65T65eMUi2;rw5683<=ILY(mp`f59Ml$#7 ztJlB0`R&$%3CHH7hcN9-o9{@QBV%m)o*5NzUG=#BYE922mi_Wj<{}73ilbto)T}vL z(uR2E)Q~LvZL;t>$imqq3yKYif*V_Llx>j)rF~ZhbGDJ@eFcpQ(IT0AYW{==3x*1sPsQIv{*@%>Q5cF?Kc3BlF!{VjG!7obNQ6<|xK};80br|n z9Z3>#xB)0>@v{6;4ii^gX8G5J{7EEl5`iPhl;zltS~kI~U|De?Z@!feUt!B`$yY6! zaw#i$78e*Uh^3+6z7lYpzRs3w!hK&GG ztbpRex3rC^u+?$&6;eu3eX0$#8*#KPq(w_|CH&T~sgcip5oy}v1d@&QRBKE(d~Oo1 z=Z36Jb)^{V3fATnY@Tbz1Hj0bJBz&UlCJ3>MJH0sT7=lh1z(=|#$qfFpI#tzcl!rO zZihhS`{MTuhPbB}hrVx!pO68>kGV1JWL-QB&W_B{@cAh^8mzyg;q2pQ+`fMG_U+D& z26vl&hKub&fFU`ul`&(dJ(YA{x5c-S)+Lwkt&pgp zknYKex(Mj?_%5l&SX|LURlteE-;j9drqH4i)V9tQG7K+dDw41GwiyWaC58#dqO?o>#2ndwpXa z^0n29=oF;|;mdloO`0Ho+4du}KPfP7<)DnhO~CzuQ%Q)aFr zK^#;4pXQ2K2%laR>qDkh9GeTt%IrtmD>+0C1GP;V`(D!Gbr3%X*%jK5wzwZK1F_-& zm9qgh9U7i2Xc~f&9z?rUOaOHd-F5*N5Ktf>iGU^oq6nx;?YZxix>)yvUrb3feR9uS zkpPvbZJ-O>9Af)u0K`TZn=@C~T*1gU*J$l`N(UWVHR|(PQQtw5 zK^`Er2T1J!QhV9}oLSK4@xI9*7jNs`M}1q$i6Og#O6P2N!ag6s>TqHVz3I00f0y^& zS>Q5Lb9H(h0I$L@6mtoWB(SR$#o zblIS-1XQ@_E!1?Zdssc&b}UiSd-DjoRCHr;K zE4tL{Qqg7Gj2J_GfsvXrVx2a;5PW2=IHs2(%z(c5A9AX%evZTd4*pPwIOOQTbb+%KG?zDsSL$s$eos$JbV1Nh= z5P_W;B6z58lamT-a&*_}5R-#!%PyAzl!NMHa_TZpeZ0+i?aanrPe0W+S6=f>l`N^bgN6)c zP`P7F%EZv|U@qBz7YwhPtjulD=Z4M{aJ~HpPV`13wC64YLtYU#*Yri{{(G*pyht}c z<=Bea2$74QGNhlPy0~`sQBbR{E!WsVe3ZHgsqR9m+mH~`S7%nm79tbU2#dVxUuf3;%%n7V5NP(J_}kpnQKDterJR_VZaf zoyCHW?a(*mU5a2sHl%%ccYF8eoAw$_mAM;mXzJ_Lw^0Q)es9pf`Q^$qtu z^bMOkk^~_``BLO?gFW1205`@nG;(InI^okh3ZnsY%i7mBB|y&{Y3v(RQgizu$m#7+ z{P6y^UQ8Gb02Q6Kh$D1tO$aLNyChWxOsdp-V0TZgw7LxKX h9DZ)8mHpe4mSsS%X8)V@ETi7#@_*HxpDfg5006XfGNJ$g literal 0 HcmV?d00001 diff --git a/doc/privilege.md b/doc/privilege.md new file mode 100644 index 0000000..6c53b77 --- /dev/null +++ b/doc/privilege.md @@ -0,0 +1,90 @@ +# Privilege Modes Support + +FRISCV supports machine mode as default mode. it's always implemented as required by the +specification. The core can also support user, supervisor and hypervisor modes, activable +all by paramters, `USER_MODE`, `SUPERVISOR_MODE`, `HYPERVISOR_MODE`. + +All modes use the same `XLEN` width. If `XLEN` = 32 bits, `MXLEN`, `SXLEN`, `UXLEN` and +`HXLEN` will be setup to 32 bits. + +The software navigates through the privilege levels with ECALL / xRET instructions + +``` + ┌────────────────────────────────┐ + │ MACHINE │ + └────────────────────────────────┘ + │ ▲ + MRET │ │ ECALL + ▼ │ + ┌────────────────────────────────┐ + │ SUPERVISOR │ + └────────────────────────────────┘ + │ ▲ + SRET │ │ ECALL + ▼ │ + ┌────────────────────────────────┐ + │ USER │ + └────────────────────────────────┘ +``` + +CSR registers address encodes inner attributes: + +``` + 11/10 9/8 7/4 3/0 + ┌───────┬───────────┬───────────┬───────────┐ + │ R/W │ Privilege │ Use │ Address │ + └───────┴───────────┴───────────┴───────────┘ +``` + +Bit[11:10]: +- `11`: read-only +- Others: read/write + +Bits [9:8]: +- `00`: User +- `01`: Supervisor +- `10`: Hypervisor +- `11`: Machine + + +# TODO + +Plan: +- 1. user mode + PMP +- 2. supervisor mode + virtual memory support +- 3. hypervisor mode +- 4. debug mode + +1. User mode + +- Implement MSTATUS based on latest spec +- Support U-mode: + - Previous privilege mode interrupt is stored in xPP to support nested trap + - Ecall move to M-mode + - Mret move to U-mode +- Support exceptions + - M-mode instructions executed in U-mode must raise an illegal instruction exception + - Access to M-mode only registers must raise an illegal instruction exception +- Support PMP (Physical Memory Protection) + - Instruction read or data R/W access are checked against PMP to secure the hart + - Address is checked with CSRs pmpcfg + - Up to 16 zones can be defined + - A zone can be readable, writable, executable + - PMP checks are applied to all accesses whose effective privilege mode is S or U, including + instruction fetches and data accesses in S and U mode, and data accesses in M-mode when the + MPRV bit in mstatus is set and the MPP field in mstatus contains S or U (page 56) +- Study PMA (section 3.6) + +2. Supervisor +- Support interrupts + - disable them for lower mode. If is SUPERVISOR, USER interrupts are disabled + - interrupts for higher mode are enabled, whatever xIE bit. If is SUPERVISOR, + HYPERVISOR interrupt are enabled + - previous privilege mode interrupt is stored in xPP to support nested trap + - medeleg & mideleg: delegate an trap to a mode means this mode can handle it. Traps never + transition from a more-privileged mode to a less-privileged mode (page 45) +- Support virtual memory for supervisor mode (TVM correct support) +- Support timer extension for each modes +- Support priv mode in cache stages +- Support TW (section 3.1.6.5) +- V & F extensions support: XS, FS, VS fields diff --git a/rtl/friscv_control.sv b/rtl/friscv_control.sv index 2cca23c..7937156 100644 --- a/rtl/friscv_control.sv +++ b/rtl/friscv_control.sv @@ -1062,12 +1062,14 @@ module friscv_control // PC is not aligned with XLEN boundary assign inst_addr_misaligned = (pc[1:0]!=2'b0) ? jump_branch : 1'b0; - // TODO: Support correctly TW with prividge mode - // When TW=1, if WFI is executed in any less-privileged mode, and it - // does not complete within an implementation-specific, bounded time - // limit, the WFI instruction causes an illegal instruction exception + // TODO: Support correctly TW with privilege mode + // When TW=0, the WFI instruction may execute in lower privilege modes when not prevented for some + // other reason. When TW=1, then if WFI is executed in any less-privileged mode, and it does not + // complete within an implementation-specific, bounded time limit, the WFI instruction causes an + // illegal instruction exception. An implementation may have WFI always raise an illegal instruction + // exception in less-privileged modes when TW=1, even if there are pending globally-disabled interrupts + // when the instruction is executed. TW is read-only 0 when there are no modes less privileged than M. assign wfi_not_allowed = 1'b0; - // assign wfi_not_allowed = (sys[`IS_WFI] && sb_mstatus[21]) ? 1'b1 : 1'b0; assign load_misaligned = proc_exceptions[`LD_MA]; assign store_misaligned = proc_exceptions[`ST_MA]; diff --git a/rtl/friscv_csr.sv b/rtl/friscv_csr.sv index fa735df..da50317 100644 --- a/rtl/friscv_csr.sv +++ b/rtl/friscv_csr.sv @@ -18,6 +18,12 @@ module friscv_csr parameter F_EXTENSION = 0, // Multiply/Divide extension support parameter M_EXTENSION = 0, + // Support hypervisor mode + parameter HYPERVISOR_MODE = 0, + // Support supervisor mode + parameter SUPERVISOR_MODE = 0, + // Support user mode + parameter USER_MODE = 0, // Reduced RV32 arch parameter RV32E = 0, // MHART_ID CSR value @@ -31,6 +37,8 @@ module friscv_csr input wire ext_irq, input wire sw_irq, input wire timer_irq, + // privilege bus, encoding current mode + input wire [4 -1:0] priv, // Instruction bus input wire valid, output logic ready, @@ -91,40 +99,157 @@ module friscv_csr logic timer_irq_sync; logic sw_irq_sync; + + function automatic logic [XLEN-1:0] get_mstatus ( + input logic [XLEN-1:0] data + ); + // SD + get_mstatus[31] = '0; + // WPRI + get_mstatus[30:23] = '0; + // TSR + if (SUPERVISOR_MODE) + get_mstatus[22] = data[22]; + else + get_mstatus[22] = '0; + // TW + if (SUPERVISOR_MODE || USER_MODE) + get_mstatus[21] = data[21]; + else + get_mstatus[21] = '0; + // TVM + if (SUPERVISOR_MODE) + get_mstatus[20] = data[20]; + else + get_mstatus[20] = '0; + // MXR + if (SUPERVISOR_MODE) + get_mstatus[19] = data[19]; + else + get_mstatus[19] = '0; + // SUM + if (SUPERVISOR_MODE) + get_mstatus[18] = data[18]; + else + get_mstatus[18] = '0; + // MPRV + if (SUPERVISOR_MODE) + get_mstatus[17] = data[17]; + else + get_mstatus[17] = '0; + // XS + get_mstatus[16:15] = '0; + // FS + if (F_EXTENSION) + get_mstatus[14:13] = data[14:13]; + else + get_mstatus[14:13] = '0; + // MPP + get_mstatus[12:11] = data[12:11]; + // VS + get_mstatus[10:9] = '0; + // SPP + if (SUPERVISOR_MODE) + get_mstatus[8] = data[8]; + else + get_mstatus[8] = '0; + // MPIE + get_mstatus[7] = data[7]; + // UBE + get_mstatus[6] = '0; + // SPIE + if (SUPERVISOR_MODE) + get_mstatus[5] = data[5]; + else + get_mstatus[5] = '0; + // WPRI + get_mstatus[4] = '0; + // MIE + get_mstatus[3] = data[3]; + // WPRI + get_mstatus[2] = '0; + // SIE + if (SUPERVISOR_MODE) + get_mstatus[1] = data[1]; + else + get_mstatus[1] = '0; + // WPRI + get_mstatus[0] = '0; + + endfunction + ////////////////////////////////////////////////////////////////////////// - // Machine-level CSRs: + // CSR Addresses ////////////////////////////////////////////////////////////////////////// - localparam MHART_ID = 12'hF14; - localparam MSTATUS = 12'h300; - localparam MISA = 12'h301; - localparam MEDELEG = 12'h302; - localparam MIDELEG = 12'h303; - localparam MIE = 12'h304; - localparam MTVEC = 12'h305; - localparam MCOUNTEREN = 12'h306; - localparam MSCRATCH = 12'h340; - localparam MEPC = 12'h341; - localparam MCAUSE = 12'h342; - localparam MTVAL = 12'h343; - localparam MIP = 12'h344; - localparam RDCYCLE = 12'hC00; - localparam RDTIME = 12'hC01; - localparam RDINSTRET = 12'hC02; - localparam RDCYCLEH = 12'hC80; - localparam RDTIMEH = 12'hC81; - localparam RDINSTRETH = 12'hC82; - - // Custom registers - localparam INSTREQ_ACTIVE = 12'hFC0; - localparam INSTREQ_SLEEP = 12'hFC1; - localparam INSTREQ_STALL = 12'hFC2; - localparam INSTCPL_ACTIVE = 12'hFC3; - localparam INSTCPL_SLEEP = 12'hFC4; - localparam INSTCPL_STALL = 12'hFC5; - localparam PROC_ACTIVE = 12'hFC6; - localparam PROC_SLEEP = 12'hFC7; - localparam PROC_STALL = 12'hFC8; + /* + * Machine-level CSR addresses + */ + + // Machine Information Registers + localparam MHART_ID = 12'hF14; + // Machine Trap Setup + localparam MSTATUS = 12'h300; + localparam MISA = 12'h301; + localparam MEDELEG = 12'h302; + localparam MIDELEG = 12'h303; + localparam MIE = 12'h304; + localparam MTVEC = 12'h305; + localparam MCOUNTEREN = 12'h306; + // Machine Trap Handling + localparam MSCRATCH = 12'h340; + localparam MEPC = 12'h341; + localparam MCAUSE = 12'h342; + localparam MTVAL = 12'h343; + localparam MIP = 12'h344; + + /* + * Supervisor-level CSR addresses + */ + + // Supervisor Trap Setup + localparam SSTATUS = 12'h100; + localparam SIE = 12'h104; + localparam STVEC = 12'h105; + localparam SCOUNTEREN = 12'h100; + // Supervisor Configuration + localparam SENVCFG = 12'h10A; + // Supervisor Trap Handling + localparam SSCRATCH = 12'h140; + localparam SEPC = 12'h141; + localparam SCAUSE = 12'h142; + localparam STVAL = 12'h143; + localparam SIP = 12'h144; + // Supervisor Protection and Translation + localparam SATP = 12'h180; + // Debug/Trace Registers + localparam SCONTEXT = 12'h5A8; + + /* + * Unprivileged CSR addresses + */ + + localparam RDCYCLE = 12'hC00; + localparam RDTIME = 12'hC01; + localparam RDINSTRET = 12'hC02; + localparam RDCYCLEH = 12'hC80; + localparam RDTIMEH = 12'hC81; + localparam RDINSTRETH = 12'hC82; + + /* + * Custom unprivileged CSR addresses + */ + + localparam INSTREQ_ACTIVE = 12'hFC0; + localparam INSTREQ_SLEEP = 12'hFC1; + localparam INSTREQ_STALL = 12'hFC2; + localparam INSTCPL_ACTIVE = 12'hFC3; + localparam INSTCPL_SLEEP = 12'hFC4; + localparam INSTCPL_STALL = 12'hFC5; + localparam PROC_ACTIVE = 12'hFC6; + localparam PROC_SLEEP = 12'hFC7; + localparam PROC_STALL = 12'hFC8; + // Machine Information Status // logic [XLEN-1:0] mvendorid; // 0xF11 MRO (not implemented) @@ -161,6 +286,7 @@ module friscv_csr logic [64 -1:0] rdtime; // 0xC01 MRO (0xC81 for 32b MSBs) logic [64 -1:0] rdinstret; // 0xC02 MRO (0xC82 for 32b MSBs) + // Custom register spying on AXI4-lite bus logic [32 -1:0] instreq_perf_active; logic [32 -1:0] instreq_perf_sleep; logic [32 -1:0] instreq_perf_stall; @@ -200,7 +326,7 @@ module friscv_csr assign rs1_addr = rs1; - // Always handshakes the request but htis flag could stop + // Always handshakes the request but this flag could stop // the transfer if needed in case of extra pipeline assign ready = 1'b1; @@ -249,11 +375,11 @@ module friscv_csr ////////////////////////////////////////////////////////////////////////// - // CSR execution machine + // ISA register Write Stage ////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (aresetn==1'b0) begin + if (!aresetn) begin rd_wr_en <= 1'b0; rd_wr_addr <= 5'b0; rd_wr_val <= {XLEN{1'b0}}; @@ -376,32 +502,32 @@ module friscv_csr /////////////////////////////////////////////////////////////////////////// // Supported extensions - assign misa[0] = 1'b0; // A Atomic extension - assign misa[1] = 1'b0; // B Tentatively reserved for Bit-Manipulation extension - assign misa[2] = 1'b0; // C Compressed extension - assign misa[3] = 1'b0; // D Double-precision floating-point extension - assign misa[4] = (RV32E) ? 1'b1 : 1'b0; // E RV32E base ISA - assign misa[5] = (F_EXTENSION) ? 1'b1 : 1'b0; // F Single-precision floating-point extension - assign misa[6] = 1'b0; // G Additional standard extensions present - assign misa[7] = 1'b0; // H Hypervisor extension - assign misa[8] = (~RV32E) ? 1'b1 : 1'b0; // I RV32I/64I/128I base ISA - assign misa[9] = 1'b0; // J Tentatively reserved for Dynamically Translated Languages extension - assign misa[10] = 1'b0; // K Reserved - assign misa[11] = 1'b0; // L Tentatively reserved for Decimal Floating-Point extension - assign misa[12] = (M_EXTENSION) ? 1'b1 : 1'b0; // M Integer Multiply/Divide extension - assign misa[13] = 1'b0; // N User-level interrupts supported - assign misa[14] = 1'b0; // O Reserved - assign misa[15] = 1'b0; // P Tentatively reserved for Packed-SIMD extension - assign misa[16] = 1'b0; // Q Quad-precision floating-point extension - assign misa[17] = 1'b0; // R Reserved - assign misa[18] = 1'b0; // S Supervisor mode implemented - assign misa[19] = 1'b0; // T Tentatively reserved for Transactional Memory extension - assign misa[20] = 1'b0; // U User mode implemented - assign misa[21] = 1'b0; // V Tentatively reserved for Vector extension - assign misa[22] = 1'b0; // W Reserved - assign misa[23] = 1'b0; // X Non-standard extensions present - assign misa[24] = 1'b0; // Y Reserved - assign misa[25] = 1'b0; // Z Reserved + assign misa[0] = 1'b0; // A Atomic extension + assign misa[1] = 1'b0; // B Tentatively reserved for Bit-Manipulation extension + assign misa[2] = 1'b0; // C Compressed extension + assign misa[3] = 1'b0; // D Double-precision floating-point extension + assign misa[4] = (RV32E) ? 1'b1 : 1'b0; // E RV32E base ISA + assign misa[5] = (F_EXTENSION) ? 1'b1 : 1'b0; // F Single-precision floating-point extension + assign misa[6] = 1'b0; // G Additional standard extensions present + assign misa[7] = (HYPERVISOR_MODE) ? 1'b1 : 1'b0; // H Hypervisor extension + assign misa[8] = (!RV32E) ? 1'b1 : 1'b0; // I RV32I/64I/128I base ISA + assign misa[9] = 1'b0; // J Tentatively reserved for Dynamically Translated Languages extension + assign misa[10] = 1'b0; // K Reserved + assign misa[11] = 1'b0; // L Tentatively reserved for Decimal Floating-Point extension + assign misa[12] = (M_EXTENSION) ? 1'b1 : 1'b0; // M Integer Multiply/Divide extension + assign misa[13] = 1'b0; // N User-level interrupts supported + assign misa[14] = 1'b0; // O Reserved + assign misa[15] = 1'b0; // P Tentatively reserved for Packed-SIMD extension + assign misa[16] = 1'b0; // Q Quad-precision floating-point extension + assign misa[17] = 1'b0; // R Reserved + assign misa[18] = (SUPERVISOR_MODE) ? 1'b1 : 1'b0; // S Supervisor mode implemented + assign misa[19] = 1'b0; // T Tentatively reserved for Transactional Memory extension + assign misa[20] = (USER_MODE) ? 1'b1 : 1'b0; // U User mode implemented + assign misa[21] = 1'b0; // V Tentatively reserved for Vector extension + assign misa[22] = 1'b0; // W Reserved + assign misa[23] = 1'b0; // X Non-standard extensions present + assign misa[24] = 1'b0; // Y Reserved + assign misa[25] = 1'b0; // Z Reserved // MXLEN field encoding generate @@ -414,49 +540,59 @@ module friscv_csr end endgenerate - /////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// // MSTATUS - 0x300 // - // 31: SD related to XS FS, 0 for the moment - // 30:23: (WPRI) - // 22: TSR Supervisor mode, 0 N/A - // 21: TW Timeout Wait, 0 N/A - // 20: TVM Virtualization, 0 N/A - // 19: MXR Virtual Mem, 0 N/A - // 18: SUM Virtual Mem, 0 N/A - // 17: MPRV Virtual Mem, 0 N/A - // 16:15: XS FP, 0 N/A - // 14:13: FS FP, 0 N/A - // 12:11: MPP: Machine-mode, previous priviledge mode, 0 N/A - // 10:9: (WPRI) - // 8: SPP Supervisor mode, 0 N/A - // 7: MPIE: Machine-mode, Interrupt enable (prior to the trap) - // 6: (WPRI) - // 5: SPIE Supervisor mode, 0 N/A - // 4: UPIE User mode, 0 N/A - // 3: MIE: Machine-mode, Interrupt enable - // 2: (WPRI) - // 1: SIE Supervisor mode, 0 N/A - // 0: UIE User mode, 0 N/A + // [31] SD, Dirty State based XS / FS / VS + // [30:23] (WPRI) + // [22] TSR, Trap SRET + // = 1, attempts to execute SRET while executing in S-mode will raise + // an illegal instruction exception + // = 0, this operation is permitted in S-mode. + // [21] TW, Timeout Wait + // = 0, WFI instruction may execute in lower privilege modes + // = 1, if WFI is executed in any less-privileged mode, + // instruction causes an illegal instruction exception + // [20] TVM, Trap Virtual Memory + // = 1, attempts to read or write the satp or exec SFENCE.VMA or + // SINVAL.VMA will raise an exception + // = 0, these operations are permitted in S-mode + // [19] MXR, Make eXecutable Readable + // = 0, only loads from pages marked readable + // = 1, loads from pages marked either readable or executable + // [18] SUM: Supervisor User Memory access + // = 0, S-mode memory accesses to pages that are accessible by U-mode + // = 1, these accesses are permitted + // [17] MPRV, Modify PRiVilege for load/store operation (for user mode) + // = 0, follow current privilege + // = 1, load/store are translated and protected + // [16:15] XS, encode user extension state + // [14:13] FS, encode Floating-point extension State + // [12:11] MPP: Machine-mode, previous privilege mode + // [10:9] VS, encode Vector extension State + // [8] SPP Supervisor mode + // [7] MPIE: Machine-mode interrupt enable (prior to the trap) + // [6] UBE: User Byte Endianess. Always little-endian so 0 + // [5] SPIE Supervisor mode Interrupt Enable (Prior to the trap) + // [4] (WPRI) + // [3] MIE: Machine-mode Interrupt Enable + // [2] (WPRI) + // [1] SIE Supervisor mode Interrupt Enable + // [0] (WPRI) // - /////////////////////////////////////////////////////////////////////////// + // mstatush is not inmplemented so always 0, making the core always + // in little-endian mode only + // + ////////////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mstatus <= {XLEN{1'b0}}; end else if (srst) begin mstatus <= {XLEN{1'b0}}; - end else begin - if (ctrl_mstatus_wr) begin - mstatus <= {ctrl_mstatus[31], 8'b0, ctrl_mstatus[22:11], 2'b0, - ctrl_mstatus[8:7], 1'b0, ctrl_mstatus[5:3], 1'b0, - ctrl_mstatus[1:0]}; - end else if (csr_wren) begin - if (csr==MSTATUS) begin - mstatus <= {newval[31], 8'b0, newval[22:11], 2'b0, - newval[8:7], 1'b0, newval[5:3], 1'b0, - newval[1:0]}; - end - end + end else if (ctrl_mstatus_wr) begin + mstatus <= get_mstatus(ctrl_mstatus); + end else if (csr_wren && csr==MSTATUS) begin + mstatus <= get_mstatus(newval); end end @@ -464,7 +600,7 @@ module friscv_csr // MIE - 0x304 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mie <= {XLEN{1'b0}}; end else if (srst) begin mie <= {XLEN{1'b0}}; @@ -481,7 +617,7 @@ module friscv_csr // MTVEC - 0x305 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mtvec <= {XLEN{1'b0}}; end else if (srst) begin mtvec <= {XLEN{1'b0}}; @@ -498,7 +634,7 @@ module friscv_csr // MSCRATCH - 0x340 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mscratch <= {XLEN{1'b0}}; end else if (srst) begin mscratch <= {XLEN{1'b0}}; @@ -515,7 +651,7 @@ module friscv_csr // MEPC, only support IALIGN=32 - 0x341 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mepc <= {XLEN{1'b0}}; end else if (srst) begin mepc <= {XLEN{1'b0}}; @@ -534,7 +670,7 @@ module friscv_csr // MCAUSE - 0x342 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mcause <= {XLEN{1'b0}}; end else if (srst) begin mcause <= {XLEN{1'b0}}; @@ -553,7 +689,7 @@ module friscv_csr // MTVAL - 0x343 /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mtval <= {XLEN{1'b0}}; end else if (srst) begin mtval <= {XLEN{1'b0}}; @@ -573,7 +709,7 @@ module friscv_csr // TODO: Study race condition when CSR is written and interrupt arrives /////////////////////////////////////////////////////////////////////////// always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin mip <= {XLEN{1'b0}}; end else if (srst) begin mip <= {XLEN{1'b0}}; @@ -617,7 +753,7 @@ module friscv_csr // Number of active cycles since moved out of reset always @ (posedge aclk or negedge aresetn) begin - if (~aresetn) begin + if (!aresetn) begin rdtime <= {64{1'b0}}; end else if (srst) begin rdtime <= {64{1'b0}}; @@ -641,9 +777,9 @@ module friscv_csr assign instcpl_perf_active = perfs[3*32+:32]; assign instcpl_perf_sleep = perfs[4*32+:32]; assign instcpl_perf_stall = perfs[5*32+:32]; - assign proc_perf_active = perfs[6*32+:32]; - assign proc_perf_sleep = perfs[7*32+:32]; - assign proc_perf_stall = perfs[8*32+:32]; + assign proc_perf_active = perfs[6*32+:32]; + assign proc_perf_sleep = perfs[7*32+:32]; + assign proc_perf_stall = perfs[8*32+:32]; ////////////////////////////////////////////////////////////////////////// diff --git a/rtl/friscv_rv32i_core.sv b/rtl/friscv_rv32i_core.sv index 1a762bb..03cc19c 100644 --- a/rtl/friscv_rv32i_core.sv +++ b/rtl/friscv_rv32i_core.sv @@ -40,6 +40,12 @@ module friscv_rv32i_core parameter F_EXTENSION = 0, // Multiply/Divide extension support parameter M_EXTENSION = 0, + // Support hypervisor mode + parameter HYPERVISOR_MODE = 0, + // Support supervisor mode + parameter SUPERVISOR_MODE = 0, + // Support user mode + parameter USER_MODE = 0, // Insert a pipeline on instruction bus coming from the controller parameter PROCESSING_BUS_PIPELINE = 0, @@ -72,7 +78,7 @@ module friscv_rv32i_core parameter ICACHE_BLOCK_W = ILEN*4, // Number of blocks in the cache parameter ICACHE_DEPTH = 512, - + // IO regions for direct read/write access parameter IO_MAP_NB = 0, // IO address ranges, organized by memory region as END-ADDR_START-ADDR: @@ -516,13 +522,16 @@ module friscv_rv32i_core friscv_csr #( - .PERF_REG_W (PERF_REG_W), - .PERF_NB_BUS (PERF_NB_BUS), - .RV32E (RV32E), - .HART_ID (HART_ID), - .XLEN (XLEN), - .F_EXTENSION (F_EXTENSION), - .M_EXTENSION (M_EXTENSION) + .PERF_REG_W (PERF_REG_W), + .PERF_NB_BUS (PERF_NB_BUS), + .RV32E (RV32E), + .HART_ID (HART_ID), + .XLEN (XLEN), + .F_EXTENSION (F_EXTENSION), + .M_EXTENSION (M_EXTENSION), + .HYPERVISOR_MODE (HYPERVISOR_MODE), + .SUPERVISOR_MODE (SUPERVISOR_MODE), + .USER_MODE (USER_MODE) ) csrs ( @@ -532,6 +541,7 @@ module friscv_rv32i_core .ext_irq (ext_irq), .sw_irq (sw_irq), .timer_irq (timer_irq), + .priv ('0), .valid (csr_en), .ready (csr_ready), .instbus (csr_instbus), @@ -549,23 +559,23 @@ module friscv_rv32i_core .ctrl_mtval_wr (ctrl_mtval_wr), .ctrl_mtval (ctrl_mtval), .ctrl_rdinstret (ctrl_rdinstret), - .perfs (perfs), + .perfs (perfs), .csr_sb (csr_sb) ); - friscv_bus_perf + friscv_bus_perf #( - .REG_W (PERF_REG_W), - .NB_BUS (PERF_NB_BUS) + .REG_W (PERF_REG_W), + .NB_BUS (PERF_NB_BUS) ) - bus_perf + bus_perf ( - .aclk (aclk), - .aresetn (aresetn), - .srst (srst), - .valid ({proc_valid, inst_rvalid_s, inst_arvalid_s}), - .ready ({proc_ready, inst_rready_s, inst_arready_s}), - .perfs (perfs) + .aclk (aclk), + .aresetn (aresetn), + .srst (srst), + .valid ({proc_valid, inst_rvalid_s, inst_arvalid_s}), + .ready ({proc_ready, inst_rready_s, inst_arready_s}), + .perfs (perfs) ); diff --git a/rtl/friscv_rv32i_platform.sv b/rtl/friscv_rv32i_platform.sv index ffb8449..0fa28c0 100644 --- a/rtl/friscv_rv32i_platform.sv +++ b/rtl/friscv_rv32i_platform.sv @@ -41,6 +41,12 @@ module friscv_rv32i_platform parameter F_EXTENSION = 0, // Multiply/Divide extension support parameter M_EXTENSION = 0, + // Support hypervisor mode + parameter HYPERVISOR_MODE = 0, + // Support supervisor mode + parameter SUPERVISOR_MODE = 0, + // Support user mode + parameter USER_MODE = 0, // Insert a pipeline on instruction bus coming from the controller parameter PROCESSING_BUS_PIPELINE = 0, @@ -313,31 +319,34 @@ module friscv_rv32i_platform friscv_rv32i_core #( - .ILEN (ILEN), - .XLEN (XLEN), - .M_EXTENSION (M_EXTENSION), - .F_EXTENSION (F_EXTENSION), - .PROCESSING_BUS_PIPELINE (PROCESSING_BUS_PIPELINE), - .BOOT_ADDR (BOOT_ADDR), - .INST_OSTDREQ_NUM (INST_OSTDREQ_NUM), - .DATA_OSTDREQ_NUM (DATA_OSTDREQ_NUM), - .HART_ID (HART_ID), - .RV32E (RV32E), - .AXI_ADDR_W (AXI_ADDR_W), - .AXI_ID_W (AXI_ID_W), - .AXI_IMEM_W (AXI_IMEM_W), - .AXI_DMEM_W (AXI_DMEM_W), - .AXI_IMEM_MASK (AXI_IMEM_MASK), - .AXI_DMEM_MASK (AXI_DMEM_MASK), - .CACHE_EN (CACHE_EN), - .ICACHE_PREFETCH_EN (ICACHE_PREFETCH_EN), - .ICACHE_BLOCK_W (ICACHE_BLOCK_W), - .ICACHE_DEPTH (ICACHE_DEPTH), - .IO_MAP_NB (IO_MAP_NB), - .IO_MAP (IO_MAP), - .DCACHE_PREFETCH_EN (DCACHE_PREFETCH_EN), - .DCACHE_BLOCK_W (DCACHE_BLOCK_W), - .DCACHE_DEPTH (DCACHE_DEPTH) + .ILEN (ILEN), + .XLEN (XLEN), + .M_EXTENSION (M_EXTENSION), + .F_EXTENSION (F_EXTENSION), + .HYPERVISOR_MODE (HYPERVISOR_MODE), + .SUPERVISOR_MODE (SUPERVISOR_MODE), + .USER_MODE (USER_MODE), + .PROCESSING_BUS_PIPELINE (PROCESSING_BUS_PIPELINE), + .BOOT_ADDR (BOOT_ADDR), + .INST_OSTDREQ_NUM (INST_OSTDREQ_NUM), + .DATA_OSTDREQ_NUM (DATA_OSTDREQ_NUM), + .HART_ID (HART_ID), + .RV32E (RV32E), + .AXI_ADDR_W (AXI_ADDR_W), + .AXI_ID_W (AXI_ID_W), + .AXI_IMEM_W (AXI_IMEM_W), + .AXI_DMEM_W (AXI_DMEM_W), + .AXI_IMEM_MASK (AXI_IMEM_MASK), + .AXI_DMEM_MASK (AXI_DMEM_MASK), + .CACHE_EN (CACHE_EN), + .ICACHE_PREFETCH_EN (ICACHE_PREFETCH_EN), + .ICACHE_BLOCK_W (ICACHE_BLOCK_W), + .ICACHE_DEPTH (ICACHE_DEPTH), + .IO_MAP_NB (IO_MAP_NB), + .IO_MAP (IO_MAP), + .DCACHE_PREFETCH_EN (DCACHE_PREFETCH_EN), + .DCACHE_BLOCK_W (DCACHE_BLOCK_W), + .DCACHE_DEPTH (DCACHE_DEPTH) ) cpu0 ( diff --git a/test/common/friscv_testbench.sv b/test/common/friscv_testbench.sv index ccc0d44..25fd5ff 100644 --- a/test/common/friscv_testbench.sv +++ b/test/common/friscv_testbench.sv @@ -97,6 +97,12 @@ module friscv_testbench( parameter F_EXTENSION = 0; // Multiply/Divide extension support parameter M_EXTENSION = 1; + // Support hypervisor mode + parameter HYPERVISOR_MODE = 0; + // Support supervisor mode + parameter SUPERVISOR_MODE = 0; + // Support user mode + parameter USER_MODE = 0; // Insert a pipeline on instruction bus coming from the controller parameter PROCESSING_BUS_PIPELINE = 1; @@ -291,6 +297,9 @@ module friscv_testbench( .RV32E (RV32E), .M_EXTENSION (M_EXTENSION), .F_EXTENSION (F_EXTENSION), + .HYPERVISOR_MODE (HYPERVISOR_MODE), + .SUPERVISOR_MODE (SUPERVISOR_MODE), + .USER_MODE (USER_MODE), .PROCESSING_BUS_PIPELINE (PROCESSING_BUS_PIPELINE), .AXI_ADDR_W (AXI_ADDR_W), .AXI_ID_W (AXI_ID_W), @@ -477,6 +486,9 @@ module friscv_testbench( .RV32E (RV32E), .M_EXTENSION (M_EXTENSION), .F_EXTENSION (F_EXTENSION), + .HYPERVISOR_MODE (HYPERVISOR_MODE), + .SUPERVISOR_MODE (SUPERVISOR_MODE), + .USER_MODE (USER_MODE), .PROCESSING_BUS_PIPELINE (PROCESSING_BUS_PIPELINE), .AXI_ADDR_W (AXI_ADDR_W), .AXI_ID_W (AXI_ID_W),