From 8066ba45e8300c3783ba8357403ee1b04915cd99 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 8 May 2022 06:46:35 +0000 Subject: [PATCH] Preliminary support for big endian modes. Regression passes but no big endian tests written yet. --- pipelined/config/buildroot/wally-config.vh | 1 + pipelined/config/fpga/wally-config.vh | 1 + pipelined/config/rv32e/wally-config.vh | 1 + pipelined/config/rv32gc/wally-config.vh | 1 + pipelined/config/rv32i/wally-config.vh | 1 + pipelined/config/rv32ic/wally-config.vh | 1 + pipelined/config/rv64BP/wally-config.vh | 1 + pipelined/config/rv64fp/wally-config.vh | 1 + pipelined/config/rv64gc/wally-config.vh | 1 + pipelined/config/rv64i/wally-config.vh | 1 + pipelined/config/rv64ic/wally-config.vh | 1 + pipelined/src/lsu/lsu.sv | 38 ++++++++---- pipelined/src/lsu/subwordwrite.sv | 18 +++--- pipelined/src/mmu/hptw.sv | 20 +++---- pipelined/src/privileged/csr.sv | 13 +++-- pipelined/src/privileged/csrm.sv | 4 +- pipelined/src/privileged/csrsr.sv | 68 ++++++++++++++++++---- pipelined/src/privileged/privileged.sv | 9 ++- pipelined/src/privileged/trap.sv | 12 ++-- pipelined/src/wally/wallypipelinedcore.sv | 11 ++-- 20 files changed, 140 insertions(+), 64 deletions(-) diff --git a/pipelined/config/buildroot/wally-config.vh b/pipelined/config/buildroot/wally-config.vh index a9a9bc7ea..1419cca90 100644 --- a/pipelined/config/buildroot/wally-config.vh +++ b/pipelined/config/buildroot/wally-config.vh @@ -53,6 +53,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 1 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/fpga/wally-config.vh b/pipelined/config/fpga/wally-config.vh index 863c33853..83561e3e4 100644 --- a/pipelined/config/fpga/wally-config.vh +++ b/pipelined/config/fpga/wally-config.vh @@ -55,6 +55,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 1 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv32e/wally-config.vh b/pipelined/config/rv32e/wally-config.vh index 8774625d3..c849fc4ee 100644 --- a/pipelined/config/rv32e/wally-config.vh +++ b/pipelined/config/rv32e/wally-config.vh @@ -56,6 +56,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 0 `define VECTORED_INTERRUPTS_SUPPORTED 0 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 0 diff --git a/pipelined/config/rv32gc/wally-config.vh b/pipelined/config/rv32gc/wally-config.vh index 5deae9f82..7cadca0bc 100644 --- a/pipelined/config/rv32gc/wally-config.vh +++ b/pipelined/config/rv32gc/wally-config.vh @@ -54,6 +54,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 1 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv32i/wally-config.vh b/pipelined/config/rv32i/wally-config.vh index 64560dbb1..cb56b6b85 100644 --- a/pipelined/config/rv32i/wally-config.vh +++ b/pipelined/config/rv32i/wally-config.vh @@ -56,6 +56,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv32ic/wally-config.vh b/pipelined/config/rv32ic/wally-config.vh index c0cd6fb8f..ccdd3cb9e 100644 --- a/pipelined/config/rv32ic/wally-config.vh +++ b/pipelined/config/rv32ic/wally-config.vh @@ -54,6 +54,7 @@ `define IBUS 0 `define VIRTMEM_SUPPORTED 0 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 0 diff --git a/pipelined/config/rv64BP/wally-config.vh b/pipelined/config/rv64BP/wally-config.vh index 0f4357297..06525ec01 100644 --- a/pipelined/config/rv64BP/wally-config.vh +++ b/pipelined/config/rv64BP/wally-config.vh @@ -56,6 +56,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv64fp/wally-config.vh b/pipelined/config/rv64fp/wally-config.vh index a99ae2df7..c6f80d497 100644 --- a/pipelined/config/rv64fp/wally-config.vh +++ b/pipelined/config/rv64fp/wally-config.vh @@ -53,6 +53,7 @@ `define IMEM `MEM_CACHE `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv64gc/wally-config.vh b/pipelined/config/rv64gc/wally-config.vh index f1476ea1e..35b74c6d2 100644 --- a/pipelined/config/rv64gc/wally-config.vh +++ b/pipelined/config/rv64gc/wally-config.vh @@ -55,6 +55,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 1 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv64i/wally-config.vh b/pipelined/config/rv64i/wally-config.vh index 89e399428..b9b2e0f6e 100644 --- a/pipelined/config/rv64i/wally-config.vh +++ b/pipelined/config/rv64i/wally-config.vh @@ -55,6 +55,7 @@ `define IBUS 1 `define VIRTMEM_SUPPORTED 1 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 32 diff --git a/pipelined/config/rv64ic/wally-config.vh b/pipelined/config/rv64ic/wally-config.vh index 5dbf70b19..fc77b8484 100644 --- a/pipelined/config/rv64ic/wally-config.vh +++ b/pipelined/config/rv64ic/wally-config.vh @@ -55,6 +55,7 @@ `define IBUS 0 `define VIRTMEM_SUPPORTED 0 `define VECTORED_INTERRUPTS_SUPPORTED 1 +`define BIGENDIAN_SUPPORTED 0 // TLB configuration. Entries should be a power of 2 `define ITLB_ENTRIES 0 diff --git a/pipelined/src/lsu/lsu.sv b/pipelined/src/lsu/lsu.sv index 81e5fcbc2..eaad232df 100644 --- a/pipelined/src/lsu/lsu.sv +++ b/pipelined/src/lsu/lsu.sv @@ -53,7 +53,8 @@ module lsu ( input logic [`XLEN-1:0] WriteDataE, output logic [`XLEN-1:0] ReadDataM, // cpu privilege - input logic [1:0] PrivilegeModeW, + input logic [1:0] PrivilegeModeW, + input logic BigEndianM, input logic DTLBFlushM, // faults output logic LoadPageFaultM, StoreAmoPageFaultM, @@ -77,7 +78,7 @@ module lsu ( input logic InstrDAPageFaultF, output logic [`XLEN-1:0] PTE, output logic [1:0] PageType, - output logic ITLBWriteF, + output logic ITLBWriteF, SelHPTW, input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // *** this one especially has a large note attached to it in pmpchecker. ); @@ -96,7 +97,6 @@ module lsu ( logic CPUBusy; logic DCacheStallM; logic CacheableM; - logic SelHPTW; logic BusStall; logic InterlockStall; logic IgnoreRequestTLB, IgnoreRequestTrapM; @@ -182,8 +182,8 @@ module lsu ( // Memory System // Either Data Cache or Data Tightly Integrated Memory or just bus interface ///////////////////////////////////////////////////////////////////////////////////////////// - logic [`XLEN-1:0] AMOWriteDataM, FinalWriteDataM; - logic [`XLEN-1:0] ReadDataWordM; + logic [`XLEN-1:0] AMOWriteDataM, FinalWriteDataM, LittleEndianWriteDataM; + logic [`XLEN-1:0] ReadDataWordM, LittleEndianReadDataWordM; logic [`XLEN-1:0] ReadDataWordMuxM; logic IgnoreRequest; logic SelUncachedAdr; @@ -220,7 +220,7 @@ module lsu ( .SelUncachedAdr, .IgnoreRequest, .LSURWM, .CPUBusy, .CacheableM, .BusStall, .BusCommittedM); - mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM), .d1(DCacheBusWriteData[`XLEN-1:0]), + mux2 #(`XLEN) UnCachedDataMux(.d0(LittleEndianReadDataWordM), .d1(DCacheBusWriteData[`XLEN-1:0]), .s(SelUncachedAdr), .y(ReadDataWordMuxM)); mux2 #(`XLEN) LsuBushwdataMux(.d0(ReadDataWordM), .d1(FinalWriteDataM), .s(SelUncachedAdr), .y(LSUBusHWDATA)); @@ -244,12 +244,9 @@ module lsu ( end end else begin: nobus // block: bus assign {LSUBusHWDATA, SelUncachedAdr} = '0; - assign ReadDataWordMuxM = ReadDataWordM; + assign ReadDataWordMuxM = LittleEndianReadDataWordM; end - subwordread subwordread(.ReadDataWordMuxM, .LSUPAdrM(LSUPAdrM[2:0]), - .Funct3M(LSUFunct3M), .ReadDataM); - ///////////////////////////////////////////////////////////////////////////////////////////// // Atomic operations ///////////////////////////////////////////////////////////////////////////////////////////// @@ -261,8 +258,25 @@ module lsu ( assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign AMOWriteDataM = LSUWriteDataM; end + ///////////////////////////////////////////////////////////////////////////////////////////// + // Subword Accesses + ///////////////////////////////////////////////////////////////////////////////////////////// subwordwrite subwordwrite(.LSUPAdrM(LSUPAdrM[2:0]), - .LSUFunct3M, .AMOWriteDataM, .FinalWriteDataM, .ByteMaskM); + .LSUFunct3M, .AMOWriteDataM, .LittleEndianWriteDataM, .ByteMaskM); + subwordread subwordread(.ReadDataWordMuxM, .LSUPAdrM(LSUPAdrM[2:0]), + .Funct3M(LSUFunct3M), .ReadDataM); + + ///////////////////////////////////////////////////////////////////////////////////////////// + // Big Endian Byte Swapper + // hart works little-endian internally + // swap the bytes when read from big-endian memory + ///////////////////////////////////////////////////////////////////////////////////////////// + if (`BIGENDIAN_SUPPORTED) begin:endian + bigendianswap storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(FinalWriteDataM)); + bigendianswap loadswap(.BigEndianM, .a(ReadDataWordM), .y(LittleEndianReadDataWordM)); + end else begin + assign FinalWriteDataM = LittleEndianWriteDataM; + assign LittleEndianReadDataWordM = ReadDataWordM; + end - endmodule diff --git a/pipelined/src/lsu/subwordwrite.sv b/pipelined/src/lsu/subwordwrite.sv index 7f2a6b8d7..43c50e882 100644 --- a/pipelined/src/lsu/subwordwrite.sv +++ b/pipelined/src/lsu/subwordwrite.sv @@ -34,7 +34,7 @@ module subwordwrite ( input logic [2:0] LSUPAdrM, input logic [2:0] LSUFunct3M, input logic [`XLEN-1:0] AMOWriteDataM, - output logic [`XLEN-1:0] FinalWriteDataM, + output logic [`XLEN-1:0] LittleEndianWriteDataM, output logic [`XLEN/8-1:0] ByteMaskM ); @@ -45,18 +45,18 @@ module subwordwrite ( if (`XLEN == 64) begin:sww always_comb case(LSUFunct3M[1:0]) - 2'b00: FinalWriteDataM = {8{AMOWriteDataM[7:0]}}; // sb - 2'b01: FinalWriteDataM = {4{AMOWriteDataM[15:0]}}; // sh - 2'b10: FinalWriteDataM = {2{AMOWriteDataM[31:0]}}; // sw - 2'b11: FinalWriteDataM = AMOWriteDataM; // sw + 2'b00: LittleEndianWriteDataM = {8{AMOWriteDataM[7:0]}}; // sb + 2'b01: LittleEndianWriteDataM = {4{AMOWriteDataM[15:0]}}; // sh + 2'b10: LittleEndianWriteDataM = {2{AMOWriteDataM[31:0]}}; // sw + 2'b11: LittleEndianWriteDataM = AMOWriteDataM; // sw endcase end else begin:sww // 32-bit always_comb case(LSUFunct3M[1:0]) - 2'b00: FinalWriteDataM = {4{AMOWriteDataM[7:0]}}; // sb - 2'b01: FinalWriteDataM = {2{AMOWriteDataM[15:0]}}; // sh - 2'b10: FinalWriteDataM = AMOWriteDataM; // sw - default: FinalWriteDataM = AMOWriteDataM; // shouldn't happen + 2'b00: LittleEndianWriteDataM = {4{AMOWriteDataM[7:0]}}; // sb + 2'b01: LittleEndianWriteDataM = {2{AMOWriteDataM[15:0]}}; // sh + 2'b10: LittleEndianWriteDataM = AMOWriteDataM; // sw + default: LittleEndianWriteDataM = AMOWriteDataM; // shouldn't happen endcase end endmodule diff --git a/pipelined/src/mmu/hptw.sv b/pipelined/src/mmu/hptw.sv index 39ec91d5a..eb0fc9bd0 100644 --- a/pipelined/src/mmu/hptw.sv +++ b/pipelined/src/mmu/hptw.sv @@ -210,17 +210,17 @@ module hptw // Initial state and misalignment for RV32/64 if (`XLEN == 32) begin - assign InitialWalkerState = L1_ADR; - assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0 - // *** Possible bug - should be L1_ADR? - assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned); + assign InitialWalkerState = L1_ADR; + assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0 + // *** Possible bug - should be L1_ADR? + assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned); end else begin - logic GigapageMisaligned, TerapageMisaligned; - assign InitialWalkerState = (SvMode == `SV48) ? L3_ADR : L2_ADR; - assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0 - assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0 - assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0 - assign Misaligned = ((WalkerState == L2_ADR) & TerapageMisaligned) | ((WalkerState == L1_ADR) & GigapageMisaligned) | ((WalkerState == L0_ADR) & MegapageMisaligned); + logic GigapageMisaligned, TerapageMisaligned; + assign InitialWalkerState = (SvMode == `SV48) ? L3_ADR : L2_ADR; + assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0 + assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0 + assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0 + assign Misaligned = ((WalkerState == L2_ADR) & TerapageMisaligned) | ((WalkerState == L1_ADR) & GigapageMisaligned) | ((WalkerState == L0_ADR) & MegapageMisaligned); end // Page Table Walker FSM diff --git a/pipelined/src/privileged/csr.sv b/pipelined/src/privileged/csr.sv index afb9c5ef1..258f0f64e 100644 --- a/pipelined/src/privileged/csr.sv +++ b/pipelined/src/privileged/csr.sv @@ -56,6 +56,7 @@ module csr #(parameter input logic ICacheAccess, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic [`XLEN-1:0] CauseM, NextFaultMtvalM, + input logic SelHPTW, output logic [1:0] STATUS_MPP, output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, output logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, STVEC_REGW, MTVEC_REGW, @@ -72,7 +73,7 @@ module csr #(parameter output logic [2:0] FRM_REGW, // output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW, output logic [`XLEN-1:0] CSRReadValW, - output logic IllegalCSRAccessM + output logic IllegalCSRAccessM, BigEndianM ); localparam NOP = 32'h13; @@ -84,7 +85,7 @@ module csr #(parameter (* mark_debug = "true" *) logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW; logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW; - logic WriteMSTATUSM, WriteSSTATUSM; + logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM; logic WriteFRMM, WriteFFLAGSM; @@ -136,13 +137,13 @@ module csr #(parameter .MExtIntM, .SExtIntM, .TimerIntM, .SwIntM, .MIP_REGW, .MIE_REGW, .SIP_REGW, .SIE_REGW, .MIDELEG_REGW, .IP_REGW_writeable); csrsr csrsr(.clk, .reset, .StallW, - .WriteMSTATUSM, .WriteSSTATUSM, + .WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM, .TrapM, .FRegWriteM, .NextPrivilegeModeM, .PrivilegeModeW, - .mretM, .sretM, .WriteFRMM, .WriteFFLAGSM, .CSRWriteValM, + .mretM, .sretM, .WriteFRMM, .WriteFFLAGSM, .CSRWriteValM, .SelHPTW, .MSTATUS_REGW, .SSTATUS_REGW, .MSTATUSH_REGW, .STATUS_MPP, .STATUS_SPP, .STATUS_TSR, .STATUS_TW, .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM, - .STATUS_FS); + .STATUS_FS, .BigEndianM); csrc counters(.clk, .reset, .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, .InstrValidM, .LoadStallD, .CSRMWriteM, @@ -157,7 +158,7 @@ module csr #(parameter .CSRWriteValM, .CSRMReadValM, .MTVEC_REGW, .MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW, .MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, + .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM, .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM); csrs csrs(.clk, .reset, .InstrValidNotFlushedM, .StallW, .CSRSWriteM, .STrapM, .CSRAdrM, diff --git a/pipelined/src/privileged/csrm.sv b/pipelined/src/privileged/csrm.sv index eecf67893..21234fc60 100644 --- a/pipelined/src/privileged/csrm.sv +++ b/pipelined/src/privileged/csrm.sv @@ -86,7 +86,7 @@ module csrm #(parameter output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], (* mark_debug = "true" *) input logic [11:0] MIP_REGW, MIE_REGW, - output logic WriteMSTATUSM, + output logic WriteMSTATUSM, WriteMSTATUSHM, output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM ); @@ -134,7 +134,7 @@ module csrm #(parameter // Write machine Mode CSRs assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS) & InstrValidNotFlushedM; - // writes to MSTATUSH are not yet supported because the register is always 0 + assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & InstrValidNotFlushedM & (`XLEN==32); assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC) & InstrValidNotFlushedM; assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG) & InstrValidNotFlushedM; assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG) & InstrValidNotFlushedM; diff --git a/pipelined/src/privileged/csrsr.sv b/pipelined/src/privileged/csrsr.sv index 0d1912c16..c4f841959 100644 --- a/pipelined/src/privileged/csrsr.sv +++ b/pipelined/src/privileged/csrsr.sv @@ -33,31 +33,34 @@ module csrsr ( input logic clk, reset, StallW, - input logic WriteMSTATUSM, WriteSSTATUSM, + input logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM, input logic TrapM, FRegWriteM, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic mretM, sretM, input logic WriteFRMM, WriteFFLAGSM, input logic [`XLEN-1:0] CSRWriteValM, + input logic SelHPTW, output logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW, output logic [1:0] STATUS_MPP, output logic STATUS_SPP, STATUS_TSR, STATUS_TW, output logic STATUS_MIE, STATUS_SIE, output logic STATUS_MXR, STATUS_SUM, output logic STATUS_MPRV, STATUS_TVM, - output logic [1:0] STATUS_FS + output logic [1:0] STATUS_FS, + output logic BigEndianM ); logic STATUS_SD, STATUS_TW_INT, STATUS_TSR_INT, STATUS_TVM_INT, STATUS_MXR_INT, STATUS_SUM_INT, STATUS_MPRV_INT; logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS_INT, STATUS_MPP_NEXT; logic STATUS_MPIE, STATUS_SPIE, STATUS_UBE, STATUS_SBE, STATUS_MBE; + logic nextMBE, nextSBE; // STATUS REGISTER FIELD // See Privileged Spec Section 3.1.6 // Lower privilege status registers are a subset of the full status register // *** consider adding MBE, SBE, UBE fields, parameterized to be fixed or adjustable if (`XLEN==64) begin: csrsr64 // RV64 - assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_UBE, STATUS_SXL, STATUS_UXL, 9'b0, + assign MSTATUS_REGW = {STATUS_SD, 25'b0, STATUS_MBE, STATUS_SBE, STATUS_SXL, STATUS_UXL, 9'b0, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, STATUS_SPP, STATUS_MPIE, STATUS_UBE, STATUS_SPIE, 1'b0, @@ -80,14 +83,23 @@ module csrsr ( /*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0}; end + // extract values to write to upper status register on 64/32-bit access + if (`XLEN==64) begin:upperstatus + assign nextMBE = CSRWriteValM[37] & `BIGENDIAN_SUPPORTED; + assign nextSBE = CSRWriteValM[36] & `S_SUPPORTED & `BIGENDIAN_SUPPORTED; + end else begin:upperstatus + assign nextMBE = STATUS_MBE; + assign nextSBE = STATUS_SBE; + end + // harwired STATUS bits assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported - assign STATUS_UBE = 0; // little-endian +/* assign STATUS_UBE = 0; // little-endian assign STATUS_SBE = 0; // little-endian - assign STATUS_MBE = 0; // little-endian + assign STATUS_MBE = 0; // little-endian */ // SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not assign STATUS_SXL = `S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported assign STATUS_UXL = `U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported @@ -100,7 +112,29 @@ module csrsr ( always_comb if (CSRWriteValM[12:11] == `U_MODE & `U_SUPPORTED) STATUS_MPP_NEXT = `U_MODE; else if (CSRWriteValM[12:11] == `S_MODE & `S_SUPPORTED) STATUS_MPP_NEXT = `S_MODE; - else STATUS_MPP_NEXT = `M_MODE; + else STATUS_MPP_NEXT = `M_MODE; + + /////////////////////////////////////////// + // Endianness logic Privileged Spec 3.1.6.4 + /////////////////////////////////////////// + + if (`BIGENDIAN_SUPPORTED) begin: endianmux + // determine whether bit endian accesses should be made + logic [1:0] EndiannessPrivMode; + always_comb begin + if (SelHPTW) EndiannessPrivMode = `S_MODE; + else if (PrivilegeModeW == `M_MODE & STATUS_MPRV) EndiannessPrivMode = STATUS_MPP; + else EndiannessPrivMode = PrivilegeModeW; + + case (EndiannessPrivMode) + `M_MODE: BigEndianM = STATUS_MBE; + `S_MODE: BigEndianM = STATUS_SBE; + default: BigEndianM = STATUS_UBE; + endcase + end + end else begin: endianmux + assign BigEndianM = 0; + end // registers for STATUS bits // complex register with reset, write enable, and the ability to update other bits in certain cases @@ -113,12 +147,15 @@ module csrsr ( STATUS_SUM_INT <= #1 0; STATUS_MPRV_INT <= #1 0; // Per Priv 3.3 STATUS_FS_INT <= #1 `F_SUPPORTED ? 2'b01 : 2'b00; - STATUS_MPP <= #1 0; //`M_MODE; - STATUS_SPP <= #1 0; //1'b1; - STATUS_MPIE <= #1 0; //1; - STATUS_SPIE <= #1 0; //`S_SUPPORTED; - STATUS_MIE <= #1 0; // Per Priv 3.3 - STATUS_SIE <= #1 0; //`S_SUPPORTED; + STATUS_MPP <= #1 0; + STATUS_SPP <= #1 0; + STATUS_MPIE <= #1 0; + STATUS_SPIE <= #1 0; + STATUS_MIE <= #1 0; + STATUS_SIE <= #1 0; + STATUS_MBE <= #1 0; + STATUS_SBE <= #1 0; + STATUS_UBE <= #1 0; end else if (~StallW) begin if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #1 2'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else; @@ -161,6 +198,12 @@ module csrsr ( STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; STATUS_MIE <= #1 CSRWriteValM[3]; STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; + STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED; + STATUS_MBE <= #1 nextMBE; + STATUS_SBE <= #1 nextSBE; + end else if (WriteMSTATUSHM) begin + STATUS_MBE <= #1 CSRWriteValM[5] & `BIGENDIAN_SUPPORTED; + STATUS_SBE <= #1 CSRWriteValM[4] & `S_SUPPORTED & `BIGENDIAN_SUPPORTED; end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits STATUS_MXR_INT <= #1 CSRWriteValM[19]; STATUS_SUM_INT <= #1 CSRWriteValM[18]; @@ -168,6 +211,7 @@ module csrsr ( STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8]; STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; + STATUS_UBE <= #1 CSRWriteValM[6] & `U_SUPPORTED & `BIGENDIAN_SUPPORTED; end end endmodule diff --git a/pipelined/src/privileged/privileged.sv b/pipelined/src/privileged/privileged.sv index 21c7eab2b..2d2877df2 100644 --- a/pipelined/src/privileged/privileged.sv +++ b/pipelined/src/privileged/privileged.sv @@ -67,6 +67,7 @@ module privileged ( input logic InstrAccessFaultF, input logic LoadAccessFaultM, input logic StoreAmoAccessFaultM, + input logic SelHPTW, output logic ExceptionM, output logic IllegalFPUInstrE, @@ -78,7 +79,7 @@ module privileged ( output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW, - output logic BreakpointFaultM, EcallFaultM, wfiM, IntPendingM + output logic BreakpointFaultM, EcallFaultM, wfiM, IntPendingM, BigEndianM ); logic [1:0] NextPrivilegeModeM; @@ -142,6 +143,7 @@ module privileged ( assign WFITimeoutM = ((STATUS_TW & PrivilegeModeW != `M_MODE) | (`S_SUPPORTED & PrivilegeModeW == `U_MODE)) & WFICount[`WFI_TIMEOUT_BIT]; end else assign WFITimeoutM = 0; + /////////////////////////////////////////// // decode privileged instructions /////////////////////////////////////////// @@ -165,7 +167,8 @@ module privileged ( .BPPredDirWrongM, .BTBPredPCWrongM, .RASPredPCWrongM, .BPPredClassNonCFIWrongM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .NextPrivilegeModeM, .PrivilegeModeW, - .CauseM, .NextFaultMtvalM, .STATUS_MPP, + .CauseM, .NextFaultMtvalM, .SelHPTW, + .STATUS_MPP, .STATUS_SPP, .STATUS_TSR, .STATUS_TVM, .MEPC_REGW, .SEPC_REGW, .STVEC_REGW, .MTVEC_REGW, .MEDELEG_REGW, @@ -178,7 +181,7 @@ module privileged ( .SetFflagsM, .FRM_REGW, .CSRReadValW, - .IllegalCSRAccessM); + .IllegalCSRAccessM, .BigEndianM); /////////////////////////////////////////// // Extract exceptions by name and handle them diff --git a/pipelined/src/privileged/trap.sv b/pipelined/src/privileged/trap.sv index df528fad7..953696a9a 100644 --- a/pipelined/src/privileged/trap.sv +++ b/pipelined/src/privileged/trap.sv @@ -118,12 +118,12 @@ module trap ( // Exceptions are of lower priority than all interrupts (3.1.9) always_comb if (reset) CauseM = 0; // hard reset 3.3 - else if (ValidIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int - else if (ValidIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int - else if (ValidIntsM[7]) CauseM = (1 << (`XLEN-1)) + 7; // Machine Timer Int - else if (ValidIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int - else if (ValidIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int - else if (ValidIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int + else if (ValidIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int + else if (ValidIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int + else if (ValidIntsM[7]) CauseM = (1 << (`XLEN-1)) + 7; // Machine Timer Int + else if (ValidIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int + else if (ValidIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int + else if (ValidIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int else if (InstrPageFaultM) CauseM = 12; else if (InstrAccessFaultM) CauseM = 1; else if (IllegalInstrFaultM) CauseM = 2; diff --git a/pipelined/src/wally/wallypipelinedcore.sv b/pipelined/src/wally/wallypipelinedcore.sv index 38ef3f9c4..163c18138 100644 --- a/pipelined/src/wally/wallypipelinedcore.sv +++ b/pipelined/src/wally/wallypipelinedcore.sv @@ -113,6 +113,7 @@ module wallypipelinedcore ( logic [`XLEN-1:0] PTE; logic [1:0] PageType; logic wfiM, IntPendingM; + logic SelHPTW; // PMA checker signals var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; @@ -163,6 +164,7 @@ module wallypipelinedcore ( logic ICacheAccess; logic BreakpointFaultM, EcallFaultM; logic InstrDAPageFaultF; + logic BigEndianM; ifu ifu( .clk, .reset, @@ -257,7 +259,7 @@ module wallypipelinedcore ( .LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize, // connect to csr or privilege and stay the same. - .PrivilegeModeW, // connects to csr + .PrivilegeModeW, .BigEndianM, // connects to csr .PMPCFG_ARRAY_REGW, // connects to csr .PMPADDR_ARRAY_REGW, // connects to csr // hptw keep i/o @@ -276,7 +278,7 @@ module wallypipelinedcore ( .StoreAmoAccessFaultM, // connects to privilege .InstrDAPageFaultF, - .PCF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, + .PCF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW, .LSUStallM); // change to LSUStallM @@ -336,12 +338,12 @@ module wallypipelinedcore ( // Trap signals from pmp/pma in mmu // *** do these need to be split up into one for dmem and one for ifu? // instead, could we only care about the instr and F pins that come from ifu and only care about the load/store and m pins that come from dmem? - .InstrAccessFaultF, .LoadAccessFaultM, .StoreAmoAccessFaultM, + .InstrAccessFaultF, .LoadAccessFaultM, .StoreAmoAccessFaultM, .SelHPTW, .ExceptionM, .IllegalFPUInstrE, .PrivilegeModeW, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM + .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM ); end else begin assign CSRReadValW = 0; @@ -351,6 +353,7 @@ module wallypipelinedcore ( assign wfiM = 0; assign ITLBFlushF = 0; assign DTLBFlushM = 0; + assign BigEndianM = 0; end if (`M_SUPPORTED) begin:mdu muldiv mdu(