mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main
This commit is contained in:
commit
5de7a46237
@ -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/*
|
||||||
|
@ -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,
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
@ -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];
|
||||||
|
@ -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;
|
||||||
@ -112,15 +122,15 @@ module pmpadrdec (
|
|||||||
end else begin
|
end else begin
|
||||||
assign Range = '0;
|
assign Range = '0;
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
// *** 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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user