Request queues in L1 cache

This commit is contained in:
Louis Hobson
2025-02-26 21:26:00 +00:00
committed by Jonathan Woodruff
parent 03b8face1e
commit 535d85ff35
12 changed files with 355 additions and 170 deletions

View File

@@ -58,6 +58,8 @@ typedef struct {
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram; RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram;
// replace info, actually not needed, just output for debug purposes // replace info, actually not needed, just output for debug purposes
repT repInfo; repT repInfo;
// the next-in-line queuer for this cache index
setAuxT setAuxData;
} PipeOut#( } PipeOut#(
type wayT, type wayT,
type tagT, type tagT,
@@ -67,6 +69,7 @@ typedef struct {
type otherT, type otherT,
type repT, type repT,
type lineT, type lineT,
type setAuxT,
type pipeCmdT type pipeCmdT
) deriving(Bits, Eq, FShow); ) deriving(Bits, Eq, FShow);
@@ -80,16 +83,18 @@ interface CCPipe#(
type otherT, type otherT,
type repT, type repT,
type lineT, type lineT,
type setAuxT,
type pipeCmdT type pipeCmdT
); );
method Action enq(pipeCmdT cmd, Maybe#(lineT) respLine, RespState#(msiT) toState); method Action enq(pipeCmdT cmd, Maybe#(lineT) respLine, RespState#(msiT) toState);
method Bool notFull; method Bool notFull;
method PipeOut#(Bit#(TLog#(wayNum)), tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT) first; method PipeOut#(Bit#(TLog#(wayNum)), tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT) first;
method PipeOut#(Bit#(TLog#(wayNum)), tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT) unguard_first; method PipeOut#(Bit#(TLog#(wayNum)), tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT) unguard_first;
method Bool notEmpty; method Bool notEmpty;
method Action deqWrite( method Action deqWrite(
Maybe#(pipeCmdT) newCmd, Maybe#(pipeCmdT) newCmd,
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) wrRam, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) wrRam,
setAuxT setAuxData,
Bool updateRep // update replacement info Bool updateRep // update replacement info
); );
// empty signal when we need to flush self-invalidate cache // empty signal when we need to flush self-invalidate cache
@@ -110,6 +115,7 @@ typedef struct {
// CRs/PRs info // CRs/PRs info
Maybe#(lineT) respLine; Maybe#(lineT) respLine;
RespState#(msiT) toState; RespState#(msiT) toState;
Maybe#(setAuxT) setAuxData;
} Enq2Match#( } Enq2Match#(
numeric type wayNum, numeric type wayNum,
type tagT, type tagT,
@@ -119,6 +125,7 @@ typedef struct {
type otherT, type otherT,
type repT, type repT,
type lineT, type lineT,
type setAuxT,
type pipeCmdT type pipeCmdT
) deriving(Bits, Eq, FShow); ) deriving(Bits, Eq, FShow);
@@ -134,6 +141,7 @@ typedef struct {
repT repInfo; repT repInfo;
// bypassed or resp line // bypassed or resp line
Maybe#(lineT) line; Maybe#(lineT) line;
setAuxT setAuxData;
} Match2Out#( } Match2Out#(
type wayT, type wayT,
type tagT, type tagT,
@@ -143,6 +151,7 @@ typedef struct {
type otherT, type otherT,
type repT, type repT,
type lineT, type lineT,
type setAuxT,
type pipeCmdT type pipeCmdT
) deriving(Bits, Eq, FShow); ) deriving(Bits, Eq, FShow);
@@ -151,6 +160,7 @@ typedef struct {
wayT way; wayT way;
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram; // data to write into RAM RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram; // data to write into RAM
repT repInfo; // replacement info write into RAM repT repInfo; // replacement info write into RAM
setAuxT setAuxData;
} BypassInfo#( } BypassInfo#(
type wayT, type wayT,
type indexT, type indexT,
@@ -160,7 +170,8 @@ typedef struct {
type ownerT, type ownerT,
type otherT, type otherT,
type repT, type repT,
type lineT type lineT,
type setAuxT
) deriving(Bits, Eq, FShow); ) deriving(Bits, Eq, FShow);
typedef struct { typedef struct {
@@ -208,19 +219,20 @@ module mkCCPipe#(
function ActionValue#(repT) updateRepInfo(repT oldRep, wayT hitWay), function ActionValue#(repT) updateRepInfo(repT oldRep, wayT hitWay),
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam, Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam,
RWBramCore#(indexT, repT) repRam, RWBramCore#(indexT, repT) repRam,
RWBramCore#(dataIndexT, lineT) dataRam RWBramCore#(dataIndexT, lineT) dataRam,
RWBramCore#(indexT, setAuxT) setAuxDataRam
)( )(
CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT) CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)
) provisos ( ) provisos (
Alias#(wayT, Bit#(TLog#(wayNum))), Alias#(wayT, Bit#(TLog#(wayNum))),
Alias#(indexT, Bit#(_indexSz)), Alias#(indexT, Bit#(_indexSz)),
Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)), Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)),
Alias#(respStateT, RespState#(msiT)), Alias#(respStateT, RespState#(msiT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT)), Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT)),
Bits#(tagT, _tagSz), Bits#(tagT, _tagSz),
Bits#(msiT, _msiSz), Bits#(msiT, _msiSz),
Bits#(dirT, _dirSz), Bits#(dirT, _dirSz),
@@ -229,6 +241,7 @@ module mkCCPipe#(
Bits#(repT, _repSz), Bits#(repT, _repSz),
Bits#(lineT, _lineSz), Bits#(lineT, _lineSz),
Bits#(pipeCmdT, _pipeCmdSz), Bits#(pipeCmdT, _pipeCmdSz),
Bits#(setAuxT, _setOtherSz),
// index to data ram: {way, normal index} // index to data ram: {way, normal index}
Alias#(dataIndexT, Bit#(TAdd#(TLog#(wayNum), _indexSz))) Alias#(dataIndexT, Bit#(TAdd#(TLog#(wayNum), _indexSz)))
); );
@@ -274,6 +287,8 @@ module mkCCPipe#(
end end
repRam.deqRdResp; repRam.deqRdResp;
repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo); repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo);
setAuxDataRam.deqRdResp;
setAuxT setAuxData = fromMaybe(setAuxDataRam.rdResp, e2m.setAuxData);
// do tag match to get way to occupy // do tag match to get way to occupy
Vector#(wayNum, tagT) tagVec; Vector#(wayNum, tagT) tagVec;
Vector#(wayNum, msiT) csVec; Vector#(wayNum, msiT) csVec;
@@ -297,7 +312,8 @@ module mkCCPipe#(
pRqMiss: pRqMiss, pRqMiss: pRqMiss,
info: infoVec[way], info: infoVec[way],
repInfo: repInfo, repInfo: repInfo,
line: e2m.respLine line: e2m.respLine,
setAuxData: setAuxData
}; };
if(e2m.toState matches tagged UpCs .s) begin if(e2m.toState matches tagged UpCs .s) begin
UpdateByUpCs#(msiT) upd <- updateByUpCs( UpdateByUpCs#(msiT) upd <- updateByUpCs(
@@ -332,7 +348,8 @@ module mkCCPipe#(
info: m2o.info, info: m2o.info,
line: fromMaybe(dataRam.rdResp, m2o.line) line: fromMaybe(dataRam.rdResp, m2o.line)
}, },
repInfo: m2o.repInfo repInfo: m2o.repInfo,
setAuxData: m2o.setAuxData
}; };
endfunction endfunction
@@ -348,17 +365,20 @@ module mkCCPipe#(
infoRam[i].rdReq(index); infoRam[i].rdReq(index);
end end
repRam.rdReq(index); repRam.rdReq(index);
setAuxDataRam.rdReq(index);
// write reg & get bypass // write reg & get bypass
enq2MatchT e2m = Enq2Match { enq2MatchT e2m = Enq2Match {
cmd: cmd, cmd: cmd,
infoVec: replicate(Invalid), infoVec: replicate(Invalid),
repInfo: Invalid, repInfo: Invalid,
respLine: respLine, respLine: respLine,
toState: toState toState: toState,
setAuxData: Invalid
}; };
if(bypass.wget matches tagged Valid .b &&& b.index == index) begin if(bypass.wget matches tagged Valid .b &&& b.index == index) begin
e2m.infoVec[b.way] = Valid (b.ram.info); e2m.infoVec[b.way] = Valid (b.ram.info);
e2m.repInfo = Valid (b.repInfo); e2m.repInfo = Valid (b.repInfo);
e2m.setAuxData = Valid(b.setAuxData);
end end
enq2Mat_enq <= Valid (e2m); enq2Mat_enq <= Valid (e2m);
endmethod endmethod
@@ -375,7 +395,7 @@ module mkCCPipe#(
method Bool notEmpty = deq_guard; method Bool notEmpty = deq_guard;
method Action deqWrite(Maybe#(pipeCmdT) newCmd, ramDataT wrRam, Bool updateRep) if(deq_guard); method Action deqWrite(Maybe#(pipeCmdT) newCmd, ramDataT wrRam, setAuxT setAuxData, Bool updateRep) if(deq_guard);
match2OutT m2o = fromMaybe(?, mat2Out_out); match2OutT m2o = fromMaybe(?, mat2Out_out);
wayT way = m2o.way; wayT way = m2o.way;
indexT index = getIndex(m2o.cmd); indexT index = getIndex(m2o.cmd);
@@ -388,12 +408,14 @@ module mkCCPipe#(
infoRam[way].wrReq(index, wrRam.info); infoRam[way].wrReq(index, wrRam.info);
repRam.wrReq(index, repInfo); repRam.wrReq(index, repInfo);
dataRam.wrReq(getDataRamIndex(way, index), wrRam.line); dataRam.wrReq(getDataRamIndex(way, index), wrRam.line);
setAuxDataRam.wrReq(index, setAuxData);
// set bypass to Enq and Match stages // set bypass to Enq and Match stages
bypass.wset(BypassInfo { bypass.wset(BypassInfo {
index: index, index: index,
way: way, way: way,
ram: wrRam, ram: wrRam,
repInfo: repInfo repInfo: repInfo,
setAuxData: setAuxData
}); });
// change pipeline reg // change pipeline reg
if(newCmd matches tagged Valid .cmd) begin if(newCmd matches tagged Valid .cmd) begin
@@ -404,7 +426,8 @@ module mkCCPipe#(
pRqMiss: False, // reset (not valid for swapped in pRq) pRqMiss: False, // reset (not valid for swapped in pRq)
info: wrRam.info, // get bypass info: wrRam.info, // get bypass
repInfo: repInfo, // get bypass repInfo: repInfo, // get bypass
line: Valid (wrRam.line) // get bypass line: Valid (wrRam.line), // get bypass
setAuxData: setAuxData
}); });
end end
else begin else begin
@@ -443,19 +466,20 @@ module mkCCPipeSingleCycle#(
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam, Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam,
RWBramCore#(indexT, repT) repRam, RWBramCore#(indexT, repT) repRam,
// Must be BRAMs with integrated forwarding; e.g. mkRWBramCoreForwarded // Must be BRAMs with integrated forwarding; e.g. mkRWBramCoreForwarded
Vector#(wayNum, RWBramCore#(dataIndexT, lineT)) dataRam Vector#(wayNum, RWBramCore#(dataIndexT, lineT)) dataRam,
RWBramCore#(indexT, setAuxT) setAuxDataRam
)( )(
CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT) CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)
) provisos ( ) provisos (
Alias#(wayT, Bit#(TLog#(wayNum))), Alias#(wayT, Bit#(TLog#(wayNum))),
Alias#(indexT, Bit#(_indexSz)), Alias#(indexT, Bit#(_indexSz)),
Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)), Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)),
Alias#(respStateT, RespState#(msiT)), Alias#(respStateT, RespState#(msiT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)), Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, pipeCmdT)),
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT)), Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT)),
Bits#(tagT, _tagSz), Bits#(tagT, _tagSz),
Bits#(msiT, _msiSz), Bits#(msiT, _msiSz),
Bits#(dirT, _dirSz), Bits#(dirT, _dirSz),
@@ -464,6 +488,7 @@ module mkCCPipeSingleCycle#(
Bits#(repT, _repSz), Bits#(repT, _repSz),
Bits#(lineT, _lineSz), Bits#(lineT, _lineSz),
Bits#(pipeCmdT, _pipeCmdSz), Bits#(pipeCmdT, _pipeCmdSz),
Bits#(setAuxT, _setOtherSz),
Alias#(dataIndexT, Bit#(_indexSz)) Alias#(dataIndexT, Bit#(_indexSz))
); );
@@ -494,6 +519,9 @@ module mkCCPipeSingleCycle#(
end end
repRam.deqRdResp; repRam.deqRdResp;
repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo); repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo);
setAuxDataRam.deqRdResp;
setAuxT setAuxData = fromMaybe(setAuxDataRam.rdResp, e2m.setAuxData);
//$display("%t : doTagMatch repRamdeqRdResp ", $time);
// do tag match to get way to occupy // do tag match to get way to occupy
Vector#(wayNum, tagT) tagVec; Vector#(wayNum, tagT) tagVec;
Vector#(wayNum, msiT) csVec; Vector#(wayNum, msiT) csVec;
@@ -513,7 +541,8 @@ module mkCCPipeSingleCycle#(
pRqMiss: pRqMiss, pRqMiss: pRqMiss,
info: infoVec[way], info: infoVec[way],
repInfo: repInfo, repInfo: repInfo,
line: isValid(e2m.respLine) ? e2m.respLine:Valid(dataVec[way]) line: isValid(e2m.respLine) ? e2m.respLine:Valid(dataVec[way]),
setAuxData: setAuxData
}; };
if(e2m.toState matches tagged UpCs .s) begin if(e2m.toState matches tagged UpCs .s) begin
UpdateByUpCs#(msiT) upd <- updateByUpCs( UpdateByUpCs#(msiT) upd <- updateByUpCs(
@@ -546,7 +575,8 @@ module mkCCPipeSingleCycle#(
info: m2o.info, info: m2o.info,
line: m2o.line.Valid line: m2o.line.Valid
}, },
repInfo: m2o.repInfo repInfo: m2o.repInfo,
setAuxData: m2o.setAuxData
}; };
endfunction endfunction
@@ -563,13 +593,16 @@ module mkCCPipeSingleCycle#(
dataRam[i].rdReq(index); dataRam[i].rdReq(index);
end end
repRam.rdReq(index); repRam.rdReq(index);
setAuxDataRam.rdReq(index);
//$display("%t : enq repRam.rdReq ", $time);
// write reg // write reg
enq2MatchT e2m = Enq2Match { enq2MatchT e2m = Enq2Match {
cmd: cmd, cmd: cmd,
infoVec: replicate(Invalid), infoVec: replicate(Invalid),
repInfo: Invalid, repInfo: Invalid,
respLine: respLine, respLine: respLine,
toState: toState toState: toState,
setAuxData: Invalid
}; };
enq2Mat_enq <= Valid (e2m); enq2Mat_enq <= Valid (e2m);
endmethod endmethod
@@ -586,7 +619,7 @@ module mkCCPipeSingleCycle#(
method Bool notEmpty = deq_guard; method Bool notEmpty = deq_guard;
method Action deqWrite(Maybe#(pipeCmdT) newCmd, ramDataT wrRam, Bool updateRep) if(deq_guard); method Action deqWrite(Maybe#(pipeCmdT) newCmd, ramDataT wrRam, setAuxT setAuxData, Bool updateRep) if(deq_guard);
match2OutT m2o = fromMaybe(?, mat2Out_out); match2OutT m2o = fromMaybe(?, mat2Out_out);
wayT way = m2o.way; wayT way = m2o.way;
indexT index = getIndex(m2o.cmd); indexT index = getIndex(m2o.cmd);
@@ -599,6 +632,7 @@ module mkCCPipeSingleCycle#(
infoRam[way].wrReq(index, wrRam.info); infoRam[way].wrReq(index, wrRam.info);
repRam.wrReq(index, repInfo); repRam.wrReq(index, repInfo);
dataRam[way].wrReq(index, wrRam.line); dataRam[way].wrReq(index, wrRam.line);
setAuxDataRam.wrReq(index, setAuxData);
// change pipeline reg // change pipeline reg
if(newCmd matches tagged Valid .cmd) begin if(newCmd matches tagged Valid .cmd) begin
// update pipeline reg // update pipeline reg
@@ -608,7 +642,8 @@ module mkCCPipeSingleCycle#(
pRqMiss: False, // reset (not valid for swapped in pRq) pRqMiss: False, // reset (not valid for swapped in pRq)
info: wrRam.info, info: wrRam.info,
repInfo: repInfo, repInfo: repInfo,
line: Valid(wrRam.line) line: Valid(wrRam.line),
setAuxData: setAuxData
}); });
end end
else begin else begin

