diff --git a/src_Core/RISCY_OOO/coherence/src/CCPipe.bsv b/src_Core/RISCY_OOO/coherence/src/CCPipe.bsv index 98cfa76..b8475b7 100644 --- a/src_Core/RISCY_OOO/coherence/src/CCPipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CCPipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index e98daf5..4185882 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -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 && diff --git a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv index 2aa44d0..ef279dc 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv @@ -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), diff --git a/src_Core/RISCY_OOO/coherence/src/L1CRqMshr.bsv b/src_Core/RISCY_OOO/coherence/src/L1CRqMshr.bsv index 7028a34..4aadb57 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1CRqMshr.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1CRqMshr.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/L1Pipe.bsv b/src_Core/RISCY_OOO/coherence/src/L1Pipe.bsv index 2d2a612..596d71b 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Pipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Pipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv index 1e09fce..a1af12b 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv @@ -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), diff --git a/src_Core/RISCY_OOO/coherence/src/LLPipe.bsv b/src_Core/RISCY_OOO/coherence/src/LLPipe.bsv index 45fe88e..15cd950 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLPipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLPipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/RWBramCore.bsv b/src_Core/RISCY_OOO/coherence/src/RWBramCore.bsv index 8ce2239..0367fa7 100644 --- a/src_Core/RISCY_OOO/coherence/src/RWBramCore.bsv +++ b/src_Core/RISCY_OOO/coherence/src/RWBramCore.bsv @@ -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) ); diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvIPipe.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvIPipe.bsv index a767949..5171821 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvIPipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvIPipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvL1Pipe.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvL1Pipe.bsv index 48792ef..c055e48 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvL1Pipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvL1Pipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvLLPipe.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvLLPipe.bsv index a577aee..b56ff77 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvLLPipe.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvLLPipe.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv index c2209a9..aab5e41 100644 --- a/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv +++ b/src_Core/RISCY_OOO/procs/lib/L1CoCache.bsv @@ -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