Merge branch 'ifetch-cleanup' into CHERI
This commit is contained in:
@@ -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
@@ -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});
|
||||
|
||||
@@ -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
|
||||
|
||||
223
src_Core/RISCY_OOO/procs/lib/IndexedMultiset.bsv
Normal file
223
src_Core/RISCY_OOO/procs/lib/IndexedMultiset.bsv
Normal 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
|
||||
Reference in New Issue
Block a user