Updated the names of the *WriteDataM inside the LSU to more meaningful names.

Moved the FWriteDataMux so that the bus and dtim both get fpu stores.
Modified the PMA to disallow double sized reads when XLEN=32.
This commit is contained in:
Ross Thompson 2022-08-23 10:34:39 -05:00
parent 7c91ed38a3
commit cd0da2e3b3
8 changed files with 63 additions and 59 deletions

View File

@ -34,15 +34,15 @@ module simpleram #(parameter BASE=0, RANGE = 65535) (
input logic clk,
input logic [31:0] a,
input logic we,
input logic [`XLEN/8-1:0] ByteMask,
input logic [`XLEN-1:0] wd,
output logic [`XLEN-1:0] rd
input logic [`LLEN/8-1:0] ByteMask,
input logic [`LLEN-1:0] wd,
output logic [`LLEN-1:0] rd
);
localparam ADDR_WDITH = $clog2(RANGE/8);
localparam OFFSET = $clog2(`XLEN/8);
localparam OFFSET = $clog2(`LLEN/8);
bram1p1rw #(`XLEN/8, 8, ADDR_WDITH)
bram1p1rw #(`LLEN/8, 8, ADDR_WDITH)
memory(.clk, .we, .bwe(ByteMask), .addr(a[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(rd), .din(wd));
endmodule

View File

@ -187,7 +187,7 @@ module ifu (
if (`IMEM == `MEM_TIM) begin : irom // *** fix up dtim taking PA_BITS rather than XLEN, *** IEUAdr is a bad name. Probably use a ROM rather than DTIM
dtim irom(.clk, .reset, .CPUBusy, .LSURWM(2'b10), .IEUAdrM({{(`XLEN-32){1'b0}}, PCPF[31:0]}), .IEUAdrE(PCNextFSpill),
.TrapM(1'b0), .FinalWriteDataM(), .ByteMaskM('0),
.TrapM(1'b0), .WriteDataM(), .ByteMaskM('0),
.ReadDataWordM({{(`XLEN-32){1'b0}}, FinalInstrRawF}), .BusStall, .LSUBusWrite(), .LSUBusRead(IFUBusRead),
.BusCommittedM(), .DCacheStallM(ICacheStallF), .Cacheable(CacheableF),
.DCacheCommittedM(), .DCacheMiss(ICacheMiss), .DCacheAccess(ICacheAccess));

View File

@ -34,23 +34,23 @@ module atomic (
input logic clk,
input logic reset, StallW,
input logic [`XLEN-1:0] ReadDataM,
input logic [`XLEN-1:0] LSUWriteDataM,
input logic [`XLEN-1:0] IMWriteDataM,
input logic [`PA_BITS-1:0] LSUPAdrM,
input logic [6:0] LSUFunct7M,
input logic [2:0] LSUFunct3M,
input logic [1:0] LSUAtomicM,
input logic [1:0] PreLSURWM,
input logic IgnoreRequest,
output logic [`XLEN-1:0] AMOWriteDataM,
output logic [`XLEN-1:0] IMAWriteDataM,
output logic SquashSCW,
output logic [1:0] LSURWM);
logic [`XLEN-1:0] AMOResult;
logic MemReadM;
amoalu amoalu(.srca(ReadDataM), .srcb(LSUWriteDataM), .funct(LSUFunct7M), .width(LSUFunct3M[1:0]),
amoalu amoalu(.srca(ReadDataM), .srcb(IMWriteDataM), .funct(LSUFunct7M), .width(LSUFunct3M[1:0]),
.result(AMOResult));
mux2 #(`XLEN) wdmux(LSUWriteDataM, AMOResult, LSUAtomicM[1], AMOWriteDataM);
mux2 #(`XLEN) wdmux(IMWriteDataM, AMOResult, LSUAtomicM[1], IMAWriteDataM);
assign MemReadM = PreLSURWM[1] & ~IgnoreRequest;
lrsc lrsc(.clk, .reset, .StallW, .MemReadM, .PreLSURWM, .LSUAtomicM, .LSUPAdrM,
.SquashSCW, .LSURWM);

View File

@ -36,10 +36,10 @@ module dtim(
input logic [`XLEN-1:0] IEUAdrM,
input logic [`XLEN-1:0] IEUAdrE,
input logic TrapM,
input logic [`XLEN-1:0] FinalWriteDataM,
input logic [`XLEN/8-1:0] ByteMaskM,
input logic [`LLEN-1:0] WriteDataM,
input logic [`LLEN/8-1:0] ByteMaskM,
input logic Cacheable,
output logic [`XLEN-1:0] ReadDataWordM,
output logic [`LLEN-1:0] ReadDataWordM,
output logic BusStall,
output logic LSUBusWrite,
output logic LSUBusRead,
@ -53,7 +53,7 @@ module dtim(
.clk, .ByteMask(ByteMaskM),
.a(CPUBusy | LSURWM[0] | reset ? IEUAdrM[31:0] : IEUAdrE[31:0]), // move mux out; this shouldn't be needed when stails are handled differently ***
.we(LSURWM[0] & Cacheable & ~TrapM), // have to ignore write if Trap.
.wd(FinalWriteDataM), .rd(ReadDataWordM));
.wd(WriteDataM), .rd(ReadDataWordM));
// since we have a local memory the bus connections are all disabled.
// There are no peripherals supported.

View File

@ -110,9 +110,10 @@ module lsu (
logic BusCommittedM, DCacheCommittedM;
logic SelLSUBusWord;
logic DataDAPageFaultM;
logic [`XLEN-1:0] LSUWriteDataM;
logic [`XLEN-1:0] IMWriteDataM, IMAWriteDataM;
logic [`LLEN-1:0] IMAFWriteDataM;
logic [`LLEN-1:0] ReadDataM;
logic [(`LLEN-1)/8:0] ByteMaskM, FinalByteMaskM;
logic [(`LLEN-1)/8:0] ByteMaskM;
// *** TO DO: Burst mode
@ -131,7 +132,7 @@ module lsu (
.TrapM, .DCacheStallM, .SATP_REGW, .PCF,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.ReadDataM(ReadDataM[`XLEN-1:0]), .WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
.IEUAdrExtM, .PTE, .LSUWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE,
.IEUAdrExtM, .PTE, .IMWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE,
.LSUAdrE, .PreLSUPAdrM, .CPUBusy, .InterlockStall, .SelHPTW,
.IgnoreRequestTLB);
end else begin
@ -140,7 +141,7 @@ module lsu (
assign LSUAdrE = IEUAdrE[11:0];
assign PreLSUPAdrM = IEUAdrExtM;
assign LSUFunct3M = Funct3M; assign LSUFunct7M = Funct7M; assign LSUAtomicM = AtomicM;
assign LSUWriteDataM = WriteDataM;
assign IMWriteDataM = WriteDataM;
end
// CommittedM tells the CPU's privilege unit the current instruction
@ -188,8 +189,7 @@ module lsu (
// Memory System
// Either Data Cache or Data Tightly Integrated Memory or just bus interface
/////////////////////////////////////////////////////////////////////////////////////////////
logic [`XLEN-1:0] AMOWriteDataM, IEUWriteDataM, LittleEndianWriteDataM;
logic [`LLEN-1:0] FinalWriteDataM;
logic [`LLEN-1:0] LSUWriteDataM, LittleEndianWriteDataM;
logic [`LLEN-1:0] ReadDataWordM, LittleEndianReadDataWordM;
logic [`LLEN-1:0] ReadDataWordMuxM;
logic IgnoreRequest;
@ -202,7 +202,7 @@ module lsu (
if (`DMEM == `MEM_TIM) begin : dtim
// *** directly instantiate RAM or ROM here. Instantiate SRAM1P1RW.
// Merge SimpleRAM and SRAM1p1rw into one that is good for synthesis and RAM libraries and flops
dtim dtim(.clk, .reset, .CPUBusy, .LSURWM, .IEUAdrM, .IEUAdrE, .TrapM, .FinalWriteDataM(IEUWriteDataM), //*** fix the dtim FinalWriteData
dtim dtim(.clk, .reset, .CPUBusy, .LSURWM, .IEUAdrM, .IEUAdrE, .TrapM, .WriteDataM(LSUWriteDataM), //*** fix the dtim FinalWriteData
.ReadDataWordM(ReadDataWordM[`XLEN-1:0]), .BusStall, .LSUBusWrite,.LSUBusRead, .BusCommittedM,
.DCacheStallM, .DCacheCommittedM, .ByteMaskM(ByteMaskM[`XLEN/8-1:0]), .Cacheable(CacheableM),
.DCacheMiss, .DCacheAccess);
@ -230,23 +230,15 @@ module lsu (
mux2 #(`LLEN) UnCachedDataMux(.d0(LittleEndianReadDataWordM), .d1({{`LLEN-`XLEN{1'b0}}, DLSUBusBuffer[`XLEN-1:0]}),
.s(SelUncachedAdr), .y(ReadDataWordMuxM));
mux2 #(`XLEN) LsuBushwdataMux(.d0(ReadDataWordM[`XLEN-1:0]), .d1(IEUWriteDataM),
mux2 #(`XLEN) LsuBushwdataMux(.d0(ReadDataWordM[`XLEN-1:0]), .d1(LSUWriteDataM),
.s(SelUncachedAdr), .y(LSUBusHWDATA));
// *** Ross fix up location of mux to be here; remove from IEU datapath
// *** look over entire FPU write and read paths
// *** Why is
if(CACHE_ENABLED) begin : dcache
if (`F_SUPPORTED)
mux2 #(`LLEN) datamux({{`LLEN/`XLEN}{IEUWriteDataM}}, FWriteDataM, FpLoadStoreM, FinalWriteDataM);
else
assign FinalWriteDataM = IEUWriteDataM;
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`XLEN), .DCACHE(1)) dcache(
.clk, .reset, .CPUBusy, .SelLSUBusWord, .RW(LSURWM), .Atomic(LSUAtomicM),
.FlushCache(FlushDCacheM), .NextAdr(LSUAdrE), .PAdr(LSUPAdrM),
.ByteMask(FinalByteMaskM), .WordCount,
.FinalWriteData(FinalWriteDataM), .Cacheable(CacheableM),
.ByteMask(ByteMaskM), .WordCount,
.FinalWriteData(LSUWriteDataM), .Cacheable(CacheableM),
.CacheStall(DCacheStallM), .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
.IgnoreRequestTLB, .TrapM, .CacheCommitted(DCacheCommittedM),
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(ReadDataWordM),
@ -266,24 +258,27 @@ module lsu (
// Atomic operations
/////////////////////////////////////////////////////////////////////////////////////////////
if (`A_SUPPORTED) begin:atomic
atomic atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[`XLEN-1:0]), .LSUWriteDataM, .LSUPAdrM,
atomic atomic(.clk, .reset, .StallW, .ReadDataM(ReadDataM[`XLEN-1:0]), .IMWriteDataM, .LSUPAdrM,
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
.AMOWriteDataM, .SquashSCW, .LSURWM);
.IMAWriteDataM, .SquashSCW, .LSURWM);
end else begin:lrsc
assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign AMOWriteDataM = LSUWriteDataM;
assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign IMAWriteDataM = IMWriteDataM;
end
if (`F_SUPPORTED)
mux2 #(`LLEN) datamux({{`LLEN/`XLEN}{IMAWriteDataM}}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM);
else assign IMAFWriteDataM = IMAWriteDataM;
/////////////////////////////////////////////////////////////////////////////////////////////
// Subword Accesses
/////////////////////////////////////////////////////////////////////////////////////////////
subwordread subwordread(.ReadDataWordMuxM, .LSUPAdrM(LSUPAdrM[2:0]),
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
subwordwrite subwordwrite(.LSUPAdrM(LSUPAdrM[2:0]),
.LSUFunct3M, .AMOWriteDataM, .LittleEndianWriteDataM);
.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
// Compute byte masks
swbytemaskword #(`LLEN) swbytemask(.Size(LSUFunct3M), .Adr(LSUPAdrM[$clog2(`LLEN/8)-1:0]), .ByteMask(ByteMaskM));
assign FinalByteMaskM = ByteMaskM;
/////////////////////////////////////////////////////////////////////////////////////////////
// MW Pipeline Register
@ -297,10 +292,10 @@ module lsu (
// swap the bytes when read from big-endian memory
/////////////////////////////////////////////////////////////////////////////////////////////
if (`BIGENDIAN_SUPPORTED) begin:endian
bigendianswap #(`XLEN) storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(IEUWriteDataM));
bigendianswap #(`LLEN) storeswap(.BigEndianM, .a(LittleEndianWriteDataM), .y(LSUWriteDataM));
bigendianswap #(`LLEN) loadswap(.BigEndianM, .a(ReadDataWordM), .y(LittleEndianReadDataWordM));
end else begin
assign IEUWriteDataM = LittleEndianWriteDataM;
assign LSUWriteDataM = LittleEndianWriteDataM;
assign LittleEndianReadDataWordM = ReadDataWordM;
end

View File

@ -54,7 +54,7 @@ module lsuvirtmem(
output logic [6:0] LSUFunct7M,
input logic [`XLEN-1:0] IEUAdrE,
output logic [`XLEN-1:0] PTE,
output logic [`XLEN-1:0] LSUWriteDataM,
output logic [`XLEN-1:0] IMWriteDataM,
output logic [1:0] PageType,
output logic [1:0] PreLSURWM,
output logic [1:0] LSUAtomicM,
@ -112,8 +112,8 @@ module lsuvirtmem(
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLSUAdrE);
mux2 #(`XLEN+2) lsupadrmux(IEUAdrExtM, HPTWAdrExt, SelHPTWAdr, PreLSUPAdrM);
if(`HPTW_WRITES_SUPPORTED)
mux2 #(`XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, LSUWriteDataM);
else assign LSUWriteDataM = WriteDataM;
mux2 #(`XLEN) lsuwritedatamux(WriteDataM, PTE, SelHPTW, IMWriteDataM);
else assign IMWriteDataM = WriteDataM;
mux2 #(12) replaymux(PreLSUAdrE, IEUAdrExtM[11:0], SelReplayMemE, LSUAdrE); // replay cpu request after hptw. *** redudant with mux in cache.
// always block interrupts when using the hardware page table walker.

View File

@ -33,25 +33,34 @@
module subwordwrite (
input logic [2:0] LSUPAdrM,
input logic [2:0] LSUFunct3M,
input logic [`XLEN-1:0] AMOWriteDataM,
output logic [`XLEN-1:0] LittleEndianWriteDataM);
input logic [`LLEN-1:0] IMAFWriteDataM,
output logic [`LLEN-1:0] LittleEndianWriteDataM);
// Replicate data for subword writes
if (`XLEN == 64) begin:sww
if (`LLEN == 128) begin:sww
always_comb
case(LSUFunct3M[2:0])
2'b000: LittleEndianWriteDataM = {16{IMAFWriteDataM[7:0]}}; // sb
2'b001: LittleEndianWriteDataM = {8{IMAFWriteDataM[15:0]}}; // sh
2'b010: LittleEndianWriteDataM = {4{IMAFWriteDataM[31:0]}}; // sw
2'b011: LittleEndianWriteDataM = {2{IMAFWriteDataM[63:0]}}; // sd
default: LittleEndianWriteDataM = IMAFWriteDataM; // sq
endcase
end else if (`LLEN == 64) begin:sww
always_comb
case(LSUFunct3M[1:0])
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
2'b00: LittleEndianWriteDataM = {8{IMAFWriteDataM[7:0]}}; // sb
2'b01: LittleEndianWriteDataM = {4{IMAFWriteDataM[15:0]}}; // sh
2'b10: LittleEndianWriteDataM = {2{IMAFWriteDataM[31:0]}}; // sw
2'b11: LittleEndianWriteDataM = IMAFWriteDataM; // sd
endcase
end else begin:sww // 32-bit
always_comb
case(LSUFunct3M[1:0])
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
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
endcase
end
endmodule

View File

@ -38,17 +38,17 @@ module adrdecs (
output logic [8:0] SelRegions
);
localparam logic [3:0] SUPPORTED_SIZE = (`XLEN == 64 ? 4'b1111 : 4'b0111);
// Determine which region of physical memory (if any) is being accessed
// *** eventually uncomment Access signals
adrdec ddr4dec(PhysicalAddress, `EXT_MEM_BASE, `EXT_MEM_RANGE, `EXT_MEM_SUPPORTED, AccessRWX, Size, 4'b1111, SelRegions[7]);
adrdec boottimdec(PhysicalAddress, `BOOTROM_BASE, `BOOTROM_RANGE, `BOOTROM_SUPPORTED, /*1'b1*/AccessRX, Size, 4'b1111, SelRegions[6]);
adrdec timdec(PhysicalAddress, `RAM_BASE, `RAM_RANGE, `RAM_SUPPORTED, /*1'b1*/AccessRWX, Size, 4'b1111, SelRegions[5]);
adrdec ddr4dec(PhysicalAddress, `EXT_MEM_BASE, `EXT_MEM_RANGE, `EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[7]);
adrdec boottimdec(PhysicalAddress, `BOOTROM_BASE, `BOOTROM_RANGE, `BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[6]);
adrdec timdec(PhysicalAddress, `RAM_BASE, `RAM_RANGE, `RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[5]);
adrdec clintdec(PhysicalAddress, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, Size, 4'b1111, SelRegions[4]);
adrdec clintdec(PhysicalAddress, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[4]);
adrdec gpiodec(PhysicalAddress, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[3]);
adrdec uartdec(PhysicalAddress, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[2]);
adrdec plicdec(PhysicalAddress, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[1]);
adrdec sdcdec(PhysicalAddress, `SDC_BASE, `SDC_RANGE, `SDC_SUPPORTED, AccessRW, Size, 4'b1100, SelRegions[0]); // *** PMA chapter says xlen only like CLINT
adrdec sdcdec(PhysicalAddress, `SDC_BASE, `SDC_RANGE, `SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[0]);
assign SelRegions[8] = ~|(SelRegions[7:0]);