View File

@@ -124,8 +124,10 @@ module mkIBank#(
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))), Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))), Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
Alias#(cacheOwnerT, Maybe#(cRqIdxT)), // owner cannot be pRq Alias#(cacheOwnerT, Maybe#(cRqIdxT)), // owner cannot be pRq
Alias#(cacheOtherT, void), // owner cannot be pRq
Alias#(cacheSetAuxT, Maybe#(cRqIdxT)),
Alias#(cacheInfoT, CacheInfo#(tagT, Msi, void, cacheOwnerT, void)), Alias#(cacheInfoT, CacheInfo#(tagT, Msi, void, cacheOwnerT, void)),
Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, void, Line)), Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, cacheOtherT, Line)),
Alias#(procRqT, ProcRqToI), Alias#(procRqT, ProcRqToI),
Alias#(cRqToPT, CRqMsg#(wayT, void)), Alias#(cRqToPT, CRqMsg#(wayT, void)),
Alias#(cRsToPT, CRsMsg#(void)), Alias#(cRsToPT, CRsMsg#(void)),
@@ -134,7 +136,7 @@ module mkIBank#(
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)), Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
Alias#(cRqSlotT, ICRqSlot#(wayT, tagT)), // cRq MSHR slot Alias#(cRqSlotT, ICRqSlot#(wayT, tagT)), // cRq MSHR slot
Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)), Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, void, RandRepInfo, Line, l1CmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, cacheOtherT, RandRepInfo, Line, cacheSetAuxT, l1CmdT)),
Mul#(2, supSz, supSzX2), Mul#(2, supSz, supSzX2),
Alias#(resultT, Vector#(supSzX2, Maybe#(Instruction16))), Alias#(resultT, Vector#(supSzX2, Maybe#(Instruction16))),
// requirements // requirements
@@ -531,7 +533,7 @@ module mkIBank#(
other: ? other: ?
}, },
line: ram.line line: ram.line
}, True); // hit, so update rep info }, Invalid, True); // hit, so update rep info
if (!cRqIsPrefetch[n]) begin if (!cRqIsPrefetch[n]) begin
prefetcher.reportAccess(req.addr, HIT); prefetcher.reportAccess(req.addr, HIT);
llcPrefetcher.reportAccess(req.addr, HIT); llcPrefetcher.reportAccess(req.addr, HIT);
@@ -594,7 +596,7 @@ module mkIBank#(
other: ? other: ?
}, },
line: ram.line line: ram.line
}, False); }, Invalid, False);
if (!cRqIsPrefetch[n]) begin if (!cRqIsPrefetch[n]) begin
prefetcher.reportAccess(procRq.addr, MISS); prefetcher.reportAccess(procRq.addr, MISS);
llcPrefetcher.reportAccess(procRq.addr, MISS); llcPrefetcher.reportAccess(procRq.addr, MISS);
@@ -616,7 +618,7 @@ module mkIBank#(
other: ? other: ?
}, },
line: ? // data is no longer used line: ? // data is no longer used
}, False); }, Invalid, False);
doAssert(ram.info.cs == S, "I$ replacement only replace S line"); doAssert(ram.info.cs == S, "I$ replacement only replace S line");
// update MSHR to save replaced tag // update MSHR to save replaced tag
// although we send req to parent later (when resp to parent is sent) // although we send req to parent later (when resp to parent is sent)
@@ -639,7 +641,7 @@ module mkIBank#(
function Action cRqSetDepNoCacheChange; function Action cRqSetDepNoCacheChange;
action action
cRqMshr.pipelineResp.setStateSlot(n, Depend, defaultValue); cRqMshr.pipelineResp.setStateSlot(n, Depend, defaultValue);
pipeline.deqWrite(Invalid, pipeOut.ram, False); pipeline.deqWrite(Invalid, pipeOut.ram, Invalid, False);
endaction endaction
endfunction endfunction
@@ -740,7 +742,7 @@ module mkIBank#(
$display("%t I %m pipelineResp: pRq: drop", $time); $display("%t I %m pipelineResp: pRq: drop", $time);
// pRq can be directly dropped, no successor (since just go through pipeline) // pRq can be directly dropped, no successor (since just go through pipeline)
pRqMshr.pipelineResp.releaseEntry(n); pRqMshr.pipelineResp.releaseEntry(n);
pipeline.deqWrite(Invalid, pipeOut.ram, False); pipeline.deqWrite(Invalid, pipeOut.ram, Invalid, False);
end end
else begin else begin
if (verbose) if (verbose)
@@ -763,7 +765,7 @@ module mkIBank#(
other: ? other: ?
}, },
line: ? // line is not useful line: ? // line is not useful
}, False); }, Invalid, False);
// pRq is done // pRq is done
pRqMshr.pipelineResp.setDone(n); pRqMshr.pipelineResp.setDone(n);
// send resp to parent // send resp to parent
@@ -824,7 +826,7 @@ module mkIBank#(
other: ? other: ?
}, },
line: ? line: ?
}, False); }, Invalid, False);
// check if we have finished all flush // check if we have finished all flush
if (flush.index == maxBound && if (flush.index == maxBound &&

View File

@@ -120,11 +120,12 @@ typedef struct {
cRqIdxT n; // AMO req MSHR idx cRqIdxT n; // AMO req MSHR idx
cRqT req; // AMO req cRqT req; // AMO req
Maybe#(cRqIdxT) succ; // same-addr-successor of AMO req Maybe#(cRqIdxT) succ; // same-addr-successor of AMO req
Maybe#(cRqIdxT) nextInQueue;
} AmoHitInfo#(type cRqIdxT, type cRqT) deriving(Bits, Eq, FShow); } AmoHitInfo#(type cRqIdxT, type cRqT) deriving(Bits, Eq, FShow);
module mkL1Bank#( module mkL1Bank#(
Bit#(lgBankNum) bankId, Bit#(lgBankNum) bankId,
module#(L1CRqMshr#(cRqNum, wayT, tagT, procRqT)) mkL1CRqMshrLocal, module#(L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal, module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal,
module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline, module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline,
L1ProcResp#(procRqIdT) procResp L1ProcResp#(procRqIdT) procResp
@@ -137,6 +138,7 @@ module mkL1Bank#(
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))), Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))), Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
Alias#(cacheOwnerT, Maybe#(cRqIdxT)), // actually owner cannot be pRq Alias#(cacheOwnerT, Maybe#(cRqIdxT)), // actually owner cannot be pRq
Alias#(cacheSetAuxT, Maybe#(cRqIdxT)),
Alias#(cacheInfoT, CacheInfo#(tagT, Msi, void, cacheOwnerT, void)), Alias#(cacheInfoT, CacheInfo#(tagT, Msi, void, cacheOwnerT, void)),
Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, void, Line)), Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, void, Line)),
Alias#(procRqT, ProcRq#(procRqIdT)), Alias#(procRqT, ProcRq#(procRqIdT)),
@@ -147,7 +149,7 @@ module mkL1Bank#(
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)), Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
Alias#(cRqSlotT, L1CRqSlot#(wayT, tagT)), // cRq MSHR slot Alias#(cRqSlotT, L1CRqSlot#(wayT, tagT)), // cRq MSHR slot
Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)), Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, void, RandRepInfo, Line, l1CmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, void, RandRepInfo, Line, cacheSetAuxT, l1CmdT)),
// requirements // requirements
Bits#(procRqIdT, _procRqIdT), Bits#(procRqIdT, _procRqIdT),
FShow#(procRqIdT), FShow#(procRqIdT),
@@ -160,7 +162,7 @@ module mkL1Bank#(
Bool verbose = False; Bool verbose = False;
L1CRqMshr#(cRqNum, wayT, tagT, procRqT) cRqMshr <- mkL1CRqMshrLocal; L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT) cRqMshr <- mkL1CRqMshrLocal;
L1PRqMshr#(pRqNum) pRqMshr <- mkL1PRqMshrLocal; L1PRqMshr#(pRqNum) pRqMshr <- mkL1PRqMshrLocal;
@@ -559,6 +561,8 @@ endfunction
L1CRqState pipeOutCState = cRqMshr.pipelineResp.getState(pipeOutCRqIdx); L1CRqState pipeOutCState = cRqMshr.pipelineResp.getState(pipeOutCRqIdx);
cRqSlotT pipeOutCSlot = cRqMshr.pipelineResp.getSlot(pipeOutCRqIdx); cRqSlotT pipeOutCSlot = cRqMshr.pipelineResp.getSlot(pipeOutCRqIdx);
Maybe#(cRqIdxT) pipeOutSucc = cRqMshr.pipelineResp.getSucc(pipeOutCRqIdx); Maybe#(cRqIdxT) pipeOutSucc = cRqMshr.pipelineResp.getSucc(pipeOutCRqIdx);
Maybe#(cRqIdxT) pipeOutNextInQueue = pipeOut.setAuxData;
Maybe#(cRqIdxT) pipeOutSecondInQueue = isValid(pipeOutNextInQueue) ? cRqMshr.pipelineResp.getSucc2(fromMaybe(?, pipeOutNextInQueue)) : Invalid;
// function to process cRq hit (MSHR slot may have garbage) // function to process cRq hit (MSHR slot may have garbage)
function Action cRqHit(cRqIdxT n, procRqT req); function Action cRqHit(cRqIdxT n, procRqT req);
@@ -639,7 +643,16 @@ endfunction
other: ? other: ?
}, },
line: newLine // write new data into cache line: newLine // write new data into cache
}, True); // hit, so update rep info }, isValid(succ) ? pipeOutNextInQueue : pipeOutSecondInQueue, True); // hit, so update rep info
if (!isValid(succ) &&& pipeOutNextInQueue matches tagged Valid .nextInQueue) begin
$display("%t L1D dequeuing queued req: mshr: %d, queueSucc: ",
$time,
nextInQueue,
fshow(pipeOutSecondInQueue)
);
cRqRetryIndexQ.enq(nextInQueue);
cRqMshr.manageQueue.resetEntry(nextInQueue);
end
if (!cRqIsPrefetch[n]) begin if (!cRqIsPrefetch[n]) begin
prefetcher.reportAccess(req.addr, req.pcHash, HIT); prefetcher.reportAccess(req.addr, req.pcHash, HIT);
llcPrefetcher.reportAccess(req.addr, req.pcHash, HIT); llcPrefetcher.reportAccess(req.addr, req.pcHash, HIT);
@@ -656,7 +669,8 @@ endfunction
processAmo <= Valid (AmoHitInfo { processAmo <= Valid (AmoHitInfo {
n: n, n: n,
req: req, req: req,
succ: succ succ: succ,
nextInQueue: pipeOutNextInQueue
}); });
if (verbose) if (verbose)
$display("%t L1 %m pipelineResp: Hit func: AMO process in next cycle", $time); $display("%t L1 %m pipelineResp: Hit func: AMO process in next cycle", $time);
@@ -676,7 +690,7 @@ endfunction
MemTaggedData current = getTaggedDataAt(curLine, dataSel); MemTaggedData current = getTaggedDataAt(curLine, dataSel);
Vector#(2, Bit#(64)) dwordData = current.data; Vector#(2, Bit#(64)) dwordData = current.data;
Vector#(4, Bit#(32)) wordData = unpack(pack(current.data)); Vector#(4, Bit#(32)) wordData = unpack(pack(current.data));
Bit#(1) dwordIdx = req.addr[3]; Bit#(1) dwordIdx = req.addr[3];
Bit#(2) wordIdx = req.addr[3:2]; Bit#(2) wordIdx = req.addr[3:2];
// resp processor // resp processor
MemTaggedData resp = case (req.amoInst.width) MemTaggedData resp = case (req.amoInst.width)
@@ -704,7 +718,7 @@ endfunction
other: ? other: ?
}, },
line: newLine // write new data into cache line: newLine // write new data into cache
}, True); // hit, so update rep info }, amoHit.nextInQueue, True); // hit, so update rep info
doAssert(req.toState == M, "AMO must req for M"); doAssert(req.toState == M, "AMO must req for M");
if (verbose) if (verbose)
$display("%t L1 %m processAmo: update ram: ", $time, $display("%t L1 %m processAmo: update ram: ", $time,
@@ -726,7 +740,8 @@ endfunction
$display("%t L1 %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq)); $display("%t L1 %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
// find end of dependency chain // find end of dependency chain
Maybe#(cRqIdxT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(procRq.addr); Maybe#(cRqIdxT) cRqDependEOC = cRqMshr.pipelineResp.searchDependEndOfChain(procRq.addr);
Maybe#(cRqIdxT) cRqQueuedEOC = cRqMshr.pipelineResp.searchQueuedEndOfChain(procRq.addr);
function Action cRqScEarlyFail(Bool resetOwner); function Action cRqScEarlyFail(Bool resetOwner);
action action
@@ -746,7 +761,7 @@ endfunction
other: ram.info.other other: ram.info.other
}, },
line: ram.line line: ram.line
}, False); }, pipeOutNextInQueue, False);
// retry successor // retry successor
Maybe#(cRqIdxT) succ = pipeOutSucc; Maybe#(cRqIdxT) succ = pipeOutSucc;
if(succ matches tagged Valid .s) begin if(succ matches tagged Valid .s) begin
@@ -793,7 +808,7 @@ endfunction
other: ? other: ?
}, },
line: ram.line line: ram.line
}, False); }, pipeOutNextInQueue, False);
if (!cRqIsPrefetch[n]) begin if (!cRqIsPrefetch[n]) begin
prefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS); prefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS);
llcPrefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS); llcPrefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS);
@@ -814,7 +829,7 @@ endfunction
other: ? other: ?
}, },
line: ? // data is no longer used line: ? // data is no longer used
}, False); }, pipeOutNextInQueue, False);
// update MSHR: may save replaced line data // update MSHR: may save replaced line data
cRqMshr.pipelineResp.setStateSlot(n, WaitNewTag, L1CRqSlot { cRqMshr.pipelineResp.setStateSlot(n, WaitNewTag, L1CRqSlot {
way: pipeOut.way, // use way from pipeline way: pipeOut.way, // use way from pipeline
@@ -841,7 +856,22 @@ endfunction
function Action cRqSetDepNoCacheChange; function Action cRqSetDepNoCacheChange;
action action
cRqMshr.pipelineResp.setStateSlot(n, Depend, defaultValue); cRqMshr.pipelineResp.setStateSlot(n, Depend, defaultValue);
pipeline.deqWrite(Invalid, pipeOut.ram, False); pipeline.deqWrite(Invalid, pipeOut.ram, pipeOutNextInQueue, False);
endaction
endfunction
function Action cRqQueue;
action
cRqMshr.pipelineResp.setStateSlot(n, Queued, defaultValue);
pipeline.deqWrite(Invalid, pipeOut.ram, Valid(fromMaybe(n, pipeOutNextInQueue)), False);
endaction
endfunction
function Action cRqDrop;
action
cRqMshr.pipelineResp.releaseEntry(n);
crqMshrDeqs <= crqMshrDeqs + 1;
pipeline.deqWrite(Invalid, pipeOut.ram, pipeOutNextInQueue, False);
endaction endaction
endfunction endfunction
@@ -857,18 +887,36 @@ endfunction
Bool cs_valid = ram.info.cs > I; Bool cs_valid = ram.info.cs > I;
if(ram.info.owner matches tagged Valid .cOwner) begin if(ram.info.owner matches tagged Valid .cOwner) begin
if(cOwner != n) begin if(cOwner != n) begin
// owner is another cRq, so must just go through tag match
// tag match must be hit (because replacement algo won't give a way with owner)
doAssert(pipeOutCState == Init, "must first time go through tag match"); doAssert(pipeOutCState == Init, "must first time go through tag match");
doAssert(cs_valid && tag_match, "cRq should hit in tag match"); // If the tags match then we want to add to a dependency chain
// should be added to a cRq in dependency chain & deq from pipeline if (tag_match) begin
doAssert(isValid(cRqEOC), ("cRq hit on another cRq, cRqEOC must be true")); // should be added to a cRq in dependency chain & deq from pipeline
cRqMshr.pipelineResp.setSucc(fromMaybe(?, cRqEOC), Valid (n)); doAssert(isValid(cRqDependEOC), ("cRq hit on another cRq, cRqDependEOC must be true"));
cRqSetDepNoCacheChange; // If this is a prefetch, we can drop the prefetch here (prefetch was probably late)
if (verbose) if (cRqIsPrefetch[n]) begin
$display("%t L1 %m pipelineResp: cRq: own by other cRq ", $time, cRqDrop;
fshow(cOwner), ", depend on cRq ", fshow(cRqEOC) end else begin
); cRqMshr.pipelineResp.setSucc(fromMaybe(?, cRqDependEOC), Valid (n));
cRqSetDepNoCacheChange;
end
if (verbose)
$display("%t L1 %m pipelineResp: cRq: own by other cRq ", $time,
fshow(cOwner), ", depend on cRq ", fshow(cRqDependEOC)
);
end
// If the tags don't match then we want to queue the cRq
else begin
// if there was an option to add a dependency, L1Pipe should have found it
doAssert(!isValid(cRqDependEOC), ("end of chain is valid but the chosen way did not match tags"));
if (cRqIsPrefetch[n]) begin
cRqDrop;
end else begin
if (cRqQueuedEOC matches tagged Valid .eoc) begin
cRqMshr.pipelineResp.setSucc(eoc, Valid (n));
end
cRqQueue;
end
end
end end
else begin else begin
// owner is myself, so must be swapped in // owner is myself, so must be swapped in
@@ -907,47 +955,38 @@ endfunction
// 2. cRq addr-depends on an Sc which fails early, just got waken up // 2. cRq addr-depends on an Sc which fails early, just got waken up
L1CRqState cState = pipeOutCState; L1CRqState cState = pipeOutCState;
// check for cRqEOC to append to dependency chain // There should be no dependency
// Only append to dep-chain if is in Init state doAssert(!isValid(cRqDependEOC), "end of chain is valid but the chosen way is not owned");
if(cRqEOC matches tagged Valid .k &&& cState == Init) begin
if (verbose) // Check hit or miss, replacment may be needed
$display("%t L1 %m pipelineResp: cRq: no owner, depend on cRq, ", $time, if(tag_match && enough_cs_to_hit) begin
fshow(cState), " ; ", fshow(cRqEOC) // Hit
doAssert(cs_valid, "hit, so cs must > I");
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, hit", $time);
cRqHit(n, procRq, False);
end
else if(scFail) begin
// Sc already fails, so we don't need to req parent. Since
// there is no owner of the line, we can reset owner to
// Invalid.
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, Sc early fails, ",
$time, fshow(linkAddr)
); );
cRqMshr.pipelineResp.setSucc(k, Valid (n)); cRqScEarlyFail(True);
cRqSetDepNoCacheChange; end
else if(cs_valid && !tag_match) begin
// Req parent, need replacement
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, replace", $time);
cRqReplacement;
end end
else begin else begin
// Check hit or miss, replacment may be needed if (verbose)
if(tag_match && enough_cs_to_hit) begin $display("%t L1 %m pipelineResp: cRq: no owner, miss no replace", $time);
// Hit // Req parent, no replacement needed
doAssert(cs_valid, "hit, so cs must > I"); cRqMissNoReplacement;
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, hit", $time);
cRqHit(n, procRq);
end
else if(scFail) begin
// Sc already fails, so we don't need to req parent. Since
// there is no owner of the line, we can reset owner to
// Invalid.
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, Sc early fails, ",
$time, fshow(linkAddr)
);
cRqScEarlyFail(True);
end
else if(cs_valid && !tag_match) begin
// Req parent, need replacement
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, replace", $time);
cRqReplacement;
end
else begin
if (verbose)
$display("%t L1 %m pipelineResp: cRq: no owner, miss no replace", $time);
// Req parent, no replacement needed
cRqMissNoReplacement;
end
end end
end end
endrule endrule
@@ -989,7 +1028,7 @@ endfunction
// pRq can be directly dropped // pRq can be directly dropped
// must go through tag match, no successor // must go through tag match, no successor
pRqMshr.pipelineResp.releaseEntry(n); pRqMshr.pipelineResp.releaseEntry(n);
pipeline.deqWrite(Invalid, pipeOut.ram, False); pipeline.deqWrite(Invalid, pipeOut.ram, pipeOutNextInQueue, False);
// sanity check (ram.info.tag != getTag(pRq.addr) is useless) // sanity check (ram.info.tag != getTag(pRq.addr) is useless)
if(!pipeOut.pRqMiss) begin if(!pipeOut.pRqMiss) begin
doAssert(ram.info.cs == S && pRq.toState == S && ram.info.tag == getTag(pRq.addr), doAssert(ram.info.cs == S && pRq.toState == S && ram.info.tag == getTag(pRq.addr),
@@ -1023,7 +1062,7 @@ endfunction
other: ? other: ?
}, },
line: ram.line line: ram.line
}, False); }, pipeOutNextInQueue, False);
rsToPIndexQ.enq(PRq (n)); rsToPIndexQ.enq(PRq (n));
// update cRq bookkeeping // update cRq bookkeeping
cRqMshr.pipelineResp.setStateSlot(cOwner, WaitSt, L1CRqSlot { cRqMshr.pipelineResp.setStateSlot(cOwner, WaitSt, L1CRqSlot {
@@ -1054,7 +1093,16 @@ endfunction
other: ? other: ?
}, },
line: ram.line line: ram.line
}, False); }, pipeOutSecondInQueue, False);
if (pipeOutNextInQueue matches tagged Valid .nextInQueue) begin
$display("%t L1D dequeuing queued req: mshr: %d, queueSucc: ",
$time,
nextInQueue,
fshow(pipeOutSecondInQueue)
);
cRqRetryIndexQ.enq(nextInQueue);
cRqMshr.manageQueue.resetEntry(nextInQueue);
end
rsToPIndexQ.enq(PRq (n)); rsToPIndexQ.enq(PRq (n));
end end
@@ -1076,6 +1124,7 @@ endfunction
// During flush, cRq MSHR is empty, so cache line cannot have owner // During flush, cRq MSHR is empty, so cache line cannot have owner
doAssert(ram.info.owner == Invalid, "flushing line cannot have owner"); doAssert(ram.info.owner == Invalid, "flushing line cannot have owner");
doAssert(pipeOutNextInQueue == Invalid, "flushing line cannot have queued requests");
// flush always goes through cache pipeline, and is directly handled // flush always goes through cache pipeline, and is directly handled
// here: either dropped or Done // here: either dropped or Done
@@ -1107,7 +1156,7 @@ endfunction
other: ? other: ?
}, },
line: ? line: ?
}, False); }, Invalid, False);
// always reset link addr // always reset link addr
linkAddr <= Invalid; linkAddr <= Invalid;
@@ -1230,8 +1279,9 @@ endmodule
// -- cRqMshr.releaseEntry // -- cRqMshr.releaseEntry
// -- read cRq MSHR req/state/slot/data currently processed // -- read cRq MSHR req/state/slot/data currently processed
// -- write cRq MSHR state/slot/data currently processed // -- write cRq MSHR state/slot/data currently processed
// -- write cRq MSHR state/succ of some existing cRq MSHR entry (in Queued)
// -- write succ of some existing cRq MSHR entry (in WaitNewTag or WaitSt) // -- write succ of some existing cRq MSHR entry (in WaitNewTag or WaitSt)
// -- read all state/req/succ in cRq MSHR entry (searchEOC) // -- read all state/req/succ in cRq MSHR entry (searchDependEOC and searchQueueEOC)
// -- not affected by write in cRqTransfer // -- not affected by write in cRqTransfer
// -- not affected by write in sendRsToP_cRq (state change is just WaitNewTag->WaitSt) // -- not affected by write in sendRsToP_cRq (state change is just WaitNewTag->WaitSt)
@@ -1260,13 +1310,16 @@ endmodule
// sendRqToP conflict free with pipelineResp_xxx // sendRqToP conflict free with pipelineResp_xxx
// pipelineResp_cRq conflicts with itself, potentially writing state/succ of multiple entries
// ---- conclusion ---- // ---- conclusion ----
// we have 4 ports from cRq MSHR // we have 5 ports from cRq MSHR
// 1. cRqTransfer // 1. cRqTransfer
// 2. sendRsToP_cRq // 2. sendRsToP_cRq
// 3. sendRqToP // 3. sendRqToP
// 4. pipelineResp // 4. pipelineResp
// 5. manageQueue
// we have 3 ports from pRq MSHR // we have 3 ports from pRq MSHR
// 1. pRqTransfer // 1. pRqTransfer
@@ -1280,7 +1333,8 @@ endmodule
// safe version: use EHR ports // safe version: use EHR ports
// sendRsToP_cRq/sendRsToP_pRq: port 0 // sendRsToP_cRq/sendRsToP_pRq: port 0
// pipelineResp: port 1 // pipelineResp: port 1
// cRqTransfer/sendRqToP/pRqTransfer: port 2 // manageQueue: port 2
// cRqTransfer/sendRqToP/pRqTransfer: port 3
// We put cRqTransfer at last because it is ordered after the issue method of // We put cRqTransfer at last because it is ordered after the issue method of
// LSQ outside cache, while pipelineResp and sendRsToP will call other methods // LSQ outside cache, while pipelineResp and sendRsToP will call other methods
@@ -1290,7 +1344,7 @@ endmodule
// group banks into cache // group banks into cache
module mkL1Cache#( module mkL1Cache#(
module#(L1CRqMshr#(cRqNum, wayT, tagT, procRqT)) mkL1CRqMshrLocal, module#(L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal, module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal,
module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline, module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline,
L1ProcResp#(procRqIdT) procResp L1ProcResp#(procRqIdT) procResp
@@ -1306,12 +1360,14 @@ module mkL1Cache#(
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))), Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))), Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
Alias#(cacheOwnerT, Maybe#(cRqIdxT)), Alias#(cacheOwnerT, Maybe#(cRqIdxT)),
Alias#(cacheOtherT, void),
Alias#(cacheSetAuxT, Maybe#(cRqIdxT)),
Alias#(procRqT, ProcRq#(procRqIdT)), Alias#(procRqT, ProcRq#(procRqIdT)),
Alias#(cRqToPT, CRqMsg#(wayT, void)), Alias#(cRqToPT, CRqMsg#(wayT, void)),
Alias#(cRsToPT, CRsMsg#(void)), Alias#(cRsToPT, CRsMsg#(void)),
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)), Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)), Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, void, RandRepInfo, Line, l1CmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, void, RandRepInfo, Line, cacheSetAuxT, l1CmdT)),
// requirements // requirements
Bits#(procRqIdT, _procRqIdT), Bits#(procRqIdT, _procRqIdT),
FShow#(procRqIdT), FShow#(procRqIdT),

