Use an (unguarded) BRAM in the Btb.
Also, assume that a target that is not taken should be removed from the Btb. (The read that checked isn't possible with BRAM timing unless we latched and had an extra port, but removing the check actually improved performance a bit in CoreMark, and the pipeline should actually only be reporting a non-taken branch if we did something wrong.)
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
//
|
||||
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
|
||||
//-
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -21,10 +21,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
|
||||
@@ -75,3 +75,29 @@ module mkRWBramCore(RWBramCore#(addrT, dataT)) provisos(
|
||||
rdReqQ.deq;
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
module mkRWBramCoreUG(RWBramCore#(addrT, dataT)) provisos(
|
||||
Bits#(addrT, addrSz), Bits#(dataT, dataSz)
|
||||
);
|
||||
BRAM_DUAL_PORT#(addrT, dataT) bram <- mkBRAMCore2(valueOf(TExp#(addrSz)), False);
|
||||
BRAM_PORT#(addrT, dataT) wrPort = bram.a;
|
||||
BRAM_PORT#(addrT, dataT) rdPort = bram.b;
|
||||
|
||||
method Action wrReq(addrT a, dataT d);
|
||||
wrPort.put(True, a, d);
|
||||
endmethod
|
||||
|
||||
method Action rdReq(addrT a);
|
||||
rdPort.put(False, a, ?);
|
||||
endmethod
|
||||
|
||||
method dataT rdResp;
|
||||
return rdPort.read;
|
||||
endmethod
|
||||
|
||||
method rdRespValid = True;
|
||||
|
||||
method Action deqRdResp;
|
||||
noAction;
|
||||
endmethod
|
||||
endmodule
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
import Types::*;
|
||||
import ProcTypes::*;
|
||||
import ConfigReg::*;
|
||||
import RegFile::*;
|
||||
import RWBramCore::*;
|
||||
import Vector::*;
|
||||
import CHERICC_Fat::*;
|
||||
import CHERICap::*;
|
||||
@@ -86,7 +86,7 @@ module mkBtb(NextAddrPred);
|
||||
Reg#(BtbTag) tag_reg <- mkRegU;
|
||||
Reg#(BtbBank) firstBank_reg <- mkRegU;
|
||||
Vector#(SupSizeX2, Reg#(BtbIndex)) idxs_reg <- replicateM(mkRegU);
|
||||
Vector#(SupSizeX2, RegFile#(BtbIndex, BtbRecord)) records <- replicateM(mkRegFileWCF(0,~0));
|
||||
Vector#(SupSizeX2, RWBramCore#(BtbIndex, BtbRecord)) records <- replicateM(mkRWBramCoreUG);
|
||||
Vector#(SupSizeX2, Vector#(BtbIndices, Reg#(Bool))) valid <- replicateM(replicateM(mkConfigReg(False)));
|
||||
|
||||
RWire#(BtbUpdate) updateEn <- mkRWire;
|
||||
@@ -115,11 +115,11 @@ module mkBtb(NextAddrPred);
|
||||
$display("cap: %x, btbaddr: ", pc, fshow(getBtbAddr(pc)), " nextPc:%x", nextPc);
|
||||
if(taken) begin
|
||||
valid[bank][index] <= True;
|
||||
records[bank].upd(index, BtbRecord{tag: tag, nextPc: nextPc});
|
||||
end else if(records[bank].sub(index).tag == tag ) begin
|
||||
// current instruction has target in btb, so clear it
|
||||
records[bank].wrReq(index, BtbRecord{tag: tag, nextPc: nextPc});
|
||||
end else
|
||||
// current instruction had been prediceted taken, so clear its target in the TLB
|
||||
valid[bank][index] <= False;
|
||||
records[bank].upd(index, BtbRecord{tag: {4'ha,0}, nextPc: nextPc}); // An invalid virtual address.
|
||||
records[bank].wrReq(index, BtbRecord{tag: {4'ha,0}, nextPc: nextPc}); // An invalid virtual address.
|
||||
end
|
||||
endrule
|
||||
|
||||
@@ -139,13 +139,14 @@ module mkBtb(NextAddrPred);
|
||||
BtbAddr a = unpack(pack(addr) + fromInteger(i));
|
||||
$display("put pc[%d]: ", i, fshow(a));
|
||||
idxs_reg[a.bank] <= a.index;
|
||||
records[a.bank].rdReq(a.index);
|
||||
end
|
||||
endmethod
|
||||
|
||||
method Vector#(SupSizeX2, Maybe#(CapMem)) pred;
|
||||
Vector#(SupSizeX2, Maybe#(BtbRecord)) recs = ?;
|
||||
for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1)
|
||||
recs[i] = (valid[i][idxs_reg[i]]) ? Valid(records[i].sub(idxs_reg[i])):Invalid;
|
||||
recs[i] = (valid[i][idxs_reg[i]]) ? Valid(records[i].rdResp):Invalid;
|
||||
function Maybe#(CapMem) tagHit(Maybe#(BtbRecord) br) =
|
||||
case (br) matches
|
||||
tagged Valid .b &&& (tag_reg == b.tag): return Valid(b.nextPc);
|
||||
|
||||
Reference in New Issue
Block a user