diff --git a/pipelined/src/ifu/spillsupport.sv b/pipelined/src/ifu/spillsupport.sv new file mode 100644 index 00000000..86c82cd7 --- /dev/null +++ b/pipelined/src/ifu/spillsupport.sv @@ -0,0 +1,100 @@ +/////////////////////////////////////////// +// spillsupport.sv +// +// Written: Ross Thompson ross1728@gmail.com January 28, 2022 +// Modified: +// +// Purpose: allows the IFU to make extra memory request if instruction address crosses +// cache line boundaries or if instruction address without a cache crosses +// XLEN/8 boundary. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// MIT LICENSE +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module spillsupport ( + input logic clk, + input logic reset, + input logic StallF, + input logic [`XLEN-1:0] PCF, + input logic [`XLEN-3:0] PCPlusUpperF, + input logic [`XLEN-1:0] PCNextF, + logic [31:0] InstrRawF, + input logic IFUCacheBusStallF, + output logic [`XLEN-1:0] PCNextFSpill, + output logic [`XLEN-1:0] PCFSpill, + output logic SelNextSpillF, + output logic [31:0] PostSpillInstrRawF, + output logic CompressedF); + + + localparam integer SPILLTHRESHOLD = `MEM_ICACHE ? `ICACHE_LINELENINBITS/32 : 1; + logic [`XLEN-1:0] PCPlus2F; + logic TakeSpillF; + logic SpillF; + logic SelSpillF, SpillSaveF; + logic [15:0] SpillDataLine0; + + // *** PLACE ALL THIS IN A MODULE + // this exists only if there are compressed instructions. + // reuse PC+2/4 circuitry to avoid needing a second CPA to add 2 + mux2 #(`XLEN) pcplus2mux(.d0({PCF[`XLEN-1:2], 2'b10}), .d1({PCPlusUpperF, 2'b00}), .s(PCF[1]), .y(PCPlus2F)); + mux2 #(`XLEN) pcnextspillmux(.d0(PCNextF), .d1(PCPlus2F), .s(SelNextSpillF), .y(PCNextFSpill)); + mux2 #(`XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCFSpill)); + + assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1]; + + typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype; + (* mark_debug = "true" *) statetype CurrState, NextState; + + always_ff @(posedge clk) + if (reset) CurrState <= #1 STATE_SPILL_READY; + else CurrState <= #1 NextState; + + assign TakeSpillF = SpillF & ~IFUCacheBusStallF; + + always_comb begin + case (CurrState) + STATE_SPILL_READY: if (TakeSpillF) NextState = STATE_SPILL_SPILL; + else NextState = STATE_SPILL_READY; + STATE_SPILL_SPILL: if(IFUCacheBusStallF | StallF) NextState = STATE_SPILL_SPILL; + else NextState = STATE_SPILL_READY; + default: NextState = STATE_SPILL_READY; + endcase + end + + assign SelSpillF = (CurrState == STATE_SPILL_SPILL); + assign SelNextSpillF = (CurrState == STATE_SPILL_READY & TakeSpillF) | + (CurrState == STATE_SPILL_SPILL & IFUCacheBusStallF); + assign SpillSaveF = (CurrState == STATE_SPILL_READY) & TakeSpillF; + + flopenr #(16) SpillInstrReg(.clk(clk), + .en(SpillSaveF), + .reset(reset), + .d(`MEM_ICACHE ? InstrRawF[15:0] : InstrRawF[31:16]), + .q(SpillDataLine0)); + + assign PostSpillInstrRawF = SpillF ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF; + assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11; + +endmodule diff --git a/pipelined/src/lsu/busdp.sv b/pipelined/src/lsu/busdp.sv new file mode 100644 index 00000000..1c5d793a --- /dev/null +++ b/pipelined/src/lsu/busdp.sv @@ -0,0 +1,99 @@ +/////////////////////////////////////////// +// busdp.sv +// +// Written: Ross Thompson ross1728@gmail.com January 30, 2022 +// Modified: +// +// Purpose: Bus data path. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// MIT LICENSE +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module busdp #(parameter WORDSPERLINE, parameter LINELEN, parameter LOGWPL, parameter WordCountThreshold) + ( + input logic clk, reset, + // bus interface + input logic [`XLEN-1:0] LSUBusHRDATA, + input logic LSUBusAck, + output logic LSUBusWrite, + output logic LSUBusRead, + output logic [`XLEN-1:0] LSUBusHWDATA, + output logic [2:0] LSUBusSize, + input logic [2:0] LSUFunct3M, + output logic [`PA_BITS-1:0] LSUBusAdr, + + // cache interface. + input logic [`PA_BITS-1:0] DCacheBusAdr, + input logic [`XLEN-1:0] ReadDataLineSetsM [WORDSPERLINE-1:0], + input logic DCacheFetchLine, + input logic DCacheWriteLine, + output logic DCacheBusAck, + output logic [LINELEN-1:0] DCacheMemWriteData, + + // lsu interface + input logic [`PA_BITS-1:0] LSUPAdrM, + input logic [`XLEN-1:0] FinalAMOWriteDataM, + input logic [`XLEN-1:0] ReadDataWordM, + output logic [`XLEN-1:0] ReadDataWordMuxM, + input logic IgnoreRequest, + input logic [1:0] LSURWM, + input logic CPUBusy, + input logic CacheableM, + output logic BusStall, + output logic BusCommittedM); + + + logic SelUncachedAdr; + logic [`XLEN-1:0] PreLSUBusHWDATA; + logic [`PA_BITS-1:0] LocalLSUBusAdr; + logic [LOGWPL-1:0] WordCount; + genvar index; + + for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer + flopen #(`XLEN) fb(.clk, .en(LSUBusAck & LSUBusRead & (index == WordCount)), + .d(LSUBusHRDATA), .q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN])); + end + + assign LocalLSUBusAdr = SelUncachedAdr ? LSUPAdrM : DCacheBusAdr ; + assign LSUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLSUBusAdr; + assign PreLSUBusHWDATA = ReadDataLineSetsM[WordCount]; // only in lsu, not ifu + // exclude the subword write for uncached. We don't read the data first so we cannot + // select the subword by masking. Subword write also exists inside the uncore to + // suport subword masking for i/o. I'm not sure if this is necessary. + assign LSUBusHWDATA = SelUncachedAdr ? FinalAMOWriteDataM : PreLSUBusHWDATA; // only in lsu, not ifu + + assign LSUBusSize = SelUncachedAdr ? LSUFunct3M : (`XLEN == 32 ? 3'b010 : 3'b011); // ifu: always the XLEN value. + + // select between dcache and direct from the BUS. Always selected if no dcache. + mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM), + .d1(DCacheMemWriteData[`XLEN-1:0]), + .s(SelUncachedAdr), + .y(ReadDataWordMuxM)); + + busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE) + busfsm(.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine, + .LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusRead, + .DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount); + +endmodule diff --git a/pipelined/src/lsu/lsu.sv b/pipelined/src/lsu/lsu.sv index 82f09a8c..88f28a46 100644 --- a/pipelined/src/lsu/lsu.sv +++ b/pipelined/src/lsu/lsu.sv @@ -189,14 +189,6 @@ module lsu ( .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); - // *** lsumisaligned lsumisaligned(Funct3M, IEUAdrM, MemRW, LoadMisalignedFaultM, StoreAmoMisalignedFaultM); - // *** lump into lsumislaigned module - // Determine if an Unaligned access is taking place - // hptw guarantees alignment, only check inputs from IEU. - - // *** modify MMU to put out LoadMisalignedFault and StoreMisalignedFault rather than DataMisalignedM - - end else begin assign {DTLBMissM, LoadAccessFaultM, StoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0; assign {LoadPageFaultM, StoreAmoPageFaultM} = '0; @@ -255,40 +247,19 @@ module lsu ( assign ReadDataLineSetsM[0] = 0; assign DCacheMiss = 1'b0; assign DCacheAccess = 1'b0; end else begin : bus - // replace from here up to if (`MEM_DCACHE) with busdp *** // Bus Side logic // register the fetch data from the next level of memory. // This register should be necessary for timing. There is no register in the uncore or // ahblite controller between the memories and this cache. - logic [LOGWPL-1:0] WordCount; - - genvar index; - for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer - flopen #(`XLEN) fb(.clk, .en(LSUBusAck & LSUBusRead & (index == WordCount)), - .d(LSUBusHRDATA), .q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN])); - end - - assign LocalLSUBusAdr = SelUncachedAdr ? LSUPAdrM : DCacheBusAdr ; - assign LSUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLSUBusAdr; - assign PreLSUBusHWDATA = ReadDataLineSetsM[WordCount]; // only in lsu, not ifu - // exclude the subword write for uncached. We don't read the data first so we cannot - // select the subword by masking. Subword write also exists inside the uncore to - // suport subword masking for i/o. I'm not sure if this is necessary. - assign LSUBusHWDATA = SelUncachedAdr ? FinalAMOWriteDataM : PreLSUBusHWDATA; // only in lsu, not ifu - - assign LSUBusSize = SelUncachedAdr ? LSUFunct3M : (`XLEN == 32 ? 3'b010 : 3'b011); // ifu: always the XLEN value. - - // select between dcache and direct from the BUS. Always selected if no dcache. - mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM), - .d1(DCacheMemWriteData[`XLEN-1:0]), - .s(SelUncachedAdr), - .y(ReadDataWordMuxM)); - - busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE) - busfsm(.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine, - .LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusRead, - .DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount); + busdp #(WORDSPERLINE, LINELEN, LOGWPL, WordCountThreshold) + busdp(.clk, .reset, + .LSUBusHRDATA, .LSUBusAck, .LSUBusWrite, .LSUBusRead, .LSUBusHWDATA, .LSUBusSize, + .LSUFunct3M, .LSUBusAdr, .DCacheBusAdr, .ReadDataLineSetsM, .DCacheFetchLine, + .DCacheWriteLine, .DCacheBusAck, .DCacheMemWriteData, .LSUPAdrM, .FinalAMOWriteDataM, + .ReadDataWordM, .ReadDataWordMuxM, .IgnoreRequest, .LSURWM, .CPUBusy, .CacheableM, + .BusStall, .BusCommittedM); + if(`MEM_DCACHE) begin : dcache cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN), .NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1))