2-byte aligned instruction memory to simplify compressed instruction

fetch.
This commit is contained in:
jon
2020-07-24 12:38:37 +01:00
parent ecce475b97
commit 1f968b0c07
9 changed files with 113 additions and 165 deletions

View File

@@ -97,7 +97,7 @@ typedef TDiv#(MemDataSz, 8) MemDataSzBytes;
typedef TLog#(MemDataSzBytes) LgMemDataSzBytes;
typedef Bit#(LgMemDataSzBytes) MemDataBytesOffset;
typedef TDiv#(InstSz, 8) InstSzBytes;
typedef TDiv#(Inst16_Sz, 8) InstSzBytes;
typedef TLog#(InstSzBytes) LgInstSzBytes;
// 64B cache line -- XXX same with parameters in CacheUtils.bsv
@@ -230,7 +230,7 @@ typedef struct {
// I$ req/resp
interface InstServer#(numeric type supSz);
interface Put#(Addr) req;
interface Get#(Vector#(supSz, Maybe#(Instruction))) resp;
interface Get#(Vector#(TMul#(supSz,2), Maybe#(Instruction16))) resp;
`ifdef DEBUG_ICACHE
interface Get#(DebugICacheResp) done; // the id and cache line of the I$ req that truly performs
`endif

View File

@@ -124,7 +124,8 @@ module mkIBank#(
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#(resultT, Vector#(supSz, Maybe#(Instruction))),
Mul#(2, supSz, supSzX2),
Alias#(resultT, Vector#(supSzX2, Maybe#(Instruction16))),
// requirements
FShow#(pipeOutT),
Add#(tagSz, a__, AddrSz),
@@ -156,13 +157,13 @@ module mkIBank#(
// index Q to order all in flight cRq for in-order resp
FIFO#(cRqIdxT) cRqIndexQ <- mkSizedFIFO(valueof(cRqNum));
`ifdef DEBUG_ICACHE
// id for each cRq, incremented when each new req comes
Reg#(Bit#(64)) cRqId <- mkReg(0);
// FIFO to signal the id of cRq that is performed
// FIFO has 0 cycle latency to match L1 D$ resp latency
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
`endif
// security flush
@@ -248,8 +249,8 @@ module mkIBank#(
mshrIdx: n
}));
if (verbose)
$display("%t I %m pRqTransfer: ", $time,
fshow(n), " ; ",
$display("%t I %m pRqTransfer: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -268,7 +269,7 @@ module mkIBank#(
$display("%t I %m pRsTransfer: ", $time, fshow(resp));
doAssert(resp.toState == S && isValid(resp.data), "I$ must upgrade to S with data");
endrule
`ifdef SECURITY
// start flush when cRq MSHR is empty
rule startFlushReq(!flushDone && !flushReqStart && cRqMshr.emptyForFlush);
@@ -326,8 +327,8 @@ module mkIBank#(
// (prevent parent resp from coming to release MSHR entry before replace resp is sent)
rqToPIndexQ_sendRsToP.enq(n);
if (verbose)
$display("%t I %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
$display("%t I %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
fshow(resp)
@@ -347,9 +348,9 @@ module mkIBank#(
rsToPQ.enq(resp);
pRqMshr.sendRsToP_pRq.releaseEntry(n); // mshr entry released
if (verbose)
$display("%t I %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
$display("%t I %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
fshow(resp)
);
doAssert(req.toState == I, "I$ only has downgrade req to I");
@@ -370,10 +371,10 @@ module mkIBank#(
};
rqToPQ.enq(cRqToP);
if (verbose)
$display("%t I %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
$display("%t I %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
@@ -404,14 +405,14 @@ module mkIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line.data));
Vector#(LineSzInst, Instruction16) 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
LineInstOffset maxCntMinusOne = maxBound - startSel;
// read inst superscalaer
resultT val = ?;
for(Integer i = 0; i < valueof(supSz); i = i+1) begin
for(Integer i = 0; i < valueof(supSzX2); i = i+1) begin
if(fromInteger(i) <= maxCntMinusOne) begin
LineInstOffset sel = startSel + fromInteger(i);
val[i] = Valid (instVec[sel]);
@@ -474,7 +475,7 @@ module mkIBank#(
procRqT procRq = pipeOutCRq;
if (verbose)
$display("%t I %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
// find end of dependency chain
Maybe#(cRqIdxT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(procRq.addr);
@@ -487,7 +488,7 @@ module mkIBank#(
// and this func is only called when cs < S (otherwise will hit)
// because L1 has no children to wait for
doAssert(!cSlot.waitP && ram.info.cs == I, "waitP must be false and cs must be I");
// 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
@@ -537,7 +538,7 @@ module mkIBank#(
rsToPIndexQ.enq(CRq (n));
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -786,7 +787,7 @@ module mkIBank#(
};
endmethod
endinterface
interface pRqStuck = pRqMshr.stuck;
`ifdef SECURITY
@@ -886,4 +887,3 @@ endmodule
// unsafe version: all reads read the original reg value, except sendRsToC, which should bypass from pipelineResp
// all writes are cononicalized. NOTE: writes of sendRsToC should be after pipelineResp
// we maintain the logical ordering in safe version

View File

@@ -122,7 +122,8 @@ module mkSelfInvIBank#(
Alias#(cRqSlotT, ICRqSlot#(wayT, tagT)), // cRq MSHR slot
Alias#(iCmdT, SelfInvICmd#(cRqIdxT)),
Alias#(pipeOutT, PipeOut#(wayT, tagT, Msi, void, cacheOwnerT, otherT, RandRepInfo, Line, iCmdT)),
Alias#(resultT, Vector#(supSz, Maybe#(Instruction))),
Mul#(2, supSz, supSzX2),
Alias#(resultT, Vector#(supSzX2, Maybe#(Instruction16))),
// requirements
FShow#(pipeOutT),
Add#(tagSz, a__, AddrSz),
@@ -146,7 +147,7 @@ module mkSelfInvIBank#(
// index Q to order all in flight cRq for in-order resp
FIFO#(cRqIdxT) cRqIndexQ <- mkSizedFIFO(valueof(cRqNum));
// Reconcile states
Reg#(Bool) needReconcile <- mkReg(False);
Reg#(Bool) waitReconcileDone <- mkReg(False);
@@ -156,7 +157,7 @@ module mkSelfInvIBank#(
Reg#(Bit#(64)) cRqId <- mkReg(0);
// FIFO to signal the id of cRq that is performed
// FIFO has 0 cycle latency to match L1 D$ resp latency
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
Fifo#(1, DebugICacheResp) cRqDoneQ <- mkBypassFifo;
`endif
`ifdef PERF_COUNT
@@ -244,7 +245,7 @@ module mkSelfInvIBank#(
$display("%t I %m pRsTransfer: ", $time, fshow(resp));
doAssert(resp.toState == S && isValid(resp.data), "I$ must upgrade to S with data");
endrule
rule sendRqToP;
rqToPIndexQ.deq;
cRqIdxT n = rqToPIndexQ.first;
@@ -260,10 +261,10 @@ module mkSelfInvIBank#(
};
rqToPQ.enq(cRqToP);
if (verbose)
$display("%t I %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
$display("%t I %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
@@ -294,14 +295,14 @@ module mkSelfInvIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line.data));
Vector#(LineSzInst, Instruction16) 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
LineInstOffset maxCntMinusOne = maxBound - startSel;
// read inst superscalaer
resultT val = ?;
for(Integer i = 0; i < valueof(supSz); i = i+1) begin
for(Integer i = 0; i < valueof(supSzX2); i = i+1) begin
if(fromInteger(i) <= maxCntMinusOne) begin
LineInstOffset sel = startSel + fromInteger(i);
val[i] = Valid (instVec[sel]);
@@ -364,7 +365,7 @@ module mkSelfInvIBank#(
procRqT procRq = pipeOutCRq;
if (verbose)
$display("%t I %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
// find end of dependency chain
Maybe#(cRqIdxT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(procRq.addr);
@@ -380,7 +381,7 @@ module mkSelfInvIBank#(
doAssert(ram.info.cs <= S, "no exclusive in I$");
// This cannot be a hit
doAssert(ram.info.cs == I || ram.info.tag != getTag(procRq.addr), "cannot hit");
// Thus we must send req to parent
// Thus we must send req to parent
rqToPIndexQ.enq(n);
// update mshr
cRqMshr.pipelineResp.setStateSlot(n, WaitSt, ICRqSlot {
@@ -551,7 +552,7 @@ module mkSelfInvIBank#(
};
endmethod
endinterface
interface pRqStuck = nullGet;
`ifdef SECURITY
@@ -659,4 +660,3 @@ endmodule
// unsafe version: all reads read the original reg value, except sendRsToC, which should bypass from pipelineResp
// all writes are cononicalized. NOTE: writes of sendRsToC should be after pipelineResp
// we maintain the logical ordering in safe version