Merge branch 'ifetch-cleanup' into CHERI

This commit is contained in:
Peter Rugg
2021-03-02 11:57:31 +00:00
5 changed files with 611 additions and 621 deletions

View File

@@ -48,7 +48,6 @@ import GetPut::*;
import ClientServer::*;
import Connectable::*;
import FIFOF :: *;
// import BRAMCore::*;
// ----------------
// BSV additional libs
@@ -943,19 +942,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
$display (" ", fshow (req));
end
endrule
/*
function Vector #(SupSizeX2, Maybe #(Instruction16)) prepareFinalInstResp(Vector #(SupSize, Maybe #(Instruction)) respBigInsts, Bit#(1) addr_bit_1);
Vector #(SupSizeX2, Maybe #(Instruction16)) respSmallInsts = replicate (Invalid);
for (Integer i = 0; i < valueOf (SupSize); i = i+1) begin
if (respBigInsts[i] matches tagged Valid .inst) begin
respSmallInsts[i*2] = tagged Valid (truncate(inst));
respSmallInsts[(i*2) + 1] = tagged Valid (truncateLSB(inst));
end
end
// This unconventional zero-extension of addr_bit_1 works around a type error in shiftOutFrom0.
return shiftOutFrom0(Invalid, respSmallInsts, {4'b0, addr_bit_1});
endfunction
*/
rule rl_mmio_from_fabric_ifetch_rsp (curReq matches tagged MMIO_Fabric_Adapter .addr
&&& (state == WaitResp)
&&& isInstFetch);

File diff suppressed because it is too large Load Diff

View File

