Request queues in L1 cache
This commit is contained in:
committed by
Jonathan Woodruff
parent
03b8face1e
commit
535d85ff35
@@ -58,6 +58,8 @@ typedef struct {
|
||||
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram;
|
||||
// replace info, actually not needed, just output for debug purposes
|
||||
repT repInfo;
|
||||
// the next-in-line queuer for this cache index
|
||||
setAuxT setAuxData;
|
||||
} PipeOut#(
|
||||
type wayT,
|
||||
type tagT,
|
||||
@@ -67,6 +69,7 @@ typedef struct {
|
||||
type otherT,
|
||||
type repT,
|
||||
type lineT,
|
||||
type setAuxT,
|
||||
type pipeCmdT
|
||||
) deriving(Bits, Eq, FShow);
|
||||
|
||||
@@ -80,16 +83,18 @@ interface CCPipe#(
|
||||
type otherT,
|
||||
type repT,
|
||||
type lineT,
|
||||
type setAuxT,
|
||||
type pipeCmdT
|
||||
);
|
||||
method Action enq(pipeCmdT cmd, Maybe#(lineT) respLine, RespState#(msiT) toState);
|
||||
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, pipeCmdT) unguard_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, setAuxT, pipeCmdT) unguard_first;
|
||||
method Bool notEmpty;
|
||||
method Action deqWrite(
|
||||
Maybe#(pipeCmdT) newCmd,
|
||||
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) wrRam,
|
||||
setAuxT setAuxData,
|
||||
Bool updateRep // update replacement info
|
||||
);
|
||||
// empty signal when we need to flush self-invalidate cache
|
||||
@@ -110,6 +115,7 @@ typedef struct {
|
||||
// CRs/PRs info
|
||||
Maybe#(lineT) respLine;
|
||||
RespState#(msiT) toState;
|
||||
Maybe#(setAuxT) setAuxData;
|
||||
} Enq2Match#(
|
||||
numeric type wayNum,
|
||||
type tagT,
|
||||
@@ -119,6 +125,7 @@ typedef struct {
|
||||
type otherT,
|
||||
type repT,
|
||||
type lineT,
|
||||
type setAuxT,
|
||||
type pipeCmdT
|
||||
) deriving(Bits, Eq, FShow);
|
||||
|
||||
@@ -134,6 +141,7 @@ typedef struct {
|
||||
repT repInfo;
|
||||
// bypassed or resp line
|
||||
Maybe#(lineT) line;
|
||||
setAuxT setAuxData;
|
||||
} Match2Out#(
|
||||
type wayT,
|
||||
type tagT,
|
||||
@@ -143,6 +151,7 @@ typedef struct {
|
||||
type otherT,
|
||||
type repT,
|
||||
type lineT,
|
||||
type setAuxT,
|
||||
type pipeCmdT
|
||||
) deriving(Bits, Eq, FShow);
|
||||
|
||||
@@ -151,6 +160,7 @@ typedef struct {
|
||||
wayT way;
|
||||
RamData#(tagT, msiT, dirT, ownerT, otherT, lineT) ram; // data to write into RAM
|
||||
repT repInfo; // replacement info write into RAM
|
||||
setAuxT setAuxData;
|
||||
} BypassInfo#(
|
||||
type wayT,
|
||||
type indexT,
|
||||
@@ -160,7 +170,8 @@ typedef struct {
|
||||
type ownerT,
|
||||
type otherT,
|
||||
type repT,
|
||||
type lineT
|
||||
type lineT,
|
||||
type setAuxT
|
||||
) deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef struct {
|
||||
@@ -208,19 +219,20 @@ module mkCCPipe#(
|
||||
function ActionValue#(repT) updateRepInfo(repT oldRep, wayT hitWay),
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam,
|
||||
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 (
|
||||
Alias#(wayT, Bit#(TLog#(wayNum))),
|
||||
Alias#(indexT, Bit#(_indexSz)),
|
||||
Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)),
|
||||
Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)),
|
||||
Alias#(respStateT, RespState#(msiT)),
|
||||
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT)),
|
||||
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, 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, setAuxT, pipeCmdT)),
|
||||
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT)),
|
||||
Bits#(tagT, _tagSz),
|
||||
Bits#(msiT, _msiSz),
|
||||
Bits#(dirT, _dirSz),
|
||||
@@ -229,6 +241,7 @@ module mkCCPipe#(
|
||||
Bits#(repT, _repSz),
|
||||
Bits#(lineT, _lineSz),
|
||||
Bits#(pipeCmdT, _pipeCmdSz),
|
||||
Bits#(setAuxT, _setOtherSz),
|
||||
// index to data ram: {way, normal index}
|
||||
Alias#(dataIndexT, Bit#(TAdd#(TLog#(wayNum), _indexSz)))
|
||||
);
|
||||
@@ -274,6 +287,8 @@ module mkCCPipe#(
|
||||
end
|
||||
repRam.deqRdResp;
|
||||
repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo);
|
||||
setAuxDataRam.deqRdResp;
|
||||
setAuxT setAuxData = fromMaybe(setAuxDataRam.rdResp, e2m.setAuxData);
|
||||
// do tag match to get way to occupy
|
||||
Vector#(wayNum, tagT) tagVec;
|
||||
Vector#(wayNum, msiT) csVec;
|
||||
@@ -297,7 +312,8 @@ module mkCCPipe#(
|
||||
pRqMiss: pRqMiss,
|
||||
info: infoVec[way],
|
||||
repInfo: repInfo,
|
||||
line: e2m.respLine
|
||||
line: e2m.respLine,
|
||||
setAuxData: setAuxData
|
||||
};
|
||||
if(e2m.toState matches tagged UpCs .s) begin
|
||||
UpdateByUpCs#(msiT) upd <- updateByUpCs(
|
||||
@@ -332,7 +348,8 @@ module mkCCPipe#(
|
||||
info: m2o.info,
|
||||
line: fromMaybe(dataRam.rdResp, m2o.line)
|
||||
},
|
||||
repInfo: m2o.repInfo
|
||||
repInfo: m2o.repInfo,
|
||||
setAuxData: m2o.setAuxData
|
||||
};
|
||||
endfunction
|
||||
|
||||
@@ -348,17 +365,20 @@ module mkCCPipe#(
|
||||
infoRam[i].rdReq(index);
|
||||
end
|
||||
repRam.rdReq(index);
|
||||
setAuxDataRam.rdReq(index);
|
||||
// write reg & get bypass
|
||||
enq2MatchT e2m = Enq2Match {
|
||||
cmd: cmd,
|
||||
infoVec: replicate(Invalid),
|
||||
repInfo: Invalid,
|
||||
respLine: respLine,
|
||||
toState: toState
|
||||
toState: toState,
|
||||
setAuxData: Invalid
|
||||
};
|
||||
if(bypass.wget matches tagged Valid .b &&& b.index == index) begin
|
||||
e2m.infoVec[b.way] = Valid (b.ram.info);
|
||||
e2m.repInfo = Valid (b.repInfo);
|
||||
e2m.setAuxData = Valid(b.setAuxData);
|
||||
end
|
||||
enq2Mat_enq <= Valid (e2m);
|
||||
endmethod
|
||||
@@ -375,7 +395,7 @@ module mkCCPipe#(
|
||||
|
||||
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);
|
||||
wayT way = m2o.way;
|
||||
indexT index = getIndex(m2o.cmd);
|
||||
@@ -388,12 +408,14 @@ module mkCCPipe#(
|
||||
infoRam[way].wrReq(index, wrRam.info);
|
||||
repRam.wrReq(index, repInfo);
|
||||
dataRam.wrReq(getDataRamIndex(way, index), wrRam.line);
|
||||
setAuxDataRam.wrReq(index, setAuxData);
|
||||
// set bypass to Enq and Match stages
|
||||
bypass.wset(BypassInfo {
|
||||
index: index,
|
||||
way: way,
|
||||
ram: wrRam,
|
||||
repInfo: repInfo
|
||||
repInfo: repInfo,
|
||||
setAuxData: setAuxData
|
||||
});
|
||||
// change pipeline reg
|
||||
if(newCmd matches tagged Valid .cmd) begin
|
||||
@@ -404,7 +426,8 @@ module mkCCPipe#(
|
||||
pRqMiss: False, // reset (not valid for swapped in pRq)
|
||||
info: wrRam.info, // get bypass
|
||||
repInfo: repInfo, // get bypass
|
||||
line: Valid (wrRam.line) // get bypass
|
||||
line: Valid (wrRam.line), // get bypass
|
||||
setAuxData: setAuxData
|
||||
});
|
||||
end
|
||||
else begin
|
||||
@@ -443,19 +466,20 @@ module mkCCPipeSingleCycle#(
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam,
|
||||
RWBramCore#(indexT, repT) repRam,
|
||||
// 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 (
|
||||
Alias#(wayT, Bit#(TLog#(wayNum))),
|
||||
Alias#(indexT, Bit#(_indexSz)),
|
||||
Alias#(infoT, CacheInfo#(tagT, msiT, dirT, ownerT, otherT)),
|
||||
Alias#(ramDataT, RamData#(tagT, msiT, dirT, ownerT, otherT, lineT)),
|
||||
Alias#(respStateT, RespState#(msiT)),
|
||||
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(enq2MatchT, Enq2Match#(wayNum, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(match2OutT, Match2Out#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)),
|
||||
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT)),
|
||||
Alias#(pipeOutT, PipeOut#(wayT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT, 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, setAuxT, pipeCmdT)),
|
||||
Alias#(bypassInfoT, BypassInfo#(wayT, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, setAuxT)),
|
||||
Bits#(tagT, _tagSz),
|
||||
Bits#(msiT, _msiSz),
|
||||
Bits#(dirT, _dirSz),
|
||||
@@ -464,6 +488,7 @@ module mkCCPipeSingleCycle#(
|
||||
Bits#(repT, _repSz),
|
||||
Bits#(lineT, _lineSz),
|
||||
Bits#(pipeCmdT, _pipeCmdSz),
|
||||
Bits#(setAuxT, _setOtherSz),
|
||||
Alias#(dataIndexT, Bit#(_indexSz))
|
||||
);
|
||||
|
||||
@@ -494,6 +519,9 @@ module mkCCPipeSingleCycle#(
|
||||
end
|
||||
repRam.deqRdResp;
|
||||
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
|
||||
Vector#(wayNum, tagT) tagVec;
|
||||
Vector#(wayNum, msiT) csVec;
|
||||
@@ -513,7 +541,8 @@ module mkCCPipeSingleCycle#(
|
||||
pRqMiss: pRqMiss,
|
||||
info: infoVec[way],
|
||||
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
|
||||
UpdateByUpCs#(msiT) upd <- updateByUpCs(
|
||||
@@ -546,7 +575,8 @@ module mkCCPipeSingleCycle#(
|
||||
info: m2o.info,
|
||||
line: m2o.line.Valid
|
||||
},
|
||||
repInfo: m2o.repInfo
|
||||
repInfo: m2o.repInfo,
|
||||
setAuxData: m2o.setAuxData
|
||||
};
|
||||
endfunction
|
||||
|
||||
@@ -563,13 +593,16 @@ module mkCCPipeSingleCycle#(
|
||||
dataRam[i].rdReq(index);
|
||||
end
|
||||
repRam.rdReq(index);
|
||||
setAuxDataRam.rdReq(index);
|
||||
//$display("%t : enq repRam.rdReq ", $time);
|
||||
// write reg
|
||||
enq2MatchT e2m = Enq2Match {
|
||||
cmd: cmd,
|
||||
infoVec: replicate(Invalid),
|
||||
repInfo: Invalid,
|
||||
respLine: respLine,
|
||||
toState: toState
|
||||
toState: toState,
|
||||
setAuxData: Invalid
|
||||
};
|
||||
enq2Mat_enq <= Valid (e2m);
|
||||
endmethod
|
||||
@@ -586,7 +619,7 @@ module mkCCPipeSingleCycle#(
|
||||
|
||||
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);
|
||||
wayT way = m2o.way;
|
||||
indexT index = getIndex(m2o.cmd);
|
||||
@@ -599,6 +632,7 @@ module mkCCPipeSingleCycle#(
|
||||
infoRam[way].wrReq(index, wrRam.info);
|
||||
repRam.wrReq(index, repInfo);
|
||||
dataRam[way].wrReq(index, wrRam.line);
|
||||
setAuxDataRam.wrReq(index, setAuxData);
|
||||
// change pipeline reg
|
||||
if(newCmd matches tagged Valid .cmd) begin
|
||||
// update pipeline reg
|
||||
@@ -608,7 +642,8 @@ module mkCCPipeSingleCycle#(
|
||||
pRqMiss: False, // reset (not valid for swapped in pRq)
|
||||
info: wrRam.info,
|
||||
repInfo: repInfo,
|
||||
line: Valid(wrRam.line)
|
||||
line: Valid(wrRam.line),
|
||||
setAuxData: setAuxData
|
||||
});
|
||||
end
|
||||
else begin
|
||||
|
||||
@@ -124,8 +124,10 @@ module mkIBank#(
|
||||
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
|
||||
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
|
||||
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#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, void, Line)),
|
||||
Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, cacheOtherT, Line)),
|
||||
Alias#(procRqT, ProcRqToI),
|
||||
Alias#(cRqToPT, CRqMsg#(wayT, void)),
|
||||
Alias#(cRsToPT, CRsMsg#(void)),
|
||||
@@ -134,7 +136,7 @@ module mkIBank#(
|
||||
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
|
||||
Alias#(cRqSlotT, ICRqSlot#(wayT, tagT)), // cRq MSHR slot
|
||||
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),
|
||||
Alias#(resultT, Vector#(supSzX2, Maybe#(Instruction16))),
|
||||
// requirements
|
||||
@@ -531,7 +533,7 @@ module mkIBank#(
|
||||
other: ?
|
||||
},
|
||||
line: ram.line
|
||||
}, True); // hit, so update rep info
|
||||
}, Invalid, True); // hit, so update rep info
|
||||
if (!cRqIsPrefetch[n]) begin
|
||||
prefetcher.reportAccess(req.addr, HIT);
|
||||
llcPrefetcher.reportAccess(req.addr, HIT);
|
||||
@@ -594,7 +596,7 @@ module mkIBank#(
|
||||
other: ?
|
||||
},
|
||||
line: ram.line
|
||||
}, False);
|
||||
}, Invalid, False);
|
||||
if (!cRqIsPrefetch[n]) begin
|
||||
prefetcher.reportAccess(procRq.addr, MISS);
|
||||
llcPrefetcher.reportAccess(procRq.addr, MISS);
|
||||
@@ -616,7 +618,7 @@ module mkIBank#(
|
||||
other: ?
|
||||
},
|
||||
line: ? // data is no longer used
|
||||
}, False);
|
||||
}, Invalid, False);
|
||||
doAssert(ram.info.cs == S, "I$ replacement only replace S line");
|
||||
// update MSHR to save replaced tag
|
||||
// although we send req to parent later (when resp to parent is sent)
|
||||
@@ -639,7 +641,7 @@ module mkIBank#(
|
||||
function Action cRqSetDepNoCacheChange;
|
||||
action
|
||||
cRqMshr.pipelineResp.setStateSlot(n, Depend, defaultValue);
|
||||
pipeline.deqWrite(Invalid, pipeOut.ram, False);
|
||||
pipeline.deqWrite(Invalid, pipeOut.ram, Invalid, False);
|
||||
endaction
|
||||
endfunction
|
||||
|
||||
@@ -740,7 +742,7 @@ module mkIBank#(
|
||||
$display("%t I %m pipelineResp: pRq: drop", $time);
|
||||
// pRq can be directly dropped, no successor (since just go through pipeline)
|
||||
pRqMshr.pipelineResp.releaseEntry(n);
|
||||
pipeline.deqWrite(Invalid, pipeOut.ram, False);
|
||||
pipeline.deqWrite(Invalid, pipeOut.ram, Invalid, False);
|
||||
end
|
||||
else begin
|
||||
if (verbose)
|
||||
@@ -763,7 +765,7 @@ module mkIBank#(
|
||||
other: ?
|
||||
},
|
||||
line: ? // line is not useful
|
||||
}, False);
|
||||
}, Invalid, False);
|
||||
// pRq is done
|
||||
pRqMshr.pipelineResp.setDone(n);
|
||||
// send resp to parent
|
||||
@@ -824,7 +826,7 @@ module mkIBank#(
|
||||
other: ?
|
||||
},
|
||||
line: ?
|
||||
}, False);
|
||||
}, Invalid, False);
|
||||
|
||||
// check if we have finished all flush
|
||||
if (flush.index == maxBound &&
|
||||
|
||||
@@ -120,11 +120,12 @@ typedef struct {
|
||||
cRqIdxT n; // AMO req MSHR idx
|
||||
cRqT req; // AMO req
|
||||
Maybe#(cRqIdxT) succ; // same-addr-successor of AMO req
|
||||
Maybe#(cRqIdxT) nextInQueue;
|
||||
} AmoHitInfo#(type cRqIdxT, type cRqT) deriving(Bits, Eq, FShow);
|
||||
|
||||
module mkL1Bank#(
|
||||
Bit#(lgBankNum) bankId,
|
||||
module#(L1CRqMshr#(cRqNum, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
|
||||
module#(L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
|
||||
module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal,
|
||||
module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline,
|
||||
L1ProcResp#(procRqIdT) procResp
|
||||
@@ -137,6 +138,7 @@ module mkL1Bank#(
|
||||
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
|
||||
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
|
||||
Alias#(cacheOwnerT, Maybe#(cRqIdxT)), // actually owner cannot be pRq
|
||||
Alias#(cacheSetAuxT, Maybe#(cRqIdxT)),
|
||||
Alias#(cacheInfoT, CacheInfo#(tagT, Msi, void, cacheOwnerT, void)),
|
||||
Alias#(ramDataT, RamData#(tagT, Msi, void, cacheOwnerT, void, Line)),
|
||||
Alias#(procRqT, ProcRq#(procRqIdT)),
|
||||
@@ -147,7 +149,7 @@ module mkL1Bank#(
|
||||
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
|
||||
Alias#(cRqSlotT, L1CRqSlot#(wayT, tagT)), // cRq MSHR slot
|
||||
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
|
||||
Bits#(procRqIdT, _procRqIdT),
|
||||
FShow#(procRqIdT),
|
||||
@@ -160,7 +162,7 @@ module mkL1Bank#(
|
||||
|
||||
Bool verbose = False;
|
||||
|
||||
L1CRqMshr#(cRqNum, wayT, tagT, procRqT) cRqMshr <- mkL1CRqMshrLocal;
|
||||
L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT) cRqMshr <- mkL1CRqMshrLocal;
|
||||
|
||||
L1PRqMshr#(pRqNum) pRqMshr <- mkL1PRqMshrLocal;
|
||||
|
||||
@@ -559,6 +561,8 @@ endfunction
|
||||
L1CRqState pipeOutCState = cRqMshr.pipelineResp.getState(pipeOutCRqIdx);
|
||||
cRqSlotT pipeOutCSlot = cRqMshr.pipelineResp.getSlot(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 Action cRqHit(cRqIdxT n, procRqT req);
|
||||
@@ -639,7 +643,16 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
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
|
||||
prefetcher.reportAccess(req.addr, req.pcHash, HIT);
|
||||
llcPrefetcher.reportAccess(req.addr, req.pcHash, HIT);
|
||||
@@ -656,7 +669,8 @@ endfunction
|
||||
processAmo <= Valid (AmoHitInfo {
|
||||
n: n,
|
||||
req: req,
|
||||
succ: succ
|
||||
succ: succ,
|
||||
nextInQueue: pipeOutNextInQueue
|
||||
});
|
||||
if (verbose)
|
||||
$display("%t L1 %m pipelineResp: Hit func: AMO process in next cycle", $time);
|
||||
@@ -676,7 +690,7 @@ endfunction
|
||||
MemTaggedData current = getTaggedDataAt(curLine, dataSel);
|
||||
Vector#(2, Bit#(64)) dwordData = 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];
|
||||
// resp processor
|
||||
MemTaggedData resp = case (req.amoInst.width)
|
||||
@@ -704,7 +718,7 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
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");
|
||||
if (verbose)
|
||||
$display("%t L1 %m processAmo: update ram: ", $time,
|
||||
@@ -726,7 +740,8 @@ endfunction
|
||||
$display("%t L1 %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
|
||||
|
||||
// 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);
|
||||
action
|
||||
@@ -746,7 +761,7 @@ endfunction
|
||||
other: ram.info.other
|
||||
},
|
||||
line: ram.line
|
||||
}, False);
|
||||
}, pipeOutNextInQueue, False);
|
||||
// retry successor
|
||||
Maybe#(cRqIdxT) succ = pipeOutSucc;
|
||||
if(succ matches tagged Valid .s) begin
|
||||
@@ -793,7 +808,7 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
line: ram.line
|
||||
}, False);
|
||||
}, pipeOutNextInQueue, False);
|
||||
if (!cRqIsPrefetch[n]) begin
|
||||
prefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS);
|
||||
llcPrefetcher.reportAccess(procRq.addr, procRq.pcHash, MISS);
|
||||
@@ -814,7 +829,7 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
line: ? // data is no longer used
|
||||
}, False);
|
||||
}, pipeOutNextInQueue, False);
|
||||
// update MSHR: may save replaced line data
|
||||
cRqMshr.pipelineResp.setStateSlot(n, WaitNewTag, L1CRqSlot {
|
||||
way: pipeOut.way, // use way from pipeline
|
||||
@@ -841,7 +856,22 @@ endfunction
|
||||
function Action cRqSetDepNoCacheChange;
|
||||
action
|
||||
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
|
||||
endfunction
|
||||
|
||||
@@ -857,18 +887,36 @@ endfunction
|
||||
Bool cs_valid = ram.info.cs > I;
|
||||
if(ram.info.owner matches tagged Valid .cOwner) 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(cs_valid && tag_match, "cRq should hit in tag match");
|
||||
// should be added to a cRq in dependency chain & deq from pipeline
|
||||
doAssert(isValid(cRqEOC), ("cRq hit on another cRq, cRqEOC must be true"));
|
||||
cRqMshr.pipelineResp.setSucc(fromMaybe(?, cRqEOC), Valid (n));
|
||||
cRqSetDepNoCacheChange;
|
||||
if (verbose)
|
||||
$display("%t L1 %m pipelineResp: cRq: own by other cRq ", $time,
|
||||
fshow(cOwner), ", depend on cRq ", fshow(cRqEOC)
|
||||
);
|
||||
// If the tags match then we want to add to a dependency chain
|
||||
if (tag_match) begin
|
||||
// should be added to a cRq in dependency chain & deq from pipeline
|
||||
doAssert(isValid(cRqDependEOC), ("cRq hit on another cRq, cRqDependEOC must be true"));
|
||||
// If this is a prefetch, we can drop the prefetch here (prefetch was probably late)
|
||||
if (cRqIsPrefetch[n]) begin
|
||||
cRqDrop;
|
||||
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
|
||||
else begin
|
||||
// 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
|
||||
L1CRqState cState = pipeOutCState;
|
||||
|
||||
// check for cRqEOC to append to dependency chain
|
||||
// Only append to dep-chain if is in Init state
|
||||
if(cRqEOC matches tagged Valid .k &&& cState == Init) begin
|
||||
if (verbose)
|
||||
$display("%t L1 %m pipelineResp: cRq: no owner, depend on cRq, ", $time,
|
||||
fshow(cState), " ; ", fshow(cRqEOC)
|
||||
// There should be no dependency
|
||||
doAssert(!isValid(cRqDependEOC), "end of chain is valid but the chosen way is not owned");
|
||||
|
||||
// Check hit or miss, replacment may be needed
|
||||
if(tag_match && enough_cs_to_hit) begin
|
||||
// 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));
|
||||
cRqSetDepNoCacheChange;
|
||||
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
|
||||
// Check hit or miss, replacment may be needed
|
||||
if(tag_match && enough_cs_to_hit) begin
|
||||
// Hit
|
||||
doAssert(cs_valid, "hit, so cs must > I");
|
||||
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
|
||||
if (verbose)
|
||||
$display("%t L1 %m pipelineResp: cRq: no owner, miss no replace", $time);
|
||||
// Req parent, no replacement needed
|
||||
cRqMissNoReplacement;
|
||||
end
|
||||
end
|
||||
endrule
|
||||
@@ -989,7 +1028,7 @@ endfunction
|
||||
// pRq can be directly dropped
|
||||
// must go through tag match, no successor
|
||||
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)
|
||||
if(!pipeOut.pRqMiss) begin
|
||||
doAssert(ram.info.cs == S && pRq.toState == S && ram.info.tag == getTag(pRq.addr),
|
||||
@@ -1023,7 +1062,7 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
line: ram.line
|
||||
}, False);
|
||||
}, pipeOutNextInQueue, False);
|
||||
rsToPIndexQ.enq(PRq (n));
|
||||
// update cRq bookkeeping
|
||||
cRqMshr.pipelineResp.setStateSlot(cOwner, WaitSt, L1CRqSlot {
|
||||
@@ -1054,7 +1093,16 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
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));
|
||||
end
|
||||
|
||||
@@ -1076,6 +1124,7 @@ endfunction
|
||||
|
||||
// During flush, cRq MSHR is empty, so cache 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
|
||||
// here: either dropped or Done
|
||||
@@ -1107,7 +1156,7 @@ endfunction
|
||||
other: ?
|
||||
},
|
||||
line: ?
|
||||
}, False);
|
||||
}, Invalid, False);
|
||||
|
||||
// always reset link addr
|
||||
linkAddr <= Invalid;
|
||||
@@ -1230,8 +1279,9 @@ endmodule
|
||||
// -- cRqMshr.releaseEntry
|
||||
// -- read cRq MSHR req/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)
|
||||
// -- 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 sendRsToP_cRq (state change is just WaitNewTag->WaitSt)
|
||||
|
||||
@@ -1260,13 +1310,16 @@ endmodule
|
||||
|
||||
// sendRqToP conflict free with pipelineResp_xxx
|
||||
|
||||
// pipelineResp_cRq conflicts with itself, potentially writing state/succ of multiple entries
|
||||
|
||||
// ---- conclusion ----
|
||||
|
||||
// we have 4 ports from cRq MSHR
|
||||
// we have 5 ports from cRq MSHR
|
||||
// 1. cRqTransfer
|
||||
// 2. sendRsToP_cRq
|
||||
// 3. sendRqToP
|
||||
// 4. pipelineResp
|
||||
// 5. manageQueue
|
||||
|
||||
// we have 3 ports from pRq MSHR
|
||||
// 1. pRqTransfer
|
||||
@@ -1280,7 +1333,8 @@ endmodule
|
||||
// safe version: use EHR ports
|
||||
// sendRsToP_cRq/sendRsToP_pRq: port 0
|
||||
// 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
|
||||
// LSQ outside cache, while pipelineResp and sendRsToP will call other methods
|
||||
@@ -1290,7 +1344,7 @@ endmodule
|
||||
|
||||
// group banks into cache
|
||||
module mkL1Cache#(
|
||||
module#(L1CRqMshr#(cRqNum, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
|
||||
module#(L1CRqMshr#(cRqNum, indexT, wayT, tagT, procRqT)) mkL1CRqMshrLocal,
|
||||
module#(L1PRqMshr#(pRqNum)) mkL1PRqMshrLocal,
|
||||
module#(L1Pipe#(lgBankNum, wayNum, indexT, tagT, cRqIdxT, pRqIdxT)) mkL1Pipeline,
|
||||
L1ProcResp#(procRqIdT) procResp
|
||||
@@ -1306,12 +1360,14 @@ module mkL1Cache#(
|
||||
Alias#(cRqIdxT, Bit#(TLog#(cRqNum))),
|
||||
Alias#(pRqIdxT, Bit#(TLog#(pRqNum))),
|
||||
Alias#(cacheOwnerT, Maybe#(cRqIdxT)),
|
||||
Alias#(cacheOtherT, void),
|
||||
Alias#(cacheSetAuxT, Maybe#(cRqIdxT)),
|
||||
Alias#(procRqT, ProcRq#(procRqIdT)),
|
||||
Alias#(cRqToPT, CRqMsg#(wayT, void)),
|
||||
Alias#(cRsToPT, CRsMsg#(void)),
|
||||
Alias#(pRqRsFromPT, PRqRsMsg#(wayT, void)),
|
||||
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
|
||||
Bits#(procRqIdT, _procRqIdT),
|
||||
FShow#(procRqIdT),
|
||||
|
||||
@@ -57,7 +57,8 @@ typedef enum {
|
||||
WaitNewTag, // waiting replacement resp to send (but tag in RAM is already updated)
|
||||
WaitSt, // wait pRs/cRs to come
|
||||
Done, // resp is in index FIFO
|
||||
Depend
|
||||
Depend,
|
||||
Queued // wait for a way to be free
|
||||
} L1CRqState deriving(Bits, Eq, FShow);
|
||||
|
||||
// CRq info returned to outside
|
||||
@@ -129,6 +130,7 @@ endinterface
|
||||
// port for pipelineResp
|
||||
interface L1CRqMshr_pipelineResp#(
|
||||
numeric type cRqNum,
|
||||
type indexT,
|
||||
type wayT,
|
||||
type tagT,
|
||||
type reqT
|
||||
@@ -149,16 +151,26 @@ interface L1CRqMshr_pipelineResp#(
|
||||
// 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))) getSucc2(Bit#(TLog#(cRqNum)) n);
|
||||
method Action setSucc(Bit#(TLog#(cRqNum)) n, Maybe#(Bit#(TLog#(cRqNum))) succ);
|
||||
// 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
|
||||
// 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
|
||||
|
||||
interface L1CRqMshr#(
|
||||
numeric type cRqNum,
|
||||
type indexT,
|
||||
type wayT,
|
||||
type tagT,
|
||||
type reqT // child req type
|
||||
@@ -173,7 +185,10 @@ interface L1CRqMshr#(
|
||||
interface L1CRqMshr_sendRqToP#(cRqNum, wayT, tagT, reqT) sendRqToP;
|
||||
|
||||
// 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
|
||||
method Bool emptyForFlush;
|
||||
@@ -187,12 +202,14 @@ endinterface
|
||||
// safe version //
|
||||
//////////////////
|
||||
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 (
|
||||
Alias#(cRqIndexT, Bit#(TLog#(cRqNum))),
|
||||
Alias#(slotT, L1CRqSlot#(wayT, tagT)),
|
||||
Alias#(indexT, Bit#(_indexSz)),
|
||||
Alias#(wayT, Bit#(_waySz)),
|
||||
Alias#(tagT, Bit#(_tagSz)),
|
||||
Bits#(reqT, _reqSz)
|
||||
@@ -205,20 +222,21 @@ module mkL1CRqMshrSafe#(
|
||||
Integer sendRqToP_port = 0; // sendRqToP is read only
|
||||
Integer sendRsToP_cRq_port = 0;
|
||||
Integer pipelineResp_port = 1;
|
||||
Integer cRqTransfer_port = 2;
|
||||
Integer manageQueue_port = 2;
|
||||
Integer cRqTransfer_port = 3;
|
||||
|
||||
// MSHR entry state
|
||||
Vector#(cRqNum, Ehr#(3, L1CRqState)) stateVec <- replicateM(mkEhr(Empty));
|
||||
Vector#(cRqNum, Ehr#(4, L1CRqState)) stateVec <- replicateM(mkEhr(Empty));
|
||||
// cRq req contents
|
||||
Vector#(cRqNum, Ehr#(3, reqT)) reqVec <- replicateM(mkEhr(?));
|
||||
Vector#(cRqNum, Ehr#(4, reqT)) reqVec <- replicateM(mkEhr(?));
|
||||
// cRq mshr slots
|
||||
Vector#(cRqNum, Ehr#(3, slotT)) slotVec <- replicateM(mkEhr(defaultValue));
|
||||
Vector#(cRqNum, Ehr#(4, slotT)) slotVec <- replicateM(mkEhr(defaultValue));
|
||||
// data valid bit
|
||||
Vector#(cRqNum, Ehr#(3, Bool)) dataValidVec <- replicateM(mkEhr(False));
|
||||
Vector#(cRqNum, Ehr#(4, Bool)) dataValidVec <- replicateM(mkEhr(False));
|
||||
// data values
|
||||
RegFile#(cRqIndexT, Line) dataFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1));
|
||||
// successor valid bit
|
||||
Vector#(cRqNum, Ehr#(3, Bool)) succValidVec <- replicateM(mkEhr(False));
|
||||
Vector#(cRqNum, Ehr#(4, Bool)) succValidVec <- replicateM(mkEhr(False));
|
||||
// successor MSHR index
|
||||
RegFile#(cRqIndexT, cRqIndexT) succFile <- mkRegFile(0, fromInteger(valueOf(cRqNum) - 1));
|
||||
// empty entry FIFO
|
||||
@@ -346,24 +364,47 @@ module mkL1CRqMshrSafe#(
|
||||
return succValidVec[n][pipelineResp_port] ? (Valid (succFile.sub(n))) : Invalid;
|
||||
endmethod
|
||||
|
||||
method Action setSucc(cRqIndexT n, Maybe#(cRqIndexT) succ);
|
||||
succValidVec[n][pipelineResp_port] <= isValid(succ);
|
||||
succFile.upd(n, fromMaybe(?, succ));
|
||||
method Maybe#(cRqIndexT) getSucc2(cRqIndexT n);
|
||||
return succValidVec[n][pipelineResp_port] ? (Valid (succFile.sub(n))) : Invalid;
|
||||
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);
|
||||
// check entry i is end of chain or not
|
||||
L1CRqState state = stateVec[i][pipelineResp_port];
|
||||
Bool notDone = state != Done;
|
||||
Bool processedOnce = state != Empty && state != Init;
|
||||
Bool isDepend = state == WaitSt || state == WaitNewTag || state == Depend;
|
||||
Bool addrMatch = getLineAddr(getAddrFromReq(reqVec[i][pipelineResp_port])) == getLineAddr(addr);
|
||||
Bool noSucc = !succValidVec[i][pipelineResp_port];
|
||||
return notDone && processedOnce && addrMatch && noSucc;
|
||||
return isDepend && addrMatch && noSucc;
|
||||
endfunction
|
||||
Vector#(cRqNum, Integer) idxVec = genVector;
|
||||
return searchIndex(isEndOfChain, idxVec);
|
||||
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
|
||||
|
||||
method Bool emptyForFlush;
|
||||
@@ -381,14 +422,16 @@ endmodule
|
||||
|
||||
// exported version
|
||||
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 (
|
||||
Alias#(indexT, Bit#(_indexSz)),
|
||||
Alias#(wayT, Bit#(_waySz)),
|
||||
Alias#(tagT, Bit#(_tagSz)),
|
||||
Bits#(reqT, _reqSz)
|
||||
);
|
||||
let m <- mkL1CRqMshrSafe(getAddrFromReq);
|
||||
let m <- mkL1CRqMshrSafe(getAddrFromReq, getIndexFromAddr);
|
||||
return m;
|
||||
endmodule
|
||||
|
||||
@@ -126,11 +126,12 @@ interface L1Pipe#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, void, // no dir
|
||||
Maybe#(cRqIdxT), void, RandRepInfo, // no other
|
||||
Line, L1Cmd#(indexT, cRqIdxT, pRqIdxT)
|
||||
Line, Maybe#(cRqIdxT), L1Cmd#(indexT, cRqIdxT, pRqIdxT)
|
||||
) first;
|
||||
method Action deqWrite(
|
||||
Maybe#(cRqIdxT) swapRq,
|
||||
RamData#(tagT, Msi, void, Maybe#(cRqIdxT), void, Line) wrRam, // always write BRAM
|
||||
Maybe#(cRqIdxT) nextInQueue,
|
||||
Bool updateRep
|
||||
);
|
||||
endinterface
|
||||
@@ -162,11 +163,12 @@ module mkL1Pipe(
|
||||
Alias#(dirT, void), // no directory
|
||||
Alias#(ownerT, Maybe#(cRqIdxT)),
|
||||
Alias#(otherT, void), // no other cache info
|
||||
Alias#(setAuxT, Maybe#(cRqIdxT)),
|
||||
Alias#(repT, RandRepInfo), // use random replace
|
||||
Alias#(pipeInT, L1PipeIn#(wayT, indexT, cRqIdxT, pRqIdxT)),
|
||||
Alias#(pipeCmdT, L1PipeCmd#(wayT, 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#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
|
||||
Alias#(respStateT, RespState#(Msi)),
|
||||
@@ -189,6 +191,7 @@ module mkL1Pipe(
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCoreForwarded);
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
Vector#(wayNum, RWBramCore#(indexT, Line)) dataRam <- replicateM(mkRWBramCoreForwarded);
|
||||
RWBramCore#(indexT, setAuxT) queueRam <- mkRWBramCoreForwarded;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
@@ -205,6 +208,7 @@ module mkL1Pipe(
|
||||
});
|
||||
end
|
||||
repRam.wrReq(initIndex, randRepInitInfo); // useless for random replace
|
||||
queueRam.wrReq(initIndex, Invalid);
|
||||
initIndex <= initIndex + 1;
|
||||
if(initIndex == maxBound) begin
|
||||
initDone <= True;
|
||||
@@ -272,11 +276,11 @@ module mkL1Pipe(
|
||||
Addr addr = getAddrFromCmd(cmd);
|
||||
tagT tag = getTag(addr);
|
||||
// find hit way (nothing is being replaced)
|
||||
function Bool isMatch(Tuple2#(Msi, tagT) csTag);
|
||||
match {.cs, .t} = csTag;
|
||||
return cs > I && t == tag;
|
||||
function Bool isMatch(Tuple3#(Msi, tagT, ownerT) csTagOwner);
|
||||
match {.cs, .t, .o} = csTagOwner;
|
||||
return (cs > I || isValid(o)) && t == tag;
|
||||
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
|
||||
return TagMatchResult {
|
||||
way: w,
|
||||
@@ -300,9 +304,14 @@ module mkL1Pipe(
|
||||
end
|
||||
Maybe#(wayT) repWay = randRep.getReplaceWay(unlocked, invalid);
|
||||
// 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
|
||||
$fwrite(stderr, "[L1Pipe] ERROR: ", fshow(cmd), " cannot find way to replace\n");
|
||||
$finish;
|
||||
if(verbose)
|
||||
$display("%t L1 %m tagMatch: set oversubscription", $time);
|
||||
//$fwrite(stderr, "[L1Pipe] ERROR: ", fshow(cmd), " cannot find way to replace\n");
|
||||
//$finish;
|
||||
end
|
||||
return TagMatchResult {
|
||||
way: fromMaybe(?, repWay),
|
||||
@@ -339,11 +348,11 @@ module mkL1Pipe(
|
||||
endfunction
|
||||
|
||||
CCPipe#(
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, setAuxT, pipeCmdT
|
||||
) pipe <- mkCCPipeSingleCycle(
|
||||
regToReadOnly(initDone), getIndex, tagMatch,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
infoRam, repRam, dataRam, queueRam
|
||||
);
|
||||
|
||||
method Action send(pipeInT req);
|
||||
@@ -387,11 +396,12 @@ module mkL1Pipe(
|
||||
way: pout.way,
|
||||
pRqMiss: pout.pRqMiss,
|
||||
ram: pout.ram,
|
||||
repInfo: pout.repInfo
|
||||
repInfo: pout.repInfo,
|
||||
setAuxData: pout.setAuxData
|
||||
};
|
||||
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
|
||||
Maybe#(pipeCmdT) newCmd = Invalid;
|
||||
if(swapRq matches tagged Valid .idx) begin // swap in cRq
|
||||
@@ -403,6 +413,6 @@ module mkL1Pipe(
|
||||
`endif
|
||||
end
|
||||
// call pipe
|
||||
pipe.deqWrite(newCmd, wrRam, updateRep);
|
||||
pipe.deqWrite(newCmd, wrRam, nextInQueue, updateRep);
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
@@ -179,7 +179,7 @@ module mkLLBank#(
|
||||
Alias#(cRqT, LLRq#(cRqIdT, dmaRqIdT, childT)),
|
||||
Alias#(cRqSlotT, LLCRqSlot#(wayT, tagT, Vector#(childNum, DirPend))), // cRq MSHR slot
|
||||
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
|
||||
Bits#(cRqIdT, _cRqIdSz),
|
||||
Bits#(dmaRqIdT, _dmaRqIdSz),
|
||||
|
||||
@@ -95,13 +95,13 @@ interface LLPipe#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, Vector#(childNum, Msi),
|
||||
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;
|
||||
method PipeOut#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, Vector#(childNum, Msi),
|
||||
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;
|
||||
method Action deqWrite(
|
||||
Maybe#(cRqIdxT) swapRq,
|
||||
@@ -143,7 +143,7 @@ module mkLLPipe(
|
||||
Alias#(pipeInT, LLPipeIn#(childT, wayT, cRqIdxT)),
|
||||
Alias#(pipeCmdT, LLPipeCmd#(childT, wayT, 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#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
|
||||
Alias#(respStateT, RespState#(Msi)),
|
||||
@@ -165,6 +165,7 @@ module mkLLPipe(
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore);
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
|
||||
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
@@ -322,14 +323,14 @@ module mkLLPipe(
|
||||
endactionvalue
|
||||
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,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
infoRam, repRam, dataRam, setAuxDataRam
|
||||
);
|
||||
|
||||
// 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 {
|
||||
cmd: (case(pout.cmd) matches
|
||||
tagged CRq .rq: LLCRq (rq.mshrIdx);
|
||||
@@ -340,7 +341,8 @@ module mkLLPipe(
|
||||
way: pout.way,
|
||||
pRqMiss: pout.pRqMiss,
|
||||
ram: pout.ram,
|
||||
repInfo: pout.repInfo
|
||||
repInfo: pout.repInfo,
|
||||
setAuxData: ?
|
||||
};
|
||||
endfunction
|
||||
|
||||
@@ -383,6 +385,6 @@ module mkLLPipe(
|
||||
newCmd = Valid (CRq (LLPipeCRqIn {addr: addr, mshrIdx: idx}));
|
||||
end
|
||||
// call pipe
|
||||
pipe.deqWrite(newCmd, wrRam, updateRep);
|
||||
pipe.deqWrite(newCmd, wrRam, ?, updateRep);
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
@@ -45,6 +45,34 @@ interface RWBramCore#(type addrT, type dataT);
|
||||
method Action deqRdResp;
|
||||
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(
|
||||
Bits#(addrT, addrSz), Bits#(dataT, dataSz)
|
||||
);
|
||||
|
||||
@@ -100,7 +100,7 @@ interface SelfInvIPipe#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, void, // no dir
|
||||
Maybe#(cRqIdxT), void, RandRepInfo, // no other
|
||||
Line, SelfInvICmd#(cRqIdxT)
|
||||
Line, void, SelfInvICmd#(cRqIdxT) // no aux set data
|
||||
) first;
|
||||
method Action deqWrite(
|
||||
Maybe#(cRqIdxT) swapRq,
|
||||
@@ -239,7 +239,7 @@ module mkSelfInvIPipe(
|
||||
Alias#(pipeInT, SelfInvIPipeIn#(wayT, cRqIdxT)),
|
||||
Alias#(pipeCmdT, SelfInvIPipeCmd#(wayT, 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#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
|
||||
Alias#(respStateT, RespState#(Msi)),
|
||||
@@ -262,6 +262,7 @@ module mkSelfInvIPipe(
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
// data RAM
|
||||
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
|
||||
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
@@ -392,11 +393,11 @@ module mkSelfInvIPipe(
|
||||
endfunction
|
||||
|
||||
CCPipe#(
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT
|
||||
) pipe <- mkCCPipe(
|
||||
regToReadOnly(initDone), getIndex, tagMatch,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
infoRam, repRam, dataRam, setAuxDataRam
|
||||
);
|
||||
|
||||
// reconcile: wait until pipeline empty and drop all S states. Stall
|
||||
@@ -458,7 +459,8 @@ module mkSelfInvIPipe(
|
||||
way: pout.way,
|
||||
pRqMiss: pout.pRqMiss,
|
||||
ram: pout.ram,
|
||||
repInfo: pout.repInfo
|
||||
repInfo: pout.repInfo,
|
||||
setAuxData: ?
|
||||
};
|
||||
endmethod
|
||||
|
||||
@@ -470,7 +472,7 @@ module mkSelfInvIPipe(
|
||||
newCmd = Valid (CRq (SelfInvIPipeRqIn {addr: addr, mshrIdx: idx}));
|
||||
end
|
||||
// call pipe
|
||||
pipe.deqWrite(newCmd, wrRam, updateRep);
|
||||
pipe.deqWrite(newCmd, wrRam, ?, updateRep);
|
||||
// conflict with reconcile
|
||||
conflict_reconcile_deq.wset(?);
|
||||
endmethod
|
||||
|
||||
@@ -113,7 +113,7 @@ interface SelfInvL1Pipe#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, void, // no dir
|
||||
Maybe#(cRqIdxT), SelfInvL1Hits#(maxHitNum), RandRepInfo,
|
||||
Line, SelfInvL1Cmd#(cRqIdxT, pRqIdxT)
|
||||
Line, void, SelfInvL1Cmd#(cRqIdxT, pRqIdxT) // no aux set data
|
||||
) first;
|
||||
method Action deqWrite(
|
||||
Maybe#(cRqIdxT) swapRq,
|
||||
@@ -252,7 +252,7 @@ module mkSelfInvL1Pipe(
|
||||
Alias#(pipeInT, SelfInvL1PipeIn#(wayT, cRqIdxT, pRqIdxT)),
|
||||
Alias#(pipeCmdT, SelfInvL1PipeCmd#(wayT, 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#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
|
||||
Alias#(respStateT, RespState#(Msi)),
|
||||
@@ -277,6 +277,7 @@ module mkSelfInvL1Pipe(
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
// data RAM
|
||||
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
|
||||
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
@@ -414,11 +415,11 @@ module mkSelfInvL1Pipe(
|
||||
endfunction
|
||||
|
||||
CCPipe#(
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, void, pipeCmdT
|
||||
) pipe <- mkCCPipe(
|
||||
regToReadOnly(initDone), getIndex, tagMatch,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
infoRam, repRam, dataRam, setAuxDataRam
|
||||
);
|
||||
|
||||
// reconcile: wait until pipeline empty and drop all S states. Stall
|
||||
@@ -484,7 +485,8 @@ module mkSelfInvL1Pipe(
|
||||
way: pout.way,
|
||||
pRqMiss: pout.pRqMiss,
|
||||
ram: pout.ram,
|
||||
repInfo: pout.repInfo
|
||||
repInfo: pout.repInfo,
|
||||
setAuxData: ?
|
||||
};
|
||||
endmethod
|
||||
|
||||
@@ -496,7 +498,7 @@ module mkSelfInvL1Pipe(
|
||||
newCmd = Valid (CRq (SelfInvL1PipeRqIn {addr: addr, mshrIdx: idx}));
|
||||
end
|
||||
// call pipe
|
||||
pipe.deqWrite(newCmd, wrRam, updateRep);
|
||||
pipe.deqWrite(newCmd, wrRam, ?, updateRep);
|
||||
// conflict with reconcile
|
||||
conflict_reconcile_deq.wset(?);
|
||||
endmethod
|
||||
|
||||
@@ -95,13 +95,13 @@ interface SelfInvLLPipe#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))),
|
||||
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;
|
||||
method PipeOut#(
|
||||
Bit#(TLog#(wayNum)),
|
||||
tagT, Msi, SelfInvDir#(Bit#(TLog#(childNum))),
|
||||
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;
|
||||
method Action deqWrite(
|
||||
Maybe#(cRqIdxT) swapRq,
|
||||
@@ -143,7 +143,7 @@ module mkSelfInvLLPipe(
|
||||
Alias#(pipeInT, SelfInvLLPipeIn#(childT, wayT, cRqIdxT)),
|
||||
Alias#(pipeCmdT, SelfInvLLPipeCmd#(childT, wayT, 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#(ramDataT, RamData#(tagT, Msi, dirT, ownerT, otherT, Line)),
|
||||
Alias#(respStateT, RespState#(Msi)),
|
||||
@@ -165,6 +165,7 @@ module mkSelfInvLLPipe(
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore);
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
|
||||
RWBramCore#(indexT, void) setAuxDataRam <- mkDummyBramCore;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
@@ -318,14 +319,14 @@ module mkSelfInvLLPipe(
|
||||
endactionvalue
|
||||
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,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
infoRam, repRam, dataRam, setAuxDataRam
|
||||
);
|
||||
|
||||
// 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 {
|
||||
cmd: (case(pout.cmd) matches
|
||||
tagged CRq .rq: LLCRq (rq.mshrIdx);
|
||||
@@ -336,7 +337,8 @@ module mkSelfInvLLPipe(
|
||||
way: pout.way,
|
||||
pRqMiss: pout.pRqMiss,
|
||||
ram: pout.ram,
|
||||
repInfo: pout.repInfo
|
||||
repInfo: pout.repInfo,
|
||||
setAuxData: ?
|
||||
};
|
||||
endfunction
|
||||
|
||||
@@ -379,7 +381,7 @@ module mkSelfInvLLPipe(
|
||||
newCmd = Valid (CRq (SelfInvLLPipeCRqIn {addr: addr, mshrIdx: idx}));
|
||||
end
|
||||
// call pipe
|
||||
pipe.deqWrite(newCmd, wrRam, updateRep);
|
||||
pipe.deqWrite(newCmd, wrRam, ?, updateRep);
|
||||
endmethod
|
||||
endmodule
|
||||
`endif // SELF_INV_CACHE
|
||||
|
||||
@@ -112,12 +112,15 @@ typedef Bit#(TMax#(SizeOf#(LdQTag), SizeOf#(SBIndex))) DProcReqId;
|
||||
|
||||
(* synthesize *)
|
||||
module mkDCRqMshrWrapper(
|
||||
L1CRqMshr#(DCRqNum, L1Way, DTag, ProcRq#(DProcReqId))
|
||||
L1CRqMshr#(DCRqNum, DIndex, L1Way, DTag, ProcRq#(DProcReqId))
|
||||
);
|
||||
function Addr getAddrFromReq(ProcRq#(DProcReqId) r);
|
||||
return r.addr;
|
||||
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;
|
||||
endmodule
|
||||
|
||||
|
||||
Reference in New Issue
Block a user