Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main

This commit is contained in:
Ross Thompson 2021-06-23 09:34:42 -05:00
commit 5de7a46237
10 changed files with 87 additions and 76 deletions

View File

@ -65,17 +65,17 @@ add wave -hex /testbench/dut/hart/priv/csr/genblk1/csrm/MEPC_REGW
add wave -divider add wave -divider
# peripherals # peripherals
add wave -hex /testbench/dut/uncore/plic/* #add wave -hex /testbench/dut/uncore/plic/*
add wave -hex /testbench/dut/uncore/plic/intPriority #add wave -hex /testbench/dut/uncore/plic/intPriority
add wave -hex /testbench/dut/uncore/plic/pendingArray #add wave -hex /testbench/dut/uncore/plic/pendingArray
add wave -divider #add wave -divider
add wave -hex /testbench/dut/uncore/uart/u/* #add wave -hex /testbench/dut/uncore/uart/u/*
add wave -divider #add wave -divider
add wave -hex /testbench/dut/uncore/gpio/* #add wave -hex /testbench/dut/uncore/gpio/*
add wave -divider #add wave -divider
add wave -hex /testbench/dut/hart/ebu/* #add wave -hex /testbench/dut/hart/ebu/*
add wave -divider #add wave -divider
add wave -divider #add wave -divider
# everything else # everything else
add wave -hex -r /testbench/* add wave -hex -r /testbench/*

View File

@ -1,10 +1,10 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// dmem.sv // lsu.sv
// //
// Written: David_Harris@hmc.edu 9 January 2021 // Written: David_Harris@hmc.edu 9 January 2021
// Modified: // Modified:
// //
// Purpose: Data memory // Purpose: Load/Store Unit
// Top level of the memory-stage hart logic // Top level of the memory-stage hart logic
// Contains data cache, DTLB, subword read/write datapath, interface to external bus // Contains data cache, DTLB, subword read/write datapath, interface to external bus
// //
@ -28,7 +28,7 @@
`include "wally-config.vh" `include "wally-config.vh"
// *** Ross Thompson amo misalignment check? // *** Ross Thompson amo misalignment check?
module dmem ( module lsu (
input logic clk, reset, input logic clk, reset,
input logic StallM, FlushM, StallW, FlushW, input logic StallM, FlushM, StallW, FlushW,
//output logic DataStall, //output logic DataStall,

View File

@ -28,17 +28,25 @@
module adrdec ( module adrdec (
input logic [31:0] HADDR, input logic [31:0] HADDR,
input logic [31:0] Base, Range, input logic [31:0] Base, Range,
input logic Supported,
input logic AccessValid,
input logic [2:0] Size,
input logic [3:0] SizeMask,
output logic HSEL output logic HSEL
); );
logic [31:0] match; logic Match;
logic SizeValid;
// determine if an address is in a range starting at the base // determine if an address is in a range starting at the base
// for example, if Base = 0x04002000 and range = 0x00000FFF, // for example, if Base = 0x04002000 and range = 0x00000FFF,
// then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1) // then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1)
assign Match = &((HADDR ~^ Base) | Range);
assign match = (HADDR ~^ Base) | Range; // determine if legal size of access is being made (byte, halfword, word, doubleword)
assign HSEL = &match; assign SizeValid = SizeMask[Size[1:0]];
assign HSEL = Match && Supported && AccessValid && SizeValid;
endmodule endmodule

View File

@ -1,10 +1,10 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// pmaadrdec.sv // adrdecs.sv
// //
// Written: David_Harris@hmc.edu 29 January 2021 // Written: David_Harris@hmc.edu 22 June 2021
// Modified: // Modified:
// //
// Purpose: Address decoder // Purpose: All the address decoders for peripherals
// //
// A component of the Wally configurable RISC-V project. // A component of the Wally configurable RISC-V project.
// //
@ -25,28 +25,20 @@
`include "wally-config.vh" `include "wally-config.vh"
module pmaadrdec ( module adrdecs (
input logic [31:0] HADDR, input logic [31:0] HADDR, // *** will need to use PAdr in mmu, stick with HADDR in uncore
input logic [31:0] Base, Range, input logic AccessRW, AccessRX, AccessRWX,
input logic Supported, input logic [2:0] HSIZE,
input logic AccessValid, output logic [5:0] HSELRegions
input logic [2:0] Size,
input logic [3:0] SizeMask,
output logic HSEL
); );
logic Match; // Determine which region of physical memory (if any) is being accessed
logic SizeValid; // *** eventually uncomment Access signals
adrdec boottimdec(HADDR, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, 1'b1/*AccessRX*/, HSIZE, 4'b1111, HSELRegions[5]);
// determine if an address is in a range starting at the base adrdec timdec(HADDR, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, 1'b1/*AccessRWX*/, HSIZE, 4'b1111, HSELRegions[4]);
// for example, if Base = 0x04002000 and range = 0x00000FFF, adrdec clintdec(HADDR, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, HSIZE, 4'b1111, HSELRegions[3]);
// then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1) adrdec gpiodec(HADDR, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[2]);
assign Match = &((HADDR ~^ Base) | Range); adrdec uartdec(HADDR, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, HSIZE, 4'b0001, HSELRegions[1]);
adrdec plicdec(HADDR, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[0]);
// determine if legal size of access is being made (byte, halfword, word, doubleword)
assign SizeValid = SizeMask[Size[1:0]];
assign HSEL = Match && Supported && AccessValid && SizeValid;
endmodule endmodule

View File

@ -58,13 +58,7 @@ module pmachecker (
assign AccessRX = ReadAccessM | ExecuteAccessF; assign AccessRX = ReadAccessM | ExecuteAccessF;
// Determine which region of physical memory (if any) is being accessed // Determine which region of physical memory (if any) is being accessed
// *** linux tests fail early when Access is anything other than 1b1 adrdecs adrdecs(HADDR, AccessRW, AccessRX, AccessRWX, HSIZE, HSELRegions);
pmaadrdec boottimdec(HADDR, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, 1'b1/*AccessRX*/, HSIZE, 4'b1111, HSELRegions[5]);
pmaadrdec timdec(HADDR, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, 1'b1/*AccessRWX*/, HSIZE, 4'b1111, HSELRegions[4]);
pmaadrdec clintdec(HADDR, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, HSIZE, 4'b1111, HSELRegions[3]);
pmaadrdec gpiodec(HADDR, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[2]);
pmaadrdec uartdec(HADDR, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, HSIZE, 4'b0001, HSELRegions[1]);
pmaadrdec plicdec(HADDR, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[0]);
// Only RAM memory regions are cacheable // Only RAM memory regions are cacheable
assign Cacheable = HSELRegions[5] | HSELRegions[4]; assign Cacheable = HSELRegions[5] | HSELRegions[4];

View File

@ -30,11 +30,8 @@
`include "wally-config.vh" `include "wally-config.vh"
module pmpadrdec ( module pmpadrdec (
input logic [31:0] HADDR, input logic [31:0] HADDR, // *** replace with PAdr
input logic [1:0] AdrMode, input logic [1:0] AdrMode,
// input logic [`XLEN-1:0] PreviousPMPAdr,
input logic [`XLEN-1:0] CurrentPMPAdr, input logic [`XLEN-1:0] CurrentPMPAdr,
input logic AdrAtLeastPreviousPMP, input logic AdrAtLeastPreviousPMP,
output logic AdrAtLeastCurrentPMP, output logic AdrAtLeastCurrentPMP,
@ -45,35 +42,48 @@ module pmpadrdec (
localparam NA4 = 2'b10; localparam NA4 = 2'b10;
localparam NAPOT = 2'b11; localparam NAPOT = 2'b11;
logic TORMatch, NA4Match, NAPOTMatch; logic TORMatch, NAMatch;
logic AdrBelowCurrentPMP; logic AdrBelowCurrentPMP;
logic [`PA_BITS-1:0] CurrentAdrFull;
logic [`PA_BITS-1:0] FakePhysAdr;
logic [31:0] CurrentAdrFull; // ***replace this when the true physical address from MMU is available
// logic [31:0] PreviousAdrFull; assign FakePhysAdr = {{(`PA_BITS-32){1'b0}}, HADDR};
logic [33:0] Range;
//assign PreviousAdrFull = {PreviousPMPAdr[29:0], 2'b00};
assign CurrentAdrFull = {CurrentPMPAdr[29:0], 2'b00};
// Top-of-range (TOR) // Top-of-range (TOR)
// *** Check if this synthesizes // Append two implicit trailing 0's to PMPAdr value
// if not, literally do comparison (HADDR - PreviousAdrFull == 0) assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00};
assign AdrBelowCurrentPMP = HADDR < CurrentAdrFull; assign AdrBelowCurrentPMP = /*HADDR */FakePhysAdr < CurrentAdrFull; // *** make sure unsigned comparison works correctly
assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP; assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP;
assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP;
// Naturally aligned four-byte region // Naturally aligned regions
adrdec na4dec(HADDR, CurrentAdrFull, (2**2)-1, NA4Match); // *** should be able to optimize away bottom 2 bits
// verilator lint_off UNOPTFLAT
logic [`PA_BITS-1:0] Mask;
genvar i;
// create a mask of which bits to ignore
generate generate
if (`XLEN == 32 || `XLEN == 64) begin assign Mask[1:0] = 2'b11;
assign Mask[2] = (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region
for (i=3; i < `PA_BITS; i=i+1)
assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore
endgenerate
// verilator lint_on UNOPTFLAT
assign NAMatch = &((FakePhysAdr ~^ CurrentAdrFull) | Mask);
/* generate
if (`XLEN == 32 || `XLEN == 64) begin // ***redo for various sizes
// priority encoder to translate address to range // priority encoder to translate address to range
// *** We'd like to replace this with a better priority encoder // *** We'd like to replace this with a better priority encoder
// *** We should not be truncating 64 bit physical addresses to 32 bits... // *** We should not be truncating 64 bit physical addresses to 32 bits...
// *** there is an easy combinatinoal way to do this with a cascade of AND gates O(32) rather than O(32^2) dh
always_comb always_comb
casez (CurrentPMPAdr[31:0]) if (AdrMode == NA4) Range = (2**2) - 1;
else casez (CurrentPMPAdr[31:0]) // NAPOT regions
32'b???????????????????????????????0: Range = (2**3) - 1; 32'b???????????????????????????????0: Range = (2**3) - 1;
32'b??????????????????????????????01: Range = (2**4) - 1; 32'b??????????????????????????????01: Range = (2**4) - 1;
32'b?????????????????????????????011: Range = (2**5) - 1; 32'b?????????????????????????????011: Range = (2**5) - 1;
@ -116,11 +126,11 @@ module pmpadrdec (
// *** Range should not be truncated... but our physical address space is // *** Range should not be truncated... but our physical address space is
// currently only 32 bits wide. // currently only 32 bits wide.
adrdec napotdec(HADDR, CurrentAdrFull, Range[31:0], NAPOTMatch); // with a bit of combining of range selection, this could be shared with NA4Match ***
assign NAMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]);*/
assign Match = (AdrMode == TOR) ? TORMatch : assign Match = (AdrMode == TOR) ? TORMatch :
(AdrMode == NA4) ? NA4Match : (AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch :
(AdrMode == NAPOT) ? NAPOTMatch :
0; 0;
endmodule endmodule

View File

@ -76,6 +76,8 @@ module pmpchecker (
logic L_Bit, X_Bit, W_Bit, R_Bit; logic L_Bit, X_Bit, W_Bit, R_Bit;
logic InvalidExecute, InvalidWrite, InvalidRead; logic InvalidExecute, InvalidWrite, InvalidRead;
// *** extend to optionally 64 configurations
assign {PMPCFG[15], PMPCFG[14], PMPCFG[13], PMPCFG[12], assign {PMPCFG[15], PMPCFG[14], PMPCFG[13], PMPCFG[12],
PMPCFG[11], PMPCFG[10], PMPCFG[9], PMPCFG[8]} = PMPCFG23_REGW; PMPCFG[11], PMPCFG[10], PMPCFG[9], PMPCFG[8]} = PMPCFG23_REGW;
@ -107,6 +109,7 @@ module pmpchecker (
// Only enforce PMP checking for S and U modes when at least one PMP is active // Only enforce PMP checking for S and U modes when at least one PMP is active
assign EnforcePMP = |ActiveRegion; assign EnforcePMP = |ActiveRegion;
// *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region
always_comb always_comb
casez (Regions) casez (Regions)
16'b???????????????1: MatchedRegion = 0; 16'b???????????????1: MatchedRegion = 0;
@ -137,6 +140,7 @@ module pmpchecker (
assign InvalidWrite = WriteAccessM && ~W_Bit; assign InvalidWrite = WriteAccessM && ~W_Bit;
assign InvalidRead = ReadAccessM && ~R_Bit; assign InvalidRead = ReadAccessM && ~R_Bit;
// *** don't cause faults when there are no PMPs
assign PMPInstrAccessFaultF = (PrivilegeModeW == `M_MODE) ? assign PMPInstrAccessFaultF = (PrivilegeModeW == `M_MODE) ?
Match && L_Bit && InvalidExecute : Match && L_Bit && InvalidExecute :
EnforcePMP && InvalidExecute; EnforcePMP && InvalidExecute;

View File

@ -47,8 +47,6 @@ module uncore (
input logic [2:0] HADDRD, input logic [2:0] HADDRD,
input logic [3:0] HSIZED, input logic [3:0] HSIZED,
input logic HWRITED, input logic HWRITED,
// PMA checker signals
input logic [5:0] HSELRegions,
// bus interface // bus interface
// PMA checker now handles access faults. *** This can be deleted // PMA checker now handles access faults. *** This can be deleted
// output logic DataAccessFaultM, // output logic DataAccessFaultM,
@ -64,6 +62,7 @@ module uncore (
logic [`XLEN-1:0] HWDATA; logic [`XLEN-1:0] HWDATA;
logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART; logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART;
logic [5:0] HSELRegions;
logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART; logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART;
logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD; logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD;
logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART; logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART;
@ -73,6 +72,10 @@ module uncore (
logic [1:0] MemRWboottim; logic [1:0] MemRWboottim;
logic UARTIntr,GPIOIntr; logic UARTIntr,GPIOIntr;
// Determine which region of physical memory (if any) is being accessed
// Use a trimmed down portion of the PMA checker - only the address decoders
adrdecs adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE, HSELRegions);
// unswizzle HSEL signals // unswizzle HSEL signals
assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions; assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions;

View File

@ -161,7 +161,7 @@ module wallypipelinedhart (
mux2 #(`XLEN) OutputInput2mux(WriteDataM, FWriteDataM, FMemRWM[0], WriteDatatmpM); mux2 #(`XLEN) OutputInput2mux(WriteDataM, FWriteDataM, FMemRWM[0], WriteDatatmpM);
dmem dmem(.MemRWM(MemRWM|FMemRWM), .WriteDataM(WriteDatatmpM),.*); // data cache unit lsu lsu(.MemRWM(MemRWM|FMemRWM), .WriteDataM(WriteDatatmpM),.*); // data cache unit
ahblite ebu( ahblite ebu(
//.InstrReadF(1'b0), //.InstrReadF(1'b0),