@@ -43,11 +43,16 @@ import Vector::*;
import CHERICC_Fat::*;
import CHERICap::*;
export PredPcIfc(..);
export NextAddrPred(..);
export mkBtb;
interface NextAddrPred;
interface PredPcIfc;
method Maybe#(CapMem) predPc(CapMem pc);
endinterface
interface NextAddrPred;
interface Vector#(SupSizeX2, PredPcIfc) pred;
method Action update(CapMem pc, CapMem brTarget, Bool taken);
// security
method Action flush;
@@ -66,12 +71,12 @@ typedef struct {
Bool taken;
} BtbUpdate deriving(Bits, Eq, FShow);
// No synthesize boundary because we need to call predPC several times
(* synthesize *)
module mkBtb(NextAddrPred);
// Read and Write ordering doesn't matter since this is a predictor
// mkRegFileWCF is the RegFile version of mkConfigReg
RegFile#(BtbIndex, CapMem) next_addrs <- mkRegFileWCF(0,fromInteger(valueOf(BtbEntries)-1));
RegFile#(BtbIndex, BtbTag) tags <- mkRegFileWCF(0,fromInteger(valueOf(BtbEntries)-1));
Vector#(SupSizeX2, RegFile#(BtbIndex, CapMem)) next_addrs <- replicateM(mkRegFileWCF(0,fromInteger(valueOf(BtbEntries)-1)));
Vector#(SupSizeX2, RegFile#(BtbIndex, BtbTag)) tags <- replicateM(mkRegFileWCF(0,fromInteger(valueOf(BtbEntries)-1)));
Vector#(BtbEntries, Reg#(Bool)) valid <- replicateM(mkConfigReg(False));
RWire#(BtbUpdate) updateEn <- mkRWire;
@@ -96,9 +101,11 @@ module mkBtb(NextAddrPred);
let tag = getTag(pc);
if(taken) begin
valid[index] <= True;
tags.upd(index, tag);
next_addrs.upd(index, nextPc);
end else if( tags.sub(index) == tag ) begin
for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1) begin
tags[i].upd(index, tag);
next_addrs[i].upd(index, nextPc);
end
end else if( tags[0].sub(index) == tag ) begin
// current instruction has target in btb, so clear it
valid[index] <= False;
end
@@ -112,14 +119,21 @@ module mkBtb(NextAddrPred);
endrule
`endif
method Maybe#(CapMem) predPc(CapMem pc);
BtbIndex index = getIndex(pc);
BtbTag tag = getTag(pc);
if(valid[index] && tag == tags.sub(index))
return tagged Valid next_addrs.sub(index);
else
return tagged Invalid;
endmethod
Vector#(SupSizeX2, PredPcIfc) predPcs;
for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1) begin
predPcs[i] = interface PredPcIfc;
method Maybe#(CapMem) predPc(CapMem pc);
BtbIndex index = getIndex(pc);
BtbTag tag = getTag(pc);
if(valid[index] && tag == tags[i].sub(index))
return tagged Valid next_addrs[i].sub(index);
else
return tagged Invalid;
endmethod
endinterface;
end
method pred = predPcs;
method Action update(CapMem pc, CapMem nextPc, Bool taken);
updateEn.wset(BtbUpdate {pc: pc, nextPc: nextPc, taken: taken});

View File

@@ -160,7 +160,7 @@ endinstance
// endfunction
// endinstance
module mkSupFifo(SupFifo#(k,n,t)) provisos (
module mkUGSupFifo(SupFifo#(k,n,t)) provisos (
Bits#(t,tSz),
FShow#(t),
Add#(TExp#(TLog#(k)), 0, k) // k must be power of 2
@@ -177,7 +177,7 @@ module mkSupFifo(SupFifo#(k,n,t)) provisos (
Bool can_enq = internalFifos[fifoIdx].notFull;
return (interface SupFifoEnq;
method Bool canEnq = can_enq;
method Action enq(t x) if(can_enq);
method Action enq(t x);
enqueueElement[i][0] <= tagged Valid x;
endmethod
endinterface);
@@ -188,10 +188,10 @@ module mkSupFifo(SupFifo#(k,n,t)) provisos (
Bool can_deq = internalFifos[fifoIdx].notEmpty;
return (interface SupFifoDeq;
method Bool canDeq = can_deq;
method t first if(can_deq);
method t first;
return internalFifos[fifoIdx].first;
endmethod
method Action deq if(can_deq);
method Action deq;
willDequeue[i][0] <= True;
endmethod
endinterface);
@@ -231,6 +231,35 @@ module mkSupFifo(SupFifo#(k,n,t)) provisos (
endmethod
endmodule
module mkSupFifo(SupFifo#(k,n,t)) provisos (
Bits#(t,tSz),
FShow#(t),
Add#(TExp#(TLog#(k)), 0, k) // k must be power of 2
);
SupFifo#(k,n,t) ugf <- mkUGSupFifo;
function SupFifoEnq#(t) getEnqIfc(Integer i);
return (interface SupFifoEnq;
method Bool canEnq = ugf.enqS[i].canEnq;
method Action enq(t x) if(ugf.enqS[i].canEnq) = ugf.enqS[i].enq(x);
endinterface);
endfunction
function SupFifoDeq#(t) getDeqIfc(Integer i);
return (interface SupFifoDeq;
method Bool canDeq = ugf.deqS[i].canDeq;
method t first if(ugf.deqS[i].canDeq) = ugf.deqS[i].first;
method Action deq if(ugf.deqS[i].canDeq) = ugf.deqS[i].deq;
endinterface);
endfunction
Vector#(k,Integer) indexes = genVector;
interface Vector enqS = map(getEnqIfc, indexes);
interface Vector deqS = map(getDeqIfc, indexes);
method Bool internalEmpty = ugf.internalEmpty;
endmodule
// A Conflict free implementation of n element FIFO

View File

@@ -0,0 +1,223 @@
/*-
* Copyright (c) 2020 Jonathan Woodruff
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory (Department of Computer Science and
* Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
* DARPA SSITH research programme.
*
* @BERI_LICENSE_HEADER_START@
*
* Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. BERI licenses this
* file to you under the BERI Hardware-Software License, Version 1.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.beri-open-systems.org/legal/license-1-0.txt
*
* Unless required by applicable law or agreed to in writing, Work distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* @BERI_LICENSE_HEADER_END@
*/
import Vector::*;
import Assert::*;
interface IndexedMultisetRemoveIfc#(type idxT);
method Action remove(idxT i);
endinterface
interface IndexedMultiset#(type idxT, type datT, numeric type remWidth);
method ActionValue#(idxT) insert(datT d);
// Reserved data values must be the same as the next inserted value or they will be overwritten.
method ActionValue#(IndexedMultisetIndices#(idxT)) insertAndReserve(datT ins, datT res);
method datT lookup(idxT i);
interface Vector#(remWidth, IndexedMultisetRemoveIfc#(idxT)) rPort;
method Action clearAll;
endinterface
typedef struct {
datT data;
ctr count;
} IndexedMultisetRecord#(type datT, type ctr) deriving(Bits);
typedef struct {
idxT inserted;
idxT reserved;
} IndexedMultisetIndices#(type idxT) deriving(Bits);
typedef struct {
idxT idx;
datT dat;
} IndexedMultisetInsert#(type idxT, type datT) deriving(Bits);
module mkIndexedMultiset(IndexedMultiset#(idxT, datT, remWidth))
provisos (
Bits#(datT, _datsz),
Eq#(datT),
Bits#(idxT, _idxsz),
PrimIndex#(idxT, a__),
Alias#(wide_idxT, Bit#(TAdd#(_idxsz,2))) // Allow for generous number of duplicates per data value; 4x index capacity.
);
Vector#(TExp#(_idxsz), Reg#(IndexedMultisetRecord#(datT,wide_idxT)))
records <- replicateM(mkReg(unpack(0)));
let recsRead = readVReg(records);
RWire#(IndexedMultisetInsert#(idxT,datT)) insertW <- mkRWire;
RWire#(IndexedMultisetInsert#(idxT,datT)) reserveW <- mkRWire;
Vector#(remWidth, RWire#(idxT)) removeW <- replicateM(mkRWire);
PulseWire clearW <- mkPulseWire;
(* no_implicit_conditions *)
rule canon;
Vector#(TExp#(_idxsz),IndexedMultisetRecord#(datT,wide_idxT)) recs = readVReg(records);
if (insertW.wget matches tagged Valid .r) begin
recs[r.idx].data = r.dat;
recs[r.idx].count = recs[r.idx].count + 1;
end
if (reserveW.wget matches tagged Valid .r) recs[r.idx].data = r.dat;
for (Integer i = 0; i < valueOf(remWidth); i = i + 1)
if (removeW[i].wget matches tagged Valid .r) recs[r].count = recs[r].count - 1;
if (clearW) recs = replicate(IndexedMultisetRecord{data: ?, count: 0});
writeVReg(records, recs);
endrule
function isEmpty(r) = (r.count == 0);
function isFull(r) = (r.count == ~0);
function dataMatch(d, r) = (r.data == d);
function ActionValue#(idxT) findIdx(datT d, Vector#(TExp#(_idxsz), IndexedMultisetRecord#(datT,wide_idxT)) recs) =
actionvalue
let mi = findIndex(dataMatch(d),recs);
if (!isValid(mi)) mi = findIndex(isEmpty,recs);
dynamicAssert(isValid(mi), "failed to insert in indexed multiset");
return unpack(pack(validValue(mi)));
endactionvalue;
Vector#(remWidth, IndexedMultisetRemoveIfc#(idxT)) removes;
for (Integer i = 0; i < valueOf(remWidth); i = i + 1) begin
removes[i] = interface IndexedMultisetRemoveIfc#(idxT);
method Action remove(idxT index);
dynamicAssert(recsRead[index].count != 0, "removed empty item in indexed multiset");
removeW[i].wset(index);
endmethod
endinterface;
end
Bool anyEmpty = any(isEmpty,recsRead);
Bool anyFull = any(isFull,recsRead);
method ActionValue#(idxT) insert(datT d) if (anyEmpty && !anyFull);
let i <- findIdx(d,recsRead);
insertW.wset(IndexedMultisetInsert{idx:i, dat:d});
return i;
endmethod
method ActionValue#(IndexedMultisetIndices#(idxT)) insertAndReserve(datT ins, datT res);
let insIdx <- findIdx(ins,recsRead);
insertW.wset(IndexedMultisetInsert{idx:insIdx, dat:ins});
let newRecs = recsRead;
newRecs[insIdx].data = ins;
let resIdx <- findIdx(res,newRecs);
reserveW.wset(IndexedMultisetInsert{idx:resIdx, dat:res});
return IndexedMultisetIndices{inserted: insIdx, reserved: resIdx};
endmethod
method datT lookup(idxT i) = records[i].data;
interface rPort = removes;
method Action clearAll = clearW.send;
endmodule
// An implementation of Indexed Multiset that depends on inserting and removing in the same order.
module mkIndexedMultisetQueue(IndexedMultiset#(Bit#(idxTSz), datT, remWidth))
provisos (
Alias#(idxT, Bit#(idxTSz)),
Bits#(datT, _datsz),
Eq#(datT)
);
Vector#(TExp#(idxTSz), Reg#(datT)) records <- replicateM(mkRegU);
Vector#(TExp#(idxTSz), datT) recsRead = readVReg(records);
Reg#(Bit#(TAdd#(idxTSz,1))) lhead <- mkReg(0);
Reg#(Bit#(TAdd#(idxTSz,1))) ltail <- mkReg(0);
idxT head = truncate(lhead);
Bit#(TAdd#(idxTSz,1)) level = lhead - ltail;
//Bool empty = (level==0);
Bool full = (level==fromInteger(valueOf(TExp#(idxTSz))));
Bool almostFull = (level>=fromInteger(valueOf(TExp#(idxTSz)))-1);
RWire#(datT) insertW <- mkRWire;
RWire#(datT) reserveW <- mkRWire;
Vector#(remWidth, RWire#(idxT)) removeW <- replicateM(mkRWire);
PulseWire clearW <- mkPulseWire;
function Bit#(TAdd#(idxTSz,1)) updateWidePointer(Bit#(TAdd#(idxTSz,1)) lIdx, idxT idx);
idxT diff = idx - truncate(lIdx);
return lIdx + zeroExtend(diff);
endfunction
(* no_implicit_conditions *)
rule canon;
Vector#(TExp#(idxTSz),datT) recs = recsRead;
Bit#(TAdd#(idxTSz,1)) nlhead = lhead;
Bit#(TAdd#(idxTSz,1)) nltail = ltail;
if (insertW.wget matches tagged Valid .d) begin
idxT i = truncate(nlhead);
recs[i] = d;
nlhead = nlhead + 1;
end
if (reserveW.wget matches tagged Valid .d) begin
idxT i = truncate(nlhead);
recs[i] = d;
end
for (Integer i = 0; i < valueOf(remWidth); i = i + 1)
if (removeW[i].wget matches tagged Valid .r)
nltail = updateWidePointer(nltail, r);
if (clearW) begin
nlhead = 0;
nltail = 0;
end
lhead <= nlhead;
ltail <= nltail;
writeVReg(records, recs);
endrule
Vector#(remWidth, IndexedMultisetRemoveIfc#(idxT)) removes;
for (Integer i = 0; i < valueOf(remWidth); i = i + 1) begin
removes[i] = interface IndexedMultisetRemoveIfc#(idxT);
method Action remove(idxT idx) = removeW[i].wset(idx);
endinterface;
end
method ActionValue#(idxT) insert(datT d) if (!full);
Bool next = (recsRead[head-1]!=d);
if (next) insertW.wset(d);
return (next) ? head:head-1;
endmethod
// Reserved data values must be the same as the next inserted value or they will be overwritten.
method ActionValue#(IndexedMultisetIndices#(idxT)) insertAndReserve(datT ins, datT res) if (!almostFull);
idxT insIdx = head - 1; // Default, assuming a match.
idxT resIdx = head - 1; // Default, assuming a match.
if (recsRead[head - 1]!=ins) begin
insIdx = head;
insertW.wset(ins); // Increment head.
if (res!=ins) begin
resIdx = head + 1;
reserveW.wset(res); // Increment head again!
end else resIdx = head;
end else if (recsRead[head - 1]!=res) begin
resIdx = head;
reserveW.wset(res);
end
return IndexedMultisetIndices{inserted: insIdx, reserved: resIdx};
endmethod
method datT lookup(idxT i) = recsRead[i];
interface rPort = removes;
method Action clearAll = clearW.send;
endmodule