Try new types to hold capabilities

This commit is contained in:
Alexandre Joannou
2020-03-20 15:41:50 +00:00
committed by Alexandre Joannou
parent 0b68498940
commit b70498e00a
25 changed files with 615 additions and 486 deletions

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +8,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -32,9 +32,9 @@ import GetPut::*;
import ClientServer::*;
typedef enum {
I = 2'd0,
S = 2'd1,
E = 2'd2,
I = 2'd0,
S = 2'd1,
E = 2'd2,
M = 2'd3
} MESI deriving(Bits, Eq, FShow);
typedef MESI Msi;
@@ -79,54 +79,59 @@ typedef TDiv#(DataSz, 8) DataSzBytes;
typedef TLog#(DataSzBytes) LgDataSzBytes;
typedef Bit#(LgDataSzBytes) DataBytesOffset;
typedef TDiv#(MemDataSz, 8) MemDataSzBytes;
typedef TLog#(MemDataSzBytes) LgMemDataSzBytes;
typedef Bit#(LgMemDataSzBytes) MemDataBytesOffset;
typedef TDiv#(InstSz, 8) InstSzBytes;
typedef TLog#(InstSzBytes) LgInstSzBytes;
// 64B cache line -- XXX same with parameters in CacheUtils.bsv
typedef CacheUtils::LogCLineNumData LgLineSzData;
typedef CacheUtils::LogCLineNumBytes LgLineSzBytes;
typedef CacheUtils::LogCLineNumMemTaggedData LgLineSzData;
typedef CacheUtils::LogCLineNumMemDataBytes LgLineSzBytes;
typedef CacheUtils::CLineAddrSz LineAddrSz;
typedef CacheUtils::CLineAddr LineAddr;
typedef CacheUtils::CLineNumData LineSzData;
typedef CacheUtils::CLine Line;
typedef CacheUtils::CLineDataSel LineDataOffset;
typedef CacheUtils::CLineMemTaggedDataSel LineMemDataOffset;
typedef CacheUtils::CLineNumBytes LineSzBytes;
typedef CacheUtils::CLineByteEn LineByteEn;
typedef CacheUtils::CLineDataNumBytes LineSzBytes;
typedef CacheUtils::CLineMemDataByteEn LineByteEn;
typedef CacheUtils::CLineDataByteEn LineDataByteEn;
typedef TDiv#(LineSzBytes, InstSzBytes) LineSzInst;
typedef Bit#(TLog#(LineSzInst)) LineInstOffset;
typedef Vector#(LineSzData, Data) Line;
function LineAddr getLineAddr(Addr addr) = truncateLSB(addr);
function LineDataOffset getLineDataOffset(Addr a);
return truncate(a >> valueOf(LgDataSzBytes));
endfunction
function LineMemDataOffset getLineMemDataOffset(Addr a);
return truncate(a >> valueOf(LgMemDataSzBytes));
endfunction
function LineInstOffset getLineInstOffset(Addr a);
return truncate(a >> valueof(LgInstSzBytes));
endfunction
function Line getUpdatedLine(Line curLine, LineByteEn wrBE, Line wrLine);
Vector#(LineSzBytes, Bit#(8)) curVec = unpack(pack(curLine));
Vector#(LineSzBytes, Bit#(8)) wrVec = unpack(pack(wrLine));
function Bit#(8) getNewByte(Integer i);
return wrBE[i] ? wrVec[i] : curVec[i];
// handle data merge
Vector#(LineSzBytes, Bit#(8)) newDataVec = mergeDataBE(curLine.data, wrLine.data, wrBE);
// handle tag merge
Vector#(CLineNumMemTaggedData, MemTag) curTagVec = curLine.tag;
Vector#(CLineNumMemTaggedData, MemTag) wrTagVec = wrLine.tag;
function MemTag getNewTag(Integer i);
let res = curTagVec[i];
if (pack(wrBE[i]) == ~0) res = wrTagVec[i];
return res;
endfunction
Vector#(LineSzBytes, Bit#(8)) newVec = map(getNewByte, genVector);
return unpack(pack(newVec));
endfunction
function Data getUpdatedData(Data curData, ByteEn wrBE, Data wrData);
Vector#(DataSzBytes, Bit#(8)) curVec = unpack(pack(curData));
Vector#(DataSzBytes, Bit#(8)) wrVec = unpack(pack(wrData));
function Bit#(8) getNewByte(Integer i);
return wrBE[i] ? wrVec[i] : curVec[i];
endfunction
Vector#(DataSzBytes, Bit#(8)) newVec = map(getNewByte, genVector);
return pack(newVec);
Vector#(CLineNumMemTaggedData, MemTag) newTagVec = genWith(getNewTag);
// compose updated line
return CLine { tag: newTagVec
, data: unpack(pack(newDataVec)) };
endfunction
// calculate tag
@@ -191,8 +196,8 @@ typedef struct {
Msi toState;
// below are detailed mem op
MemOp op; // Ld, St, Lr, Sc, Amo
ByteEn byteEn; // valid when op == Sc
Data data; // valid when op == Sc/Amo
MemDataByteEn byteEn; // valid when op == Sc
MemTaggedData data; // valid when op == Sc/Amo
AmoInst amoInst; // valid when op == Amo
} ProcRq#(type idT) deriving(Bits, Eq, FShow);
@@ -201,8 +206,8 @@ interface L1ProcReq#(type idT);
endinterface
interface L1ProcResp#(type idT);
method Action respLd(idT id, Data resp);
method Action respLrScAmo(idT id, Data resp);
method Action respLd(idT id, MemTaggedData resp);
method Action respLrScAmo(idT id, MemTaggedData resp);
method ActionValue#(Tuple2#(LineByteEn, Line)) respSt(idT id);
method Action evict(LineAddr a); // called when cache line is evicted
endinterface
@@ -371,7 +376,7 @@ endinterface
instance Connectable#(MemFifoServer#(idT, childT), MemFifoClient#(idT, childT));
module mkConnection#(
MemFifoServer#(idT, childT) server,
MemFifoServer#(idT, childT) server,
MemFifoClient#(idT, childT) client
)(Empty);
rule doCToM;

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -392,7 +391,7 @@ module mkIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line));
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line.data));
// the start offset for reading inst
LineInstOffset startSel = getLineInstOffset(addr);
// calculate the maximum inst count that could be read from line

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -189,7 +188,7 @@ module mkL1Bank#(
Count#(Data) ldMissLat <- mkCount(0);
Count#(Data) stMissLat <- mkCount(0);
Count#(Data) amoMissLat <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrReqCnt(MemOp op);
@@ -244,8 +243,8 @@ module mkL1Bank#(
mshrIdx: n
}));
if (verbose)
$display("%t L1 %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t L1 %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -258,7 +257,7 @@ module mkL1Bank#(
cRqIdxT n <- cRqMshr.cRqTransfer.getEmptyEntryInit(r);
// send to pipeline
pipeline.send(CRq (L1PipeRqIn {
addr: r.addr,
addr: r.addr,
mshrIdx: n
}));
`ifdef PERF_COUNT
@@ -266,7 +265,7 @@ module mkL1Bank#(
incrReqCnt(r.op);
`endif
if (verbose)
$display("%t L1 %m cRqTransfer_new: ", $time,
$display("%t L1 %m cRqTransfer_new: ", $time,
fshow(n), " ; ",
fshow(r)
);
@@ -282,8 +281,8 @@ module mkL1Bank#(
mshrIdx: n
}));
if (verbose)
$display("%t L1 %m pRqTransfer: ", $time,
fshow(n), " ; ",
$display("%t L1 %m pRqTransfer: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -348,8 +347,8 @@ module mkL1Bank#(
cRqSlotT slot = cRqMshr.sendRsToP_cRq.getSlot(n);
Maybe#(Line) data = cRqMshr.sendRsToP_cRq.getData(n);
L1CRqState state = cRqMshr.sendRsToP_cRq.getState(n);
doAssert(state == WaitNewTag,
"send replacement resp to parent, state should be WaitNewTag"
doAssert(state == WaitNewTag,
"send replacement resp to parent, state should be WaitNewTag"
);
// send resp to parent
cRsToPT resp = CRsMsg {
@@ -370,9 +369,9 @@ module mkL1Bank#(
// inform processor of line eviction
procResp.evict(getLineAddr(resp.addr));
if (verbose)
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
fshow(req), " ; ",
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
fshow(req), " ; ",
fshow(resp)
);
endrule
@@ -393,9 +392,9 @@ module mkL1Bank#(
// inform processor of line eviction
procResp.evict(getLineAddr(resp.addr));
if (verbose)
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
fshow(resp)
);
endrule
@@ -415,10 +414,10 @@ module mkL1Bank#(
};
rqToPQ.enq(cRqToP);
if (verbose)
$display("%t L1 %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
$display("%t L1 %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
@@ -466,13 +465,13 @@ module mkL1Bank#(
// TODO when we have MESI, cache state may also need update
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
case(req.op) matches
Ld: begin
procResp.respLd(req.id, curLine[dataSel]);
procResp.respLd(req.id, getTaggedDataAt(curLine, dataSel));
end
Lr: begin
procResp.respLrScAmo(req.id, curLine[dataSel]);
procResp.respLrScAmo(req.id, getTaggedDataAt(curLine, dataSel));
// set link addr
linkAddr <= Valid (getLineAddr(req.addr));
end
@@ -483,11 +482,14 @@ module mkL1Bank#(
// check Sc succeeds or not
Bool succeed = linkAddr == Valid (getLineAddr(req.addr));
// resp to proc
Data respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
MemTaggedData respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
procResp.respLrScAmo(req.id, respVal);
// calculate new data to write
if(succeed) begin
newLine[dataSel] = getUpdatedData(curLine[dataSel], req.byteEn, req.data);
let taggedData = getTaggedDataAt(curLine, dataSel);
let newTaggedData =
mergeMemTaggedDataBE(taggedData, req.data, zeroExtend(pack(req.byteEn)));
newLine = setTaggedDataAt( newLine, dataSel, newTaggedData);
end
// reset link addr
linkAddr <= Invalid;
@@ -548,16 +550,28 @@ module mkL1Bank#(
// get line and sel
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
Bool upper32 = req.addr[2] == 1;
Data curData = curLine[dataSel];
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
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#(2) wordIdx = req.addr[3:2];
// resp processor
Data resp = req.amoInst.doubleWord ? curData : signExtend(
upper32 ? curData[63:32] : curData[31:0]
);
MemTaggedData resp = case (req.amoInst.width)
QWord: current;
DWord: MemTaggedData {
tag: False,
data: unpack(signExtend(dwordData[dwordIdx]))
};
Word: MemTaggedData {
tag: False,
data: unpack(signExtend(wordData[wordIdx]))
};
endcase;
procResp.respLrScAmo(req.id, resp);
// calculate new data to write
newLine[dataSel] = amoExec(req.amoInst, curData, req.data, upper32);
let newData = amoExec(req.amoInst, wordIdx, current, req.data);
newLine = setTaggedDataAt(newLine, dataSel, newData);
// deq pipeline or swap in successor
pipeline.deqWrite(succ, RamData {
info: CacheInfo {
@@ -588,7 +602,7 @@ module mkL1Bank#(
procRqT procRq = pipeOutCRq;
if (verbose)
$display("%t L1 %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
// find end of dependency chain
Maybe#(cRqIdxT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(procRq.addr);
@@ -634,10 +648,10 @@ module mkL1Bank#(
// because cRq is not set to Depend when pRq invalidates it (pRq just directly resp)
// and this func is only called when cs < toState (otherwise will hit)
// because L1 has no children to wait for
doAssert(!cSlot.waitP && !enoughCacheState(ram.info.cs, procRq.toState),
doAssert(!cSlot.waitP && !enoughCacheState(ram.info.cs, procRq.toState),
"waitP must be false and cs must not be enough"
);
// Thus we must send req to parent
// Thus we must send req to parent
// XXX first send to a temp indexQ to avoid conflict, then merge to rqToPIndexQ later
rqToPIndexQ_pipelineResp.enq(n);
// update mshr
@@ -692,7 +706,7 @@ module mkL1Bank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1024,7 +1038,7 @@ module mkL1Bank#(
};
endmethod
endinterface
interface pRqStuck = pRqMshr.stuck;
`ifdef SECURITY
@@ -1043,7 +1057,7 @@ module mkL1Bank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(L1DPerfType t);
return (case(t)

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -47,7 +46,7 @@ export mkLLBank;
// this also ensures that cache pipeline is never blocked
// so we do not need to buffer mem resp that needs to refill cache
// XXX we need to maintain the invariant that
// XXX we need to maintain the invariant that
// at most 1 pRq sent to a child for an addr
// and we have to wait for resp before sending anthoer one
@@ -220,7 +219,7 @@ module mkLLBank#(
Count#(Data) upRespDataCnt <- mkCount(0);
Count#(Data) dmaLdReqCnt <- mkCount(0);
Count#(Data) dmaStReqCnt <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
@@ -303,8 +302,8 @@ module mkLLBank#(
mshrIdx: n
}));
if (verbose)
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -355,15 +354,15 @@ module mkLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, Invalid);
// send to pipeline
pipeline.send(CRq (LLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
if (verbose)
$display("%t LL %m cRqTransfer_new_child: ", $time,
$display("%t LL %m cRqTransfer_new_child: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
endrule
@@ -393,7 +392,7 @@ module mkLLBank#(
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
rqFromDmaQ.deq;
dmaRqT r = rqFromDmaQ.first;
Bool write = r.byteEn != replicate(False);
Bool write = r.byteEn != replicate(replicate(False));
cRqT cRq = LLRq {
addr: r.addr,
fromState: I,
@@ -407,15 +406,15 @@ module mkLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, write ? Valid (r.data) : Invalid);
// send to pipeline
pipeline.send(CRq (LLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
if (verbose)
$display("%t LL %m cRqTransfer_new_dma: ", $time,
$display("%t LL %m cRqTransfer_new_dma: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
`ifdef PERF_COUNT
@@ -468,7 +467,7 @@ module mkLLBank#(
end
`endif
endrule
// mem resp for child req, will refill cache, send it to pipeline
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
`ifdef PERF_COUNT
@@ -534,7 +533,7 @@ module mkLLBank#(
cRqSlotT cSlot = cRqMshr.sendToM.getSlot(n);
Maybe#(Line) data = cRqMshr.sendToM.getData(n);
if (verbose)
$display("%t LL %m sendToM: ", $time,
$display("%t LL %m sendToM: ", $time,
fshow(toMInfoQ.first), " ; ",
fshow(cRq), " ; ",
fshow(cSlot), " ; ",
@@ -614,7 +613,7 @@ module mkLLBank#(
else begin // do write back part
toMemT msg = Wb (WbMemRs {
addr: {cSlot.repTag, truncate(cRq.addr)},
byteEn: replicate(True),
byteEn: replicate(replicate(True)),
data: validValue(data)
});
toMQ.enq(msg);
@@ -646,7 +645,7 @@ module mkLLBank#(
doAssert(isValid(data), "dma read req always has valid data");
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn == replicate(False) && cRq.toState == S,
doAssert(cRq.byteEn == replicate(replicate(False)) && cRq.toState == S,
"cRq should be DMA read"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -669,7 +668,7 @@ module mkLLBank#(
);
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn != replicate(False) && cRq.toState == M,
doAssert(cRq.byteEn != replicate(replicate(False)) && cRq.toState == M,
"cRq should be DMA write"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -687,9 +686,9 @@ module mkLLBank#(
cRqT cRq = cRqMshr.sendRsToDmaC.getRq(n);
Maybe#(Line) rsData = cRqMshr.sendRsToDmaC.getData(n);
if (verbose)
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
fshow(rsData), " ; ",
fshow(toState)
);
@@ -719,7 +718,7 @@ module mkLLBank#(
// round robin select cRq to downgrade child
// but downgrade must wait for all upgrade resp
Reg#(cRqIndexT) whichCRq <- mkReg(0);
// we don't perform sending downgrade to child for a cRq processing by pipelineResp_cRs
// otherwise atomicity issue may arise
// for safety, we check cRq processed by all pipelineResp_xxx rules
@@ -757,7 +756,7 @@ module mkLLBank#(
cRqT cRq = cRqMshr.sendRqToC.getRq(n);
cRqSlotT cSlot = cRqMshr.sendRqToC.getSlot(n);
LLCRqState cState = cRqMshr.sendRqToC.getState(n);
doAssert(cState == WaitSt || cState == WaitOldTag,
doAssert(cState == WaitSt || cState == WaitOldTag,
"only WaitSt and WaitOldTag needs req child"
);
// find a child to downgrade
@@ -828,7 +827,7 @@ module mkLLBank#(
function Action cRqFromCHit(cRqIndexT n, cRqT cRq, Bool isMRs);
action
if (verbose)
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -836,7 +835,7 @@ module mkLLBank#(
doAssert(isRqFromC(cRq.id), "should be cRq from child");
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
// this function is called by mRs, cRq, cRs
// tag should match even for mRs, because
// tag should match even for mRs, because
// tag has been written into cache before sending req to parent
("cRqHit but tag or cs incorrect")
);
@@ -886,7 +885,7 @@ module mkLLBank#(
function Action cRqFromDmaHit(cRqIndexT n, cRqT cRq);
action
if (verbose)
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -895,7 +894,7 @@ module mkLLBank#(
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
"cRqHit but tag or cs incorrect"
);
doAssert((cRq.byteEn != replicate(False)) == (cRq.toState == M), "toState should match byteEn");
doAssert((cRq.byteEn != replicate(replicate(False))) == (cRq.toState == M), "toState should match byteEn");
// update cs (may have E -> M)
Msi newCs = ram.info.cs;
if(cRq.toState == M) begin
@@ -903,7 +902,7 @@ module mkLLBank#(
end
// update cache line
Maybe#(Line) wrData = cRqMshr.pipelineResp.getData(n);
doAssert(isValid(wrData) == (cRq.byteEn != replicate(False)),
doAssert(isValid(wrData) == (cRq.byteEn != replicate(replicate(False))),
"dma write should carry valid data"
);
Line newLine = getUpdatedLine(ram.line, cRq.byteEn, validValue(wrData));
@@ -999,7 +998,7 @@ module mkLLBank#(
cRqT cRq = pipeOutCRq;
if (verbose)
$display("%t LL %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(cRq));
// find end of dependency chain
Maybe#(cRqIndexT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(cRq.addr);
@@ -1141,7 +1140,7 @@ module mkLLBank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1156,7 +1155,7 @@ module mkLLBank#(
LLCRqState cState = pipeOutCState;
doAssert(cState == Init, "owner is other, must first time go through tag match");
// tag match must be hit (because replacement algo won't give a way with owner)
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
("cRq should hit in tag match")
);
// could be two cases:
@@ -1239,7 +1238,7 @@ module mkLLBank#(
if(cRqEOC matches tagged Valid .m &&& cState == Init) begin
if (verbose)
$display("%t LL %m pipelineResp: cRq: no owner, depend on cRq ", $time,
fshow(cState), " ; ",
fshow(cState), " ; ",
fshow(cRqEOC)
);
cRqMshr.pipelineResp.setAddrSucc(m, Valid (n));
@@ -1497,7 +1496,7 @@ module mkLLBank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(LLCPerfType t);
return (case(t)

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -281,7 +280,7 @@ module mkSelfInvIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line));
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line.data));
// the start offset for reading inst
LineInstOffset startSel = getLineInstOffset(addr);
// calculate the maximum inst count that could be read from line

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -453,13 +452,13 @@ module mkSelfInvL1Bank#(
// The silent E->M update is already done in pipeline
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
case(req.op) matches
Ld: begin
procResp.respLd(req.id, curLine[dataSel]);
procResp.respLd(req.id, getTaggedDataAt(curLine, dataSel));
end
Lr: begin
procResp.respLrScAmo(req.id, curLine[dataSel]);
procResp.respLrScAmo(req.id, getTaggedDataAt(curLine, dataSel));
// set link addr
linkAddr <= Valid (getLineAddr(req.addr));
end
@@ -470,11 +469,14 @@ module mkSelfInvL1Bank#(
// check Sc succeeds or not
Bool succeed = linkAddr == Valid (getLineAddr(req.addr));
// resp to proc
Data respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
MemTaggedData respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
procResp.respLrScAmo(req.id, respVal);
// calculate new data to write
if(succeed) begin
newLine[dataSel] = getUpdatedData(curLine[dataSel], req.byteEn, req.data);
let taggedData = getTaggedDataAt(curLine, dataSel);
let newTaggedData =
mergeMemTaggedDataBE(taggedData, req.data, zeroExtend(pack(req.byteEn)));
newLine = setTaggedDataAt( newLine, dataSel, newTaggedData);
end
// reset link addr
linkAddr <= Invalid;
@@ -559,16 +561,28 @@ module mkSelfInvL1Bank#(
// get line and sel
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
Bool upper32 = req.addr[2] == 1;
Data curData = curLine[dataSel];
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
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#(2) wordIdx = req.addr[3:2];
// resp processor
Data resp = req.amoInst.doubleWord ? curData : signExtend(
upper32 ? curData[63:32] : curData[31:0]
);
MemTaggedData resp = case (req.amoInst.width)
QWord: current;
DWord: MemTaggedData {
tag: False,
data: unpack(signExtend(dwordData[dwordIdx]))
};
Word: MemTaggedData {
tag: False,
data: unpack(signExtend(wordData[wordIdx]))
};
endcase;
procResp.respLrScAmo(req.id, resp);
// calculate new data to write
newLine[dataSel] = amoExec(req.amoInst, curData, req.data, upper32);
let newData = amoExec(req.amoInst, wordIdx, current, req.data);
newLine = setTaggedDataAt(newLine, dataSel, newData);
// deq pipeline or swap in successor
// Since AMO always hits in M, hit count is 0 and never self inv
pipeline.deqWrite(succ, RamData {

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -8,10 +7,10 @@
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -42,7 +41,7 @@ import RandomReplace::*;
// this also ensures that cache pipeline is never blocked
// so we do not need to buffer mem resp that needs to refill cache
// XXX we need to maintain the invariant that
// XXX we need to maintain the invariant that
// at most 1 pRq sent to a child for an addr
// and we have to wait for resp before sending anthoer one
@@ -213,7 +212,7 @@ module mkSelfInvLLBank#(
Count#(Data) upRespDataCnt <- mkCount(0);
Count#(Data) dmaLdReqCnt <- mkCount(0);
Count#(Data) dmaStReqCnt <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
@@ -295,8 +294,8 @@ module mkSelfInvLLBank#(
addr: req.addr,
mshrIdx: n
}));
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -347,14 +346,14 @@ module mkSelfInvLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, Invalid);
// send to pipeline
pipeline.send(CRq (SelfInvLLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
$display("%t LL %m cRqTransfer_new_child: ", $time,
$display("%t LL %m cRqTransfer_new_child: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
endrule
@@ -384,7 +383,7 @@ module mkSelfInvLLBank#(
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
rqFromDmaQ.deq;
dmaRqT r = rqFromDmaQ.first;
Bool write = r.byteEn != replicate(False);
Bool write = r.byteEn != replicate(replicate(False));
cRqT cRq = LLRq {
addr: r.addr,
fromState: I,
@@ -398,14 +397,14 @@ module mkSelfInvLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, write ? Valid (r.data) : Invalid);
// send to pipeline
pipeline.send(CRq (SelfInvLLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
$display("%t LL %m cRqTransfer_new_dma: ", $time,
$display("%t LL %m cRqTransfer_new_dma: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
`ifdef PERF_COUNT
@@ -457,7 +456,7 @@ module mkSelfInvLLBank#(
end
`endif
endrule
// mem resp for child req, will refill cache, send it to pipeline
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
`ifdef PERF_COUNT
@@ -520,7 +519,7 @@ module mkSelfInvLLBank#(
cRqT cRq = cRqMshr.sendToM.getRq(n);
cRqSlotT cSlot = cRqMshr.sendToM.getSlot(n);
Maybe#(Line) data = cRqMshr.sendToM.getData(n);
$display("%t LL %m sendToM: ", $time,
$display("%t LL %m sendToM: ", $time,
fshow(toMInfoQ.first), " ; ",
fshow(cRq), " ; ",
fshow(cSlot), " ; ",
@@ -597,7 +596,7 @@ module mkSelfInvLLBank#(
else begin // do write back part
toMemT msg = Wb (WbMemRs {
addr: {cSlot.repTag, truncate(cRq.addr)},
byteEn: replicate(True),
byteEn: replicate(replicate(True)),
data: validValue(data)
});
toMQ.enq(msg);
@@ -627,7 +626,7 @@ module mkSelfInvLLBank#(
doAssert(isValid(data), "dma read req always has valid data");
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn == replicate(False) && cRq.toState == S,
doAssert(cRq.byteEn == replicate(replicate(False)) && cRq.toState == S,
"cRq should be DMA read"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -649,7 +648,7 @@ module mkSelfInvLLBank#(
);
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn != replicate(False) && cRq.toState == M,
doAssert(cRq.byteEn != replicate(replicate(False)) && cRq.toState == M,
"cRq should be DMA write"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -666,9 +665,9 @@ module mkSelfInvLLBank#(
Msi toState = rsToCIndexQ.first.toState;
cRqT cRq = cRqMshr.sendRsToDmaC.getRq(n);
Maybe#(Line) rsData = cRqMshr.sendRsToDmaC.getData(n);
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
fshow(rsData), " ; ",
fshow(toState)
);
@@ -698,7 +697,7 @@ module mkSelfInvLLBank#(
// round robin select cRq to downgrade child
// but downgrade must wait for all upgrade resp
Reg#(cRqIndexT) whichCRq <- mkReg(0);
// we don't perform sending downgrade to child for a cRq processing by pipelineResp_cRs
// otherwise atomicity issue may arise
// for safety, we check cRq processed by all pipelineResp_xxx rules
@@ -736,7 +735,7 @@ module mkSelfInvLLBank#(
cRqT cRq = cRqMshr.sendRqToC.getRq(n);
cRqSlotT cSlot = cRqMshr.sendRqToC.getSlot(n);
LLCRqState cState = cRqMshr.sendRqToC.getState(n);
doAssert(cState == WaitSt || cState == WaitOldTag,
doAssert(cState == WaitSt || cState == WaitOldTag,
"only WaitSt and WaitOldTag needs req child"
);
// find the child to downgrade
@@ -797,7 +796,7 @@ module mkSelfInvLLBank#(
// function to process cRq hit (MSHR slot may have garbage)
function Action cRqFromCHit(cRqIndexT n, cRqT cRq);
action
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -805,7 +804,7 @@ module mkSelfInvLLBank#(
doAssert(isRqFromC(cRq.id), "should be cRq from child");
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
// this function is called by mRs, cRq, cRs
// tag should match even for mRs, because
// tag should match even for mRs, because
// tag has been written into cache before sending req to parent
("cRqHit but tag or cs incorrect")
);
@@ -858,7 +857,7 @@ module mkSelfInvLLBank#(
// function to process DMA req hit (MSHR slot may have garbage)
function Action cRqFromDmaHit(cRqIndexT n, cRqT cRq);
action
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -867,7 +866,7 @@ module mkSelfInvLLBank#(
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
"cRqHit but tag or cs incorrect"
);
doAssert((cRq.byteEn != replicate(False)) == (cRq.toState == M), "toState should match byteEn");
doAssert((cRq.byteEn != replicate(replicate(False))) == (cRq.toState == M), "toState should match byteEn");
// update cs (may have E -> M)
Msi newCs = ram.info.cs;
if(cRq.toState == M) begin
@@ -875,7 +874,7 @@ module mkSelfInvLLBank#(
end
// update cache line
Maybe#(Line) wrData = cRqMshr.pipelineResp.getData(n);
doAssert(isValid(wrData) == (cRq.byteEn != replicate(False)),
doAssert(isValid(wrData) == (cRq.byteEn != replicate(replicate(False))),
"dma write should carry valid data"
);
Line newLine = getUpdatedLine(ram.line, cRq.byteEn, validValue(wrData));
@@ -969,7 +968,7 @@ module mkSelfInvLLBank#(
cRqT cRq = pipeOutCRq;
$display("%t LL %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(cRq));
// find end of dependency chain
Maybe#(cRqIndexT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(cRq.addr);
@@ -1112,7 +1111,7 @@ module mkSelfInvLLBank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1127,7 +1126,7 @@ module mkSelfInvLLBank#(
LLCRqState cState = pipeOutCState;
doAssert(cState == Init, "owner is other, must first time go through tag match");
// tag match must be hit (because replacement algo won't give a way with owner)
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
("cRq should hit in tag match")
);
// could be two cases:
@@ -1203,7 +1202,7 @@ module mkSelfInvLLBank#(
// only check for cRqEOC to append to dependency chain when firt time go through tag match
if(cRqEOC matches tagged Valid .m &&& cState == Init) begin
$display("%t LL %m pipelineResp: cRq: no owner, depend on cRq ", $time,
fshow(cState), " ; ",
fshow(cState), " ; ",
fshow(cRqEOC)
);
cRqMshr.pipelineResp.setAddrSucc(m, Valid (n));
@@ -1408,7 +1407,7 @@ module mkSelfInvLLBank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(LLCPerfType t);
return (case(t)