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:
jon
2021-03-06 07:19:50 +00:00
parent 4b411bf752
commit 8da520175f
2 changed files with 37 additions and 10 deletions

View File

@@ -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

View File

@@ -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);