Include the new single-cycle CCPipe as a seperate implementation, and
use it only in the L1 caches so that the L2 cache can have lower resource utilisation and better timing. (Resource utilisation is up about 5% with the new design, and it's not necessary for the L2 cache.)
This commit is contained in:
@@ -133,7 +133,7 @@ typedef struct {
|
||||
CacheInfo#(tagT, msiT, dirT, ownerT, otherT) info;
|
||||
repT repInfo;
|
||||
// bypassed or resp line
|
||||
lineT line;
|
||||
Maybe#(lineT) line;
|
||||
} Match2Out#(
|
||||
type wayT,
|
||||
type tagT,
|
||||
@@ -176,7 +176,7 @@ typedef struct {
|
||||
msiT cs;
|
||||
dirT dir;
|
||||
} UpdateByDownDir#(type msiT, type dirT) deriving(Bits, Eq, FShow);
|
||||
/*
|
||||
|
||||
// index to data ram: {way, normal index}
|
||||
function dataIndexT getDataRamIndex(wayT w, indexT i) provisos(
|
||||
Alias#(wayT, Bit#(_waySz)),
|
||||
@@ -185,7 +185,7 @@ function dataIndexT getDataRamIndex(wayT w, indexT i) provisos(
|
||||
);
|
||||
return {w, i};
|
||||
endfunction
|
||||
*/
|
||||
|
||||
module mkCCPipe#(
|
||||
ReadOnly#(Bool) initDone,
|
||||
function indexT getIndex(pipeCmdT cmd),
|
||||
@@ -208,7 +208,7 @@ module mkCCPipe#(
|
||||
function ActionValue#(repT) updateRepInfo(repT oldRep, wayT hitWay),
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam,
|
||||
RWBramCore#(indexT, repT) repRam,
|
||||
Vector#(wayNum, RWBramCore#(dataIndexT, lineT)) dataRam
|
||||
RWBramCore#(dataIndexT, lineT) dataRam
|
||||
)(
|
||||
CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, pipeCmdT)
|
||||
) provisos (
|
||||
@@ -230,6 +230,240 @@ module mkCCPipe#(
|
||||
Bits#(lineT, _lineSz),
|
||||
Bits#(pipeCmdT, _pipeCmdSz),
|
||||
// index to data ram: {way, normal index}
|
||||
Alias#(dataIndexT, Bit#(TAdd#(TLog#(wayNum), _indexSz)))
|
||||
);
|
||||
|
||||
// pipeline regs
|
||||
|
||||
Ehr#(3, Maybe#(enq2MatchT)) enq2Mat <- mkEhr(Invalid);
|
||||
// port 0: bypass
|
||||
Reg#(Maybe#(enq2MatchT)) enq2Mat_bypass = enq2Mat[0];
|
||||
// port 1: tag match
|
||||
Reg#(Maybe#(enq2MatchT)) enq2Mat_match = enq2Mat[1];
|
||||
// port 2: enq
|
||||
Reg#(Maybe#(enq2MatchT)) enq2Mat_enq = enq2Mat[2];
|
||||
|
||||
Ehr#(2, Maybe#(match2OutT)) mat2Out <- mkEhr(Invalid);
|
||||
// port 0: out
|
||||
Reg#(Maybe#(match2OutT)) mat2Out_out = mat2Out[0];
|
||||
// port 1: tag match
|
||||
Reg#(Maybe#(match2OutT)) mat2Out_match = mat2Out[1];
|
||||
|
||||
// bypass write to ram
|
||||
RWire#(bypassInfoT) bypass <- mkRWire;
|
||||
|
||||
// stage 2: first get bypass
|
||||
(* fire_when_enabled, no_implicit_conditions *)
|
||||
rule doMatch_bypass(isValid(bypass.wget) && isValid(enq2Mat_bypass) && initDone);
|
||||
bypassInfoT b = fromMaybe(?, bypass.wget);
|
||||
enq2MatchT e2m = fromMaybe(?, enq2Mat_bypass);
|
||||
if(b.index == getIndex(e2m.cmd)) begin
|
||||
e2m.infoVec[b.way] = Valid (b.ram.info);
|
||||
e2m.repInfo = Valid (b.repInfo);
|
||||
end
|
||||
enq2Mat_bypass <= Valid (e2m);
|
||||
endrule
|
||||
|
||||
rule doTagMatch(isValid(enq2Mat_match) && !isValid(mat2Out_match) && initDone);
|
||||
enq2MatchT e2m = fromMaybe(?, enq2Mat_match);
|
||||
// get cache output & merge with bypass
|
||||
Vector#(wayNum, infoT) infoVec;
|
||||
for(Integer i = 0; i < valueOf(wayNum); i = i+1) begin
|
||||
infoRam[i].deqRdResp;
|
||||
infoVec[i] = fromMaybe(infoRam[i].rdResp, e2m.infoVec[i]);
|
||||
end
|
||||
repRam.deqRdResp;
|
||||
repT repInfo = fromMaybe(repRam.rdResp, e2m.repInfo);
|
||||
// do tag match to get way to occupy
|
||||
Vector#(wayNum, tagT) tagVec;
|
||||
Vector#(wayNum, msiT) csVec;
|
||||
Vector#(wayNum, ownerT) ownerVec;
|
||||
for(Integer i = 0; i < valueOf(wayNum); i = i+1) begin
|
||||
tagVec[i] = infoVec[i].tag;
|
||||
csVec[i] = infoVec[i].cs;
|
||||
ownerVec[i] = infoVec[i].owner;
|
||||
end
|
||||
let tmRes <- tagMatch(e2m.cmd, tagVec, csVec, ownerVec, repInfo);
|
||||
wayT way = tmRes.way;
|
||||
Bool pRqMiss = tmRes.pRqMiss;
|
||||
// read data
|
||||
indexT index = getIndex(e2m.cmd);
|
||||
dataRam.rdReq(getDataRamIndex(way, index));
|
||||
// set mat2out & merge with CRs/PRs & merge with data bypass
|
||||
// resp data has higher priority than data bypass
|
||||
match2OutT m2o = Match2Out {
|
||||
cmd: e2m.cmd,
|
||||
way: way,
|
||||
pRqMiss: pRqMiss,
|
||||
info: infoVec[way],
|
||||
repInfo: repInfo,
|
||||
line: e2m.respLine
|
||||
};
|
||||
if(e2m.toState matches tagged UpCs .s) begin
|
||||
UpdateByUpCs#(msiT) upd <- updateByUpCs(
|
||||
e2m.cmd, s, isValid(e2m.respLine), m2o.info.cs
|
||||
);
|
||||
m2o.info.cs = upd.cs;
|
||||
end
|
||||
else if(e2m.toState matches tagged DownDir .s) begin
|
||||
UpdateByDownDir#(msiT, dirT) upd <- updateByDownDir(
|
||||
e2m.cmd, s, isValid(e2m.respLine), m2o.info.cs, m2o.info.dir
|
||||
);
|
||||
m2o.info.cs = upd.cs;
|
||||
m2o.info.dir = upd.dir;
|
||||
end
|
||||
if(bypass.wget matches tagged Valid .b &&& b.index == index &&& b.way == way &&& !isValid(m2o.line)) begin
|
||||
// bypass has lower priority than resp data
|
||||
m2o.line = Valid (b.ram.line);
|
||||
end
|
||||
mat2Out_match <= Valid (m2o);
|
||||
// reset enq2mat
|
||||
enq2Mat_match <= Invalid;
|
||||
endrule
|
||||
|
||||
// construct output with bypass/resp data
|
||||
function pipeOutT firstOut;
|
||||
match2OutT m2o = fromMaybe(?, mat2Out_out);
|
||||
return PipeOut {
|
||||
cmd: m2o.cmd,
|
||||
way: m2o.way,
|
||||
pRqMiss: m2o.pRqMiss,
|
||||
ram: RamData {
|
||||
info: m2o.info,
|
||||
line: fromMaybe(dataRam.rdResp, m2o.line)
|
||||
},
|
||||
repInfo: m2o.repInfo
|
||||
};
|
||||
endfunction
|
||||
|
||||
Bool enq_guard = !isValid(enq2Mat_enq) && initDone;
|
||||
|
||||
Bool deq_guard = isValid(mat2Out_out) && initDone;
|
||||
|
||||
// stage 1: enq req to pipeline: access info+rep RAM & bypass
|
||||
method Action enq(pipeCmdT cmd, Maybe#(lineT) respLine, respStateT toState) if(enq_guard);
|
||||
// read ram
|
||||
indexT index = getIndex(cmd);
|
||||
for(Integer i = 0; i < valueOf(wayNum); i = i+1) begin
|
||||
infoRam[i].rdReq(index);
|
||||
end
|
||||
repRam.rdReq(index);
|
||||
// write reg & get bypass
|
||||
enq2MatchT e2m = Enq2Match {
|
||||
cmd: cmd,
|
||||
infoVec: replicate(Invalid),
|
||||
repInfo: Invalid,
|
||||
respLine: respLine,
|
||||
toState: toState
|
||||
};
|
||||
if(bypass.wget matches tagged Valid .b &&& b.index == index) begin
|
||||
e2m.infoVec[b.way] = Valid (b.ram.info);
|
||||
e2m.repInfo = Valid (b.repInfo);
|
||||
end
|
||||
enq2Mat_enq <= Valid (e2m);
|
||||
endmethod
|
||||
|
||||
method Bool notFull = enq_guard;
|
||||
|
||||
method pipeOutT first if(deq_guard);
|
||||
return firstOut;
|
||||
endmethod
|
||||
|
||||
method pipeOutT unguard_first;
|
||||
return firstOut;
|
||||
endmethod
|
||||
|
||||
method Bool notEmpty = deq_guard;
|
||||
|
||||
method Action deqWrite(Maybe#(pipeCmdT) newCmd, ramDataT wrRam, Bool updateRep) if(deq_guard);
|
||||
match2OutT m2o = fromMaybe(?, mat2Out_out);
|
||||
wayT way = m2o.way;
|
||||
indexT index = getIndex(m2o.cmd);
|
||||
// update replacement info
|
||||
repT repInfo = m2o.repInfo;
|
||||
if(updateRep) begin
|
||||
repInfo <- updateRepInfo(m2o.repInfo, way);
|
||||
end
|
||||
// write ram
|
||||
infoRam[way].wrReq(index, wrRam.info);
|
||||
repRam.wrReq(index, repInfo);
|
||||
dataRam.wrReq(getDataRamIndex(way, index), wrRam.line);
|
||||
// set bypass to Enq and Match stages
|
||||
bypass.wset(BypassInfo {
|
||||
index: index,
|
||||
way: way,
|
||||
ram: wrRam,
|
||||
repInfo: repInfo
|
||||
});
|
||||
// change pipeline reg
|
||||
if(newCmd matches tagged Valid .cmd) begin
|
||||
// update pipeline reg
|
||||
mat2Out_out <= Valid (Match2Out {
|
||||
cmd: cmd, // swapped in new cmd
|
||||
way: way, // keep way same
|
||||
pRqMiss: False, // reset (not valid for swapped in pRq)
|
||||
info: wrRam.info, // get bypass
|
||||
repInfo: repInfo, // get bypass
|
||||
line: Valid (wrRam.line) // get bypass
|
||||
});
|
||||
end
|
||||
else begin
|
||||
// XXX deq ram resp, I think this should not block
|
||||
dataRam.deqRdResp;
|
||||
// reset pipeline reg
|
||||
mat2Out_out <= Invalid;
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Bool emptyForFlush;
|
||||
return !isValid(mat2Out[0]) && !isValid(enq2Mat[0]);
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkCCPipeSingleCycle#(
|
||||
ReadOnly#(Bool) initDone,
|
||||
function indexT getIndex(pipeCmdT cmd),
|
||||
function ActionValue#(TagMatchResult#(wayT)) tagMatch(
|
||||
// actionvalue enable us to do checking inside the function
|
||||
pipeCmdT cmd,
|
||||
// below are current RAM outputs, is merged with ram write from final stage
|
||||
// but is NOT merged with state changes carried in PRs/CRs
|
||||
Vector#(wayNum, tagT) tagVec,
|
||||
Vector#(wayNum, msiT) csVec,
|
||||
Vector#(wayNum, ownerT) ownerVec,
|
||||
repT repInfo
|
||||
),
|
||||
function ActionValue#(UpdateByUpCs#(msiT)) updateByUpCs(
|
||||
pipeCmdT cmd, msiT toState, Bool dataValid, msiT oldCs
|
||||
),
|
||||
function ActionValue#(UpdateByDownDir#(msiT, dirT)) updateByDownDir(
|
||||
pipeCmdT cmd, msiT toState, Bool dataValid, msiT oldCs, dirT oldDir
|
||||
),
|
||||
function ActionValue#(repT) updateRepInfo(repT oldRep, wayT hitWay),
|
||||
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
|
||||
)(
|
||||
CCPipe#(wayNum, indexT, tagT, msiT, dirT, ownerT, otherT, repT, lineT, 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)),
|
||||
Bits#(tagT, _tagSz),
|
||||
Bits#(msiT, _msiSz),
|
||||
Bits#(dirT, _dirSz),
|
||||
Bits#(ownerT, _ownerSz),
|
||||
Bits#(otherT, _otherSz),
|
||||
Bits#(repT, _repSz),
|
||||
Bits#(lineT, _lineSz),
|
||||
Bits#(pipeCmdT, _pipeCmdSz),
|
||||
Alias#(dataIndexT, Bit#(_indexSz))
|
||||
);
|
||||
|
||||
@@ -280,7 +514,7 @@ module mkCCPipe#(
|
||||
pRqMiss: pRqMiss,
|
||||
info: infoVec[way],
|
||||
repInfo: repInfo,
|
||||
line: fromMaybe(dataVec[way],e2m.respLine)
|
||||
line: isValid(e2m.respLine) ? e2m.respLine:Valid(dataVec[way])
|
||||
};
|
||||
if(e2m.toState matches tagged UpCs .s) begin
|
||||
UpdateByUpCs#(msiT) upd <- updateByUpCs(
|
||||
@@ -295,12 +529,9 @@ module mkCCPipe#(
|
||||
m2o.info.cs = upd.cs;
|
||||
m2o.info.dir = upd.dir;
|
||||
end
|
||||
indexT index = getIndex(e2m.cmd);
|
||||
if (e2m.respLine matches tagged Valid .rl) begin
|
||||
m2o.line = rl;
|
||||
end else begin
|
||||
m2o.line = dataVec[way];
|
||||
end mat2Out_match <= Valid (m2o);
|
||||
//indexT index = getIndex(e2m.cmd);
|
||||
//m2o.line = isValid(e2m.respLine) ? e2m.respLine:Valid(dataVec[way]);
|
||||
mat2Out_match <= Valid (m2o);
|
||||
// reset enq2mat
|
||||
enq2Mat_match <= Invalid;
|
||||
endrule
|
||||
@@ -314,7 +545,7 @@ module mkCCPipe#(
|
||||
pRqMiss: m2o.pRqMiss,
|
||||
ram: RamData {
|
||||
info: m2o.info,
|
||||
line: m2o.line
|
||||
line: m2o.line.Valid
|
||||
},
|
||||
repInfo: m2o.repInfo
|
||||
};
|
||||
@@ -379,7 +610,7 @@ module mkCCPipe#(
|
||||
pRqMiss: False, // reset (not valid for swapped in pRq)
|
||||
info: wrRam.info,
|
||||
repInfo: repInfo,
|
||||
line: wrRam.line
|
||||
line: Valid(wrRam.line)
|
||||
});
|
||||
end
|
||||
else begin
|
||||
|
||||
@@ -340,7 +340,7 @@ module mkL1Pipe(
|
||||
|
||||
CCPipe#(
|
||||
wayNum, indexT, tagT, Msi, dirT, ownerT, otherT, repT, Line, pipeCmdT
|
||||
) pipe <- mkCCPipe(
|
||||
) pipe <- mkCCPipeSingleCycle(
|
||||
regToReadOnly(initDone), getIndex, tagMatch,
|
||||
updateByUpCs, updateByDownDir, updateRepInfo,
|
||||
infoRam, repRam, dataRam
|
||||
|
||||
@@ -162,9 +162,9 @@ module mkLLPipe(
|
||||
Bool verbose = False;
|
||||
|
||||
// RAMs
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCoreForwarded);
|
||||
Vector#(wayNum, RWBramCore#(indexT, infoT)) infoRam <- replicateM(mkRWBramCore);
|
||||
RWBramCore#(indexT, repT) repRam <- mkRandRepRam;
|
||||
Vector#(wayNum, RWBramCore#(indexT, Line)) dataRam <- replicateM(mkRWBramCoreForwarded);
|
||||
RWBramCore#(dataIndexT, Line) dataRam <- mkRWBramCore;
|
||||
|
||||
// initialize RAM
|
||||
Reg#(Bool) initDone <- mkReg(False);
|
||||
|
||||
Reference in New Issue
Block a user