View File

@@ -57,7 +57,8 @@ typedef enum {
WaitNewTag, // waiting replacement resp to send (but tag in RAM is already updated) WaitNewTag, // waiting replacement resp to send (but tag in RAM is already updated)
WaitSt, // wait pRs/cRs to come WaitSt, // wait pRs/cRs to come
Done, // resp is in index FIFO Done, // resp is in index FIFO
Depend Depend,
Queued // wait for a way to be free
} L1CRqState deriving(Bits, Eq, FShow); } L1CRqState deriving(Bits, Eq, FShow);
// CRq info returned to outside // CRq info returned to outside
@@ -129,6 +130,7 @@ endinterface
// port for pipelineResp // port for pipelineResp
interface L1CRqMshr_pipelineResp#( interface L1CRqMshr_pipelineResp#(
numeric type cRqNum, numeric type cRqNum,
type indexT,
type wayT, type wayT,
type tagT, type tagT,
type reqT type reqT
@@ -149,16 +151,26 @@ interface L1CRqMshr_pipelineResp#(
// cannot be used to release MSHR entry (use releaseSlot instead) // cannot be used to release MSHR entry (use releaseSlot instead)
method Maybe#(Bit#(TLog#(cRqNum))) getSucc(Bit#(TLog#(cRqNum)) n); method Maybe#(Bit#(TLog#(cRqNum))) getSucc(Bit#(TLog#(cRqNum)) n);
method Maybe#(Bit#(TLog#(cRqNum))) getSucc2(Bit#(TLog#(cRqNum)) n);
method Action setSucc(Bit#(TLog#(cRqNum)) n, Maybe#(Bit#(TLog#(cRqNum))) succ); method Action setSucc(Bit#(TLog#(cRqNum)) n, Maybe#(Bit#(TLog#(cRqNum))) succ);
// index in setSucc is usually different from other getXXX methods // index in setSucc is usually different from other getXXX methods
// find existing cRq which has gone through pipeline, but not in Done state, and has not successor // find existing cRq which has gone through pipeline, but not in Done state, and has not successor
// i.e. search the end of dependency chain // i.e. search the end of dependency chain
method Maybe#(Bit#(TLog#(cRqNum))) searchEndOfChain(Addr addr); method Maybe#(Bit#(TLog#(cRqNum))) searchDependEndOfChain(Addr addr);
method Maybe#(Bit#(TLog#(cRqNum))) searchQueuedEndOfChain(Addr addr);
endinterface
// port to manage the state of queued instructions in parallel with pipelineResp
interface L1CRqMshr_manageQueue#(
numeric type cRqNum
);
method Action resetEntry(Bit#(TLog#(cRqNum)) n);
endinterface endinterface
interface L1CRqMshr#( interface L1CRqMshr#(
numeric type cRqNum, numeric type cRqNum,
type indexT,
type wayT, type wayT,
type tagT, type tagT,
type reqT // child req type type reqT // child req type
@@ -173,7 +185,10 @@ interface L1CRqMshr#(
interface L1CRqMshr_sendRqToP#(cRqNum, wayT, tagT, reqT) sendRqToP; interface L1CRqMshr_sendRqToP#(cRqNum, wayT, tagT, reqT) sendRqToP;
// port for pipelineResp // port for pipelineResp
interface L1CRqMshr_pipelineResp#(cRqNum, wayT, tagT, reqT) pipelineResp; interface L1CRqMshr_pipelineResp#(cRqNum, indexT, wayT, tagT, reqT) pipelineResp;
// port for manageQueue
interface L1CRqMshr_manageQueue#(cRqNum) manageQueue;
// port for security flush // port for security flush
method Bool emptyForFlush; method Bool emptyForFlush;
@@ -187,12 +202,14 @@ endinterface
// safe version // // safe version //
////////////////// //////////////////
module mkL1CRqMshrSafe#( module mkL1CRqMshrSafe#(
function Addr getAddrFromReq(reqT r) function Addr getAddrFromReq(reqT r),
function indexT getIndexFromAddr(Addr addr)
)( )(
L1CRqMshr#(cRqNum, wayT, tagT, reqT) L1CRqMshr#(cRqNum, indexT, wayT, tagT, reqT)
) provisos ( ) provisos (
Alias#(cRqIndexT, Bit#(TLog#(cRqNum))), Alias#(cRqIndexT, Bit#(TLog#(cRqNum))),
Alias#(slotT, L1CRqSlot#(wayT, tagT)), Alias#(slotT, L1CRqSlot#(wayT, tagT)),
Alias#(indexT, Bit#(_indexSz)),
Alias#(wayT, Bit#(_waySz)), Alias#(wayT, Bit#(_waySz)),
Alias#(tagT, Bit#(_tagSz)), Alias#(tagT, Bit#(_tagSz)),
Bits#(reqT, _reqSz) Bits#(reqT, _reqSz)
@@ -205,20 +222,21 @@ module mkL1CRqMshrSafe#(
Integer sendRqToP_port = 0; // sendRqToP is read only Integer sendRqToP_port = 0; // sendRqToP is read only
Integer sendRsToP_cRq_port = 0; Integer sendRsToP_cRq_port = 0;
Integer pipelineResp_port = 1; Integer pipelineResp_port = 1;
Integer cRqTransfer_port = 2; Integer manageQueue_port = 2;
Integer cRqTransfer_port = 3;
// MSHR entry state // MSHR entry state
Vector#(cRqNum, Ehr#(3, L1CRqState)) stateVec <- replicateM(mkEhr(Empty)); Vector#(cRqNum, Ehr#(4, L1CRqState)) stateVec <- replicateM(mkEhr(Empty));
// cRq req contents // cRq req contents
Vector#(cRqNum, Ehr#(3, reqT)) reqVec <- replicateM(mkEhr(?)); Vector#(cRqNum, Ehr#(4, reqT)) reqVec <- replicateM(mkEhr(?));
// cRq mshr slots // cRq mshr slots
Vector#(cRqNum, Ehr#(3, slotT)) slotVec <- replicateM(mkEhr(defaultValue)); Vector#(cRqNum, Ehr#(4, slotT)) slotVec <- replicateM(mkEhr(defaultValue));
// data valid bit // data valid bit
Vector#(cRqNum, Ehr#(3, Bool)) dataValidVec <- replicateM(mkEhr(False)); Vector#(cRqNum, Ehr#(4, Bool)) dataValidVec <- replicateM(mkEhr(False));
// data values // data values
RegFile#(cRqIndexT, Line) dataFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1)); RegFile#(cRqIndexT, Line) dataFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1));
// successor valid bit // successor valid bit
Vector#(cRqNum, Ehr#(3, Bool)) succValidVec <- replicateM(mkEhr(False)); Vector#(cRqNum, Ehr#(4, Bool)) succValidVec <- replicateM(mkEhr(False));
// successor MSHR index // successor MSHR index
RegFile#(cRqIndexT, cRqIndexT) succFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1)); RegFile#(cRqIndexT, cRqIndexT) succFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1));
// empty entry FIFO // empty entry FIFO
@@ -346,24 +364,47 @@ module mkL1CRqMshrSafe#(
return succValidVec[n][pipelineResp_port] ? (Valid (succFile.sub(n))) : Invalid; return succValidVec[n][pipelineResp_port] ? (Valid (succFile.sub(n))) : Invalid;
endmethod endmethod
method Action setSucc(cRqIndexT n, Maybe#(cRqIndexT) succ); method Maybe#(cRqIndexT) getSucc2(cRqIndexT n);
succValidVec[n][pipelineResp_port] <= isValid(succ); return succValidVec[n][pipelineResp_port] ? (Valid (succFile.sub(n))) : Invalid;
succFile.upd(n, fromMaybe(?, succ));
endmethod endmethod
method Maybe#(cRqIndexT) searchEndOfChain(Addr addr); method Action setSucc(cRqIndexT n, Maybe#(cRqIndexT) succ);
succValidVec[n][pipelineResp_port] <= isValid(succ);
if (succ matches tagged Valid .s)
succFile.upd(n, s);
endmethod
method Maybe#(cRqIndexT) searchDependEndOfChain(Addr addr);
function Bool isEndOfChain(Integer i); function Bool isEndOfChain(Integer i);
// check entry i is end of chain or not // check entry i is end of chain or not
L1CRqState state = stateVec[i][pipelineResp_port]; L1CRqState state = stateVec[i][pipelineResp_port];
Bool notDone = state != Done; Bool isDepend = state == WaitSt || state == WaitNewTag || state == Depend;
Bool processedOnce = state != Empty && state != Init;
Bool addrMatch = getLineAddr(getAddrFromReq(reqVec[i][pipelineResp_port])) == getLineAddr(addr); Bool addrMatch = getLineAddr(getAddrFromReq(reqVec[i][pipelineResp_port])) == getLineAddr(addr);
Bool noSucc = !succValidVec[i][pipelineResp_port]; Bool noSucc = !succValidVec[i][pipelineResp_port];
return notDone && processedOnce && addrMatch && noSucc; return isDepend && addrMatch && noSucc;
endfunction endfunction
Vector#(cRqNum, Integer) idxVec = genVector; Vector#(cRqNum, Integer) idxVec = genVector;
return searchIndex(isEndOfChain, idxVec); return searchIndex(isEndOfChain, idxVec);
endmethod endmethod
method Maybe#(Bit#(TLog#(cRqNum))) searchQueuedEndOfChain(Addr addr);
function Bool isEndOfChain(Integer i);
L1CRqState state = stateVec[i][pipelineResp_port];
Bool isQueued = state == Queued;
Bool indexMatch = getIndexFromAddr(getAddrFromReq(reqVec[i][pipelineResp_port])) == getIndexFromAddr(addr);
Bool noSucc = !succValidVec[i][pipelineResp_port];
return isQueued && indexMatch && noSucc;
endfunction
Vector#(cRqNum, Integer) idxVec = genVector;
return searchIndex(isEndOfChain, idxVec);
endmethod
endinterface
interface L1CRqMshr_manageQueue manageQueue;
method Action resetEntry(Bit#(TLog#(cRqNum)) n);
stateVec[n][manageQueue_port] <= Init;
succValidVec[n][manageQueue_port] <= False;
endmethod
endinterface endinterface
method Bool emptyForFlush; method Bool emptyForFlush;
@@ -381,14 +422,16 @@ endmodule
// exported version // exported version
module mkL1CRqMshr#( module mkL1CRqMshr#(
function Addr getAddrFromReq(reqT r) function Addr getAddrFromReq(reqT r),
function indexT getIndexFromAddr(Addr addr)
)( )(
L1CRqMshr#(cRqNum, wayT, tagT, reqT) L1CRqMshr#(cRqNum, indexT, wayT, tagT, reqT)
) provisos ( ) provisos (
Alias#(indexT, Bit#(_indexSz)),
Alias#(wayT, Bit#(_waySz)), Alias#(wayT, Bit#(_waySz)),
Alias#(tagT, Bit#(_tagSz)), Alias#(tagT, Bit#(_tagSz)),
Bits#(reqT, _reqSz) Bits#(reqT, _reqSz)
); );
let m <- mkL1CRqMshrSafe(getAddrFromReq); let m <- mkL1CRqMshrSafe(getAddrFromReq, getIndexFromAddr);
return m; return m;
endmodule endmodule

View File

@@ -126,11 +126,12 @@ interface L1Pipe#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, void, // no dir tagT, Msi, void, // no dir
Maybe#(cRqIdxT), void, RandRepInfo, // no other Maybe#(cRqIdxT), void, RandRepInfo, // no other
Line, L1Cmd#(indexT, cRqIdxT, pRqIdxT) Line, Maybe#(cRqIdxT), L1Cmd#(indexT, cRqIdxT, pRqIdxT)
) first; ) first;
method Action deqWrite( method Action deqWrite(
Maybe#(cRqIdxT) swapRq, Maybe#(cRqIdxT) swapRq,
RamData#(tagT, Msi, void, Maybe#(cRqIdxT), void, Line) wrRam, // always write BRAM RamData#(tagT, Msi, void, Maybe#(cRqIdxT), void, Line) wrRam, // always write BRAM
Maybe#(cRqIdxT) nextInQueue,
Bool updateRep Bool updateRep
); );
endinterface endinterface
@@ -162,11 +163,12 @@ module mkL1Pipe(
Alias#(dirT, void), // no directory Alias#(dirT, void), // no directory
Alias#(ownerT, Maybe#(cRqIdxT)), Alias#(ownerT, Maybe#(cRqIdxT)),
Alias#(otherT, void), // no other cache info Alias#(otherT, void), // no other cache info
Alias#(setAuxT, Maybe#(cRqIdxT)),
Alias#(repT, RandRepInfo), // use random replace Alias#(repT, RandRepInfo), // use random replace
Alias#(pipeInT, L1PipeIn#(wayT, indexT, cRqIdxT, pRqIdxT)), Alias#(pipeInT, L1PipeIn#(wayT, indexT, cRqIdxT, pRqIdxT)),
Alias#(pipeCmdT, L1PipeCmd#(wayT, indexT, cRqIdxT, pRqIdxT)), Alias#(pipeCmdT, L1PipeCmd#(wayT, indexT, cRqIdxT, pRqIdxT)),
Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)), Alias#(l1CmdT, L1Cmd#(indexT, cRqIdxT, pRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, l1CmdT)), // output type Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, setAuxT, l1CmdT)), // output type
Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)), Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
Alias#(respStateT, RespState#(Msi)), Alias#(respStateT, RespState#(Msi)),
@@ -189,6 +191,7 @@ module mkL1Pipe(
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCoreForwarded); Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCoreForwarded);
RWBramCore#(indexT, repT) repRam <- mkRandRepRam; RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
Vector#(wayNum, RWBramCore#(indexT, Line)) dataRam <- replicateM(mkRWBramCoreForwarded); Vector#(wayNum, RWBramCore#(indexT, Line)) dataRam <- replicateM(mkRWBramCoreForwarded);
RWBramCore#(indexT, setAuxT) queueRam <- mkRWBramCoreForwarded;
// initialize RAM // initialize RAM
Reg#(Bool) initDone <- mkReg(False); Reg#(Bool) initDone <- mkReg(False);
@@ -205,6 +208,7 @@ module mkL1Pipe(
}); });
end end
repRam.wrReq(initIndex, randRepInitInfo); // useless for random replace repRam.wrReq(initIndex, randRepInitInfo); // useless for random replace
queueRam.wrReq(initIndex, Invalid);
initIndex <= initIndex + 1; initIndex <= initIndex + 1;
if(initIndex == maxBound) begin if(initIndex == maxBound) begin
initDone <= True; initDone <= True;
@@ -272,11 +276,11 @@ module mkL1Pipe(
Addr addr = getAddrFromCmd(cmd); Addr addr = getAddrFromCmd(cmd);
tagT tag = getTag(addr); tagT tag = getTag(addr);
// find hit way (nothing is being replaced) // find hit way (nothing is being replaced)
function Bool isMatch(Tuple2#(Msi, tagT) csTag); function Bool isMatch(Tuple3#(Msi, tagT, ownerT) csTagOwner);
match {.cs, .t} = csTag; match {.cs, .t, .o} = csTagOwner;
return cs > I && t == tag; return (cs > I || isValid(o)) && t == tag;
endfunction endfunction
Maybe#(wayT) hitWay = searchIndex(isMatch, zip(csVec, tagVec)); Maybe#(wayT) hitWay = searchIndex(isMatch, zip3(csVec, tagVec, ownerVec));
if(hitWay matches tagged Valid .w) begin if(hitWay matches tagged Valid .w) begin
return TagMatchResult { return TagMatchResult {
way: w, way: w,
@@ -300,9 +304,14 @@ module mkL1Pipe(
end end
Maybe#(wayT) repWay = randRep.getReplaceWay(unlocked, invalid); Maybe#(wayT) repWay = randRep.getReplaceWay(unlocked, invalid);
// sanity check: repWay must be valid // sanity check: repWay must be valid
// ^ Not true if there are more MSHRs than ways
// Just choose a locked way. This will create a dependency chain.
// TODO: Maybe would be nice to replace the way that becomes free the soonest.
if(!isValid(repWay)) begin if(!isValid(repWay)) begin
$fwrite(stderr, "[L1Pipe] ERROR: ", fshow(cmd), " cannot find way to replace\n"); if(verbose)
$finish; $display("%t L1 %m tagMatch: set oversubscription", $time);
//$fwrite(stderr, "[L1Pipe] ERROR: ", fshow(cmd), " cannot find way to replace\n");
//$finish;
end end
return TagMatchResult { return TagMatchResult {
way: fromMaybe(?, repWay), way: fromMaybe(?, repWay),
@@ -339,11 +348,11 @@ module mkL1Pipe(
endfunction endfunction
CCPipe#( CCPipe#(
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, setAuxT, pipeCmdT
) pipe <- mkCCPipeSingleCycle( ) pipe <- mkCCPipeSingleCycle(
regToReadOnly(initDone), getIndex, tagMatch, regToReadOnly(initDone), getIndex, tagMatch,
updateByUpCs, updateByDownDir, updateRepInfo, updateByUpCs, updateByDownDir, updateRepInfo,
infoRam, repRam, dataRam infoRam, repRam, dataRam, queueRam
); );
method Action send(pipeInT req); method Action send(pipeInT req);
@@ -387,11 +396,12 @@ module mkL1Pipe(
way: pout.way, way: pout.way,
pRqMiss: pout.pRqMiss, pRqMiss: pout.pRqMiss,
ram: pout.ram, ram: pout.ram,
repInfo: pout.repInfo repInfo: pout.repInfo,
setAuxData: pout.setAuxData
}; };
endmethod endmethod
method Action deqWrite(Maybe#(cRqIdxT) swapRq, ramDataT wrRam, Bool updateRep); method Action deqWrite(Maybe#(cRqIdxT) swapRq, ramDataT wrRam, Maybe#(cRqIdxT) nextInQueue, Bool updateRep);
// get new cmd // get new cmd
Maybe#(pipeCmdT) newCmd = Invalid; Maybe#(pipeCmdT) newCmd = Invalid;
if(swapRq matches tagged Valid .idx) begin // swap in cRq if(swapRq matches tagged Valid .idx) begin // swap in cRq
@@ -403,6 +413,6 @@ module mkL1Pipe(
`endif `endif
end end
// call pipe // call pipe
pipe.deqWrite(newCmd, wrRam, updateRep); pipe.deqWrite(newCmd, wrRam, nextInQueue, updateRep);
endmethod endmethod
endmodule endmodule

View File

@@ -179,7 +179,7 @@ module mkLLBank#(
Alias#(cRqT, LLRq#(cRqIdT, dmaRqIdT, childT)), Alias#(cRqT, LLRq#(cRqIdT, dmaRqIdT, childT)),
Alias#(cRqSlotT, LLCRqSlot#(wayT, tagT, Vector#(childNum, DirPend))), // cRq MSHR slot Alias#(cRqSlotT, LLCRqSlot#(wayT, tagT, Vector#(childNum, DirPend))), // cRq MSHR slot
Alias#(llCmdT, LLCmd#(childT, cRqIndexT)), Alias#(llCmdT, LLCmd#(childT, cRqIndexT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, cacheOwnerT, void, RandRepInfo, Line, llCmdT)), Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, cacheOwnerT, void, RandRepInfo, Line, void, llCmdT)),
// requirements // requirements
Bits#(cRqIdT, _cRqIdSz), Bits#(cRqIdT, _cRqIdSz),
Bits#(dmaRqIdT, _dmaRqIdSz), Bits#(dmaRqIdT, _dmaRqIdSz),

View File

@@ -95,13 +95,13 @@ interface LLPipe#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, Vector#(childNum, Msi), tagT, Msi, Vector#(childNum, Msi),
Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other
Line, LLCmd#(Bit#(TLog#(childNum)), cRqIdxT) Line, void, LLCmd#(Bit#(TLog#(childNum)), cRqIdxT) // no aux set data
) first; ) first;
method PipeOut#( method PipeOut#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, Vector#(childNum, Msi), tagT, Msi, Vector#(childNum, Msi),
Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other
Line, LLCmd#(Bit#(TLog#(childNum)), cRqIdxT) Line, void, LLCmd#(Bit#(TLog#(childNum)), cRqIdxT) // no aux set data
) unguard_first; ) unguard_first;
method Action deqWrite( method Action deqWrite(
Maybe#(cRqIdxT) swapRq, Maybe#(cRqIdxT) swapRq,
@@ -143,7 +143,7 @@ module mkLLPipe(
Alias#(pipeInT, LLPipeIn#(childT, wayT, cRqIdxT)), Alias#(pipeInT, LLPipeIn#(childT, wayT, cRqIdxT)),
Alias#(pipeCmdT, LLPipeCmd#(childT, wayT, cRqIdxT)), Alias#(pipeCmdT, LLPipeCmd#(childT, wayT, cRqIdxT)),
Alias#(llCmdT, LLCmd#(childT, cRqIdxT)), Alias#(llCmdT, LLCmd#(childT, cRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, llCmdT)), // output type Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, llCmdT)), // output type
Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)), Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
Alias#(respStateT, RespState#(Msi)), Alias#(respStateT, RespState#(Msi)),
@@ -165,6 +165,7 @@ module mkLLPipe(
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore); Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore);
RWBramCore#(indexT, repT) repRam <- mkRandRepRam; RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore; RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
// initialize RAM // initialize RAM
Reg#(Bool) initDone <- mkReg(False); Reg#(Bool) initDone <- mkReg(False);
@@ -322,14 +323,14 @@ module mkLLPipe(
endactionvalue endactionvalue
endfunction endfunction
CCPipe#(wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT) pipe <- mkCCPipe( CCPipe#(wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT) pipe <- mkCCPipe(
regToReadOnly(initDone), getIndex, tagMatch, regToReadOnly(initDone), getIndex, tagMatch,
updateByUpCs, updateByDownDir, updateRepInfo, updateByUpCs, updateByDownDir, updateRepInfo,
infoRam, repRam, dataRam infoRam, repRam, dataRam, setAuxDataRam
); );
// get first output from CCPipe output // get first output from CCPipe output
function pipeOutT getFirst(PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT) pout); function pipeOutT getFirst(PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT) pout);
return PipeOut { return PipeOut {
cmd: (case(pout.cmd) matches cmd: (case(pout.cmd) matches
tagged CRq .rq: LLCRq (rq.mshrIdx); tagged CRq .rq: LLCRq (rq.mshrIdx);
@@ -340,7 +341,8 @@ module mkLLPipe(
way: pout.way, way: pout.way,
pRqMiss: pout.pRqMiss, pRqMiss: pout.pRqMiss,
ram: pout.ram, ram: pout.ram,
repInfo: pout.repInfo repInfo: pout.repInfo,
setAuxData: ?
}; };
endfunction endfunction
@@ -383,6 +385,6 @@ module mkLLPipe(
newCmd = Valid (CRq (LLPipeCRqIn {addr: addr, mshrIdx: idx})); newCmd = Valid (CRq (LLPipeCRqIn {addr: addr, mshrIdx: idx}));
end end
// call pipe // call pipe
pipe.deqWrite(newCmd, wrRam, updateRep); pipe.deqWrite(newCmd, wrRam, ?, updateRep);
endmethod endmethod
endmodule endmodule

View File

@@ -45,6 +45,34 @@ interface RWBramCore#(type addrT, type dataT);
method Action deqRdResp; method Action deqRdResp;
endinterface endinterface
interface RBramCore#(type addrT, type dataT);
method Action rd1Req(addrT a);
method Action rd2Req(addrT a);
method dataT rd1Resp;
method dataT rd2Resp;
method Bool rd1RespValid;
method Bool rd2RespValid;
method Action deqRd1Resp;
method Action deqRd2Resp;
endinterface
module mkDummyBramCore(RWBramCore#(addrT, dataT)) provisos(
Bits#(addrT, addrSz), Bits#(dataT, dataSz)
);
method Action wrReq(addrT a, dataT d);
endmethod
method Action rdReq(addrT a);
endmethod
method dataT rdResp = ?;
method rdRespValid = True;
method Action deqRdResp;
endmethod
endmodule
module mkRWBramCore(RWBramCore#(addrT, dataT)) provisos( module mkRWBramCore(RWBramCore#(addrT, dataT)) provisos(
Bits#(addrT, addrSz), Bits#(dataT, dataSz) Bits#(addrT, addrSz), Bits#(dataT, dataSz)
); );

View File

@@ -100,7 +100,7 @@ interface SelfInvIPipe#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, void, // no dir tagT, Msi, void, // no dir
Maybe#(cRqIdxT), void, RandRepInfo, // no other Maybe#(cRqIdxT), void, RandRepInfo, // no other
Line, SelfInvICmd#(cRqIdxT) Line, void, SelfInvICmd#(cRqIdxT) // no aux set data
) first; ) first;
method Action deqWrite( method Action deqWrite(
Maybe#(cRqIdxT) swapRq, Maybe#(cRqIdxT) swapRq,
@@ -239,7 +239,7 @@ module mkSelfInvIPipe(
Alias#(pipeInT, SelfInvIPipeIn#(wayT, cRqIdxT)), Alias#(pipeInT, SelfInvIPipeIn#(wayT, cRqIdxT)),
Alias#(pipeCmdT, SelfInvIPipeCmd#(wayT, cRqIdxT)), Alias#(pipeCmdT, SelfInvIPipeCmd#(wayT, cRqIdxT)),
Alias#(iCmdT, SelfInvICmd#(cRqIdxT)), Alias#(iCmdT, SelfInvICmd#(cRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, iCmdT)), // output type Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, iCmdT)), // output type
Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)), Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
Alias#(respStateT, RespState#(Msi)), Alias#(respStateT, RespState#(Msi)),
@@ -262,6 +262,7 @@ module mkSelfInvIPipe(
RWBramCore#(indexT, repT) repRam <- mkRandRepRam; RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
// data RAM // data RAM
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore; RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
// initialize RAM // initialize RAM
Reg#(Bool) initDone <- mkReg(False); Reg#(Bool) initDone <- mkReg(False);
@@ -392,11 +393,11 @@ module mkSelfInvIPipe(
endfunction endfunction
CCPipe#( CCPipe#(
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT
) pipe <- mkCCPipe( ) pipe <- mkCCPipe(
regToReadOnly(initDone), getIndex, tagMatch, regToReadOnly(initDone), getIndex, tagMatch,
updateByUpCs, updateByDownDir, updateRepInfo, updateByUpCs, updateByDownDir, updateRepInfo,
infoRam, repRam, dataRam infoRam, repRam, dataRam, setAuxDataRam
); );
// reconcile: wait until pipeline empty and drop all S states. Stall // reconcile: wait until pipeline empty and drop all S states. Stall
@@ -458,7 +459,8 @@ module mkSelfInvIPipe(
way: pout.way, way: pout.way,
pRqMiss: pout.pRqMiss, pRqMiss: pout.pRqMiss,
ram: pout.ram, ram: pout.ram,
repInfo: pout.repInfo repInfo: pout.repInfo,
setAuxData: ?
}; };
endmethod endmethod
@@ -470,7 +472,7 @@ module mkSelfInvIPipe(
newCmd = Valid (CRq (SelfInvIPipeRqIn {addr: addr, mshrIdx: idx})); newCmd = Valid (CRq (SelfInvIPipeRqIn {addr: addr, mshrIdx: idx}));
end end
// call pipe // call pipe
pipe.deqWrite(newCmd, wrRam, updateRep); pipe.deqWrite(newCmd, wrRam, ?, updateRep);
// conflict with reconcile // conflict with reconcile
conflict_reconcile_deq.wset(?); conflict_reconcile_deq.wset(?);
endmethod endmethod

View File

@@ -113,7 +113,7 @@ interface SelfInvL1Pipe#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, void, // no dir tagT, Msi, void, // no dir
Maybe#(cRqIdxT), SelfInvL1Hits#(maxHitNum), RandRepInfo, Maybe#(cRqIdxT), SelfInvL1Hits#(maxHitNum), RandRepInfo,
Line, SelfInvL1Cmd#(cRqIdxT, pRqIdxT) Line, void, SelfInvL1Cmd#(cRqIdxT, pRqIdxT) // no aux set data
) first; ) first;
method Action deqWrite( method Action deqWrite(
Maybe#(cRqIdxT) swapRq, Maybe#(cRqIdxT) swapRq,
@@ -252,7 +252,7 @@ module mkSelfInvL1Pipe(
Alias#(pipeInT, SelfInvL1PipeIn#(wayT, cRqIdxT, pRqIdxT)), Alias#(pipeInT, SelfInvL1PipeIn#(wayT, cRqIdxT, pRqIdxT)),
Alias#(pipeCmdT, SelfInvL1PipeCmd#(wayT, cRqIdxT, pRqIdxT)), Alias#(pipeCmdT, SelfInvL1PipeCmd#(wayT, cRqIdxT, pRqIdxT)),
Alias#(l1CmdT, SelfInvL1Cmd#(cRqIdxT, pRqIdxT)), Alias#(l1CmdT, SelfInvL1Cmd#(cRqIdxT, pRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, l1CmdT)), // output type Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, l1CmdT)), // output type
Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)), Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
Alias#(respStateT, RespState#(Msi)), Alias#(respStateT, RespState#(Msi)),
@@ -277,6 +277,7 @@ module mkSelfInvL1Pipe(
RWBramCore#(indexT, repT) repRam <- mkRandRepRam; RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
// data RAM // data RAM
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore; RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
// initialize RAM // initialize RAM
Reg#(Bool) initDone <- mkReg(False); Reg#(Bool) initDone <- mkReg(False);
@@ -414,11 +415,11 @@ module mkSelfInvL1Pipe(
endfunction endfunction
CCPipe#( CCPipe#(
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT
) pipe <- mkCCPipe( ) pipe <- mkCCPipe(
regToReadOnly(initDone), getIndex, tagMatch, regToReadOnly(initDone), getIndex, tagMatch,
updateByUpCs, updateByDownDir, updateRepInfo, updateByUpCs, updateByDownDir, updateRepInfo,
infoRam, repRam, dataRam infoRam, repRam, dataRam, setAuxDataRam
); );
// reconcile: wait until pipeline empty and drop all S states. Stall // reconcile: wait until pipeline empty and drop all S states. Stall
@@ -484,7 +485,8 @@ module mkSelfInvL1Pipe(
way: pout.way, way: pout.way,
pRqMiss: pout.pRqMiss, pRqMiss: pout.pRqMiss,
ram: pout.ram, ram: pout.ram,
repInfo: pout.repInfo repInfo: pout.repInfo,
setAuxData: ?
}; };
endmethod endmethod
@@ -496,7 +498,7 @@ module mkSelfInvL1Pipe(
newCmd = Valid (CRq (SelfInvL1PipeRqIn {addr: addr, mshrIdx: idx})); newCmd = Valid (CRq (SelfInvL1PipeRqIn {addr: addr, mshrIdx: idx}));
end end
// call pipe // call pipe
pipe.deqWrite(newCmd, wrRam, updateRep); pipe.deqWrite(newCmd, wrRam, ?, updateRep);
// conflict with reconcile // conflict with reconcile
conflict_reconcile_deq.wset(?); conflict_reconcile_deq.wset(?);
endmethod endmethod

View File

@@ -95,13 +95,13 @@ interface SelfInvLLPipe#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))), tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))),
Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other
Line, SelfInvLLCmd#(Bit#(TLog#(childNum)), cRqIdxT) Line, void, SelfInvLLCmd#(Bit#(TLog#(childNum)), cRqIdxT) // no aux set data
) first; ) first;
method PipeOut#( method PipeOut#(
Bit#(TLog#(wayNum)), Bit#(TLog#(wayNum)),
tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))), tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))),
Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other Maybe#(CRqOwner#(cRqIdxT)), void, RandRepInfo, // no other
Line, SelfInvLLCmd#(Bit#(TLog#(childNum)), cRqIdxT) Line, void, SelfInvLLCmd#(Bit#(TLog#(childNum)), cRqIdxT) // no aux set data
) unguard_first; ) unguard_first;
method Action deqWrite( method Action deqWrite(
Maybe#(cRqIdxT) swapRq, Maybe#(cRqIdxT) swapRq,
@@ -143,7 +143,7 @@ module mkSelfInvLLPipe(
Alias#(pipeInT, SelfInvLLPipeIn#(childT, wayT, cRqIdxT)), Alias#(pipeInT, SelfInvLLPipeIn#(childT, wayT, cRqIdxT)),
Alias#(pipeCmdT, SelfInvLLPipeCmd#(childT, wayT, cRqIdxT)), Alias#(pipeCmdT, SelfInvLLPipeCmd#(childT, wayT, cRqIdxT)),
Alias#(llCmdT, SelfInvLLCmd#(childT, cRqIdxT)), Alias#(llCmdT, SelfInvLLCmd#(childT, cRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, llCmdT)), // output type Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, llCmdT)), // output type
Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)), Alias#(infoT, CacheInfo#(tagT, Msi, dirT, ownerT, otherT)),
Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)), Alias#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
Alias#(respStateT, RespState#(Msi)), Alias#(respStateT, RespState#(Msi)),
@@ -165,6 +165,7 @@ module mkSelfInvLLPipe(
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore); Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore);
RWBramCore#(indexT, repT) repRam <- mkRandRepRam; RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore; RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
// initialize RAM // initialize RAM
Reg#(Bool) initDone <- mkReg(False); Reg#(Bool) initDone <- mkReg(False);
@@ -318,14 +319,14 @@ module mkSelfInvLLPipe(
endactionvalue endactionvalue
endfunction endfunction
CCPipe#(wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT) pipe <- mkCCPipe( CCPipe#(wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT) pipe <- mkCCPipe(
regToReadOnly(initDone), getIndex, tagMatch, regToReadOnly(initDone), getIndex, tagMatch,
updateByUpCs, updateByDownDir, updateRepInfo, updateByUpCs, updateByDownDir, updateRepInfo,
infoRam, repRam, dataRam infoRam, repRam, dataRam, setAuxDataRam
); );
// get first output from CCPipe output // get first output from CCPipe output
function pipeOutT getFirst(PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT) pout); function pipeOutT getFirst(PipeOut#(wayT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT) pout);
return PipeOut { return PipeOut {
cmd: (case(pout.cmd) matches cmd: (case(pout.cmd) matches
tagged CRq .rq: LLCRq (rq.mshrIdx); tagged CRq .rq: LLCRq (rq.mshrIdx);
@@ -336,7 +337,8 @@ module mkSelfInvLLPipe(
way: pout.way, way: pout.way,
pRqMiss: pout.pRqMiss, pRqMiss: pout.pRqMiss,
ram: pout.ram, ram: pout.ram,
repInfo: pout.repInfo repInfo: pout.repInfo,
setAuxData: ?
}; };
endfunction endfunction
@@ -379,7 +381,7 @@ module mkSelfInvLLPipe(
newCmd = Valid (CRq (SelfInvLLPipeCRqIn {addr: addr, mshrIdx: idx})); newCmd = Valid (CRq (SelfInvLLPipeCRqIn {addr: addr, mshrIdx: idx}));
end end
// call pipe // call pipe
pipe.deqWrite(newCmd, wrRam, updateRep); pipe.deqWrite(newCmd, wrRam, ?, updateRep);
endmethod endmethod
endmodule endmodule
`endif // SELF_INV_CACHE `endif // SELF_INV_CACHE

View File

@@ -112,12 +112,15 @@ typedef Bit#(TMax#(SizeOf#(LdQTag), SizeOf#(SBIndex))) DProcReqId;
(* synthesize *) (* synthesize *)
module mkDCRqMshrWrapper( module mkDCRqMshrWrapper(
L1CRqMshr#(DCRqNum, L1Way, DTag, ProcRq#(DProcReqId)) L1CRqMshr#(DCRqNum, DIndex, L1Way, DTag, ProcRq#(DProcReqId))
); );
function Addr getAddrFromReq(ProcRq#(DProcReqId) r); function Addr getAddrFromReq(ProcRq#(DProcReqId) r);
return r.addr; return r.addr;
endfunction endfunction
let m <- mkL1CRqMshr(getAddrFromReq); function DIndex getIndexFromAddr(Addr addr);
return truncate(addr >> (valueOf(LgLineSzBytes) + valueOf(LgDBankNum)));
endfunction
let m <- mkL1CRqMshr(getAddrFromReq, getIndexFromAddr);
return m; return m;
endmodule endmodule