Try new types to hold capabilities
This commit is contained in:
committed by
Alexandre Joannou
parent
0b68498940
commit
b70498e00a
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user