mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Forgot to include a few files in the last few commits.
Also reorganized the dcache by read cpu path, write cpu path, and bus interface path. Changed i/o names on subwordread to match signals in dcache.
This commit is contained in:
parent
0530047f53
commit
596bc138bc
@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module cacheLRU
|
module cachereplacementpolicy
|
||||||
#(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
|
#(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
|
||||||
(input logic clk, reset,
|
(input logic clk, reset,
|
||||||
input logic [NUMWAYS-1:0] WayIn,
|
input logic [NUMWAYS-1:0] WayHit,
|
||||||
output logic [NUMWAYS-1:0] VictimWay,
|
output logic [NUMWAYS-1:0] VictimWay,
|
||||||
input logic [INDEXLEN+OFFSETLEN-1:OFFSETLEN] MemPAdrM,
|
input logic [INDEXLEN+OFFSETLEN-1:OFFSETLEN] MemPAdrM,
|
||||||
input logic [INDEXLEN-1:0] SRAMAdr,
|
input logic [INDEXLEN-1:0] RAdr,
|
||||||
input logic LRUWriteEn
|
input logic LRUWriteEn
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ module cacheLRU
|
|||||||
for(int index = 0; index < NUMLINES; index++)
|
for(int index = 0; index < NUMLINES; index++)
|
||||||
ReplacementBits[index] <= '0;
|
ReplacementBits[index] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
BlockReplacementBits <= ReplacementBits[SRAMAdr];
|
BlockReplacementBits <= ReplacementBits[RAdr];
|
||||||
if (LRUWriteEn) begin
|
if (LRUWriteEn) begin
|
||||||
ReplacementBits[MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]] <= NewReplacement;
|
ReplacementBits[MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]] <= NewReplacement;
|
||||||
end
|
end
|
||||||
@ -62,7 +62,7 @@ module cacheLRU
|
|||||||
|
|
||||||
assign LRUEn[0] = 1'b0;
|
assign LRUEn[0] = 1'b0;
|
||||||
|
|
||||||
assign NewReplacement[0] = WayIn[1];
|
assign NewReplacement[0] = WayHit[1];
|
||||||
|
|
||||||
assign VictimWay[1] = ~BlockReplacementBits[0];
|
assign VictimWay[1] = ~BlockReplacementBits[0];
|
||||||
assign VictimWay[0] = BlockReplacementBits[0];
|
assign VictimWay[0] = BlockReplacementBits[0];
|
||||||
@ -71,13 +71,13 @@ module cacheLRU
|
|||||||
|
|
||||||
// selects
|
// selects
|
||||||
assign LRUEn[2] = 1'b1;
|
assign LRUEn[2] = 1'b1;
|
||||||
assign LRUEn[1] = WayIn[3];
|
assign LRUEn[1] = WayHit[3];
|
||||||
assign LRUEn[0] = WayIn[3] | WayIn[2];
|
assign LRUEn[0] = WayHit[3] | WayHit[2];
|
||||||
|
|
||||||
// mask
|
// mask
|
||||||
assign LRUMask[0] = WayIn[1];
|
assign LRUMask[0] = WayHit[1];
|
||||||
assign LRUMask[1] = WayIn[3];
|
assign LRUMask[1] = WayHit[3];
|
||||||
assign LRUMask[2] = WayIn[3] | WayIn[2];
|
assign LRUMask[2] = WayHit[3] | WayHit[2];
|
||||||
|
|
||||||
for(index = 0; index < NUMWAYS-1; index++)
|
for(index = 0; index < NUMWAYS-1; index++)
|
||||||
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
|
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
|
||||||
@ -93,21 +93,21 @@ module cacheLRU
|
|||||||
|
|
||||||
// selects
|
// selects
|
||||||
assign LRUEn[6] = 1'b1;
|
assign LRUEn[6] = 1'b1;
|
||||||
assign LRUEn[5] = WayIn[7] | WayIn[6] | WayIn[5] | WayIn[4];
|
assign LRUEn[5] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
|
||||||
assign LRUEn[4] = WayIn[7] | WayIn[6];
|
assign LRUEn[4] = WayHit[7] | WayHit[6];
|
||||||
assign LRUEn[3] = WayIn[5] | WayIn[4];
|
assign LRUEn[3] = WayHit[5] | WayHit[4];
|
||||||
assign LRUEn[2] = WayIn[3] | WayIn[2] | WayIn[1] | WayIn[0];
|
assign LRUEn[2] = WayHit[3] | WayHit[2] | WayHit[1] | WayHit[0];
|
||||||
assign LRUEn[1] = WayIn[3] | WayIn[2];
|
assign LRUEn[1] = WayHit[3] | WayHit[2];
|
||||||
assign LRUEn[0] = WayIn[1] | WayIn[0];
|
assign LRUEn[0] = WayHit[1] | WayHit[0];
|
||||||
|
|
||||||
// mask
|
// mask
|
||||||
assign LRUMask[6] = WayIn[7] | WayIn[6] | WayIn[5] | WayIn[4];
|
assign LRUMask[6] = WayHit[7] | WayHit[6] | WayHit[5] | WayHit[4];
|
||||||
assign LRUMask[5] = WayIn[7] | WayIn[6];
|
assign LRUMask[5] = WayHit[7] | WayHit[6];
|
||||||
assign LRUMask[4] = WayIn[7];
|
assign LRUMask[4] = WayHit[7];
|
||||||
assign LRUMask[3] = WayIn[5];
|
assign LRUMask[3] = WayHit[5];
|
||||||
assign LRUMask[2] = WayIn[3] | WayIn[2];
|
assign LRUMask[2] = WayHit[3] | WayHit[2];
|
||||||
assign LRUMask[1] = WayIn[2];
|
assign LRUMask[1] = WayHit[2];
|
||||||
assign LRUMask[0] = WayIn[0];
|
assign LRUMask[0] = WayHit[0];
|
||||||
|
|
||||||
for(index = 0; index < NUMWAYS-1; index++)
|
for(index = 0; index < NUMWAYS-1; index++)
|
||||||
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
|
assign NewReplacement[index] = LRUEn[index] ? LRUMask[index] : BlockReplacementBits[index];
|
133
wally-pipelined/src/cache/dcache.sv
vendored
133
wally-pipelined/src/cache/dcache.sv
vendored
@ -90,7 +90,7 @@ module dcache
|
|||||||
|
|
||||||
|
|
||||||
logic [1:0] SelAdrM;
|
logic [1:0] SelAdrM;
|
||||||
logic [INDEXLEN-1:0] SRAMAdr;
|
logic [INDEXLEN-1:0] RAdr;
|
||||||
logic [BLOCKLEN-1:0] SRAMWriteData;
|
logic [BLOCKLEN-1:0] SRAMWriteData;
|
||||||
logic [BLOCKLEN-1:0] DCacheMemWriteData;
|
logic [BLOCKLEN-1:0] DCacheMemWriteData;
|
||||||
logic SetValid, ClearValid;
|
logic SetValid, ClearValid;
|
||||||
@ -135,84 +135,65 @@ module dcache
|
|||||||
|
|
||||||
logic LRUWriteEn;
|
logic LRUWriteEn;
|
||||||
|
|
||||||
// data path
|
// Read Path CPU (IEU) side
|
||||||
|
|
||||||
mux3 #(INDEXLEN)
|
mux3 #(INDEXLEN)
|
||||||
AdrSelMux(.d0(MemAdrE[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
AdrSelMux(.d0(MemAdrE[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
||||||
.d1(MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
.d1(VAdr[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
||||||
.d2(VAdr[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
.d2(MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
||||||
.s(SelAdrM),
|
.s(SelAdrM),
|
||||||
.y(SRAMAdr));
|
.y(RAdr));
|
||||||
|
|
||||||
|
|
||||||
onehotdecoder #(LOGWPL)
|
|
||||||
adrdec(.bin(MemPAdrM[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]),
|
|
||||||
.decoded(MemPAdrDecodedW));
|
|
||||||
|
|
||||||
|
|
||||||
assign SRAMWordEnable = SRAMBlockWriteEnableM ? '1 : MemPAdrDecodedW;
|
|
||||||
|
|
||||||
|
|
||||||
cacheway #(.NUMLINES(NUMLINES), .BLOCKLEN(BLOCKLEN), .TAGLEN(TAGLEN), .OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN))
|
cacheway #(.NUMLINES(NUMLINES), .BLOCKLEN(BLOCKLEN), .TAGLEN(TAGLEN), .OFFSETLEN(OFFSETLEN), .INDEXLEN(INDEXLEN))
|
||||||
MemWay[NUMWAYS-1:0](.clk,
|
MemWay[NUMWAYS-1:0](.clk,
|
||||||
.reset,
|
.reset,
|
||||||
.RAdr(SRAMAdr),
|
.RAdr,
|
||||||
.MemPAdrM(MemPAdrM[`PA_BITS-1:0]),
|
.MemPAdrM(MemPAdrM[`PA_BITS-1:0]),
|
||||||
.WriteEnable(SRAMWayWriteEnable),
|
.WriteEnable(SRAMWayWriteEnable),
|
||||||
.WriteWordEnable(SRAMWordEnable),
|
.WriteWordEnable(SRAMWordEnable),
|
||||||
.TagWriteEnable(SRAMBlockWayWriteEnableM),
|
.TagWriteEnable(SRAMBlockWayWriteEnableM),
|
||||||
.WriteData(SRAMWriteData),
|
.WriteData(SRAMWriteData),
|
||||||
.SetValid,
|
.SetValid,
|
||||||
.ClearValid,
|
.ClearValid,
|
||||||
.SetDirty,
|
.SetDirty,
|
||||||
.ClearDirty,
|
.ClearDirty,
|
||||||
.SelEvict,
|
.SelEvict,
|
||||||
.VictimWay,
|
.VictimWay,
|
||||||
.ReadDataBlockWayMaskedM,
|
.ReadDataBlockWayMaskedM,
|
||||||
.WayHit,
|
.WayHit,
|
||||||
.VictimDirtyWay,
|
.VictimDirtyWay,
|
||||||
.VictimTagWay);
|
.VictimTagWay);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if(NUMWAYS > 1) begin
|
if(NUMWAYS > 1) begin
|
||||||
cacheLRU #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
|
cachereplacementpolicy #(NUMWAYS, INDEXLEN, OFFSETLEN, NUMLINES)
|
||||||
cacheLRU(.clk, .reset,
|
cachereplacementpolicy(.clk, .reset,
|
||||||
.WayIn(WayHit),
|
.WayHit,
|
||||||
.VictimWay,
|
.VictimWay,
|
||||||
.MemPAdrM(MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
.MemPAdrM(MemPAdrM[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
||||||
.SRAMAdr,
|
.RAdr,
|
||||||
.LRUWriteEn);
|
.LRUWriteEn);
|
||||||
end else begin
|
end else begin
|
||||||
assign VictimWay = 1'b1;
|
assign VictimWay = 1'b1; // one hot.
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
assign SRAMBlockWayWriteEnableM = SRAMBlockWriteEnableM ? VictimWay : '0;
|
assign CacheHit = | WayHit;
|
||||||
|
assign VictimDirty = | VictimDirtyWay;
|
||||||
mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWriteEnableM ? WayHit : '0),
|
|
||||||
.d1(SRAMBlockWayWriteEnableM),
|
|
||||||
.s(SRAMBlockWriteEnableM),
|
|
||||||
.y(SRAMWayWriteEnable));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assign CacheHit = |WayHit;
|
|
||||||
// ReadDataBlockWayMaskedM is a 2d array of cache block len by number of ways.
|
// ReadDataBlockWayMaskedM is a 2d array of cache block len by number of ways.
|
||||||
// Need to OR together each way in a bitwise manner.
|
// Need to OR together each way in a bitwise manner.
|
||||||
// Final part of the AO Mux.
|
// Final part of the AO Mux. First is the AND in the cacheway.
|
||||||
or_rows #(NUMWAYS, BLOCKLEN) ReadDataAOMux(.a(ReadDataBlockWayMaskedM), .y(ReadDataBlockM));
|
or_rows #(NUMWAYS, BLOCKLEN) ReadDataAOMux(.a(ReadDataBlockWayMaskedM), .y(ReadDataBlockM));
|
||||||
or_rows #(NUMWAYS, TAGLEN) VictimTagAOMux(.a(VictimTagWay), .y(VictimTag));
|
or_rows #(NUMWAYS, TAGLEN) VictimTagAOMux(.a(VictimTagWay), .y(VictimTag));
|
||||||
|
|
||||||
assign VictimDirty = | VictimDirtyWay;
|
|
||||||
|
|
||||||
|
|
||||||
// Convert the Read data bus ReadDataSelectWay into sets of XLEN so we can
|
// Convert the Read data bus ReadDataSelectWay into sets of XLEN so we can
|
||||||
// easily build a variable input mux.
|
// easily build a variable input mux.
|
||||||
// *** consider using a limited range shift to do this final muxing.
|
// *** consider using a limited range shift to do this final muxing.
|
||||||
genvar index;
|
genvar index;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
for (index = 0; index < WORDSPERLINE; index++) begin
|
for (index = 0; index < WORDSPERLINE; index++) begin
|
||||||
assign ReadDataBlockSetsM[index] = ReadDataBlockM[((index+1)*`XLEN)-1: (index*`XLEN)];
|
assign ReadDataBlockSetsM[index] = ReadDataBlockM[((index+1)*`XLEN)-1: (index*`XLEN)];
|
||||||
@ -222,20 +203,31 @@ module dcache
|
|||||||
// variable input mux
|
// variable input mux
|
||||||
assign ReadDataWordM = ReadDataBlockSetsM[MemPAdrM[$clog2(WORDSPERLINE+`XLEN/8) : $clog2(`XLEN/8)]];
|
assign ReadDataWordM = ReadDataBlockSetsM[MemPAdrM[$clog2(WORDSPERLINE+`XLEN/8) : $clog2(`XLEN/8)]];
|
||||||
|
|
||||||
|
|
||||||
assign HWDATA = CacheableM ? ReadDataBlockSetsM[FetchCount] : WriteDataM;
|
|
||||||
|
|
||||||
mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM),
|
mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM),
|
||||||
.d1(DCacheMemWriteData[`XLEN-1:0]),
|
.d1(DCacheMemWriteData[`XLEN-1:0]),
|
||||||
.s(SelUncached),
|
.s(SelUncached),
|
||||||
.y(ReadDataWordMuxM));
|
.y(ReadDataWordMuxM));
|
||||||
|
|
||||||
// finally swr
|
// finally swr
|
||||||
// *** BUG fix HSIZED? why was it this way?
|
subwordread subwordread(.ReadDataWordMuxM,
|
||||||
subwordread subwordread(.HRDATA(ReadDataWordMuxM),
|
.MemPAdrM(MemPAdrM[2:0]),
|
||||||
.HADDRD(MemPAdrM[2:0]),
|
.Funct3M,
|
||||||
.HSIZED({Funct3M[2], 1'b0, Funct3M[1:0]}),
|
.ReadDataM);
|
||||||
.HRDATAMasked(ReadDataM));
|
|
||||||
|
// Write Path CPU (IEU) side
|
||||||
|
|
||||||
|
onehotdecoder #(LOGWPL)
|
||||||
|
adrdec(.bin(MemPAdrM[LOGWPL+LOGXLENBYTES-1:LOGXLENBYTES]),
|
||||||
|
.decoded(MemPAdrDecodedW));
|
||||||
|
|
||||||
|
assign SRAMWordEnable = SRAMBlockWriteEnableM ? '1 : MemPAdrDecodedW;
|
||||||
|
|
||||||
|
assign SRAMBlockWayWriteEnableM = SRAMBlockWriteEnableM ? VictimWay : '0;
|
||||||
|
|
||||||
|
mux2 #(NUMWAYS) WriteEnableMux(.d0(SRAMWordWriteEnableM ? WayHit : '0),
|
||||||
|
.d1(SRAMBlockWayWriteEnableM),
|
||||||
|
.s(SRAMBlockWriteEnableM),
|
||||||
|
.y(SRAMWayWriteEnable));
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`A_SUPPORTED) begin
|
if (`A_SUPPORTED) begin
|
||||||
@ -247,8 +239,6 @@ module dcache
|
|||||||
assign FinalAMOWriteDataM = WriteDataM;
|
assign FinalAMOWriteDataM = WriteDataM;
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
// write path
|
|
||||||
subwordwrite subwordwrite(.HRDATA(ReadDataWordM),
|
subwordwrite subwordwrite(.HRDATA(ReadDataWordM),
|
||||||
.HADDRD(MemPAdrM[2:0]),
|
.HADDRD(MemPAdrM[2:0]),
|
||||||
.HSIZED({Funct3M[2], 1'b0, Funct3M[1:0]}),
|
.HSIZED({Funct3M[2], 1'b0, Funct3M[1:0]}),
|
||||||
@ -256,7 +246,15 @@ module dcache
|
|||||||
.HWDATA(FinalWriteDataM));
|
.HWDATA(FinalWriteDataM));
|
||||||
|
|
||||||
|
|
||||||
|
mux2 #(BLOCKLEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteDataM}}),
|
||||||
|
.d1(DCacheMemWriteData),
|
||||||
|
.s(SRAMBlockWriteEnableM),
|
||||||
|
.y(SRAMWriteData));
|
||||||
|
|
||||||
|
// Bus Side logic
|
||||||
// register the fetch data from the next level of memory.
|
// 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.
|
||||||
generate
|
generate
|
||||||
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
|
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
|
||||||
flopen #(`XLEN) fb(.clk(clk),
|
flopen #(`XLEN) fb(.clk(clk),
|
||||||
@ -278,13 +276,7 @@ module dcache
|
|||||||
|
|
||||||
assign AHBPAdr = ({{`PA_BITS-LOGWPL{1'b0}}, FetchCount} << $clog2(`XLEN/8)) + BasePAdrMaskedM;
|
assign AHBPAdr = ({{`PA_BITS-LOGWPL{1'b0}}, FetchCount} << $clog2(`XLEN/8)) + BasePAdrMaskedM;
|
||||||
|
|
||||||
|
assign HWDATA = CacheableM ? ReadDataBlockSetsM[FetchCount] : WriteDataM;
|
||||||
|
|
||||||
mux2 #(BLOCKLEN) WriteDataMux(.d0({WORDSPERLINE{FinalWriteDataM}}),
|
|
||||||
.d1(DCacheMemWriteData),
|
|
||||||
.s(SRAMBlockWriteEnableM),
|
|
||||||
.y(SRAMWriteData));
|
|
||||||
|
|
||||||
|
|
||||||
localparam FetchCountThreshold = WORDSPERLINE - 1;
|
localparam FetchCountThreshold = WORDSPERLINE - 1;
|
||||||
|
|
||||||
@ -302,9 +294,8 @@ module dcache
|
|||||||
|
|
||||||
assign SRAMWriteEnable = SRAMBlockWriteEnableM | SRAMWordWriteEnableM;
|
assign SRAMWriteEnable = SRAMBlockWriteEnableM | SRAMWordWriteEnableM;
|
||||||
|
|
||||||
|
// controller
|
||||||
|
|
||||||
// control path *** eventually move to own module.
|
|
||||||
|
|
||||||
dcachefsm dcachefsm(.clk,
|
dcachefsm dcachefsm(.clk,
|
||||||
.reset,
|
.reset,
|
||||||
.MemRWM,
|
.MemRWM,
|
||||||
|
792
wally-pipelined/src/cache/dcachefsm.sv
vendored
Normal file
792
wally-pipelined/src/cache/dcachefsm.sv
vendored
Normal file
@ -0,0 +1,792 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// dcache (data cache) fsm
|
||||||
|
//
|
||||||
|
// Written: ross1728@gmail.com August 25, 2021
|
||||||
|
// Implements the L1 data cache fsm
|
||||||
|
//
|
||||||
|
// Purpose: Controller for the dcache fsm
|
||||||
|
//
|
||||||
|
// A component of the Wally configurable RISC-V project.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||||
|
//
|
||||||
|
// 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 dcachefsm
|
||||||
|
(input logic clk,
|
||||||
|
input logic reset,
|
||||||
|
// inputs from IEU
|
||||||
|
input logic [1:0] MemRWM,
|
||||||
|
input logic [1:0] AtomicM,
|
||||||
|
|
||||||
|
// hazard inputs
|
||||||
|
input logic ExceptionM,
|
||||||
|
input logic PendingInterruptM,
|
||||||
|
input logic StallWtoDCache,
|
||||||
|
// mmu inputs
|
||||||
|
input logic DTLBMissM,
|
||||||
|
input logic ITLBMissF,
|
||||||
|
input logic CacheableM,
|
||||||
|
input logic DTLBWriteM,
|
||||||
|
input logic ITLBWriteF,
|
||||||
|
input logic WalkerInstrPageFaultF,
|
||||||
|
// hptw inputs
|
||||||
|
input logic SelPTW,
|
||||||
|
input logic WalkerPageFaultM,
|
||||||
|
// Bus inputs
|
||||||
|
input logic AHBAck, // from ahb
|
||||||
|
// dcache internals
|
||||||
|
input logic CacheHit,
|
||||||
|
input logic FetchCountFlag,
|
||||||
|
input logic VictimDirty,
|
||||||
|
|
||||||
|
// hazard outputs
|
||||||
|
output logic DCacheStall,
|
||||||
|
output logic CommittedM,
|
||||||
|
// counter outputs
|
||||||
|
output logic DCacheMiss,
|
||||||
|
output logic DCacheAccess,
|
||||||
|
// hptw outputs
|
||||||
|
output logic MemAfterIWalkDone,
|
||||||
|
// Bus outputs
|
||||||
|
output logic AHBRead,
|
||||||
|
output logic AHBWrite,
|
||||||
|
|
||||||
|
// dcache internals
|
||||||
|
output logic [1:0] SelAdrM,
|
||||||
|
output logic CntEn,
|
||||||
|
output logic SetValid,
|
||||||
|
output logic ClearValid,
|
||||||
|
output logic SetDirty,
|
||||||
|
output logic ClearDirty,
|
||||||
|
output logic SRAMWordWriteEnableM,
|
||||||
|
output logic SRAMBlockWriteEnableM,
|
||||||
|
output logic CntReset,
|
||||||
|
output logic SelUncached,
|
||||||
|
output logic SelEvict,
|
||||||
|
output logic LRUWriteEn
|
||||||
|
);
|
||||||
|
|
||||||
|
logic PreCntEn;
|
||||||
|
logic AnyCPUReqM;
|
||||||
|
|
||||||
|
typedef enum {STATE_READY,
|
||||||
|
|
||||||
|
STATE_MISS_FETCH_WDV,
|
||||||
|
STATE_MISS_FETCH_DONE,
|
||||||
|
STATE_MISS_EVICT_DIRTY,
|
||||||
|
STATE_MISS_WRITE_CACHE_BLOCK,
|
||||||
|
STATE_MISS_READ_WORD,
|
||||||
|
STATE_MISS_READ_WORD_DELAY,
|
||||||
|
STATE_MISS_WRITE_WORD,
|
||||||
|
|
||||||
|
STATE_PTW_READY,
|
||||||
|
STATE_PTW_READ_MISS_FETCH_WDV,
|
||||||
|
STATE_PTW_READ_MISS_FETCH_DONE,
|
||||||
|
STATE_PTW_READ_MISS_WRITE_CACHE_BLOCK,
|
||||||
|
STATE_PTW_READ_MISS_EVICT_DIRTY,
|
||||||
|
STATE_PTW_READ_MISS_READ_WORD,
|
||||||
|
STATE_PTW_READ_MISS_READ_WORD_DELAY,
|
||||||
|
STATE_PTW_ACCESS_AFTER_WALK,
|
||||||
|
|
||||||
|
STATE_UNCACHED_WRITE,
|
||||||
|
STATE_UNCACHED_WRITE_DONE,
|
||||||
|
STATE_UNCACHED_READ,
|
||||||
|
STATE_UNCACHED_READ_DONE,
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_READY,
|
||||||
|
STATE_PTW_FAULT_CPU_BUSY,
|
||||||
|
STATE_PTW_FAULT_MISS_FETCH_WDV,
|
||||||
|
STATE_PTW_FAULT_MISS_FETCH_DONE,
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_CACHE_BLOCK,
|
||||||
|
STATE_PTW_FAULT_MISS_READ_WORD,
|
||||||
|
STATE_PTW_FAULT_MISS_READ_WORD_DELAY,
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_WORD,
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_WORD_DELAY,
|
||||||
|
STATE_PTW_FAULT_MISS_EVICT_DIRTY,
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_UNCACHED_WRITE,
|
||||||
|
STATE_PTW_FAULT_UNCACHED_WRITE_DONE,
|
||||||
|
STATE_PTW_FAULT_UNCACHED_READ,
|
||||||
|
STATE_PTW_FAULT_UNCACHED_READ_DONE,
|
||||||
|
|
||||||
|
STATE_CPU_BUSY,
|
||||||
|
STATE_CPU_BUSY_FINISH_AMO} statetype;
|
||||||
|
|
||||||
|
statetype CurrState, NextState;
|
||||||
|
|
||||||
|
assign AnyCPUReqM = |MemRWM | (|AtomicM);
|
||||||
|
assign CntEn = PreCntEn & AHBAck;
|
||||||
|
|
||||||
|
|
||||||
|
always_ff @(posedge clk, posedge reset)
|
||||||
|
if (reset) CurrState <= #1 STATE_READY;
|
||||||
|
else CurrState <= #1 NextState;
|
||||||
|
|
||||||
|
|
||||||
|
// next state logic and some state ouputs.
|
||||||
|
always_comb begin
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
SelAdrM = 2'b00;
|
||||||
|
PreCntEn = 1'b0;
|
||||||
|
SetValid = 1'b0;
|
||||||
|
ClearValid = 1'b0;
|
||||||
|
SetDirty = 1'b0;
|
||||||
|
ClearDirty = 1'b0;
|
||||||
|
SRAMWordWriteEnableM = 1'b0;
|
||||||
|
SRAMBlockWriteEnableM = 1'b0;
|
||||||
|
CntReset = 1'b0;
|
||||||
|
AHBRead = 1'b0;
|
||||||
|
AHBWrite = 1'b0;
|
||||||
|
CommittedM = 1'b0;
|
||||||
|
SelUncached = 1'b0;
|
||||||
|
SelEvict = 1'b0;
|
||||||
|
DCacheAccess = 1'b0;
|
||||||
|
DCacheMiss = 1'b0;
|
||||||
|
LRUWriteEn = 1'b0;
|
||||||
|
MemAfterIWalkDone = 1'b0;
|
||||||
|
|
||||||
|
case (CurrState)
|
||||||
|
STATE_READY: begin
|
||||||
|
// TLB Miss
|
||||||
|
if((AnyCPUReqM & DTLBMissM) | ITLBMissF) begin
|
||||||
|
// the LSU arbiter has not yet selected the PTW.
|
||||||
|
// The CPU needs to be stalled until that happens.
|
||||||
|
// If we set DCacheStall for 1 cycle before going to
|
||||||
|
// PTW ready the CPU will stall.
|
||||||
|
// The page table walker asserts it's control 1 cycle
|
||||||
|
// after the TLBs miss.
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
NextState = STATE_PTW_READY;
|
||||||
|
end
|
||||||
|
// amo hit
|
||||||
|
else if(AtomicM[1] & (&MemRWM) & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY_FINISH_AMO;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
// read hit valid cached
|
||||||
|
else if(MemRWM[1] & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
DCacheAccess = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
// write hit valid cached
|
||||||
|
else if (MemRWM[0] & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
// read or write miss valid cached
|
||||||
|
else if((|MemRWM) & CacheableM & ~(ExceptionM | PendingInterruptM) & ~CacheHit & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_MISS_FETCH_WDV;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
DCacheAccess = 1'b1;
|
||||||
|
DCacheMiss = 1'b1;
|
||||||
|
end
|
||||||
|
// uncached write
|
||||||
|
else if(MemRWM[0] & ~CacheableM & ~(ExceptionM | PendingInterruptM) & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_UNCACHED_WRITE;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
end
|
||||||
|
// uncached read
|
||||||
|
else if(MemRWM[1] & ~CacheableM & ~(ExceptionM | PendingInterruptM) & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_UNCACHED_READ;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
end
|
||||||
|
// fault
|
||||||
|
else if(AnyCPUReqM & (ExceptionM | PendingInterruptM) & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
else NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_FETCH_WDV: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
|
||||||
|
if (FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_MISS_FETCH_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_MISS_FETCH_WDV;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_FETCH_DONE: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(VictimDirty) begin
|
||||||
|
NextState = STATE_MISS_EVICT_DIRTY;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_WRITE_CACHE_BLOCK: begin
|
||||||
|
SRAMBlockWriteEnableM = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
NextState = STATE_MISS_READ_WORD;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
SetValid = 1'b1;
|
||||||
|
ClearDirty = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
//LRUWriteEn = 1'b1; // DO not update LRU on SRAM fetch update. Wait for subsequent read/write
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_READ_WORD: begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if (MemRWM[0]) begin // handles stores and amo write.
|
||||||
|
NextState = STATE_MISS_WRITE_WORD;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_MISS_READ_WORD_DELAY;
|
||||||
|
// delay state is required as the read signal MemRWM[1] is still high when we
|
||||||
|
// return to the ready state because the cache is stalling the cpu.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_READ_WORD_DELAY: begin
|
||||||
|
//SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(&MemRWM & AtomicM[1]) begin // amo write
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY_FINISH_AMO;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_WRITE_WORD: begin
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_MISS_EVICT_DIRTY: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelEvict = 1'b1;
|
||||||
|
if(FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_MISS_EVICT_DIRTY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READY: begin
|
||||||
|
// now all output connect to PTW instead of CPU.
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
|
||||||
|
// In this branch we remove stall and go back to ready. There is no request for memory from the
|
||||||
|
// datapath or the walker had a fault.
|
||||||
|
// types 3b, 4a, 4b, and 7c.
|
||||||
|
if ((DTLBMissM & WalkerPageFaultM) | // 3b
|
||||||
|
(ITLBMissF & (WalkerInstrPageFaultF | ITLBWriteF) & ~AnyCPUReqM & ~DTLBMissM) | // 4a and 4b
|
||||||
|
(DTLBMissM & ITLBMissF & WalkerPageFaultM)) begin // 7c
|
||||||
|
NextState = STATE_READY;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
end
|
||||||
|
// in this branch we go back to ready, but there is a memory operation from
|
||||||
|
// the datapath so we MUST stall and replay the operation.
|
||||||
|
// types 3a and 5a
|
||||||
|
else if ((DTLBMissM & DTLBWriteM) | // 3a
|
||||||
|
(ITLBMissF & ITLBWriteF & AnyCPUReqM)) begin // 5a
|
||||||
|
NextState = STATE_READY;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b01;
|
||||||
|
end
|
||||||
|
|
||||||
|
// like 5a we want to stall and go to the ready state, but we also have to save
|
||||||
|
// the WalkerInstrPageFaultF so it is held until the end of the memory operation
|
||||||
|
// from the datapath.
|
||||||
|
// types 5b
|
||||||
|
else if (ITLBMissF & WalkerInstrPageFaultF & AnyCPUReqM) begin // 5b
|
||||||
|
NextState = STATE_PTW_FAULT_READY;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b01;
|
||||||
|
end
|
||||||
|
|
||||||
|
// in this branch we stay in ptw_ready because we are doing an itlb walk
|
||||||
|
// after a dtlb walk.
|
||||||
|
// types 7a and 7b.
|
||||||
|
else if (DTLBMissM & DTLBWriteM & ITLBMissF)begin
|
||||||
|
NextState = STATE_PTW_READY;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
|
||||||
|
// read hit valid cached
|
||||||
|
end else if(MemRWM[1] & CacheableM & ~ExceptionM & CacheHit) begin
|
||||||
|
NextState = STATE_PTW_READY;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
// read miss valid cached
|
||||||
|
else if(SelPTW & MemRWM[1] & CacheableM & ~ExceptionM & ~CacheHit) begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_FETCH_WDV;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
else begin
|
||||||
|
NextState = STATE_PTW_READY;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_FETCH_WDV: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
|
||||||
|
if(FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_FETCH_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_FETCH_WDV;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_FETCH_DONE: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
if(VictimDirty) begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_EVICT_DIRTY;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_EVICT_DIRTY: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelEvict = 1'b1;
|
||||||
|
if(FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_READ_MISS_EVICT_DIRTY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_WRITE_CACHE_BLOCK: begin
|
||||||
|
SRAMBlockWriteEnableM = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
NextState = STATE_PTW_READ_MISS_READ_WORD;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
SetValid = 1'b1;
|
||||||
|
ClearDirty = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
//LRUWriteEn = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_READ_WORD: begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
NextState = STATE_PTW_READ_MISS_READ_WORD_DELAY;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_READ_MISS_READ_WORD_DELAY: begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
NextState = STATE_PTW_READY;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_ACCESS_AFTER_WALK: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_CPU_BUSY: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_CPU_BUSY_FINISH_AMO: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY_FINISH_AMO;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_UNCACHED_WRITE : begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(AHBAck) begin
|
||||||
|
NextState = STATE_UNCACHED_WRITE_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_UNCACHED_WRITE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_UNCACHED_READ : begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(AHBAck) begin
|
||||||
|
NextState = STATE_UNCACHED_READ_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_UNCACHED_READ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_UNCACHED_WRITE_DONE: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_UNCACHED_READ_DONE: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelUncached = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// itlb => instruction page fault states with memory request.
|
||||||
|
STATE_PTW_FAULT_READY: begin
|
||||||
|
// read hit valid cached
|
||||||
|
if(MemRWM[1] & CacheableM & CacheHit & ~DTLBMissM) begin
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
DCacheAccess = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// write hit valid cached
|
||||||
|
else if (MemRWM[0] & CacheableM & CacheHit & ~DTLBMissM) begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b0;
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
// read or write miss valid cached
|
||||||
|
else if((|MemRWM) & CacheableM & ~CacheHit & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_FETCH_WDV;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
DCacheAccess = 1'b1;
|
||||||
|
DCacheMiss = 1'b1;
|
||||||
|
end
|
||||||
|
// uncached write
|
||||||
|
else if(MemRWM[0] & ~CacheableM & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_WRITE;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
end
|
||||||
|
// uncached read
|
||||||
|
else if(MemRWM[1] & ~CacheableM & ~DTLBMissM) begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_READ;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
end
|
||||||
|
// fault
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_CPU_BUSY: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_FETCH_WDV: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
|
||||||
|
if(FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_FETCH_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_FETCH_WDV;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_FETCH_DONE: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CntReset = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(VictimDirty) begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_EVICT_DIRTY;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_CACHE_BLOCK: begin
|
||||||
|
SRAMBlockWriteEnableM = 1'b1;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_READ_WORD;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
SetValid = 1'b1;
|
||||||
|
ClearDirty = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
//LRUWriteEn = 1'b1; // DO not update LRU on SRAM fetch update. Wait for subsequent read/write
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_READ_WORD: begin
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(MemRWM[1]) begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_READ_WORD_DELAY;
|
||||||
|
// delay state is required as the read signal MemRWM[1] is still high when we
|
||||||
|
// return to the ready state because the cache is stalling the cpu.
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_WRITE_WORD;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_READ_WORD_DELAY: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_WORD: begin
|
||||||
|
SRAMWordWriteEnableM = 1'b1;
|
||||||
|
SetDirty = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
LRUWriteEn = 1'b1;
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_WRITE_WORD_DELAY;
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_WRITE_WORD_DELAY: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_MISS_EVICT_DIRTY: begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
PreCntEn = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelEvict = 1'b1;
|
||||||
|
if(FetchCountFlag & AHBAck) begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_WRITE_CACHE_BLOCK;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_MISS_EVICT_DIRTY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_UNCACHED_WRITE : begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBWrite = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(AHBAck) begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_WRITE_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_WRITE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_UNCACHED_READ : begin
|
||||||
|
DCacheStall = 1'b1;
|
||||||
|
AHBRead = 1'b1;
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(AHBAck) begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_READ_DONE;
|
||||||
|
end else begin
|
||||||
|
NextState = STATE_PTW_FAULT_UNCACHED_READ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_UNCACHED_WRITE_DONE: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PTW_FAULT_UNCACHED_READ_DONE: begin
|
||||||
|
CommittedM = 1'b1;
|
||||||
|
SelUncached = 1'b1;
|
||||||
|
if(StallWtoDCache) begin
|
||||||
|
NextState = STATE_PTW_FAULT_CPU_BUSY;
|
||||||
|
SelAdrM = 2'b10;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MemAfterIWalkDone = 1'b1;
|
||||||
|
NextState = STATE_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
endmodule // dcachefsm
|
||||||
|
|
@ -26,13 +26,10 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module subwordread (
|
module subwordread (
|
||||||
// from AHB Interface
|
input logic [`XLEN-1:0] ReadDataWordMuxM,
|
||||||
input logic [`XLEN-1:0] HRDATA,
|
input logic [2:0] MemPAdrM,
|
||||||
input logic [2:0] HADDRD,
|
input logic [2:0] Funct3M,
|
||||||
//input logic UnsignedLoadM,
|
output logic [`XLEN-1:0] ReadDataM
|
||||||
input logic [3:0] HSIZED,
|
|
||||||
// to ifu/dmems
|
|
||||||
output logic [`XLEN-1:0] HRDATAMasked
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [7:0] ByteM;
|
logic [7:0] ByteM;
|
||||||
@ -40,8 +37,8 @@ module subwordread (
|
|||||||
|
|
||||||
logic [`XLEN-1:0] offset0, offset1, offset2, offset3;
|
logic [`XLEN-1:0] offset0, offset1, offset2, offset3;
|
||||||
|
|
||||||
// HSIZED[3] is the unsigned bit. mask upper bits.
|
// Funct3M[2] is the unsigned bit. mask upper bits.
|
||||||
// HSIZED[1:0] is the size of the memory access.
|
// Funct3M[1:0] is the size of the memory access.
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 64) begin
|
if (`XLEN == 64) begin
|
||||||
@ -50,52 +47,52 @@ module subwordread (
|
|||||||
logic [`XLEN-1:0] offset4, offset5, offset6, offset7;
|
logic [`XLEN-1:0] offset4, offset5, offset6, offset7;
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[1:0])
|
case(Funct3M[1:0])
|
||||||
3: offset0 = HRDATA; //ld
|
3: offset0 = ReadDataWordMuxM; //ld
|
||||||
2: offset0 = HSIZED[3] ? {{32'b0}, HRDATA[31:0]} : {{32{HRDATA[31]}}, HRDATA[31:0]}; //lw(u)
|
2: offset0 = Funct3M[2] ? {{32'b0}, ReadDataWordMuxM[31:0]} : {{32{ReadDataWordMuxM[31]}}, ReadDataWordMuxM[31:0]}; //lw(u)
|
||||||
1: offset0 = HSIZED[3] ? {{48'b0}, HRDATA[15:0]} : {{48{HRDATA[15]}}, HRDATA[15:0]}; //lh(u)
|
1: offset0 = Funct3M[2] ? {{48'b0}, ReadDataWordMuxM[15:0]} : {{48{ReadDataWordMuxM[15]}}, ReadDataWordMuxM[15:0]}; //lh(u)
|
||||||
0: offset0 = HSIZED[3] ? {{56'b0}, HRDATA[7:0]} : {{56{HRDATA[7]}}, HRDATA[7:0]}; //lb(u)
|
0: offset0 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[7:0]} : {{56{ReadDataWordMuxM[7]}}, ReadDataWordMuxM[7:0]}; //lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset1 = HSIZED[3] ? {{56'b0}, HRDATA[15:8]} : {{56{HRDATA[15]}}, HRDATA[15:8]}; //lb(u)
|
assign offset1 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[15:8]} : {{56{ReadDataWordMuxM[15]}}, ReadDataWordMuxM[15:8]}; //lb(u)
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[0])
|
case(Funct3M[0])
|
||||||
1: offset2 = HSIZED[3] ? {{48'b0}, HRDATA[31:16]} : {{48{HRDATA[31]}}, HRDATA[31:16]};//lh(u)
|
1: offset2 = Funct3M[2] ? {{48'b0}, ReadDataWordMuxM[31:16]} : {{48{ReadDataWordMuxM[31]}}, ReadDataWordMuxM[31:16]};//lh(u)
|
||||||
0: offset2 = HSIZED[3] ? {{56'b0}, HRDATA[23:16]} : {{56{HRDATA[23]}}, HRDATA[23:16]};//lb(u)
|
0: offset2 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[23:16]} : {{56{ReadDataWordMuxM[23]}}, ReadDataWordMuxM[23:16]};//lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset3 = HSIZED[3] ? {{56'b0}, HRDATA[31:24]} : {{56{HRDATA[31]}}, HRDATA[31:24]};//lb(u)
|
assign offset3 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[31:24]} : {{56{ReadDataWordMuxM[31]}}, ReadDataWordMuxM[31:24]};//lb(u)
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[1:0])
|
case(Funct3M[1:0])
|
||||||
3: offset4 = HSIZED[3] ? {{32'b0}, HRDATA[63:32]} : {{32{HRDATA[63]}}, HRDATA[63:32]};//ld(u) // unaligned will cause fault.
|
3: offset4 = Funct3M[2] ? {{32'b0}, ReadDataWordMuxM[63:32]} : {{32{ReadDataWordMuxM[63]}}, ReadDataWordMuxM[63:32]};//ld(u) // unaligned will cause fault.
|
||||||
2: offset4 = HSIZED[3] ? {{32'b0}, HRDATA[63:32]} : {{32{HRDATA[63]}}, HRDATA[63:32]};//lw(u)
|
2: offset4 = Funct3M[2] ? {{32'b0}, ReadDataWordMuxM[63:32]} : {{32{ReadDataWordMuxM[63]}}, ReadDataWordMuxM[63:32]};//lw(u)
|
||||||
1: offset4 = HSIZED[3] ? {{48'b0}, HRDATA[47:32]} : {{48{HRDATA[47]}}, HRDATA[47:32]};//lh(u)
|
1: offset4 = Funct3M[2] ? {{48'b0}, ReadDataWordMuxM[47:32]} : {{48{ReadDataWordMuxM[47]}}, ReadDataWordMuxM[47:32]};//lh(u)
|
||||||
0: offset4 = HSIZED[3] ? {{56'b0}, HRDATA[39:32]} : {{56{HRDATA[39]}}, HRDATA[39:32]};//lb(u)
|
0: offset4 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[39:32]} : {{56{ReadDataWordMuxM[39]}}, ReadDataWordMuxM[39:32]};//lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset5 = HSIZED[3] ? {{56'b0}, HRDATA[47:40]} : {{56{HRDATA[47]}}, HRDATA[47:40]};//lb(u)
|
assign offset5 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[47:40]} : {{56{ReadDataWordMuxM[47]}}, ReadDataWordMuxM[47:40]};//lb(u)
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[0])
|
case(Funct3M[0])
|
||||||
1: offset6 = HSIZED[3] ? {{48'b0}, HRDATA[63:48]} : {{48{HRDATA[63]}}, HRDATA[63:48]};//lh(u)
|
1: offset6 = Funct3M[2] ? {{48'b0}, ReadDataWordMuxM[63:48]} : {{48{ReadDataWordMuxM[63]}}, ReadDataWordMuxM[63:48]};//lh(u)
|
||||||
0: offset6 = HSIZED[3] ? {{56'b0}, HRDATA[55:48]} : {{56{HRDATA[55]}}, HRDATA[55:48]};//lb(u)
|
0: offset6 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[55:48]} : {{56{ReadDataWordMuxM[55]}}, ReadDataWordMuxM[55:48]};//lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset7 = HSIZED[3] ? {{56'b0}, HRDATA[63:56]} : {{56{HRDATA[63]}}, HRDATA[63:56]};//lb(u)
|
assign offset7 = Funct3M[2] ? {{56'b0}, ReadDataWordMuxM[63:56]} : {{56{ReadDataWordMuxM[63]}}, ReadDataWordMuxM[63:56]};//lb(u)
|
||||||
|
|
||||||
// address mux
|
// address mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[2:0])
|
case(MemPAdrM[2:0])
|
||||||
0: HRDATAMasked = offset0;
|
0: ReadDataM = offset0;
|
||||||
1: HRDATAMasked = offset1;
|
1: ReadDataM = offset1;
|
||||||
2: HRDATAMasked = offset2;
|
2: ReadDataM = offset2;
|
||||||
3: HRDATAMasked = offset3;
|
3: ReadDataM = offset3;
|
||||||
4: HRDATAMasked = offset4;
|
4: ReadDataM = offset4;
|
||||||
5: HRDATAMasked = offset5;
|
5: ReadDataM = offset5;
|
||||||
6: HRDATAMasked = offset6;
|
6: ReadDataM = offset6;
|
||||||
7: HRDATAMasked = offset7;
|
7: ReadDataM = offset7;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// easier to understand but slower
|
// easier to understand but slower
|
||||||
@ -103,45 +100,45 @@ module subwordread (
|
|||||||
/* -----\/----- EXCLUDED -----\/-----
|
/* -----\/----- EXCLUDED -----\/-----
|
||||||
// ByteMe mux
|
// ByteMe mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[2:0])
|
case(MemPAdrM[2:0])
|
||||||
3'b000: ByteM = HRDATA[7:0];
|
3'b000: ByteM = ReadDataWordMuxM[7:0];
|
||||||
3'b001: ByteM = HRDATA[15:8];
|
3'b001: ByteM = ReadDataWordMuxM[15:8];
|
||||||
3'b010: ByteM = HRDATA[23:16];
|
3'b010: ByteM = ReadDataWordMuxM[23:16];
|
||||||
3'b011: ByteM = HRDATA[31:24];
|
3'b011: ByteM = ReadDataWordMuxM[31:24];
|
||||||
3'b100: ByteM = HRDATA[39:32];
|
3'b100: ByteM = ReadDataWordMuxM[39:32];
|
||||||
3'b101: ByteM = HRDATA[47:40];
|
3'b101: ByteM = ReadDataWordMuxM[47:40];
|
||||||
3'b110: ByteM = HRDATA[55:48];
|
3'b110: ByteM = ReadDataWordMuxM[55:48];
|
||||||
3'b111: ByteM = HRDATA[63:56];
|
3'b111: ByteM = ReadDataWordMuxM[63:56];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// halfword mux
|
// halfword mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[2:1])
|
case(MemPAdrM[2:1])
|
||||||
2'b00: HalfwordM = HRDATA[15:0];
|
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
|
||||||
2'b01: HalfwordM = HRDATA[31:16];
|
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
|
||||||
2'b10: HalfwordM = HRDATA[47:32];
|
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
|
||||||
2'b11: HalfwordM = HRDATA[63:48];
|
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
logic [31:0] WordM;
|
logic [31:0] WordM;
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[2])
|
case(MemPAdrM[2])
|
||||||
1'b0: WordM = HRDATA[31:0];
|
1'b0: WordM = ReadDataWordMuxM[31:0];
|
||||||
1'b1: WordM = HRDATA[63:32];
|
1'b1: WordM = ReadDataWordMuxM[63:32];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// sign extension
|
// sign extension
|
||||||
always_comb
|
always_comb
|
||||||
case({HSIZED[3], HSIZED[1:0]}) // HSIZED[3] indicates unsigned load
|
case({Funct3M[2], Funct3M[1:0]}) // Funct3M[2] indicates unsigned load
|
||||||
3'b000: HRDATAMasked = {{56{ByteM[7]}}, ByteM}; // lb
|
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
|
||||||
3'b001: HRDATAMasked = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
3'b010: HRDATAMasked = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
|
||||||
3'b011: HRDATAMasked = HRDATA; // ld
|
3'b011: ReadDataM = ReadDataWordMuxM; // ld
|
||||||
3'b100: HRDATAMasked = {56'b0, ByteM[7:0]}; // lbu
|
3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
|
||||||
3'b101: HRDATAMasked = {48'b0, HalfwordM[15:0]}; // lhu
|
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
|
||||||
3'b110: HRDATAMasked = {32'b0, WordM[31:0]}; // lwu
|
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
|
||||||
default: HRDATAMasked = HRDATA; // Shouldn't happen
|
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||||
endcase
|
endcase
|
||||||
-----/\----- EXCLUDED -----/\----- */
|
-----/\----- EXCLUDED -----/\----- */
|
||||||
end else begin // 32-bit
|
end else begin // 32-bit
|
||||||
@ -149,58 +146,58 @@ module subwordread (
|
|||||||
|
|
||||||
// fast but more complex
|
// fast but more complex
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[1:0])
|
case(Funct3M[1:0])
|
||||||
3: offset0 = HRDATA; //ld illegal
|
3: offset0 = ReadDataWordMuxM; //ld illegal
|
||||||
2: offset0 = HRDATA[31:0]; //lw
|
2: offset0 = ReadDataWordMuxM[31:0]; //lw
|
||||||
1: offset0 = HSIZED[3] ? {{16'b0}, HRDATA[15:0]} : {{16{HRDATA[15]}}, HRDATA[15:0]}; //lh(u)
|
1: offset0 = Funct3M[2] ? {{16'b0}, ReadDataWordMuxM[15:0]} : {{16{ReadDataWordMuxM[15]}}, ReadDataWordMuxM[15:0]}; //lh(u)
|
||||||
0: offset0 = HSIZED[3] ? {{24'b0}, HRDATA[7:0]} : {{24{HRDATA[7]}}, HRDATA[7:0]}; //lb(u)
|
0: offset0 = Funct3M[2] ? {{24'b0}, ReadDataWordMuxM[7:0]} : {{24{ReadDataWordMuxM[7]}}, ReadDataWordMuxM[7:0]}; //lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset1 = HSIZED[3] ? {{24'b0}, HRDATA[15:8]} : {{24{HRDATA[15]}}, HRDATA[15:8]}; //lb(u)
|
assign offset1 = Funct3M[2] ? {{24'b0}, ReadDataWordMuxM[15:8]} : {{24{ReadDataWordMuxM[15]}}, ReadDataWordMuxM[15:8]}; //lb(u)
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case(HSIZED[0])
|
case(Funct3M[0])
|
||||||
1: offset2 = HSIZED[3] ? {{16'b0}, HRDATA[31:16]} : {{16{HRDATA[31]}}, HRDATA[31:16]};//lh(u)
|
1: offset2 = Funct3M[2] ? {{16'b0}, ReadDataWordMuxM[31:16]} : {{16{ReadDataWordMuxM[31]}}, ReadDataWordMuxM[31:16]};//lh(u)
|
||||||
0: offset2 = HSIZED[3] ? {{24'b0}, HRDATA[23:16]} : {{24{HRDATA[23]}}, HRDATA[23:16]};//lb(u)
|
0: offset2 = Funct3M[2] ? {{24'b0}, ReadDataWordMuxM[23:16]} : {{24{ReadDataWordMuxM[23]}}, ReadDataWordMuxM[23:16]};//lb(u)
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign offset3 = HSIZED[3] ? {{24'b0}, HRDATA[31:24]} : {{24{HRDATA[31]}}, HRDATA[31:24]};//lb(u)
|
assign offset3 = Funct3M[2] ? {{24'b0}, ReadDataWordMuxM[31:24]} : {{24{ReadDataWordMuxM[31]}}, ReadDataWordMuxM[31:24]};//lb(u)
|
||||||
|
|
||||||
// address mux
|
// address mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[1:0])
|
case(MemPAdrM[1:0])
|
||||||
0: HRDATAMasked = offset0;
|
0: ReadDataM = offset0;
|
||||||
1: HRDATAMasked = offset1;
|
1: ReadDataM = offset1;
|
||||||
2: HRDATAMasked = offset2;
|
2: ReadDataM = offset2;
|
||||||
3: HRDATAMasked = offset3;
|
3: ReadDataM = offset3;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// slow but easier to understand
|
// slow but easier to understand
|
||||||
/* -----\/----- EXCLUDED -----\/-----
|
/* -----\/----- EXCLUDED -----\/-----
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[1:0])
|
case(MemPAdrM[1:0])
|
||||||
2'b00: ByteM = HRDATA[7:0];
|
2'b00: ByteM = ReadDataWordMuxM[7:0];
|
||||||
2'b01: ByteM = HRDATA[15:8];
|
2'b01: ByteM = ReadDataWordMuxM[15:8];
|
||||||
2'b10: ByteM = HRDATA[23:16];
|
2'b10: ByteM = ReadDataWordMuxM[23:16];
|
||||||
2'b11: ByteM = HRDATA[31:24];
|
2'b11: ByteM = ReadDataWordMuxM[31:24];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// halfword mux
|
// halfword mux
|
||||||
always_comb
|
always_comb
|
||||||
case(HADDRD[1])
|
case(MemPAdrM[1])
|
||||||
1'b0: HalfwordM = HRDATA[15:0];
|
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
|
||||||
1'b1: HalfwordM = HRDATA[31:16];
|
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// sign extension
|
// sign extension
|
||||||
always_comb
|
always_comb
|
||||||
case({HSIZED[3], HSIZED[1:0]})
|
case({Funct3M[2], Funct3M[1:0]})
|
||||||
3'b000: HRDATAMasked = {{24{ByteM[7]}}, ByteM}; // lb
|
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
|
||||||
3'b001: HRDATAMasked = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
|
||||||
3'b010: HRDATAMasked = HRDATA; // lw
|
3'b010: ReadDataM = ReadDataWordMuxM; // lw
|
||||||
3'b100: HRDATAMasked = {24'b0, ByteM[7:0]}; // lbu
|
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
|
||||||
3'b101: HRDATAMasked = {16'b0, HalfwordM[15:0]}; // lhu
|
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
|
||||||
default: HRDATAMasked = HRDATA;
|
default: ReadDataM = ReadDataWordMuxM;
|
||||||
endcase
|
endcase
|
||||||
-----/\----- EXCLUDED -----/\----- */
|
-----/\----- EXCLUDED -----/\----- */
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user