Merge branch 'CHERI' into pdr32-wip

This commit is contained in:
Peter Rugg
2020-05-11 14:08:42 +01:00
36 changed files with 928 additions and 587 deletions

View File

@@ -126,11 +126,17 @@ Inc. for more information.
----------------------------------------------------------------
## Build Instructions
First clone this repository and then inside the repository initialize the submodules:
$ git clone git@github.com:CTSRD-CHERI/Toooba.git
$ cd Toooba
$ git submodule update --init --recursive
### Dependencies
Build the Bluespec Compiler `bsc` from [this repository](https://github.com/B-Lang-org/bsc)
Build the Bluespec Compiler `bsc` from [this repository](https://github.com/B-Lang-org/bsc). You will also need set the `$BLUESPECDIR` to the `lib` folder of your `bsc` install. By default this is located in `inst/lib` directory inside your bsc repo. Also, make sure to add the `inst/bin` directory to your `$PATH` environment variable.
You need Verilator with version 3.922 or later. You can build any version of Verilator from [this repository](https://github.com/verilator/verilator/releases).
You need Verilator with version 3.922 or later. You can build any version of Verilator from [this repository](https://github.com/verilator/verilator/releases) and follow the build instructions [on the official website](https://www.veripool.org/projects/verilator/wiki/Installing).
$ verilator --version
Verilator 3.922 2018-03-17 rev verilator_3_920-32-gdf3d1a4

View File

@@ -1025,6 +1025,10 @@ module mkCsrFile #(Data hartid)(CsrFile);
default: return 0;
endcase);
end
tagged CapException .ce: begin
cause_code = pack(CHERIFault);
// populate CHERI cause register.
end
tagged Interrupt .i: begin
cause_code = zeroExtend(pack(i));
cause_interrupt = 1;

View File

@@ -53,7 +53,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
Bits#(childT, b__),
FShow#(ToMemMsg#(idT, childT)),
FShow#(MemRsMsg#(idT, childT)),
Add#(SizeOf#(Line), 0, 512)); // assert Line sz = 512
Add#(SizeOf#(Line), 0, TAdd#(512, 4))); // assert Line sz = 512 + 4 tags
// Verbosity: 0: quiet; 1: LLC transactions; 2: loop detail
Integer verbosity = 0;
@@ -141,7 +141,7 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
Reg #(Bit #(3)) rg_rd_rsp_beat <- mkReg (0);
FIFOF #(LdMemRq #(idT, childT)) f_pending_reads <- mkFIFOF;
Reg #(Bit #(512)) rg_cline <- mkRegU;
Reg #(CLine) rg_cline <- mkRegU;
rule rl_handle_read_req (llc.toM.first matches tagged Ld .ld
&&& (ctr_wr_rsps_pending.value == 0));
@@ -180,11 +180,14 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
end
// Shift next 64 bits from fabric into the cache line being assembled
let new_cline = { mem_rsp.rdata, rg_cline [511:64] };
let new_cline_tag = { mem_rsp.ruser, pack(rg_cline.tag) [3:1] };
let new_cline_data = { mem_rsp.rdata, pack(rg_cline.data) [511:64] };
let new_cline = CLine { tag: rg_rd_rsp_beat[0] == 0 ? unpack(new_cline_tag) : rg_cline.tag
, data: unpack(new_cline_data) };
if (rg_rd_rsp_beat == 7) begin
let ldreq <- pop (f_pending_reads);
MemRsMsg #(idT, childT) resp = MemRsMsg {data: unpack (new_cline),
MemRsMsg #(idT, childT) resp = MemRsMsg {data: new_cline,
child: ldreq.child,
id: ldreq.id};
@@ -214,11 +217,11 @@ module mkLLC_AXi4_Adapter #(MemFifoClient #(idT, childT) llc)
end
Addr line_addr = { wb.addr [63:6], 6'h0 }; // Addr of containing cache line
Line line_data = wb.data;
Vector #(8, Bit #(8)) line_bes = unpack (pack (wb.byteEn));
Vector #(8, Bit #(64)) line_data = unpack(pack(wb.data.data));
Addr offset = zeroExtend ( { rg_wr_req_beat, 3'b_000 } ); // Addr offset of 64b word for this beat
Bit #(64) data64 = line_data [rg_wr_req_beat];
Bit #(64) data64 = line_data[rg_wr_req_beat];
Bit #(8) strb8 = line_bes [rg_wr_req_beat];
fa_fabric_send_write_req (line_addr | offset, strb8, data64);

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2018 Massachusetts Institute of Technology
// Portions (c) 2019-2020 Bluespec, Inc.
//
//
// 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
@@ -9,10 +9,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
@@ -171,7 +171,6 @@ function Bit #(64) fn_amo_op (Bit #(2) sz, // encodes data size (.W or
Bit #(64) w1 = fn_extract_and_extend_bytes (sz, addr, ld_val);
Bit #(64) w2 = fn_extract_and_extend_bytes (sz, addr, st_val);
// Do AMO op
Int #(64) i1 = unpack (w1); // Signed, for signed ops
Int #(64) i2 = unpack (w2); // Signed, for signed ops
@@ -257,13 +256,13 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
Reg #(CoreId) reqCore <- mkRegU;
Reg #(MMIOFunc) reqFunc <- mkRegU;
Reg #(AmoFunc) reqAmofunc <- mkRegU;
Reg #(ByteEn) reqBE <- mkRegU;
Reg #(MemDataByteEn) reqBE <- mkRegU;
Reg #(Bit #(2)) reqSz <- mkRegU;
Reg #(Data) reqData <- mkRegU;
Reg #(MemTaggedData) reqData <- mkRegU;
// For inst fetch, we need more bookkeepings
// offset of the requested inst within a Data
Reg#(DataInstOffset) instSel <- mkRegU;
Reg#(MemDataInstOffset) instSel <- mkRegU;
// the current superscaler way being fetched
Reg#(SupWaySel) fetchingWay <- mkRegU;
// the already fetched insts
@@ -280,7 +279,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
// in case of AMO on mtime and mtimecmp, resp may be sent after waiting for
// CRs, we record the AMO resp at processing time
Reg#(Data) amoResp <- mkRegU;
Reg#(MemTaggedData) amoResp <- mkRegU;
// we increment mtime periodically
Reg#(Bit#(TLog#(CyclesPerTimeInc))) cycle <- mkReg(0);
@@ -474,7 +473,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
cores[lower_core].pRq.enq(MMIOPRq {
target: MSIP,
func: reqFunc,
data: truncate(reqData)
data: fromMemTaggedData(reqData)
});
waitLowerMSIPCRs <= Valid (lower_core);
waitUpperMSIPCRs <= Invalid;
@@ -484,7 +483,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
cores[upper_core].pRq.enq(MMIOPRq {
target: MSIP,
func: reqFunc,
data: truncate(reqData)
data: fromMemTaggedData(reqData)
});
waitLowerMSIPCRs <= Valid (upper_core);
waitUpperMSIPCRs <= Invalid;
@@ -507,14 +506,14 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
cores[lower_core].pRq.enq(MMIOPRq {
target: MSIP,
func: reqFunc,
data: zeroExtend(reqData[0])
data: zeroExtend(pack(reqData.data)[0])
});
end
if(upper_en) begin
cores[upper_core].pRq.enq(MMIOPRq {
target: MSIP,
func: reqFunc,
data: zeroExtend(reqData[32])
data: zeroExtend(pack(reqData.data)[32])
});
end
state <= WaitResp;
@@ -542,11 +541,11 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
end
state <= SelectReq;
cores[reqCore].pRs.enq(DataAccess (MMIODataPRs {
valid: True,
// for AMO, resp data should be signExtend(lower_data). However,
// lower_data is just 1 or 0, and upper_data is always 0, so we
// don't need to do signExtend.
data: {upper_data, lower_data}
valid: True,
// for AMO, resp data should be signExtend(lower_data). However,
// lower_data is just 1 or 0, and upper_data is always 0, so we
// don't need to do signExtend.
data: toMemTaggedData({upper_data, lower_data})
}));
if(verbosity > 0) begin
$display("[Platform - msip done] lower %x, upper %x",
@@ -557,21 +556,21 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
function Data getWriteData(Data orig);
if(reqFunc matches tagged Amo .amoFunc) begin
// amo
Bool doubleWord = reqBE[4] && reqBE[0];
Bool upper32 = reqBE[4] && !reqBE[0];
let amoInst = AmoInst {
func: amoFunc,
doubleWord: doubleWord,
width: reqBE[4] && reqBE[0] ? DWord : Word,
aq: False,
rl: False
};
return amoExec(amoInst, orig, reqData, upper32);
let res = amoExec(amoInst, {0, pack(reqBE[4] && !reqBE[0])},
toMemTaggedData(orig), reqData);
return res.data[0];
end
else begin
// normal store
Vector#(NumBytes, Bit#(8)) data = unpack(orig);
Vector#(NumBytes, Bit#(8)) wrVec = unpack(reqData);
for(Integer i = 0; i < valueof(NumBytes); i = i+1) begin
Vector#(DataBytes, Bit#(8)) data = unpack(orig);
Vector#(DataBytes, Bit#(8)) wrVec = fromMemTaggedData(reqData);
for(Integer i = 0; i < valueof(DataBytes); i = i+1) begin
if(reqBE[i]) begin
data[i] = wrVec[i];
end
@@ -621,7 +620,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
if(reqFunc == Ld) begin
cores[reqCore].pRs.enq(DataAccess (MMIODataPRs {
valid: True,
data: oldMTimeCmp
data: toMemTaggedData(oldMTimeCmp)
}));
state <= SelectReq;
if(verbosity > 0) begin
@@ -634,7 +633,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
let newData = getWriteData(oldMTimeCmp);
mtimecmp[offset] <= newData;
// get and record amo resp
let respData = getAmoResp(oldMTimeCmp);
let respData = toMemTaggedData(getAmoResp(oldMTimeCmp));
amoResp <= respData;
// check changes to MTIP
if(newData <= mtime && !mtip[offset]) begin
@@ -707,7 +706,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
end
else if(reqFunc == Ld) begin
cores[reqCore].pRs.enq(DataAccess (MMIODataPRs {
valid: True, data: mtime
valid: True, data: toMemTaggedData(mtime)
}));
state <= SelectReq;
if(verbosity > 0) begin
@@ -720,7 +719,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
let newData = getWriteData(mtime);
mtime <= newData;
// get and record AMO resp
let respData = getAmoResp(mtime);
let respData = toMemTaggedData(getAmoResp(mtime));
amoResp <= respData;
// check change in MTIP
Vector#(CoreNum, Bool) changeMTIP = replicate(False);
@@ -809,7 +808,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
else if(reqFunc == Ld) begin
resp.valid = True;
if(toHostQ.notEmpty) begin
resp.data = toHostQ.first;
resp.data = toMemTaggedData(toHostQ.first);
end
else begin
resp.data = 0;
@@ -860,7 +859,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
else if(reqFunc == Ld) begin
resp.valid = True;
if(fromHostQ.notEmpty) begin
resp.data = fromHostQ.first;
resp.data = toMemTaggedData(fromHostQ.first);
end
else begin
resp.data = 0;
@@ -950,10 +949,12 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
else begin
// Do the AMO op on the loaded value and the store value
let ld_val = dprs.data;
let new_st_val = fn_amo_op (reqSz, reqAmofunc, addr, ld_val, reqData);
let new_st_val = fn_amo_op ( reqSz, reqAmofunc, addr
, fromMemTaggedData(ld_val)
, fromMemTaggedData(reqData));
// Write back new st_val to fabric
let req = MMIOCRq {addr:addr, func:tagged St, byteEn:reqBE, data:new_st_val};
let req = MMIOCRq {addr:addr, func:tagged St, byteEn:reqBE, data:toMemTaggedData(new_st_val)};
mmio_fabric_adapter_core_side.request.put (req);
let prs = tagged DataAccess (MMIODataPRs { valid: True, data: ld_val });
@@ -1020,7 +1021,6 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
else begin
// No access fault
let data = dprs.data;
SupWaySel maxWay = 0;
if(reqFunc matches tagged Inst .w) begin
@@ -1028,7 +1028,7 @@ module mkMMIOPlatform #(Vector#(CoreNum, MMIOCoreToPlatform) cores,
end
// View Data as a vector of instructions
Vector#(DataSzInst, Instruction) instVec = unpack(data);
Vector#(MemDataSzInst, Instruction) instVec = fromMemTaggedData(dprs.data);
// extract inst from resp data
Instruction inst = instVec[instSel];
// check whether we are done or not

View File

@@ -32,6 +32,7 @@ import CreditCounter :: *;
// ----------------
// From MIT RISCY-OOO
import Types :: *;
import ProcTypes :: *;
// ----------------
@@ -68,6 +69,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
FIFOF #(MMIOCRq) f_reqs_from_core <- mkFIFOF;
FIFOF #(MMIODataPRs) f_rsps_to_core <- mkFIFOF;
Reg#(Fabric_Addr) read_req_addr <- mkRegU;
SoC_Map_IFC soc_map <- mkSoC_Map; // for m_is_IO_addr
@@ -99,6 +101,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
aruser: fabric_default_aruser};
master_xactor.slave.ar.put(mem_req_rd_addr);
read_req_addr <= addr;
// Debugging
if (cfg_verbosity > 0) begin
@@ -180,7 +183,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
fa_fabric_send_read_req (req.addr);
else begin
let rsp = MMIODataPRs {valid: False,
data: req.addr}; // For debugging convenience only
data: toMemTaggedData(req.addr)}; // For debugging convenience only
f_rsps_to_core.enq (rsp);
if (cfg_verbosity > 0) begin
$display ("%0d: %m.rl_handle_read_req: unmapped IO address; returning error response",
@@ -194,6 +197,7 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
rule rl_handle_read_rsps;
let mem_rsp <- get(master_xactor.slave.r);
dynamicAssert(mem_rsp.rlast, "TODO, implement multi-flit transactions");
if (cfg_verbosity > 0) begin
$display ("%0d: %m.rl_handle_read_rsps ", cur_cycle);
@@ -205,8 +209,10 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
$display (" ", fshow (mem_rsp));
end
let newData = MemTaggedData { tag: False
, data: unpack(zeroExtend(mem_rsp.rdata) << ((read_req_addr[3] == 1) ? 64 : 0))};
let rsp = MMIODataPRs {valid: (mem_rsp.rresp == OKAY),
data: mem_rsp.rdata};
data: newData };
f_rsps_to_core.enq (rsp);
if (cfg_verbosity > 0)
@@ -227,11 +233,12 @@ module mkMMIO_AXI4_Adapter (MMIO_AXI4_Adapter_IFC);
// Technically the following check for legal IO addrs is not
// necessary; the AXI4 fabric should return a DECERR for illegal
// addrs; but not all AXI4 fabrics do the right thing.
dynamicAssert(pack(req.byteEn)[15:8] == 0, "TODO, handle multiflit transactions");
if (soc_map.m_is_IO_addr (req.addr))
fa_fabric_send_write_req (req.addr, pack (req.byteEn), req.data);
fa_fabric_send_write_req (req.addr, truncate(pack(req.byteEn)), fromMemTaggedData(req.data));
else begin
let rsp = MMIODataPRs {valid: False,
data: req.addr}; // For debugging convenience only
data: toMemTaggedData(req.addr)}; // For debugging convenience only
f_rsps_to_core.enq (rsp);
if (cfg_verbosity > 0) begin
$display ("%0d: %m.rl_handle_write_req: unmapped IO address; returning error response",

View File

@@ -65,7 +65,7 @@ typedef enum {
typedef struct {
Bit #(6) cheri_exc_reg;
CHERIException cheri_exc_code;
} CSR_XCapCause deriving(Bits, FShow);
} CSR_XCapCause deriving(Bits, Eq, FShow);
CSR_XCapCause noCapCause = CSR_XCapCause {cheri_exc_code: None,
cheri_exc_reg: unpack(0)};

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -32,9 +32,9 @@ import GetPut::*;
import ClientServer::*;
typedef enum {
I = 2'd0,
S = 2'd1,
E = 2'd2,
I = 2'd0,
S = 2'd1,
E = 2'd2,
M = 2'd3
} MESI deriving(Bits, Eq, FShow);
typedef MESI Msi;
@@ -79,54 +79,59 @@ typedef TDiv#(DataSz, 8) DataSzBytes;
typedef TLog#(DataSzBytes) LgDataSzBytes;
typedef Bit#(LgDataSzBytes) DataBytesOffset;
typedef TDiv#(MemDataSz, 8) MemDataSzBytes;
typedef TLog#(MemDataSzBytes) LgMemDataSzBytes;
typedef Bit#(LgMemDataSzBytes) MemDataBytesOffset;
typedef TDiv#(InstSz, 8) InstSzBytes;
typedef TLog#(InstSzBytes) LgInstSzBytes;
// 64B cache line -- XXX same with parameters in CacheUtils.bsv
typedef CacheUtils::LogCLineNumData LgLineSzData;
typedef CacheUtils::LogCLineNumBytes LgLineSzBytes;
typedef CacheUtils::LogCLineNumMemTaggedData LgLineSzData;
typedef CacheUtils::LogCLineNumMemDataBytes LgLineSzBytes;
typedef CacheUtils::CLineAddrSz LineAddrSz;
typedef CacheUtils::CLineAddr LineAddr;
typedef CacheUtils::CLineNumData LineSzData;
typedef CacheUtils::CLine Line;
typedef CacheUtils::CLineDataSel LineDataOffset;
typedef CacheUtils::CLineMemTaggedDataSel LineMemDataOffset;
typedef CacheUtils::CLineNumBytes LineSzBytes;
typedef CacheUtils::CLineByteEn LineByteEn;
typedef CacheUtils::CLineDataNumBytes LineSzBytes;
typedef CacheUtils::CLineMemDataByteEn LineByteEn;
typedef CacheUtils::CLineDataByteEn LineDataByteEn;
typedef TDiv#(LineSzBytes, InstSzBytes) LineSzInst;
typedef Bit#(TLog#(LineSzInst)) LineInstOffset;
typedef Vector#(LineSzData, Data) Line;
function LineAddr getLineAddr(Addr addr) = truncateLSB(addr);
function LineDataOffset getLineDataOffset(Addr a);
return truncate(a >> valueOf(LgDataSzBytes));
endfunction
function LineMemDataOffset getLineMemDataOffset(Addr a);
return truncate(a >> valueOf(LgMemDataSzBytes));
endfunction
function LineInstOffset getLineInstOffset(Addr a);
return truncate(a >> valueof(LgInstSzBytes));
endfunction
function Line getUpdatedLine(Line curLine, LineByteEn wrBE, Line wrLine);
Vector#(LineSzBytes, Bit#(8)) curVec = unpack(pack(curLine));
Vector#(LineSzBytes, Bit#(8)) wrVec = unpack(pack(wrLine));
function Bit#(8) getNewByte(Integer i);
return wrBE[i] ? wrVec[i] : curVec[i];
// handle data merge
Vector#(LineSzBytes, Bit#(8)) newDataVec = mergeDataBE(curLine.data, wrLine.data, wrBE);
// handle tag merge
Vector#(CLineNumMemTaggedData, MemTag) curTagVec = curLine.tag;
Vector#(CLineNumMemTaggedData, MemTag) wrTagVec = wrLine.tag;
function MemTag getNewTag(Integer i);
let res = curTagVec[i];
if (pack(wrBE[i]) == ~0) res = wrTagVec[i];
return res;
endfunction
Vector#(LineSzBytes, Bit#(8)) newVec = map(getNewByte, genVector);
return unpack(pack(newVec));
endfunction
function Data getUpdatedData(Data curData, ByteEn wrBE, Data wrData);
Vector#(DataSzBytes, Bit#(8)) curVec = unpack(pack(curData));
Vector#(DataSzBytes, Bit#(8)) wrVec = unpack(pack(wrData));
function Bit#(8) getNewByte(Integer i);
return wrBE[i] ? wrVec[i] : curVec[i];
endfunction
Vector#(DataSzBytes, Bit#(8)) newVec = map(getNewByte, genVector);
return pack(newVec);
Vector#(CLineNumMemTaggedData, MemTag) newTagVec = genWith(getNewTag);
// compose updated line
return CLine { tag: newTagVec
, data: unpack(pack(newDataVec)) };
endfunction
// calculate tag
@@ -191,8 +196,8 @@ typedef struct {
Msi toState;
// below are detailed mem op
MemOp op; // Ld, St, Lr, Sc, Amo
ByteEn byteEn; // valid when op == Sc
Data data; // valid when op == Sc/Amo
MemDataByteEn byteEn; // valid when op == Sc
MemTaggedData data; // valid when op == Sc/Amo
AmoInst amoInst; // valid when op == Amo
} ProcRq#(type idT) deriving(Bits, Eq, FShow);
@@ -201,8 +206,8 @@ interface L1ProcReq#(type idT);
endinterface
interface L1ProcResp#(type idT);
method Action respLd(idT id, Data resp);
method Action respLrScAmo(idT id, Data resp);
method Action respLd(idT id, MemTaggedData resp);
method Action respLrScAmo(idT id, MemTaggedData resp);
method ActionValue#(Tuple2#(LineByteEn, Line)) respSt(idT id);
method Action evict(LineAddr a); // called when cache line is evicted
endinterface
@@ -371,7 +376,7 @@ endinterface
instance Connectable#(MemFifoServer#(idT, childT), MemFifoClient#(idT, childT));
module mkConnection#(
MemFifoServer#(idT, childT) server,
MemFifoServer#(idT, childT) server,
MemFifoClient#(idT, childT) client
)(Empty);
rule doCToM;

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -392,7 +391,7 @@ module mkIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line));
Vector#(LineSzInst, Instruction) 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

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -189,7 +188,7 @@ module mkL1Bank#(
Count#(Data) ldMissLat <- mkCount(0);
Count#(Data) stMissLat <- mkCount(0);
Count#(Data) amoMissLat <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrReqCnt(MemOp op);
@@ -244,8 +243,8 @@ module mkL1Bank#(
mshrIdx: n
}));
if (verbose)
$display("%t L1 %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t L1 %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -258,7 +257,7 @@ module mkL1Bank#(
cRqIdxT n <- cRqMshr.cRqTransfer.getEmptyEntryInit(r);
// send to pipeline
pipeline.send(CRq (L1PipeRqIn {
addr: r.addr,
addr: r.addr,
mshrIdx: n
}));
`ifdef PERF_COUNT
@@ -266,7 +265,7 @@ module mkL1Bank#(
incrReqCnt(r.op);
`endif
if (verbose)
$display("%t L1 %m cRqTransfer_new: ", $time,
$display("%t L1 %m cRqTransfer_new: ", $time,
fshow(n), " ; ",
fshow(r)
);
@@ -282,8 +281,8 @@ module mkL1Bank#(
mshrIdx: n
}));
if (verbose)
$display("%t L1 %m pRqTransfer: ", $time,
fshow(n), " ; ",
$display("%t L1 %m pRqTransfer: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -348,8 +347,8 @@ module mkL1Bank#(
cRqSlotT slot = cRqMshr.sendRsToP_cRq.getSlot(n);
Maybe#(Line) data = cRqMshr.sendRsToP_cRq.getData(n);
L1CRqState state = cRqMshr.sendRsToP_cRq.getState(n);
doAssert(state == WaitNewTag,
"send replacement resp to parent, state should be WaitNewTag"
doAssert(state == WaitNewTag,
"send replacement resp to parent, state should be WaitNewTag"
);
// send resp to parent
cRsToPT resp = CRsMsg {
@@ -370,9 +369,9 @@ module mkL1Bank#(
// inform processor of line eviction
procResp.evict(getLineAddr(resp.addr));
if (verbose)
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
fshow(req), " ; ",
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first)," ; ",
fshow(req), " ; ",
fshow(resp)
);
endrule
@@ -393,9 +392,9 @@ module mkL1Bank#(
// inform processor of line eviction
procResp.evict(getLineAddr(resp.addr));
if (verbose)
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
$display("%t L1 %m sendRsToP: ", $time,
fshow(rsToPIndexQ.first), " ; ",
fshow(req), " ; ",
fshow(resp)
);
endrule
@@ -415,10 +414,10 @@ module mkL1Bank#(
};
rqToPQ.enq(cRqToP);
if (verbose)
$display("%t L1 %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
$display("%t L1 %m sendRqToP: ", $time,
fshow(n), " ; ",
fshow(req), " ; ",
fshow(slot), " ; ",
fshow(cRqToP)
);
`ifdef PERF_COUNT
@@ -466,13 +465,13 @@ module mkL1Bank#(
// TODO when we have MESI, cache state may also need update
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
case(req.op) matches
Ld: begin
procResp.respLd(req.id, curLine[dataSel]);
procResp.respLd(req.id, getTaggedDataAt(curLine, dataSel));
end
Lr: begin
procResp.respLrScAmo(req.id, curLine[dataSel]);
procResp.respLrScAmo(req.id, getTaggedDataAt(curLine, dataSel));
// set link addr
linkAddr <= Valid (getLineAddr(req.addr));
end
@@ -483,11 +482,14 @@ module mkL1Bank#(
// check Sc succeeds or not
Bool succeed = linkAddr == Valid (getLineAddr(req.addr));
// resp to proc
Data respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
MemTaggedData respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
procResp.respLrScAmo(req.id, respVal);
// calculate new data to write
if(succeed) begin
newLine[dataSel] = getUpdatedData(curLine[dataSel], req.byteEn, req.data);
let taggedData = getTaggedDataAt(curLine, dataSel);
let newTaggedData =
mergeMemTaggedDataBE(taggedData, req.data, zeroExtend(pack(req.byteEn)));
newLine = setTaggedDataAt( newLine, dataSel, newTaggedData);
end
// reset link addr
linkAddr <= Invalid;
@@ -548,16 +550,28 @@ module mkL1Bank#(
// get line and sel
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
Bool upper32 = req.addr[2] == 1;
Data curData = curLine[dataSel];
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
MemTaggedData current = getTaggedDataAt(curLine, dataSel);
Vector#(2, Bit#(64)) dwordData = current.data;
Vector#(4, Bit#(32)) wordData = unpack(pack(current.data));
Bit#(1) dwordIdx = req.addr[3];
Bit#(2) wordIdx = req.addr[3:2];
// resp processor
Data resp = req.amoInst.doubleWord ? curData : signExtend(
upper32 ? curData[63:32] : curData[31:0]
);
MemTaggedData resp = case (req.amoInst.width)
QWord: current;
DWord: MemTaggedData {
tag: False,
data: unpack(signExtend(dwordData[dwordIdx]))
};
Word: MemTaggedData {
tag: False,
data: unpack(signExtend(wordData[wordIdx]))
};
endcase;
procResp.respLrScAmo(req.id, resp);
// calculate new data to write
newLine[dataSel] = amoExec(req.amoInst, curData, req.data, upper32);
let newData = amoExec(req.amoInst, wordIdx, current, req.data);
newLine = setTaggedDataAt(newLine, dataSel, newData);
// deq pipeline or swap in successor
pipeline.deqWrite(succ, RamData {
info: CacheInfo {
@@ -588,7 +602,7 @@ module mkL1Bank#(
procRqT procRq = pipeOutCRq;
if (verbose)
$display("%t L1 %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(procRq));
// find end of dependency chain
Maybe#(cRqIdxT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(procRq.addr);
@@ -634,10 +648,10 @@ module mkL1Bank#(
// because cRq is not set to Depend when pRq invalidates it (pRq just directly resp)
// and this func is only called when cs < toState (otherwise will hit)
// because L1 has no children to wait for
doAssert(!cSlot.waitP && !enoughCacheState(ram.info.cs, procRq.toState),
doAssert(!cSlot.waitP && !enoughCacheState(ram.info.cs, procRq.toState),
"waitP must be false and cs must not be enough"
);
// 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
@@ -692,7 +706,7 @@ module mkL1Bank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1024,7 +1038,7 @@ module mkL1Bank#(
};
endmethod
endinterface
interface pRqStuck = pRqMshr.stuck;
`ifdef SECURITY
@@ -1043,7 +1057,7 @@ module mkL1Bank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(L1DPerfType t);
return (case(t)

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -47,7 +46,7 @@ export mkLLBank;
// this also ensures that cache pipeline is never blocked
// so we do not need to buffer mem resp that needs to refill cache
// XXX we need to maintain the invariant that
// XXX we need to maintain the invariant that
// at most 1 pRq sent to a child for an addr
// and we have to wait for resp before sending anthoer one
@@ -220,7 +219,7 @@ module mkLLBank#(
Count#(Data) upRespDataCnt <- mkCount(0);
Count#(Data) dmaLdReqCnt <- mkCount(0);
Count#(Data) dmaStReqCnt <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
@@ -303,8 +302,8 @@ module mkLLBank#(
mshrIdx: n
}));
if (verbose)
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -355,15 +354,15 @@ module mkLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, Invalid);
// send to pipeline
pipeline.send(CRq (LLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
if (verbose)
$display("%t LL %m cRqTransfer_new_child: ", $time,
$display("%t LL %m cRqTransfer_new_child: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
endrule
@@ -393,7 +392,7 @@ module mkLLBank#(
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
rqFromDmaQ.deq;
dmaRqT r = rqFromDmaQ.first;
Bool write = r.byteEn != replicate(False);
Bool write = r.byteEn != replicate(replicate(False));
cRqT cRq = LLRq {
addr: r.addr,
fromState: I,
@@ -407,15 +406,15 @@ module mkLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, write ? Valid (r.data) : Invalid);
// send to pipeline
pipeline.send(CRq (LLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
if (verbose)
$display("%t LL %m cRqTransfer_new_dma: ", $time,
$display("%t LL %m cRqTransfer_new_dma: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
`ifdef PERF_COUNT
@@ -468,7 +467,7 @@ module mkLLBank#(
end
`endif
endrule
// mem resp for child req, will refill cache, send it to pipeline
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
`ifdef PERF_COUNT
@@ -534,7 +533,7 @@ module mkLLBank#(
cRqSlotT cSlot = cRqMshr.sendToM.getSlot(n);
Maybe#(Line) data = cRqMshr.sendToM.getData(n);
if (verbose)
$display("%t LL %m sendToM: ", $time,
$display("%t LL %m sendToM: ", $time,
fshow(toMInfoQ.first), " ; ",
fshow(cRq), " ; ",
fshow(cSlot), " ; ",
@@ -614,7 +613,7 @@ module mkLLBank#(
else begin // do write back part
toMemT msg = Wb (WbMemRs {
addr: {cSlot.repTag, truncate(cRq.addr)},
byteEn: replicate(True),
byteEn: replicate(replicate(True)),
data: validValue(data)
});
toMQ.enq(msg);
@@ -646,7 +645,7 @@ module mkLLBank#(
doAssert(isValid(data), "dma read req always has valid data");
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn == replicate(False) && cRq.toState == S,
doAssert(cRq.byteEn == replicate(replicate(False)) && cRq.toState == S,
"cRq should be DMA read"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -669,7 +668,7 @@ module mkLLBank#(
);
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn != replicate(False) && cRq.toState == M,
doAssert(cRq.byteEn != replicate(replicate(False)) && cRq.toState == M,
"cRq should be DMA write"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -687,9 +686,9 @@ module mkLLBank#(
cRqT cRq = cRqMshr.sendRsToDmaC.getRq(n);
Maybe#(Line) rsData = cRqMshr.sendRsToDmaC.getData(n);
if (verbose)
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
fshow(rsData), " ; ",
fshow(toState)
);
@@ -719,7 +718,7 @@ module mkLLBank#(
// round robin select cRq to downgrade child
// but downgrade must wait for all upgrade resp
Reg#(cRqIndexT) whichCRq <- mkReg(0);
// we don't perform sending downgrade to child for a cRq processing by pipelineResp_cRs
// otherwise atomicity issue may arise
// for safety, we check cRq processed by all pipelineResp_xxx rules
@@ -757,7 +756,7 @@ module mkLLBank#(
cRqT cRq = cRqMshr.sendRqToC.getRq(n);
cRqSlotT cSlot = cRqMshr.sendRqToC.getSlot(n);
LLCRqState cState = cRqMshr.sendRqToC.getState(n);
doAssert(cState == WaitSt || cState == WaitOldTag,
doAssert(cState == WaitSt || cState == WaitOldTag,
"only WaitSt and WaitOldTag needs req child"
);
// find a child to downgrade
@@ -828,7 +827,7 @@ module mkLLBank#(
function Action cRqFromCHit(cRqIndexT n, cRqT cRq, Bool isMRs);
action
if (verbose)
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -836,7 +835,7 @@ module mkLLBank#(
doAssert(isRqFromC(cRq.id), "should be cRq from child");
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
// this function is called by mRs, cRq, cRs
// tag should match even for mRs, because
// tag should match even for mRs, because
// tag has been written into cache before sending req to parent
("cRqHit but tag or cs incorrect")
);
@@ -886,7 +885,7 @@ module mkLLBank#(
function Action cRqFromDmaHit(cRqIndexT n, cRqT cRq);
action
if (verbose)
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -895,7 +894,7 @@ module mkLLBank#(
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
"cRqHit but tag or cs incorrect"
);
doAssert((cRq.byteEn != replicate(False)) == (cRq.toState == M), "toState should match byteEn");
doAssert((cRq.byteEn != replicate(replicate(False))) == (cRq.toState == M), "toState should match byteEn");
// update cs (may have E -> M)
Msi newCs = ram.info.cs;
if(cRq.toState == M) begin
@@ -903,7 +902,7 @@ module mkLLBank#(
end
// update cache line
Maybe#(Line) wrData = cRqMshr.pipelineResp.getData(n);
doAssert(isValid(wrData) == (cRq.byteEn != replicate(False)),
doAssert(isValid(wrData) == (cRq.byteEn != replicate(replicate(False))),
"dma write should carry valid data"
);
Line newLine = getUpdatedLine(ram.line, cRq.byteEn, validValue(wrData));
@@ -999,7 +998,7 @@ module mkLLBank#(
cRqT cRq = pipeOutCRq;
if (verbose)
$display("%t LL %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(cRq));
// find end of dependency chain
Maybe#(cRqIndexT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(cRq.addr);
@@ -1141,7 +1140,7 @@ module mkLLBank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1156,7 +1155,7 @@ module mkLLBank#(
LLCRqState cState = pipeOutCState;
doAssert(cState == Init, "owner is other, must first time go through tag match");
// tag match must be hit (because replacement algo won't give a way with owner)
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
("cRq should hit in tag match")
);
// could be two cases:
@@ -1239,7 +1238,7 @@ module mkLLBank#(
if(cRqEOC matches tagged Valid .m &&& cState == Init) begin
if (verbose)
$display("%t LL %m pipelineResp: cRq: no owner, depend on cRq ", $time,
fshow(cState), " ; ",
fshow(cState), " ; ",
fshow(cRqEOC)
);
cRqMshr.pipelineResp.setAddrSucc(m, Valid (n));
@@ -1497,7 +1496,7 @@ module mkLLBank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(LLCPerfType t);
return (case(t)

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -281,7 +280,7 @@ module mkSelfInvIBank#(
// function to get superscaler inst read result
function resultT readInst(Line line, Addr addr);
Vector#(LineSzInst, Instruction) instVec = unpack(pack(line));
Vector#(LineSzInst, Instruction) 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

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -453,13 +452,13 @@ module mkSelfInvL1Bank#(
// The silent E->M update is already done in pipeline
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
case(req.op) matches
Ld: begin
procResp.respLd(req.id, curLine[dataSel]);
procResp.respLd(req.id, getTaggedDataAt(curLine, dataSel));
end
Lr: begin
procResp.respLrScAmo(req.id, curLine[dataSel]);
procResp.respLrScAmo(req.id, getTaggedDataAt(curLine, dataSel));
// set link addr
linkAddr <= Valid (getLineAddr(req.addr));
end
@@ -470,11 +469,14 @@ module mkSelfInvL1Bank#(
// check Sc succeeds or not
Bool succeed = linkAddr == Valid (getLineAddr(req.addr));
// resp to proc
Data respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
MemTaggedData respVal = succeed ? fromInteger(valueof(ScSuccVal)) : fromInteger(valueof(ScFailVal));
procResp.respLrScAmo(req.id, respVal);
// calculate new data to write
if(succeed) begin
newLine[dataSel] = getUpdatedData(curLine[dataSel], req.byteEn, req.data);
let taggedData = getTaggedDataAt(curLine, dataSel);
let newTaggedData =
mergeMemTaggedDataBE(taggedData, req.data, zeroExtend(pack(req.byteEn)));
newLine = setTaggedDataAt( newLine, dataSel, newTaggedData);
end
// reset link addr
linkAddr <= Invalid;
@@ -559,16 +561,28 @@ module mkSelfInvL1Bank#(
// get line and sel
Line curLine = ram.line;
Line newLine = curLine;
LineDataOffset dataSel = getLineDataOffset(req.addr);
Bool upper32 = req.addr[2] == 1;
Data curData = curLine[dataSel];
LineMemDataOffset dataSel = getLineMemDataOffset(req.addr);
MemTaggedData current = getTaggedDataAt(curLine, dataSel);
Vector#(2, Bit#(64)) dwordData = current.data;
Vector#(4, Bit#(32)) wordData = unpack(pack(current.data));
Bit#(1) dwordIdx = req.addr[3];
Bit#(2) wordIdx = req.addr[3:2];
// resp processor
Data resp = req.amoInst.doubleWord ? curData : signExtend(
upper32 ? curData[63:32] : curData[31:0]
);
MemTaggedData resp = case (req.amoInst.width)
QWord: current;
DWord: MemTaggedData {
tag: False,
data: unpack(signExtend(dwordData[dwordIdx]))
};
Word: MemTaggedData {
tag: False,
data: unpack(signExtend(wordData[wordIdx]))
};
endcase;
procResp.respLrScAmo(req.id, resp);
// calculate new data to write
newLine[dataSel] = amoExec(req.amoInst, curData, req.data, upper32);
let newData = amoExec(req.amoInst, wordIdx, current, req.data);
newLine = setTaggedDataAt(newLine, dataSel, newData);
// deq pipeline or swap in successor
// Since AMO always hits in M, hit count is 0 and never self inv
pipeline.deqWrite(succ, RamData {

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -42,7 +41,7 @@ import RandomReplace::*;
// this also ensures that cache pipeline is never blocked
// so we do not need to buffer mem resp that needs to refill cache
// XXX we need to maintain the invariant that
// XXX we need to maintain the invariant that
// at most 1 pRq sent to a child for an addr
// and we have to wait for resp before sending anthoer one
@@ -213,7 +212,7 @@ module mkSelfInvLLBank#(
Count#(Data) upRespDataCnt <- mkCount(0);
Count#(Data) dmaLdReqCnt <- mkCount(0);
Count#(Data) dmaStReqCnt <- mkCount(0);
LatencyTimer#(cRqNum, 10) latTimer <- mkLatencyTimer; // max 1K cycle latency
function Action incrMissCnt(cRqIndexT idx, Bool isDma);
@@ -295,8 +294,8 @@ module mkSelfInvLLBank#(
addr: req.addr,
mshrIdx: n
}));
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
$display("%t LL %m cRqTransfer_retry: ", $time,
fshow(n), " ; ",
fshow(req)
);
endrule
@@ -347,14 +346,14 @@ module mkSelfInvLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, Invalid);
// send to pipeline
pipeline.send(CRq (SelfInvLLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
$display("%t LL %m cRqTransfer_new_child: ", $time,
$display("%t LL %m cRqTransfer_new_child: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
endrule
@@ -384,7 +383,7 @@ module mkSelfInvLLBank#(
rule cRqTransfer_new_dma(!cRqRetryIndexQ.notEmpty && newCRqSrc == Valid (Dma));
rqFromDmaQ.deq;
dmaRqT r = rqFromDmaQ.first;
Bool write = r.byteEn != replicate(False);
Bool write = r.byteEn != replicate(replicate(False));
cRqT cRq = LLRq {
addr: r.addr,
fromState: I,
@@ -398,14 +397,14 @@ module mkSelfInvLLBank#(
cRqIndexT n <- cRqMshr.transfer.getEmptyEntryInit(cRq, write ? Valid (r.data) : Invalid);
// send to pipeline
pipeline.send(CRq (SelfInvLLPipeCRqIn {
addr: cRq.addr,
addr: cRq.addr,
mshrIdx: n
}));
// change round robin
flipPriorNewCRqSrc;
$display("%t LL %m cRqTransfer_new_dma: ", $time,
$display("%t LL %m cRqTransfer_new_dma: ", $time,
fshow(n), " ; ",
fshow(r), " ; ",
fshow(r), " ; ",
fshow(cRq)
);
`ifdef PERF_COUNT
@@ -457,7 +456,7 @@ module mkSelfInvLLBank#(
end
`endif
endrule
// mem resp for child req, will refill cache, send it to pipeline
(* descending_urgency = "mRsTransfer, cRsTransfer, cRqTransfer_retry, cRqTransfer_new_child, cRqTransfer_new_dma" *)
`ifdef PERF_COUNT
@@ -520,7 +519,7 @@ module mkSelfInvLLBank#(
cRqT cRq = cRqMshr.sendToM.getRq(n);
cRqSlotT cSlot = cRqMshr.sendToM.getSlot(n);
Maybe#(Line) data = cRqMshr.sendToM.getData(n);
$display("%t LL %m sendToM: ", $time,
$display("%t LL %m sendToM: ", $time,
fshow(toMInfoQ.first), " ; ",
fshow(cRq), " ; ",
fshow(cSlot), " ; ",
@@ -597,7 +596,7 @@ module mkSelfInvLLBank#(
else begin // do write back part
toMemT msg = Wb (WbMemRs {
addr: {cSlot.repTag, truncate(cRq.addr)},
byteEn: replicate(True),
byteEn: replicate(replicate(True)),
data: validValue(data)
});
toMQ.enq(msg);
@@ -627,7 +626,7 @@ module mkSelfInvLLBank#(
doAssert(isValid(data), "dma read req always has valid data");
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn == replicate(False) && cRq.toState == S,
doAssert(cRq.byteEn == replicate(replicate(False)) && cRq.toState == S,
"cRq should be DMA read"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -649,7 +648,7 @@ module mkSelfInvLLBank#(
);
// send DMA resp
doAssert(isRqFromDma(cRq.id), "cRq should be DMA req");
doAssert(cRq.byteEn != replicate(False) && cRq.toState == M,
doAssert(cRq.byteEn != replicate(replicate(False)) && cRq.toState == M,
"cRq should be DMA write"
);
dmaRqIdT dmaId = getIdFromDma(cRq.id);
@@ -666,9 +665,9 @@ module mkSelfInvLLBank#(
Msi toState = rsToCIndexQ.first.toState;
cRqT cRq = cRqMshr.sendRsToDmaC.getRq(n);
Maybe#(Line) rsData = cRqMshr.sendRsToDmaC.getData(n);
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
$display("%t LL %m sendRsToC: ", $time,
fshow(n), " ; ",
fshow(cRq), " ; ",
fshow(rsData), " ; ",
fshow(toState)
);
@@ -698,7 +697,7 @@ module mkSelfInvLLBank#(
// round robin select cRq to downgrade child
// but downgrade must wait for all upgrade resp
Reg#(cRqIndexT) whichCRq <- mkReg(0);
// we don't perform sending downgrade to child for a cRq processing by pipelineResp_cRs
// otherwise atomicity issue may arise
// for safety, we check cRq processed by all pipelineResp_xxx rules
@@ -736,7 +735,7 @@ module mkSelfInvLLBank#(
cRqT cRq = cRqMshr.sendRqToC.getRq(n);
cRqSlotT cSlot = cRqMshr.sendRqToC.getSlot(n);
LLCRqState cState = cRqMshr.sendRqToC.getState(n);
doAssert(cState == WaitSt || cState == WaitOldTag,
doAssert(cState == WaitSt || cState == WaitOldTag,
"only WaitSt and WaitOldTag needs req child"
);
// find the child to downgrade
@@ -797,7 +796,7 @@ module mkSelfInvLLBank#(
// function to process cRq hit (MSHR slot may have garbage)
function Action cRqFromCHit(cRqIndexT n, cRqT cRq);
action
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from child Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -805,7 +804,7 @@ module mkSelfInvLLBank#(
doAssert(isRqFromC(cRq.id), "should be cRq from child");
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
// this function is called by mRs, cRq, cRs
// tag should match even for mRs, because
// tag should match even for mRs, because
// tag has been written into cache before sending req to parent
("cRqHit but tag or cs incorrect")
);
@@ -858,7 +857,7 @@ module mkSelfInvLLBank#(
// function to process DMA req hit (MSHR slot may have garbage)
function Action cRqFromDmaHit(cRqIndexT n, cRqT cRq);
action
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
$display("%t LL %m pipelineResp: cRq from dma Hit func: ", $time,
fshow(n), " ; ",
fshow(cRq)
);
@@ -867,7 +866,7 @@ module mkSelfInvLLBank#(
doAssert(ram.info.tag == getTag(cRq.addr) && ram.info.cs > I,
"cRqHit but tag or cs incorrect"
);
doAssert((cRq.byteEn != replicate(False)) == (cRq.toState == M), "toState should match byteEn");
doAssert((cRq.byteEn != replicate(replicate(False))) == (cRq.toState == M), "toState should match byteEn");
// update cs (may have E -> M)
Msi newCs = ram.info.cs;
if(cRq.toState == M) begin
@@ -875,7 +874,7 @@ module mkSelfInvLLBank#(
end
// update cache line
Maybe#(Line) wrData = cRqMshr.pipelineResp.getData(n);
doAssert(isValid(wrData) == (cRq.byteEn != replicate(False)),
doAssert(isValid(wrData) == (cRq.byteEn != replicate(replicate(False))),
"dma write should carry valid data"
);
Line newLine = getUpdatedLine(ram.line, cRq.byteEn, validValue(wrData));
@@ -969,7 +968,7 @@ module mkSelfInvLLBank#(
cRqT cRq = pipeOutCRq;
$display("%t LL %m pipelineResp: cRq: ", $time, fshow(n), " ; ", fshow(cRq));
// find end of dependency chain
Maybe#(cRqIndexT) cRqEOC = cRqMshr.pipelineResp.searchEndOfChain(cRq.addr);
@@ -1112,7 +1111,7 @@ module mkSelfInvLLBank#(
end
endaction
endfunction
// function to set cRq to Depend, and make no further change to cache
function Action cRqSetDepNoCacheChange;
action
@@ -1127,7 +1126,7 @@ module mkSelfInvLLBank#(
LLCRqState cState = pipeOutCState;
doAssert(cState == Init, "owner is other, must first time go through tag match");
// tag match must be hit (because replacement algo won't give a way with owner)
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
doAssert(ram.info.cs > I && ram.info.tag == getTag(cRq.addr),
("cRq should hit in tag match")
);
// could be two cases:
@@ -1203,7 +1202,7 @@ module mkSelfInvLLBank#(
// only check for cRqEOC to append to dependency chain when firt time go through tag match
if(cRqEOC matches tagged Valid .m &&& cState == Init) begin
$display("%t LL %m pipelineResp: cRq: no owner, depend on cRq ", $time,
fshow(cState), " ; ",
fshow(cState), " ; ",
fshow(cRqEOC)
);
cRqMshr.pipelineResp.setAddrSucc(m, Valid (n));
@@ -1408,7 +1407,7 @@ module mkSelfInvLLBank#(
`else
noAction;
`endif
endmethod
endmethod
method Data getPerfData(LLCPerfType t);
return (case(t)

View File

@@ -192,7 +192,7 @@ endinterface
module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline);
Bool verbose = False;
Integer verbosity = 1;
Integer verbosity = 0;
// alu reservation station
ReservationStationAlu rsAlu <- mkReservationStationAlu;

View File

@@ -204,6 +204,7 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot,
tagged CSRData .csrdata: data = csrdata;
endcase
end
CapPipe pipePc = cast(rot.pc);
return tagged Valid RVFI_DII_Execution {
rvfi_order: zeroExtend(pack(traceCnt)),
rvfi_trap: isValid(rot.trap),
@@ -214,7 +215,7 @@ function Maybe#(RVFI_DII_Execution#(DataSz,DataSz)) genRVFI(ToReorderBuffer rot,
rvfi_rs2_addr: rot.orig_inst[24:20],
rvfi_rs1_data: ?,
rvfi_rs2_data: ?,
rvfi_pc_rdata: getAddr(rot.pc),
rvfi_pc_rdata: getOffset(pipePc),
rvfi_pc_wdata: next_pc,
rvfi_mem_wdata: wdata,
rvfi_rd_addr: rd,
@@ -238,7 +239,7 @@ deriving (Eq, FShow, Bits);
`endif
module mkCommitStage#(CommitInput inIfc)(CommitStage);
Bool verbose = True;
Bool verbose = False;
Integer verbosity = 2; // Bluespec: for lightweight verbosity trace
@@ -622,15 +623,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// record trap info
Addr vaddr = ?;
if ( (trap.trap == tagged Exception InstAccessFault)
|| (trap.trap == tagged Exception InstPageFault)) begin
if ( (trap == tagged Exception InstAccessFault)
|| (trap == tagged Exception InstPageFault)) begin
vaddr = x.tval;
end
else if(x.ppc_vaddr_csrData matches tagged VAddr .va) begin
vaddr = getAddr(va);
end
let commitTrap_val = Valid (CommitTrap {
trap: trap.trap,
trap: trap,
pc: x.pc,
addr: vaddr,
orig_inst: x.orig_inst
@@ -1067,7 +1068,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
else begin
if (verbose) $display("[doCommitNormalInst - %d] ", i, fshow(inst_tag), " ; ", fshow(x));
`ifdef RVFI
rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getAddr(x.pc) + (is_16b_inst(x.orig_inst) ? 2:4));
CapPipe pipePc = cast(x.pc);
rvfis[i] = genRVFI(x, traceCnt + zeroExtend(whichTrace), getTSB(), getOffset(pipePc) + (is_16b_inst(x.orig_inst) ? 2:4));
whichTrace = whichTrace + 1;
`endif

View File

@@ -897,7 +897,7 @@ module mkFetchStage(FetchStage);
if (in.decode_epoch == decode_epoch_local) begin
doAssert(in.main_epoch == f_main_epoch, "main epoch must match");
let decode_result = decode(in.inst); // Decode 32b inst, or 32b expansion of 16b inst
let decode_result = decode(in.inst, getFlags(inst_data[i].pc)==1); // Decode 32b inst, or 32b expansion of 16b inst
// update cause and tval if decode exception and no earlier (TLB) exception
if (!isValid(cause)) begin

View File

@@ -63,6 +63,7 @@ typedef struct {
PhyRegs regs;
InstTag tag;
LdStQTag ldstq_tag;
CapChecks cap_checks;
} MemDispatchToRegRead deriving(Bits, Eq, FShow);
typedef struct {
@@ -74,6 +75,7 @@ typedef struct {
// src reg vals
CapPipe rVal1;
CapPipe rVal2;
CapChecks cap_checks;
} MemRegReadToExe deriving(Bits, FShow);
typedef struct {
@@ -82,7 +84,7 @@ typedef struct {
InstTag tag;
LdStQTag ldstq_tag;
// result
ByteEn shiftedBE;
MemDataByteEn shiftedBE;
CapPipe vaddr; // virtual addr
`ifdef INCLUDE_TANDEM_VERIF
// for those mem instrs that store data
@@ -90,6 +92,8 @@ typedef struct {
ByteEn store_data_BE;
`endif
Bool misaligned;
Maybe#(CSR_XCapCause) capException;
Maybe#(BoundsCheck) check;
} MemExeToFinish deriving(Bits, FShow);
// bookkeeping when waiting for MMIO resp which may cause exception
@@ -161,7 +165,7 @@ interface MemExeInput;
CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -207,7 +211,7 @@ interface MemExePipeline;
endinterface
module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
Bool verbose = False;
Bool verbose = True;
// we change cache request in case of single core, becaues our MSI protocol
// is not good with single core
@@ -288,7 +292,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
Fifo#(1, MemResp) respLrScAmoQ <- mkCFFifo;
// resp ifc to D$
L1ProcResp#(DProcReqId) procRespIfc = (interface L1ProcResp;
method Action respLd(DProcReqId id, Data d);
method Action respLd(DProcReqId id, MemTaggedData d);
LdQTag tag = truncate(id);
memRespLdQ.enq(tuple2(tag, d));
// early wake up RS and set SB
@@ -308,7 +312,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
end
`endif
endmethod
method Action respLrScAmo(DProcReqId id, Data d);
method Action respLrScAmo(DProcReqId id, MemTaggedData d);
respLrScAmoQ.enq(d);
if(verbose) begin
$display("[Lr/Sc/Amo resp] ", fshow(id), "; ", fshow(d));
@@ -349,7 +353,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
exeStMemLat.incr(zeroExtend(lat));
end
`endif
return tuple2(e.byteEn, unpack(e.data)); // return SB entry
return tuple2(unpack(pack(e.byteEn)), e.line); // return SB entry
endmethod
`endif
method Action evict(LineAddr lineAddr);
@@ -396,7 +400,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
imm: x.data.imm,
regs: x.regs,
tag: x.tag,
ldstq_tag: x.data.ldstq_tag
ldstq_tag: x.data.ldstq_tag,
cap_checks: x.data.cap_checks
},
spec_bits: x.spec_bits
});
@@ -438,7 +443,8 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
tag: x.tag,
ldstq_tag: x.ldstq_tag,
rVal1: rVal1,
rVal2: rVal2
rVal2: rVal2,
cap_checks: x.cap_checks
},
spec_bits: dispToReg.spec_bits
});
@@ -457,6 +463,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// get virtual addr & St/Sc/Amo data
CapPipe vaddr = modifyOffset(x.rVal1, signExtend(x.imm), True).value;
CapPipe data = x.rVal2;
MemTaggedData toMemData = unpack(pack(toMem(data)));
`ifdef RVFI_DII
memData[pack(x.ldstq_tag)] <= getAddr(data);
@@ -465,19 +472,24 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// get shifted data and BE
// we can use virtual addr to shift, since page size > dword size
ByteEn origBE = lsq.getOrigBE(x.ldstq_tag);
function Tuple2#(ByteEn, Data) getShiftedBEData(Addr addr, ByteEn be, Data d);
Bit#(TLog#(NumBytes)) byteOffset = truncate(addr);
return tuple2(unpack(pack(be) << byteOffset), d << {byteOffset, 3'b0});
MemDataByteEn origBE = lsq.getOrigBE(x.ldstq_tag);
function Tuple2#(MemDataByteEn, MemTaggedData) getShiftedBEData(
Addr addr, MemDataByteEn be, MemTaggedData d);
Bit#(TLog#(MemDataBytes)) byteOffset = truncate(addr);
return tuple2(unpack(pack(be) << byteOffset), MemTaggedData {
tag: (byteOffset == 0) ? d.tag : False
, data: unpack(pack(d.data) << {byteOffset, 3'b0})});
endfunction
let {shiftBE, shiftData} = getShiftedBEData(getAddr(vaddr), origBE, getAddr(data));
let {shiftBE, shiftData} = getShiftedBEData(getAddr(vaddr), origBE, toMemData);
// update LSQ data now
if(x.ldstq_tag matches tagged St .stTag) begin
Data d = x.mem_func == Amo ? getAddr(data) : shiftData; // XXX don't shift for AMO
MemTaggedData d = x.mem_func == Amo ? toMemData : shiftData; // XXX don't shift for AMO
lsq.updateData(stTag, d);
end
CapPipe ddc = cast(inIfc.scaprf_rd(SCR_DDC)); // ToDo: feed DDC into the prepareBoundsCheck function below somehow.
// go to next stage by sending to TLB
dTlb.procReq(DTlbReq {
inst: MemExeToFinish {
@@ -490,7 +502,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
store_data: data,
store_data_BE: origBE,
`endif
misaligned: memAddrMisaligned(getAddr(vaddr), origBE)
misaligned: memAddrMisaligned(getAddr(vaddr), origBE),
capException: capChecks(x.rVal1, x.rVal2, ddc, x.cap_checks),
check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/,
ddc, getAddr(vaddr), pack(countOnes(pack(origBE))), x.cap_checks)
},
specBits: regToExe.spec_bits
});
@@ -560,17 +575,19 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
endcase);
Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo);
Bool non_mmio_st_done = !isValid(cause) && !isMMIO && x.mem_func == St;
CapPipe pcc = cast(inIfc.rob_getPC(x.tag));
CapPipe ddc = cast(inIfc.scaprf_rd(SCR_DDC));
Bool ddc_out_of_bounds = !isInBounds(modifyOffset(ddc,getAddr(x.vaddr),True).value,True);
Bool out_of_bounds = (getFlags(pcc) == 1'b1) ? isInBounds(x.vaddr, False):ddc_out_of_bounds;
if (x.check matches tagged Valid .check &&& x.capException matches tagged Invalid) begin
if (!( (check.check_low >= check.authority_base) &&
(check.check_inclusive ? (check.check_high <= check.authority_top )
: (check.check_high < check.authority_top ))))
x.capException = Valid(CSR_XCapCause{cheri_exc_reg: check.authority_idx, cheri_exc_code: LengthViolation});
end
inIfc.rob_setExecuted_doFinishMem(x.tag, x.vaddr, store_data, store_data_BE,
access_at_commit, non_mmio_st_done,
(out_of_bounds) ? Valid(CHERIFault):Invalid
x.capException
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: memData[pack(x.ldstq_tag)],
memByteEn: unpack(pack(x.shiftedBE) >> getAddr(x.vaddr)[2:0])
memByteEn: unpack(truncate(pack(x.shiftedBE) >> getAddr(x.vaddr)[3:0]))
}
`endif
);
@@ -697,12 +714,12 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
endrule
// handle load resp
function Action doRespLd(LdQTag tag, Data data, String rule_name);
function Action doRespLd(LdQTag tag, MemTaggedData data, String rule_name);
action
LSQRespLdResult res <- lsq.respLd(tag, data);
if(verbose) $display("%t : ", $time, rule_name, " ", fshow(tag), "; ", fshow(data), "; ", fshow(res));
if(res.dst matches tagged Valid .dst) begin
inIfc.writeRegFile(dst.indx, nullWithAddr(res.data));
inIfc.writeRegFile(dst.indx, fromMem(unpack(pack(res.data))));
`ifdef INCLUDE_TANDEM_VERIF
inIfc.rob_setExecuted_doFinishMem_RegData (res.instTag, res.data);
@@ -718,7 +735,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
`endif
`ifdef RVFI
LdStQTag idx = tagged Ld tag;
memData[pack(idx)] <= res.data;
memData[pack(idx)] <= truncate(pack(res.data)); // TODO use fromMem?
$display("%t : memData[%x] <= %x", $time(), pack(idx), res.data);
`endif
end
@@ -862,10 +879,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
waitLrScAmoMMIOResp <= Invalid;
// get resp data (need shifting)
let d <- toGet(respLrScAmoQ).get;
Data resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d);
MemTaggedData resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d);
// write reg file & set ROB as Executed & wakeup rs
if(lsqDeqLd.dst matches tagged Valid .dst) begin
inIfc.writeRegFile(dst.indx, nullWithAddr(resp));
inIfc.writeRegFile(dst.indx, fromMem(unpack(pack(resp))));
inIfc.setRegReadyAggr_mem(dst.indx);
`ifdef INCLUDE_TANDEM_VERIF
inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqLd.instTag, resp);
@@ -877,7 +894,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: resp,
regWriteData: truncate(pack(resp)), // TODO use fromMem?
memByteEn: replicate(False)
}
`endif
@@ -950,10 +967,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
waitLrScAmoMMIOResp <= Invalid;
// get resp (need to shift data)
let d = inIfc.mmioRespVal.data;
Data resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d);
MemTaggedData resp = gatherLoad(lsqDeqLd.paddr, lsqDeqLd.byteEn, lsqDeqLd.unsignedLd, d);
// write reg file & wakeup rs (this wakeup is late but MMIO is rare) & set ROB as Executed
if(lsqDeqLd.dst matches tagged Valid .dst) begin
inIfc.writeRegFile(dst.indx, nullWithAddr(resp));
inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag,unpack(pack(resp.data)))));
inIfc.setRegReadyAggr_mem(dst.indx);
`ifdef INCLUDE_TANDEM_VERIF
inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqLd.instTag, resp);
@@ -962,7 +979,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqLd.instTag, Invalid, Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: resp,
regWriteData: truncate(pack(resp)), // TODO use fromMem?
memByteEn: replicate(False)
}
`endif
@@ -1014,7 +1031,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqSt.instTag, lsqDeqSt.fault, Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: lsqDeqSt.stData,
regWriteData: truncate(pack(lsqDeqSt.stData)), // TODO use fromMem?
memByteEn: replicate(False)
}
`endif
@@ -1110,7 +1127,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqSt.instTag, Invalid, Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: lsqDeqSt.stData,
regWriteData: truncate(pack(lsqDeqSt.stData)), // TODO use fromMem ?
memByteEn: replicate(False)
}
`endif
@@ -1158,7 +1175,9 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
data: lsqDeqSt.stData,
amoInst: AmoInst {
func: lsqDeqSt.amoFunc,
doubleWord: lsqDeqSt.shiftedBE == replicate(True),
width: (pack(lsqDeqSt.shiftedBE) == ~0) ? QWord :
(pack(lsqDeqSt.shiftedBE)[15:8] == ~0) ? DWord :
(pack(lsqDeqSt.shiftedBE)[7:0] == ~0) ? DWord : Word,
aq: lsqDeqSt.acq,
rl: lsqDeqSt.rel
}
@@ -1201,10 +1220,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
lsq.deqSt;
waitLrScAmoMMIOResp <= Invalid;
// get resp data (no need to shift for Sc and Amo)
Data resp <- toGet(respLrScAmoQ).get;
MemTaggedData resp <- toGet(respLrScAmoQ).get;
// write reg file & set ROB as Executed & wake up rs
if(lsqDeqSt.dst matches tagged Valid .dst) begin
inIfc.writeRegFile(dst.indx, nullWithAddr(resp));
inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag, pack(resp.data))));
inIfc.setRegReadyAggr_mem(dst.indx);
`ifdef INCLUDE_TANDEM_VERIF
inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqSt.instTag, resp);
@@ -1213,7 +1232,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqSt.instTag, Invalid, Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: resp,
regWriteData: fromMemTaggedData(resp),
memByteEn: replicate(False)
}
`endif
@@ -1307,10 +1326,10 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
lsq.deqSt;
waitLrScAmoMMIOResp <= Invalid;
// get resp (no need to shift for AMO)
Data resp = inIfc.mmioRespVal.data;
MemTaggedData resp = inIfc.mmioRespVal.data;
// write reg file & wakeup rs (this wakeup is late but MMIO is rare) & set ROB as Executed
if(lsqDeqSt.dst matches tagged Valid .dst) begin
inIfc.writeRegFile(dst.indx, nullWithAddr(resp));
inIfc.writeRegFile(dst.indx, fromMem(tuple2(resp.tag, pack(resp.data))));
inIfc.setRegReadyAggr_mem(dst.indx);
`ifdef INCLUDE_TANDEM_VERIF
inIfc.rob_setExecuted_doFinishMem_RegData (lsqDeqSt.instTag, resp);
@@ -1319,7 +1338,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqSt.instTag, Invalid, Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: resp,
regWriteData: fromMemTaggedData(resp),
memByteEn: replicate(False)
}
`endif
@@ -1351,7 +1370,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
inIfc.rob_setExecuted_deqLSQ(lsqDeqSt.instTag, Valid (StoreAccessFault), Invalid
`ifdef RVFI
, ExtraTraceBundle{
regWriteData: lsqDeqSt.stData,
regWriteData: fromMemTaggedData(lsqDeqSt.stData),
memByteEn: replicate(False)
}
`endif

View File

@@ -228,7 +228,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
Maybe#(Trap) trap = tagged Invalid;
let csr_state = csrf.decodeInfo;
let pending_interrupt = csrf.pending_interrupt;
let new_exception = checkForException(x.dInst, x.regs, csr_state);
let new_exception = checkForException(x.dInst, x.regs, csr_state, x.pc, x.orig_inst[1:0]==2'b11);
// If Fpu regs are accessed, trap if mstatus_fs is "Off" (2'b00)
Bool fpr_access = ( fn_ArchReg_is_FpuReg (x.regs.src1)
@@ -266,7 +266,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
trap = tagged Valid (tagged Interrupt fromMaybe(?, pending_interrupt));
end else if (isValid(new_exception)) begin
// newly found exception
trap = tagged Valid (tagged Exception fromMaybe(?, new_exception));
trap = new_exception;
end
else if (fs_trap || wfi_trap) begin
trap = tagged Valid (tagged Exception IllegalInst);
@@ -331,8 +331,6 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
// Flip epoch without redirecting
// This avoids doing incorrect work
incrEpochStallFetch;
Maybe#(TrapWithCap) trapWithCap = Invalid;
if (firstTrap matches tagged Valid .trap) trapWithCap = tagged Valid TrapWithCap{trap: trap, capExp: noCapCause};
// just place it in the reorder buffer
let y = ToReorderBuffer{pc: cast(pc),
orig_inst: orig_inst,
@@ -346,7 +344,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
csr: dInst.csr,
scr: dInst.scr,
claimed_phy_reg: False, // no renaming is done
trap: trapWithCap,
trap: firstTrap,
tval: tval,
// default values of FullResult
ppc_vaddr_csrData: PPC (cast(pc)), // default use PPC
@@ -675,7 +673,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
data: MemRSData {
mem_func: mem_inst.mem_func,
imm: validValue(dInst.imm),
ldstq_tag: lsqTag
ldstq_tag: lsqTag,
cap_checks: dInst.capChecks
},
regs: phy_regs,
tag: inst_tag,
@@ -1013,7 +1012,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage);
data: MemRSData {
mem_func: mem_inst.mem_func,
imm: validValue(dInst.imm),
ldstq_tag: lsqTag
ldstq_tag: lsqTag,
cap_checks: dInst.capChecks
},
regs: phy_regs,
tag: inst_tag,

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -31,6 +31,7 @@ typedef struct {
MemFunc mem_func;
ImmData imm;
LdStQTag ldstq_tag;
CapChecks cap_checks;
} MemRSData deriving(Bits, Eq, FShow);
// MEM pipeline is aggressive, i.e. it recv bypass and early RS wakeup

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -23,47 +22,46 @@
import Types::*;
import ProcTypes::*;
import Vector::*;
(* noinline *)
function Data amoExec(AmoInst amo_inst, Data current_data, Data in_data, Bool upper_32_bits);
// upper_32_bits is true if the operation is a 32-bit operation and the
// address is the upper 32-bits of a 64-bit region.
Data new_data = 0;
Data old_data = current_data;
function MemTaggedData amoExec( AmoInst amo_inst, Bit#(2) wordIdx
, MemTaggedData current, MemTaggedData inpt );
if (!amo_inst.doubleWord) begin
if (!upper_32_bits) begin
current_data = (amo_inst.func == Min || amo_inst.func == Max) ? signExtend(current_data[31:0]) : zeroExtend(current_data[31:0]);
in_data = (amo_inst.func == Min || amo_inst.func == Max) ? signExtend(in_data[31:0]) : zeroExtend(in_data[31:0]);
end else begin
// use upper 32-bits instead
current_data = (amo_inst.func == Min || amo_inst.func == Max) ? signExtend(current_data[63:32]) : zeroExtend(current_data[63:32]);
in_data = (amo_inst.func == Min || amo_inst.func == Max) ? signExtend(in_data[31:0]) : zeroExtend(in_data[31:0]);
Vector#(2, Bit#(64)) dwordOld = current.data;
Vector#(4, Bit#(32)) wordOld = unpack(pack(current.data));
function doOp (vOld, vIn) = case (amo_inst.func)
Swap: return vIn;
Add: return vOld + vIn;
Xor: return vOld ^ vIn;
And: return vOld & vIn;
Or: return vOld | vIn;
Min: return sMin(vOld, vIn);
Max: return sMax(vOld, vIn);
Minu: return uMin(vOld, vIn);
Maxu: return uMax(vOld, vIn);
endcase;
Bit#(128) tmpData = pack(doOp(pack(current.data), pack(inpt.data)));
Bit#(128) mask = ~0;
Bit#(8) shftAmnt = 0;
case (amo_inst.width)
DWord: begin
tmpData = zeroExtend(doOp(dwordOld[wordIdx[1]], truncate(pack(inpt.data))));
mask = zeroExtend(64'hffffffffffffffff);
shftAmnt = zeroExtend(wordIdx[1]) << 6;
end
Word: begin
tmpData = zeroExtend(doOp(wordOld[wordIdx], truncate(pack(inpt.data))));
mask = zeroExtend(32'hffffffff);
shftAmnt = zeroExtend(wordIdx) << 5;
end
end
case (amo_inst.func)
Swap: new_data = in_data;
Add: new_data = current_data + in_data;
Xor: new_data = current_data ^ in_data;
And: new_data = current_data & in_data;
Or: new_data = current_data | in_data;
Min: new_data = sMin(current_data, in_data);
Max: new_data = sMax(current_data, in_data);
Minu: new_data = uMin(current_data, in_data);
Maxu: new_data = uMax(current_data, in_data);
endcase
Bit#(128) newData = (pack(current.data) & ~(mask << shftAmnt)) | (tmpData << shftAmnt);
if (!amo_inst.doubleWord) begin
if (!upper_32_bits) begin
return {old_data[63:32], new_data[31:0]};
end else begin
// change upper 32-bits instead
return {new_data[31:0], old_data[31:0]};
end
end else begin
return new_data;
end
Bool newTag = (amo_inst.func == Swap && amo_inst.width == QWord) ? inpt.tag : False;
return MemTaggedData { tag: newTag, data: unpack(newData) };
endfunction
function Bit#(t) sMax( Bit#(t) a, Bit#(t) b );

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -38,32 +38,66 @@ import FShow::*;
import MsgFifo::*;
// 64B cache line
typedef 8 CLineNumData;
typedef 4 CLineNumMemTaggedData;
typedef TMul#(CLineNumMemTaggedData, 2) CLineNumData;
typedef TLog#(CLineNumMemTaggedData) LogCLineNumMemTaggedData;
typedef TLog#(CLineNumData) LogCLineNumData;
typedef Bit#(LogCLineNumData) CLineDataSel;
function CLineDataSel getCLineDataSel(Addr a);
return truncate(a >> valueOf(TLog#(NumBytes)));
typedef Bit#(LogCLineNumMemTaggedData) CLineMemTaggedDataSel;
function CLineMemTaggedDataSel getCLineMemTaggedDataSel(Addr a) =
truncate(a >> valueOf(TLog#(MemDataBytes)));
function CLineDataSel getCLineDataSel(Addr a) =
truncate(a >> valueOf(TLog#(DataBytes)));
typedef struct {
Vector#(CLineNumMemTaggedData, MemTag) tag;
Vector#(CLineNumMemTaggedData, MemData) data;
} CLine deriving (Bits, Eq, FShow);
function Data getDataAt(CLine line, CLineDataSel sel);
Vector#(CLineNumData, Data) data = unpack(pack(line.data));
return data[sel];
endfunction
function CLine setDataAt(CLine line, CLineDataSel sel, Data data);
Vector#(CLineNumData, Data) newData = unpack(pack(line.data));
newData[sel] = data;
CLineMemTaggedDataSel bigSel = truncateLSB(sel);
let newLine = line;
newLine.tag[bigSel] = False;
newLine.data = unpack(pack(newData));
return newLine;
endfunction
function CLine setDataAtBE(CLine line, CLineDataSel sel, Data data, ByteEn be);
let oldData = getDataAt(line, sel);
return setDataAt(line, sel, mergeDataBE(oldData, data, be));
endfunction
function MemTaggedData getTaggedDataAt(CLine line, CLineMemTaggedDataSel sel) =
MemTaggedData { tag: line.tag[sel], data: line.data[sel] };
function CLine setTaggedDataAt(CLine line, CLineMemTaggedDataSel sel, MemTaggedData data);
let newLine = line;
newLine.tag[sel] = data.tag;
newLine.data[sel] = data.data;
return newLine;
endfunction
typedef TMul#(CLineNumMemTaggedData, MemDataSz) CLineDataSz;
typedef TDiv#(CLineDataSz, 8) CLineDataNumBytes;
typedef TLog#(CLineDataNumBytes) LogCLineDataNumBytes;
typedef TMul#(CLineNumData, DataSz) CacheLineSz;
typedef Bit#(CacheLineSz) CacheLine;
typedef TMul#(CLineNumData, NumBytes) CLineNumBytes;
typedef TLog#(CLineNumBytes) LogCLineNumBytes;
typedef Vector#(CLineNumBytes, Bool) CLineByteEn;
typedef TMul#(CLineNumMemTaggedData, MemDataSz) CLineMemDataSz;
typedef TMul#(CLineNumMemTaggedData, MemDataBytes) CLineNumMemDataBytes;
typedef TLog#(CLineNumMemDataBytes) LogCLineNumMemDataBytes;
typedef Vector#(CLineNumMemTaggedData, Vector#(MemDataBytes, Bool)) CLineMemDataByteEn;
typedef Vector#(CLineNumData, Vector#(DataBytes, Bool)) CLineDataByteEn;
function Bool isCLineAlignAddr(Addr a);
Bit#(LogCLineNumBytes) offset = truncate(a);
Bit#(LogCLineNumMemDataBytes) offset = truncate(a);
return offset == 0;
endfunction
// cache line addr (drop the offset within cache line)
typedef TSub#(AddrSz, LogCLineNumBytes) CLineAddrSz;
typedef TSub#(AddrSz, LogCLineNumMemDataBytes) CLineAddrSz;
typedef Bit#(CLineAddrSz) CLineAddr;
// cache line v.s. instruction
typedef TDiv#(CacheLineSz, InstSz) CLineNumInst;
typedef TDiv#(CLineMemDataSz, InstSz) CLineNumInst;
typedef Bit#(TLog#(CLineNumInst)) CLineInstSel;
function CLineInstSel getCLineInstSel(Addr a);

View File

@@ -1,6 +1,8 @@
`CAP_CHECK_FIELD(ddc_tag,"ddc_tag")
`CAP_CHECK_FIELD(src1_tag,"src1_tag")
`CAP_CHECK_FIELD(src2_tag,"src2_tag")
`CAP_CHECK_FIELD(src1_sealed_with_type,"src1_sealed_with_type")
`CAP_CHECK_FIELD(ddc_unsealed,"ddc_unsealed")
`CAP_CHECK_FIELD(src1_unsealed,"src1_unsealed")
`CAP_CHECK_FIELD(src2_unsealed,"src2_unsealed")
`CAP_CHECK_FIELD(src1_sealed,"src1_sealed")

View File

@@ -34,12 +34,6 @@ Bit#(3) memWU = 3'b110;
// Smaller decode functions
function Maybe#(MemInst) decodeMemInst(Instruction inst);
MemInst mem_inst = MemInst{ mem_func: ?,
amo_func: None,
unsignedLd: False,
byteEn: replicate(False),
aq: False,
rl: False };
Bool illegalInst = False;
Opcode opcode = unpackOpcode(inst[6:0]);
let funct5 = inst[31:27];
@@ -48,7 +42,7 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst);
// mem_func + amo_func
MemFunc mem_func = Ld;
AmoFunc amo_func = None;
if (opcode == Load || opcode == LoadFp) begin
if (opcode == Load || opcode == LoadFp || opcode == MiscMem) begin
mem_func = Ld;
end else if (opcode == Store || opcode == StoreFp) begin
mem_func = St;
@@ -100,25 +94,39 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst);
unsignedLd = True;
end
Bool capWidth = (mem_func == St && funct3 == 3'b100)
|| (opcode == MiscMem && funct3 == 3'b010);
// byteEn
// TODO: Some combinations of operations and byteEn's are illegal.
// They should be detected here.
ByteEn byteEn = replicate(False);
case (funct3)
memB, memBU : byteEn[0] = True;
memH, memHU : begin
byteEn[0] = True;
byteEn[1] = True;
end
memW, memWU : begin
byteEn[0] = True;
byteEn[1] = True;
byteEn[2] = True;
byteEn[3] = True;
end
memD : byteEn = replicate(True);
default : illegalInst = True;
endcase
MemDataByteEn byteEn = (capWidth) ? replicate(True):replicate(False);
if (!capWidth) begin
case (funct3)
memB, memBU : byteEn[0] = True;
memH, memHU : begin
byteEn[0] = True;
byteEn[1] = True;
end
memW, memWU : begin
byteEn[0] = True;
byteEn[1] = True;
byteEn[2] = True;
byteEn[3] = True;
end
memD : begin
byteEn[0] = True;
byteEn[1] = True;
byteEn[2] = True;
byteEn[3] = True;
byteEn[4] = True;
byteEn[5] = True;
byteEn[6] = True;
byteEn[7] = True;
end
default : illegalInst = True;
endcase
end
// aq + rl
Bool aq = False;
@@ -138,12 +146,109 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst);
unsignedLd: unsignedLd,
byteEn: byteEn,
aq: aq,
rl: rl } );
rl: rl,
reg_bounds: False } );
end
endfunction
function Maybe#(MemInst) decodeCapMemInst(Instruction inst);
// This function trusts that its result will only be used by
// explicit capability instructions as identified by the primary
// decode case, and therefore does not attempt to return sensible
// defaults when the instruction is not a capability memory operation.
Bool illegalInst = False;
Bit#(7) funct7 = inst[31:25];
Bit#(5) mem_code = (funct7==f7_cap_Loads) ? inst[24:20]:inst[11:7];
Bool amo = unpack(mem_code[4]);
Bool bounds_from_register = unpack(mem_code[3]);
Bool unsind = unpack(mem_code[2]);
Bit#(2) width = mem_code[1:0];
Bool capWidth = (funct7 == f7_cap_Stores && unsind && width == 0);
if (funct7 == f7_cap_Loads && amo && width == 3) begin
capWidth = True;
amo = False;
end
// mem_func + amo_func
MemFunc mem_func = Ld;
AmoFunc amo_func = None;
if (funct7 == f7_cap_Loads) begin
mem_func = (amo) ? Lr:Ld;
end else if (funct7 == f7_cap_Stores) begin
mem_func = (amo) ? Sc:St;
end
// unsignedLd
// it doesn't matter if this is set to True for stores
Bool unsignedLd = unsind;
// byteEn
// TODO: Some combinations of operations and byteEn's are illegal.
// They should be detected here.
MemDataByteEn byteEn = (capWidth) ? replicate(True):replicate(False);
if (!capWidth) begin
case (width)
0 : byteEn[0] = True;
1 : begin
byteEn[0] = True;
byteEn[1] = True;
end
2 : begin
byteEn[0] = True;
byteEn[1] = True;
byteEn[2] = True;
byteEn[3] = True;
end
3 : begin
byteEn[0] = True;
byteEn[1] = True;
byteEn[2] = True;
byteEn[3] = True;
byteEn[4] = True;
byteEn[5] = True;
byteEn[6] = True;
byteEn[7] = True;
// In RV64 we don't allow unsigned double operations!
if (unsind) illegalInst = True;
end
endcase
end
if (illegalInst) begin
return tagged Invalid;
end else begin
return tagged Valid ( MemInst{
mem_func: mem_func,
amo_func: amo_func,
unsignedLd: unsignedLd,
byteEn: byteEn,
aq: amo,
rl: amo,
reg_bounds: bounds_from_register} );
end
endfunction
function CapChecks memCapChecks(Bool cap_mode);
CapChecks capChecks = unpack(0);
capChecks.check_enable = True;
capChecks.check_low_src = Vaddr;
capChecks.check_high_src = VaddrPlusSize; // Should add the access size somehow...
capChecks.check_inclusive = True;
if (cap_mode) begin
capChecks.check_authority_src = Src1;
capChecks.src1_tag = True;
capChecks.src1_unsealed = True;
end else begin
capChecks.check_authority_src = Ddc;
capChecks.ddc_tag = True;
capChecks.ddc_unsealed = True;
end
return capChecks;
endfunction
(* noinline *)
function DecodeResult decode(Instruction inst);
function DecodeResult decode(Instruction inst, Bool cap_mode);
RiscVISASubset isa = defaultValue;
// initialize dInst with default values
@@ -190,6 +295,7 @@ function DecodeResult decode(Instruction inst);
// Results of mini-decoders
Maybe#(MemInst) mem_inst = decodeMemInst(inst);
Maybe#(MemInst) cap_mem_inst = decodeCapMemInst(inst);
// TODO better detection of illegal insts
case (opcode)
@@ -372,6 +478,11 @@ function DecodeResult decode(Instruction inst);
dInst.imm = Valid(immJ);
dInst.csr = tagged Invalid;
dInst.execFunc = tagged Br AT;
dInst.capChecks.check_enable = True;
dInst.capChecks.check_authority_src = Pcc;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2;
dInst.capChecks.check_inclusive = True;
end
Jalr: begin
@@ -382,6 +493,11 @@ function DecodeResult decode(Instruction inst);
dInst.imm = Valid(immI);
dInst.csr = tagged Invalid;
dInst.execFunc = tagged Br AT;
dInst.capChecks.check_enable = True;
dInst.capChecks.check_authority_src = Pcc;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2;
dInst.capChecks.check_inclusive = True;
end
Branch: begin
@@ -399,6 +515,11 @@ function DecodeResult decode(Instruction inst);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Valid(immB);
dInst.csr = tagged Invalid;
dInst.capChecks.check_enable = True;
dInst.capChecks.check_authority_src = Pcc;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2;
dInst.capChecks.check_inclusive = True;
end
Load: begin
@@ -413,6 +534,7 @@ function DecodeResult decode(Instruction inst);
regs.src2 = Invalid;
dInst.imm = Valid(immI);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(cap_mode);
end
Store: begin
@@ -427,6 +549,7 @@ function DecodeResult decode(Instruction inst);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Valid(immS);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(cap_mode);
end
Amo: begin
@@ -582,6 +705,7 @@ function DecodeResult decode(Instruction inst);
regs.src2 = Invalid;
dInst.imm = Valid(immI);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(cap_mode);
end
end
StoreFp: begin
@@ -602,6 +726,7 @@ function DecodeResult decode(Instruction inst);
regs.src2 = Valid(tagged Fpu rs2);
dInst.imm = Valid(immS);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(cap_mode);
end
end
Fmadd, Fmsub, Fnmsub, Fnmadd: begin
@@ -637,6 +762,11 @@ function DecodeResult decode(Instruction inst);
end
MiscMem: begin
regs.dst = Invalid;
regs.src1 = Invalid;
regs.src2 = Invalid;
dInst.imm = Invalid;
dInst.csr = Invalid;
case (funct3)
fnFENCEI: begin
dInst.iType = FenceI;
@@ -672,7 +802,8 @@ function DecodeResult decode(Instruction inst);
unsignedLd: False,
byteEn: replicate(False),
aq: reconcile,
rl: commit
rl: commit,
reg_bounds: False // unused
});
end
else begin
@@ -680,13 +811,22 @@ function DecodeResult decode(Instruction inst);
dInst.execFunc = tagged Other;
end
end
fnLC: begin
dInst.iType = Ld;
if (isValid(mem_inst)) begin
dInst.execFunc = tagged Mem fromMaybe(?, mem_inst);
end else begin
illegalInst = True;
end
regs.dst = Valid(tagged Gpr rd);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Invalid;
dInst.imm = Valid(immI);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(cap_mode);
end
default: illegalInst = True;
endcase
regs.dst = Invalid;
regs.src1 = Invalid;
regs.src2 = Invalid;
dInst.imm = Invalid;
dInst.csr = Invalid;
end
System: begin
@@ -1029,12 +1169,28 @@ function DecodeResult decode(Instruction inst);
dInst.capFunc = CapModify (BuildCap);
end
f7_cap_Loads: begin
illegalInst = True;
//TODO
dInst.iType = Ld;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Valid(tagged Gpr rd);
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Invalid;
dInst.imm = Valid (0);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(mi.reg_bounds);
end
f7_cap_Stores: begin
illegalInst = True;
//TODO
dInst.iType = St;
MemInst mi = cap_mem_inst.Valid;
if (isValid(cap_mem_inst)) dInst.execFunc = tagged Mem mi;
else illegalInst = True;
regs.dst = Invalid;
regs.src1 = Valid(tagged Gpr rs1);
regs.src2 = Valid(tagged Gpr rs2);
dInst.imm = Valid (0);
dInst.csr = tagged Invalid;
dInst.capChecks = memCapChecks(mi.reg_bounds);
end
f7_cap_TwoOp: begin
case (funct5rs2)
@@ -1133,7 +1289,7 @@ function DecodeResult decode(Instruction inst);
dInst.capChecks.check_authority_src = Src1;
dInst.capChecks.check_low_src = Src1Addr;
dInst.capChecks.check_high_src = Src1AddrPlus2;
dInst.capChecks.check_inclusive = False;
dInst.capChecks.check_inclusive = True;
dInst.iType = CJALR;
dInst.execFunc = tagged Br AT;
@@ -1163,14 +1319,15 @@ function DecodeResult decode(Instruction inst);
illegalInst = True;
end
endcase
dInst.capChecks.rn1 = {1'b0, regs.src1.Valid.Gpr};
dInst.capChecks.rn2 = {1'b0, regs.src2.Valid.Gpr};
end
default: begin
illegalInst = True;
end
endcase
dInst.capChecks.rn1 = {1'b0, regs.src1.Valid.Gpr};
dInst.capChecks.rn2 = {1'b0, regs.src2.Valid.Gpr};
// XXX to ensure renaming + phy regs works correctly, must remove any write
// to x0
if(regs.dst matches tagged Valid .dst &&& dst == tagged Gpr 0) begin

View File

@@ -30,18 +30,21 @@ import CHERICC_Fat::*;
import ISA_Decls_CHERI::*;
(* noinline *)
function Maybe#(CapException) capChecks(CapPipe a, CapPipe b, CapChecks toCheck, CapPipe pcc_end);
function Maybe#(CapException) e1(CHERIException e) = Valid(CapException{cheri_exc_reg: toCheck.rn1, cheri_exc_code: e});
function Maybe#(CapException) e2(CHERIException e) = Valid(CapException{cheri_exc_reg: toCheck.rn2, cheri_exc_code: e});
Maybe#(CapException) result = Invalid;
if (!isInBounds(pcc_end, True))
result = Valid(CapException{cheri_exc_reg: {1'b1,pack(SCR_PCC)}, cheri_exc_code: LengthViolation});
function Maybe#(CSR_XCapCause) capChecks(CapPipe a, CapPipe b, CapPipe ddc, CapChecks toCheck);
function Maybe#(CSR_XCapCause) e1(CHERIException e) = Valid(CSR_XCapCause{cheri_exc_reg: toCheck.rn1, cheri_exc_code: e});
function Maybe#(CSR_XCapCause) e2(CHERIException e) = Valid(CSR_XCapCause{cheri_exc_reg: toCheck.rn2, cheri_exc_code: e});
function Maybe#(CSR_XCapCause) eDDC(CHERIException e) = Valid(CSR_XCapCause{cheri_exc_reg: 6'b100001, cheri_exc_code: e}); // Not sure where the proper reg number of DDC is stored...
Maybe#(CSR_XCapCause) result = Invalid;
if (toCheck.ddc_tag && !isValidCap(ddc))
result = eDDC(TagViolation);
else if (toCheck.src1_tag && !isValidCap(a))
result = e1(TagViolation);
else if (toCheck.src2_tag && !isValidCap(b))
result = e2(TagViolation);
else if (toCheck.src1_sealed_with_type && getKind(a) != SEALED_WITH_TYPE)
result = e1(SealViolation);
else if (toCheck.ddc_unsealed && isValidCap(ddc) && isSealed(ddc))
result = eDDC(SealViolation);
else if (toCheck.src1_unsealed && isValidCap(a) && isSealed(a))
result = e1(SealViolation);
else if (toCheck.src2_unsealed && isValidCap(b) && isSealed(b))
@@ -73,12 +76,14 @@ function Maybe#(CapException) capChecks(CapPipe a, CapPipe b, CapChecks toCheck,
else if (toCheck.src1_derivable && !isDerivable(a))
result = e1(LengthViolation);
else if (toCheck.scr_read_only && (toCheck.rn1 != 0))
result = Valid(CapException{cheri_exc_reg: {1,pack(SCR_PCC)}, cheri_exc_code: PermitASRViolation});
result = Valid(CSR_XCapCause{cheri_exc_reg: {1,pack(SCR_PCC)}, cheri_exc_code: PermitASRViolation});
return result;
endfunction
(* noinline *)
function Maybe#(BoundsCheck) prepareBoundsCheck(CapPipe a, CapPipe b, CapChecks toCheck);
function Maybe#(BoundsCheck) prepareBoundsCheck(CapPipe a, CapPipe b, CapPipe pcc,
CapPipe ddc, Data vaddr, Bit#(5) size, // These two are only used in the memory pipe. May factor into two functions later.
CapChecks toCheck);
BoundsCheck ret = ?;
CapPipe authority = ?;
case(toCheck.check_authority_src)
@@ -90,6 +95,14 @@ function Maybe#(BoundsCheck) prepareBoundsCheck(CapPipe a, CapPipe b, CapChecks
authority = b;
ret.authority_idx = toCheck.rn2;
end
Pcc: begin
authority = pcc;
ret.authority_idx = 6'b100000; // Not sure where the register number of PCC is defined...
end
Ddc: begin
authority = ddc;
ret.authority_idx = 6'b100001; // Not sure where the register number of PCC is defined...
end
endcase
ret.authority_base = getBase(authority);
ret.authority_top = getTop(authority);
@@ -99,6 +112,7 @@ function Maybe#(BoundsCheck) prepareBoundsCheck(CapPipe a, CapPipe b, CapChecks
Src1Base: ret.check_low = getBase(a);
Src2Addr: ret.check_low = getAddr(b);
Src2Type: ret.check_low = zeroExtend(getType(b));
Vaddr: ret.check_low = vaddr;
endcase
case(toCheck.check_high_src)
@@ -107,6 +121,7 @@ function Maybe#(BoundsCheck) prepareBoundsCheck(CapPipe a, CapPipe b, CapChecks
Src2Addr: ret.check_high = {1'b0,getAddr(b)};
Src2Type: ret.check_high = zeroExtend(getType(b));
ResultTop: ret.check_high = {1'b0,getAddr(a)} + {1'b0,getAddr(b)};
VaddrPlusSize: ret.check_high = {1'b0,vaddr} + zeroExtend(size);
endcase
ret.check_inclusive = toCheck.check_inclusive;
@@ -267,7 +282,7 @@ function CapPipe brAddrCalc(CapPipe pc, CapPipe val, IType iType, Data imm, Bool
Br : (taken? branchTarget : pcPlusN);
default : pcPlusN;
endcase);
return targetAddr;
return setType(targetAddr, -1);
endfunction
/*
(* noinline *)
@@ -304,15 +319,22 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
CapPipe cap_alu_result = capALU(rVal1, aluVal2, dInst.capFunc);
CapPipe link_pcc = addPc(pcc, ((orig_inst [1:0] == 2'b11) ? 4 : 2));
Maybe#(CapException) capException = capChecks(rVal1, aluVal2, dInst.capChecks, link_pcc);
Maybe#(BoundsCheck) boundsCheck = prepareBoundsCheck(rVal1, aluVal2, dInst.capChecks);
// Default branch function is not taken
BrFunc br_f = dInst.execFunc matches tagged Br .br_f ? br_f : NT;
cf.taken = aluBr(getAddr(rVal1), getAddr(rVal2), br_f);
cf.nextPc = brAddrCalc(pcc, rVal1, dInst.iType, fromMaybe(0,getDInstImm(dInst)), cf.taken, orig_inst, newPcc);
if (dInst.execFunc matches tagged Br .unused) begin
rVal1 = cf.nextPc;
if (!cf.taken) dInst.capChecks.check_enable = False;
end
cf.mispredict = cf.nextPc != ppc;
Maybe#(CSR_XCapCause) capException = capChecks(rVal1, aluVal2, nullCap, dInst.capChecks);
Maybe#(BoundsCheck) boundsCheck = prepareBoundsCheck(rVal1, aluVal2, pcc,
nullCap, 0, 0, // These three are only used in the memory pipe
dInst.capChecks);
data = (case (dInst.iType) matches
St : rVal2;
Sc : rVal2;
@@ -339,10 +361,12 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
endfunction
(* noinline *)
function Maybe#(Exception) checkForException(
function Maybe#(Trap) checkForException(
DecodedInst dInst,
ArchRegs regs,
CsrDecodeInfo csrState
CsrDecodeInfo csrState,
CapMem pcc,
Bool fourByteInst
); // regs needed to check if x0 is a src
Maybe#(Exception) exception = Invalid;
let prv = csrState.prv;
@@ -425,12 +449,24 @@ function Maybe#(Exception) checkForException(
end
end
return exception;
// Check that the end of the instruction is in bounds of PCC.
CapPipe pcc_end = cast(addPc(pcc, (fourByteInst?4:2)));
Maybe#(CSR_XCapCause) capException = Invalid;
if (!isInBounds(pcc_end, True)) capException = Valid(CSR_XCapCause{cheri_exc_reg: {1'b1,pack(SCR_PCC)}, cheri_exc_code: LengthViolation});
Maybe#(Trap) retval = Invalid;
if (capException matches tagged Valid .ce) retval = Valid(CapException(ce));
else if (exception matches tagged Valid .e) retval = Valid(Exception(e));
return retval;
endfunction
// check mem access misaligned: byteEn is unshifted (just from Decode)
function Bool memAddrMisaligned(Addr addr, ByteEn byteEn);
if(byteEn[7]) begin
function Bool memAddrMisaligned(Addr addr, MemDataByteEn byteEn);
if(byteEn[15]) begin
return addr[3:0] != 0;
end
else if(byteEn[7]) begin
return addr[2:0] != 0;
end
else if(byteEn[3]) begin
@@ -444,21 +480,24 @@ function Bool memAddrMisaligned(Addr addr, ByteEn byteEn);
end
endfunction
function Data gatherLoad(Addr addr, ByteEn byteEn, Bool unsignedLd, Data data);
function MemTaggedData gatherLoad( Addr addr, MemDataByteEn byteEn
, Bool unsignedLd, MemTaggedData data);
function extend = unsignedLd ? zeroExtend : signExtend;
Bit#(IndxShamt) offset = truncate(addr);
if(byteEn[7]) begin
return extend(data);
if(pack(byteEn) == ~0) return data;
else if(byteEn[7]) begin
Vector#(2, Bit#(64)) dataVec = unpack(pack(data.data));
return dataToMemTaggedData(extend(dataVec[offset[3]]));
end else if(byteEn[3]) begin
Vector#(2, Bit#(32)) dataVec = unpack(data);
return extend(dataVec[offset[2]]);
Vector#(4, Bit#(32)) dataVec = unpack(pack(data.data));
return dataToMemTaggedData(extend(dataVec[offset[3:2]]));
end else if(byteEn[1]) begin
Vector#(4, Bit#(16)) dataVec = unpack(data);
return extend(dataVec[offset[2:1]]);
Vector#(8, Bit#(16)) dataVec = unpack(pack(data.data));
return dataToMemTaggedData(extend(dataVec[offset[3:1]]));
end else begin
Vector#(8, Bit#(8)) dataVec = unpack(data);
return extend(dataVec[offset]);
Vector#(16, Bit#(8)) dataVec = unpack(pack(data.data));
return dataToMemTaggedData(extend(dataVec[offset]));
end
endfunction

View File

@@ -2,6 +2,7 @@
// This package implements utility functions used by the floating point
// related logic
package FP_Utils;
import Types::*;
import FloatingPoint::*;
function FloatingPoint#(e,m) canonicalNaN = FloatingPoint{sign: False, exp: '1, sfd: 1 << (valueof(m)-1)};
@@ -19,6 +20,9 @@ function Bit #(64) fv_nanbox (Bit #(64) x);
Bit #(64) fill_mask = (fill_bits << 32); // [63:32] all ones
return (x | fill_mask);
endfunction
function MemTaggedData fv_nanbox_MemTaggedData (MemTaggedData x) =
MemTaggedData { tag: x.tag
, data: dataToMemData(fv_nanbox(memDataToData(x.data))) };
// Take a 64-bit value and check if it is properly nanboxed if operating in a DP
// capable environment. If not properly nanboxed, return canonicalNaN32
@@ -28,7 +32,7 @@ function Float fv_unbox (Bit #(64) x);
return (unpack (x [31:0]));
else
return (canonicalNaN);
//`else
//`else
// return (unpack (x [31:0]));
//`endif
endfunction

View File

@@ -111,16 +111,6 @@ function Bool fn_addr_is_in_line (Addr addr, Addr line_addr);
return (fn_align_addr_to_line (addr) == line_addr);
endfunction
function Bit #(64) fn_expand_strb_to_mask (Bit #(8) strb);
function Bit #(8) fn_bit_to_byte (Integer j);
return ((strb [j] == 1'b1) ? 8'hFF : 8'h00);
endfunction
Vector #(8, Bit #(8)) v = genWith (fn_bit_to_byte);
return pack (v);
endfunction
// ================================================================
module mkLLCDmaConnect #(
@@ -163,19 +153,13 @@ module mkLLCDmaConnect #(
rg_cacheline_cache_addr)));
let wr_addr <- get (axi4_slave_xactor.master.aw);
let wr_data <- get (axi4_slave_xactor.master.w);
Addr addr = wr_addr.awaddr;
Bit #(64) data = wr_data.wdata;
Bit #(64) mask = fn_expand_strb_to_mask (wr_data.wstrb);
// Read rg_cacheline_cache_data as 64-bit words
Vector #(8, Bit #(64)) line_dwords = unpack (pack (rg_cacheline_cache_data));
// Modify relevant bytes of relevant dword
Bit #(3) dword_in_line = addr [5:3];
Bit #(64) old_dword = line_dwords [dword_in_line];
Bit #(64) new_dword = ((old_dword & (~ mask)) | (data & mask));
line_dwords [dword_in_line] = new_dword;
let newLine = setDataAtBE( rg_cacheline_cache_data
, getCLineDataSel(wr_addr.awaddr)
, wr_data.wdata, unpack(pack(wr_data.wstrb)));
// Save it
rg_cacheline_cache_data <= unpack (pack (line_dwords));
rg_cacheline_cache_data <= newLine;
rg_cacheline_cache_state <= CACHELINE_CACHE_DIRTY;
rg_cacheline_cache_dirty_delay <= '1; // start write-back delay countdown
@@ -189,8 +173,8 @@ module mkLLCDmaConnect #(
if (verbosity >= 2) begin
$display ("%0d: %m.rl_handle_MemLoader_st_req: addr %0h data %0h strb %0h",
cur_cycle, wr_addr.awaddr, wr_data.wdata, wr_data.wstrb);
$display (" old_dword: %0h", old_dword);
$display (" new_dword: %0h", old_dword);
//$display (" old_dword: %0h", old_dword);
//$display (" new_dword: %0h", old_dword);
end
endrule
@@ -203,12 +187,8 @@ module mkLLCDmaConnect #(
&& (fn_addr_is_in_line (axi4_slave_xactor.master.ar.peek.araddr,
rg_cacheline_cache_addr)));
let rd_addr <- get (axi4_slave_xactor.master.ar);
Addr addr = rd_addr.araddr;
// Read rg_cacheline_cache as 64-bit words
Vector #(8, Bit #(64)) line_dwords = unpack (pack (rg_cacheline_cache_data));
Bit #(3) dword_in_line = addr [5:3];
Bit #(64) dword = line_dwords [dword_in_line];
let dword = getDataAt( rg_cacheline_cache_data
, getCLineDataSel(rd_addr.araddr));
// Send response to external client
axi4_slave_xactor.master.r.put(AXI4_RFlit{
@@ -237,7 +217,7 @@ module mkLLCDmaConnect #(
function Action fa_writeback;
action
dmaRqT req = DmaRq {addr: rg_cacheline_cache_addr,
byteEn: replicate (True), // Write all bytes
byteEn: replicate(replicate(True)), // Write all bytes
data: rg_cacheline_cache_data,
id: tagged MemLoader (?) // TODO: use wr_addr.awid?
};
@@ -305,7 +285,7 @@ module mkLLCDmaConnect #(
action
let line_addr = fn_align_addr_to_line (addr);
dmaRqT req = DmaRq {addr: line_addr,
byteEn: replicate (False), // all False means 'read'
byteEn: replicate(replicate(False)), // all False means 'read'
data: ?,
id: tagged MemLoader (?)}; // TODO: change uniformly to wr_addr.awid
llc.memReq.enq (req);
@@ -384,7 +364,7 @@ module mkLLCDmaConnect #(
};
return DmaRq {
addr: r.addr,
byteEn: replicate(False), // tlb req is always load
byteEn: replicate(replicate(False)), // tlb req is always load
data: ?,
id: Tlb (id)
};
@@ -410,7 +390,7 @@ module mkLLCDmaConnect #(
llc.respLd.deq;
let resp = llc.respLd.first;
let ld = TlbLdResp {
data: resp.data[id.dataSel],
data: getDataAt(resp.data, id.dataSel),
id: id.id
};
tlb[id.core].respLd.enq(ld);

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2018 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -115,13 +114,14 @@ module mkMMIOCore#(MMIOCoreInput inIfc)(MMIOCore);
if(req.func matches tagged Amo .amoFunc) begin
let amoInst = AmoInst {
func: amoFunc,
doubleWord: False,
width: Word,
aq: False,
rl: False
};
let newData = amoExec(amoInst, zeroExtend(msip),
zeroExtend(req.data), False);
inIfc.setMSIP(newData[0]);
let newData =
amoExec(amoInst, 0, toMemTaggedData(msip),
toMemTaggedData(req.data));
inIfc.setMSIP(pack(newData.data)[0]);
end
end
end

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +7,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
@@ -113,7 +112,7 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
Reg#(LineDataOffset) reqSel <- mkRegU;
Reg#(LineAddr) reqAddr <- mkRegU;
Reg#(Line) reqData <- mkRegU;
Reg#(Vector#(LineSzData, Bit#(DataSzBytes))) reqBE <- mkRegU;
Reg#(LineByteEn) reqBE <- mkRegU;
// sync FIFOs to cross to portal clk
Clock userClk <- exposeCurrentClock;
@@ -137,7 +136,7 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
expectWrData <= True;
reqSel <= getLineDataOffset(req.addr);
reqAddr <= getLineAddr(req.addr);
reqBE <= replicate(0);
reqBE <= replicate(replicate(False));
// check addr align to Data
Bit#(LgDataSzBytes) offset = truncate(req.addr);
doAssert(offset == 0, "write addr not aligned to Data");
@@ -157,13 +156,12 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
hostWrDataQ.deq;
HostWrData wr = hostWrDataQ.first;
// merge with req data & BE
Line newData = reqData;
Vector#(LineSzData, Bit#(DataSzBytes)) newBE = reqBE;
newData[reqSel] = wr.data;
newBE[reqSel] = wr.byteEn;
Line newLine = setDataAt(reqData, reqSel, wr.data);
LineDataByteEn newBE = unpack(pack(reqBE));
newBE[reqSel] = unpack(pack(wr.byteEn));
// common state update
expectWrData <= !wr.last;
reqData <= newData;
reqData <= newLine;
reqSel <= reqSel + 1;
reqAddr <= reqSel == maxBound ? reqAddr + 1 : reqAddr;
// print
@@ -177,16 +175,16 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
MemLoaderMemReq req = DmaRq {
addr: {reqAddr, 0},
byteEn: unpack(pack(newBE)),
data: newData,
data: newLine,
id: ?
};
if(verbose) begin
$display("[MemLoader doStReq] req to LLC ", fshow(req));
end
// reset BE for next fresh LLC req
reqBE <= replicate(0);
reqBE <= replicate(replicate(False));
// only send real write to LLC, otherwise may spawn orphan read resp
if(req.byteEn != replicate(False)) begin
if(req.byteEn != replicate(replicate(False))) begin
memReqQ.enq(req);
pendStCnt <= pendStCnt + 1;
end
@@ -195,7 +193,7 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
end
end
else begin
reqBE <= newBE;
reqBE <= unpack(pack(newBE));
end
endrule
@@ -225,7 +223,7 @@ module mkMemLoader#(Clock portalClk, Reset portalRst)(MemLoader);
if(wrBE == replicate(False)) begin
return MMIODataPRs {
valid: True,
data: offset == 0 ? memStartAddr : zeroExtend(pack(busy))
data: offset == 0 ? toMemTaggedData(memStartAddr) : toMemTaggedData(busy)
};
end
else begin

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -29,7 +29,7 @@ import ClientServer::*;
// typedefs for mem access performed by processor
// cache line is defined in CacheUtils.bsv
typedef Data MemResp;
typedef MemTaggedData MemResp;
typedef enum{Ld, St, Lr, Sc, Amo} MemOp deriving(Eq,Bits,FShow); // add more ops
@@ -40,4 +40,3 @@ Bit#(3) memD = 3'b011;
Bit#(3) memBU = 3'b100;
Bit#(3) memHU = 3'b101;
Bit#(3) memWU = 3'b110;

View File

@@ -397,15 +397,11 @@ typedef 12 InterruptNum; // Without debugger
// Traps are either an exception or an interrupt
typedef union tagged {
CapException CapException;
Exception Exception;
Interrupt Interrupt;
} Trap deriving(Bits, Eq, FShow);
typedef struct {
Trap trap;
CSR_XCapCause capExp;
} TrapWithCap deriving(Bits, FShow);
// privilege modes
Bit#(2) prvU = 0;
Bit#(2) prvS = 1;
@@ -509,14 +505,17 @@ typedef struct {
typedef enum {
Src1,
Src2
Src2,
Pcc,
Ddc
} CheckAuthoritySrc deriving(Bits, Eq, FShow);
typedef enum {
Src1Addr,
Src2Addr,
Src2Type,
Src1Base
Src1Base,
Vaddr // Memory Pipe
} CheckLowSrc deriving(Bits, Eq, FShow);
typedef enum {
@@ -524,7 +523,8 @@ typedef enum {
Src1Top,
Src2Addr,
Src2Type,
ResultTop
ResultTop,
VaddrPlusSize // Memory Pipe
} CheckHighSrc deriving(Bits, Eq, FShow);
typedef struct {
@@ -619,10 +619,10 @@ typedef struct {
// this. We need this for to remove redundant MMIO accesses (for MSIP), and
// to determine AMO access range (upper 32 bits, lower 32 bits, or full 64
// bits). INST FETCH will not specify this field.
ByteEn byteEn;
MemDataByteEn byteEn;
// For STORE: this is store data shifted to be 64-bit aligned
// For AMO: this is UNshifted data (like normal mem req)
Data data;
MemTaggedData data;
} MMIOCRq deriving(Bits, Eq, FShow);
// resp from platform to core
@@ -634,7 +634,7 @@ typedef struct {
// shift the result before writting back to reg).
// For AMO: this is the result that can be directly written into reg, i.e.,
// for 32-bit access, the result has been shifted and sign-extended.
Data data;
MemTaggedData data;
} MMIODataPRs deriving(Bits, Eq, FShow);
typedef union tagged {
@@ -666,7 +666,7 @@ typedef struct {
// Boot rom: each block is 64-bit data
typedef `LOG_BOOT_ROM_BYTES LgBootRomBytes;
typedef TSub#(LgBootRomBytes, TLog#(NumBytes)) LgBootRomSzData;
typedef TSub#(LgBootRomBytes, TLog#(MemDataBytes)) LgBootRomSzData;
typedef Bit#(LgBootRomSzData) BootRomIndex;
// mtime: we increment mtime by 50 every 5000 cycles, this simulates a
@@ -753,6 +753,7 @@ Bit#(5) opFCVT_FW = 5'b11010;
//MiscMem
Bit#(3) fnFENCE = 3'b000;
Bit#(3) fnFENCEI = 3'b001;
Bit#(3) fnLC = 3'b010;
// System
Bit#(3) fnPRIV = 3'b000;

View File

@@ -74,7 +74,7 @@ typedef struct {
Maybe#(SCR) scr;
Maybe#(CSR) csr;
Bool claimed_phy_reg; // whether we need to commmit renaming
Maybe#(TrapWithCap)trap;
Maybe#(Trap) trap;
Addr tval; // in case of trap
PPCVAddrCSRData ppc_vaddr_csrData;
Bit#(5) fflags;
@@ -158,7 +158,7 @@ interface ReorderBufferRowEhr#(numeric type aluExeNum, numeric type fpuMulDivExe
method Action setExecuted_doFinishMem(CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -240,7 +240,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
Integer sb_enq_port = 1; // write spec_bits
Integer sb_correctSpec_port = 2; // write spec_bits
Ehr#(TAdd#(2, aluExeNum), CapMem) pc <- mkEhr(?);
Ehr#(TAdd#(2, aluExeNum), CapMem) pc <- mkEhr(?);
Reg #(Bit #(32)) orig_inst <- mkRegU;
Reg#(IType) iType <- mkRegU;
Reg #(Maybe #(ArchRIndx)) rg_dst_reg <- mkRegU;
@@ -252,8 +252,8 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
Reg#(Maybe#(CSR)) csr <- mkRegU;
Reg#(Maybe#(SCR)) scr <- mkRegU;
Reg#(Bool) claimed_phy_reg <- mkRegU;
Ehr#(TAdd#(TAdd#(2, TDiv#(aluExeNum,2)), aluExeNum), Maybe#(TrapWithCap)) trap <- mkEhr(?);
Ehr#(3, Maybe#(TrapWithCap)) mem_early_trap <- mkEhr(?);
Ehr#(TAdd#(TAdd#(2, TDiv#(aluExeNum,2)), aluExeNum), Maybe#(Trap)) trap <- mkEhr(?);
Ehr#(3, Maybe#(Trap)) mem_early_trap <- mkEhr(?);
Ehr#(TAdd#(TAdd#(2, TDiv#(aluExeNum,2)), aluExeNum), Addr) tval <- mkEhr(?);
Ehr#(TAdd#(2, aluExeNum), PPCVAddrCSRData) ppc_vaddr_csrData <- mkEhr(?);
Ehr#(TAdd#(1, fpuMulDivExeNum), Bit#(5)) fflags <- mkEhr(?);
@@ -309,7 +309,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
ppc_vaddr_csrData[pvc_finishAlu_port(i)] <= PPC (cast(cf.nextPc));
end
if (cause matches tagged Valid .exp) begin
trap[trap_finishAlu_port(i)] <= Valid (TrapWithCap{trap: tagged Exception CHERIFault, capExp: exp});
trap[trap_finishAlu_port(i)] <= Valid (CapException (exp));
tval[trap_finishAlu_port(i)] <= tval[trap_finishAlu_port(i)];
end
`ifdef RVFI
@@ -337,7 +337,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
// update fflags
fflags[fflags_finishFpuMulDiv_port(i)] <= new_fflags;
if (cause matches tagged Valid .exp) begin
trap[trap_finishFpuMulDiv_port(i)] <= Valid (TrapWithCap{trap: tagged Exception exp, capExp: noCapCause});
trap[trap_finishFpuMulDiv_port(i)] <= Valid (Exception (exp));
tval[trap_finishFpuMulDiv_port(i)] <= tval[trap_finishAlu_port(i)];
end
`ifdef RVFI
@@ -359,7 +359,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
method Action setExecuted_doFinishMem(CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -387,7 +387,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
// udpate non mmio st
nonMMIOStDone[nonMMIOSt_finishMem_port] <= non_mmio_st_done;
if (cause matches tagged Valid .exp) begin
mem_early_trap[0] <= Valid (TrapWithCap{trap: tagged Exception exp, capExp: noCapCause});
mem_early_trap[0] <= Valid ( CapException (exp));
tval[trap_finishMem_port] <= tval[trap_finishMem_port];
end
endmethod
@@ -516,7 +516,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p
// record trap
//doAssert(!isValid(trap[trap_deqLSQ_port]), "cannot have trap");
if (isValid(mem_early_trap[0])) trap[trap_deqLSQ_port] <= mem_early_trap[0];
else if(cause matches tagged Valid .e) trap[trap_deqLSQ_port] <= Valid (TrapWithCap{trap: tagged Exception e, capExp: noCapCause});
else if(cause matches tagged Valid .e) trap[trap_deqLSQ_port] <= Valid(Exception(e));
// TODO: shouldn't we record tval here as well?
// record ld misspeculation
ldKilled[ldKill_deqLSQ_port] <= ld_killed;
@@ -630,7 +630,7 @@ interface SupReorderBuffer#(numeric type aluExeNum, numeric type fpuMulDivExeNum
CapPipe vaddr,
Data store_data, ByteEn store_data_BE,
Bool access_at_commit, Bool non_mmio_st_done,
Maybe#(Exception) cause
Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, ExtraTraceBundle tb
`endif
@@ -1243,7 +1243,7 @@ module mkSupReorderBuffer#(
method Action setExecuted_doFinishMem(
InstTag x, CapPipe vaddr, Data store_data, ByteEn store_data_BE, Bool access_at_commit,
Bool non_mmio_st_done, Maybe#(Exception) cause
Bool non_mmio_st_done, Maybe#(CSR_XCapCause) cause
`ifdef RVFI
, tb
`endif

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2018 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -128,7 +128,7 @@ typedef struct {
Bool isMMIO;
// byte enable after shift to align with dword boudary. This is valid
// for all types of memory accesses.
ByteEn shiftedBE;
MemDataByteEn shiftedBE;
// ===================
// Status bits of the Ld. Typically we don't need to reset any bit as the
@@ -220,12 +220,12 @@ typedef struct {
Bool isMMIO;
// byte enable after shift to align with dword boudary. This is valid
// for all types of memory accesses.
ByteEn shiftedBE;
MemDataByteEn shiftedBE;
// St/Sc/Amo data
// for St/Sc: store data after shift to align with dword boudary
// for Amo: data is **NOT** shifted, this doesn't affect forwarding to Ld,
// because AMO never forwards data
Data stData;
MemTaggedData stData;
// ===================
// status bits of St/Sc/Amo
@@ -260,7 +260,7 @@ typedef struct {
typedef struct {
Maybe#(PhyDst) dst;
Data data; // align with dword, not final result written to reg file
MemTaggedData data; // align with dword, not final result written to reg file
} LSQForwardResult deriving(Bits, Eq, FShow);
typedef enum {LdQ, StQ, SB} LdStalledBy deriving(Bits, Eq, FShow);
@@ -274,7 +274,7 @@ typedef union tagged {
typedef struct {
LdQTag tag;
Addr paddr;
ByteEn shiftedBE;
MemDataByteEn shiftedBE;
} LSQIssueLdInfo deriving(Bits, Eq, FShow);
typedef struct {
@@ -283,7 +283,7 @@ typedef struct {
`ifdef INCLUDE_TANDEM_VERIF
InstTag instTag; // For recording Ld data in ROB
`endif
Data data;
MemTaggedData data;
} LSQRespLdResult deriving(Bits, Eq, FShow);
typedef struct {
@@ -295,14 +295,14 @@ typedef struct {
LdQTag tag;
InstTag instTag;
LdQMemFunc memFunc;
ByteEn byteEn;
MemDataByteEn byteEn;
Bool unsignedLd;
Bool acq;
Bool rel;
Maybe#(PhyDst) dst;
Addr paddr;
Bool isMMIO;
ByteEn shiftedBE;
MemDataByteEn shiftedBE;
Maybe#(Exception) fault;
Maybe#(LdKilledBy) killed;
} LdQDeqEntry deriving (Bits, Eq, FShow);
@@ -316,8 +316,8 @@ typedef struct {
Maybe#(PhyDst) dst;
Addr paddr;
Bool isMMIO;
ByteEn shiftedBE;
Data stData;
MemDataByteEn shiftedBE;
MemTaggedData stData;
Maybe#(Exception) fault;
} StQDeqEntry deriving (Bits, Eq, FShow);
@@ -336,29 +336,29 @@ interface SplitLSQ;
Maybe#(PhyDst) dst,
SpecBits spec_bits);
// A mem inst needs orignal BE (not shifted) at addr translation
method ByteEn getOrigBE(LdStQTag t);
method MemDataByteEn getOrigBE(LdStQTag t);
// Retrieve information when we want to wakeup RS early in case
// Ld/Lr/Sc/Amo hits in cache
method ActionValue#(LSQHitInfo) getHit(LdStQTag t);
// update store data (shifted for St and Sc, unshifted for AMO). XXX we
// assume data is updated before addr is updated
method Action updateData(StQTag t, Data d);
method Action updateData(StQTag t, MemTaggedData d);
// Update addr after address translation. Also search for the (oldest)
// younger load to kill. Return if the entry is waiting for wrong path
// resp, so Ld can be issued immediately.
method ActionValue#(LSQUpdateAddrResult) updateAddr(
LdStQTag lsqTag, Maybe#(Exception) fault,
// below are only meaningful wen fault is Invalid
Addr paddr, Bool isMMIO, ByteEn shiftedBE
Addr paddr, Bool isMMIO, MemDataByteEn shiftedBE
);
// Issue a load, and remove dependence on this load issue.
method ActionValue#(LSQIssueLdResult) issueLd(
LdQTag lsqTag, Addr paddr, ByteEn shiftedBE, SBSearchRes sbRes
LdQTag lsqTag, Addr paddr, MemDataByteEn shiftedBE, SBSearchRes sbRes
);
// Get the load to issue
method ActionValue#(LSQIssueLdInfo) getIssueLd;
// Get load resp
method ActionValue#(LSQRespLdResult) respLd(LdQTag t, Data alignedData);
method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData);
// Deq LQ entry, and wakeup stalled loads. The guard checks the following:
// (1) valid
// (2) one of the following is true:
@@ -444,7 +444,7 @@ endinterface
typedef Bit#(TLog#(TMul#(2, LdQSize))) LdQVirTag;
typedef Bit#(TLog#(TMul#(2, StQSize))) StQVirTag;
typedef Bit#(TSub#(AddrSz, TLog#(NumBytes))) DataAlignedAddr;
typedef Bit#(TSub#(AddrSz, TLog#(MemDataBytes))) DataAlignedAddr;
function DataAlignedAddr getDataAlignedAddr(Addr a) = truncateLSB(a);
// whether two memory accesses are to the same dword
@@ -453,28 +453,30 @@ function Bool sameAlignedAddr(Addr a, Addr b);
endfunction
// whether two memory accesses overlap
function Bool overlapAddr(Addr addr_1, ByteEn shift_be_1,
Addr addr_2, ByteEn shift_be_2);
function Bool overlapAddr(Addr addr_1, MemDataByteEn shift_be_1,
Addr addr_2, MemDataByteEn shift_be_2);
Bool be_overlap = (pack(shift_be_1) & pack(shift_be_2)) != 0;
return be_overlap && sameAlignedAddr(addr_1, addr_2);
endfunction
// check shiftBE1 covers shiftBE2
function Bool be1CoverBe2(ByteEn shift_be_1, ByteEn shift_be_2);
function Bool be1CoverBe2(MemDataByteEn shift_be_1, MemDataByteEn shift_be_2);
return (pack(shift_be_1) & pack(shift_be_2)) == pack(shift_be_2);
endfunction
// check whether mem op addr is aligned w.r.t data size
function Bool checkAddrAlign(Addr paddr, ByteEn be);
Bit#(TLog#(NumBytes)) byteOffset = truncate(paddr);
if(be[7]) begin
return byteOffset == 0;
function Bool checkAddrAlign(Addr addr, MemDataByteEn byteEn);
if(byteEn[15]) begin
return addr[3:0] == 0;
end
else if(be[3]) begin
return byteOffset[1:0] == 0;
else if(byteEn[7]) begin
return addr[2:0] == 0;
end
else if(be[1]) begin
return byteOffset[0] == 0;
else if(byteEn[3]) begin
return addr[1:0] == 0;
end
else if(byteEn[1]) begin
return addr[0] == 0;
end
else begin
return True;
@@ -614,13 +616,13 @@ module mkSplitLSQ(SplitLSQ);
Vector#(LdQSize, Reg#(InstTag)) ld_instTag <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(LdQMemFunc)) ld_memFunc <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(Bool)) ld_unsigned <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(ByteEn)) ld_byteEn <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(MemDataByteEn)) ld_byteEn <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(Bool)) ld_acq <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(Bool)) ld_rel <- replicateM(mkRegU);
Vector#(LdQSize, Reg#(Maybe#(PhyDst))) ld_dst <- replicateM(mkRegU);
Vector#(LdQSize, Ehr#(2, Addr)) ld_paddr <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(2, Bool)) ld_isMMIO <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(2, ByteEn)) ld_shiftedBE <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(2, MemDataByteEn)) ld_shiftedBE <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(2, Maybe#(Exception))) ld_fault <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(2, Bool)) ld_computed <- replicateM(mkEhr(?));
Vector#(LdQSize, Ehr#(3, Bool)) ld_inIssueQ <- replicateM(mkEhr(?));
@@ -803,14 +805,14 @@ module mkSplitLSQ(SplitLSQ);
Vector#(StQSize, Reg#(InstTag)) st_instTag <- replicateM(mkRegU);
Vector#(StQSize, Reg#(StQMemFunc)) st_memFunc <- replicateM(mkRegU);
Vector#(StQSize, Reg#(AmoFunc)) st_amoFunc <- replicateM(mkRegU);
Vector#(StQSize, Reg#(ByteEn)) st_byteEn <- replicateM(mkRegU);
Vector#(StQSize, Reg#(MemDataByteEn)) st_byteEn <- replicateM(mkRegU);
Vector#(StQSize, Reg#(Bool)) st_acq <- replicateM(mkRegU);
Vector#(StQSize, Reg#(Bool)) st_rel <- replicateM(mkRegU);
Vector#(StQSize, Reg#(Maybe#(PhyDst))) st_dst <- replicateM(mkRegU);
Vector#(StQSize, Ehr#(2, Addr)) st_paddr <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, Bool)) st_isMMIO <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, ByteEn)) st_shiftedBE <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(1, Data)) st_stData <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, MemDataByteEn)) st_shiftedBE <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(1, MemTaggedData)) st_stData <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, Maybe#(Exception))) st_fault <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, Bool)) st_computed <- replicateM(mkEhr(?));
Vector#(StQSize, Ehr#(2, Bool)) st_verified <- replicateM(mkEhr(?));
@@ -1373,7 +1375,7 @@ module mkSplitLSQ(SplitLSQ);
endinterface);
end
method ByteEn getOrigBE(LdStQTag t);
method MemDataByteEn getOrigBE(LdStQTag t);
return (case(t) matches
tagged Ld .tag: (ld_byteEn[tag]);
tagged St .tag: (st_byteEn[tag]);
@@ -1498,7 +1500,7 @@ module mkSplitLSQ(SplitLSQ);
wrongSpec_enq_conflict.wset(?);
endmethod
method Action updateData(StQTag t, Data d);
method Action updateData(StQTag t, MemTaggedData d);
`ifndef INORDER_CORE
// in-order core allocates entry and write data in the same rule
doAssert(st_valid_updData[t], "entry must be valid");
@@ -1509,7 +1511,7 @@ module mkSplitLSQ(SplitLSQ);
method ActionValue#(LSQUpdateAddrResult) updateAddr(
LdStQTag lsqTag, Maybe#(Exception) fault,
Addr pa, Bool mmio, ByteEn shift_be
Addr pa, Bool mmio, MemDataByteEn shift_be
);
// index vec for vector functions
Vector#(LdQSize, LdQTag) idxVec = genWith(fromInteger);
@@ -1685,7 +1687,7 @@ module mkSplitLSQ(SplitLSQ);
method ActionValue#(LSQIssueLdResult) issueLd(LdQTag tag,
Addr pa,
ByteEn shift_be,
MemDataByteEn shift_be,
SBSearchRes sbRes);
if(verbose) begin
$display("[LSQ - issueLd] ", fshow(tag), "; ", fshow(pa),
@@ -1974,7 +1976,7 @@ module mkSplitLSQ(SplitLSQ);
return issueLdQ.first.data;
endmethod
method ActionValue#(LSQRespLdResult) respLd(LdQTag t, Data alignedData);
method ActionValue#(LSQRespLdResult) respLd(LdQTag t, MemTaggedData alignedData);
let res = LSQRespLdResult {
wrongPath: False,
dst: Invalid,
@@ -2009,8 +2011,9 @@ module mkSplitLSQ(SplitLSQ);
let is32BitLd = (bEn[3] && !bEn[7]);
res.dst = ld_dst[t];
if (dst.Valid.isFpuReg && is32BitLd)
res.data = fv_nanbox (gatherLoad(ld_paddr_resp[t], ld_byteEn[t],
ld_unsigned[t], alignedData));
res.data = fv_nanbox_MemTaggedData(
gatherLoad(ld_paddr_resp[t], ld_byteEn[t],
ld_unsigned[t], alignedData));
else
res.data = gatherLoad(ld_paddr_resp[t], ld_byteEn[t],
ld_unsigned[t], alignedData);

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Massachusetts Institute of Technology
//
//
// 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
@@ -8,10 +8,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
@@ -32,50 +32,49 @@ import Ehr::*;
import CacheUtils::*;
// store buffer data block byte size == cache line
typedef CLineNumBytes SBBlockNumBytes;
typedef TMul#(8, SBBlockNumBytes) SBBlockSz;
typedef TMul#(8, CLineDataNumBytes) SBBlockSz;
typedef Bit#(SBBlockSz) SBBlock;
typedef Vector#(SBBlockNumBytes, Bool) SBByteEn;
typedef Vector#(CLineDataNumBytes, Bool) SBByteEn;
// aligned addr
typedef TSub#(AddrSz, TLog#(SBBlockNumBytes)) SBBlockAddrSz;
typedef TSub#(AddrSz, LogCLineDataNumBytes) SBBlockAddrSz;
typedef Bit#(SBBlockAddrSz) SBBlockAddr;
function SBBlockAddr getSBBlockAddr(Addr a);
return truncateLSB(a);
endfunction
// SB block vs. normal data
typedef TDiv#(SBBlockSz, DataSz) SBBlockNumData;
typedef Bit#(TLog#(SBBlockNumData)) SBBlockDataSel;
function SBBlockDataSel getSBBlockDataSel(Addr a);
return truncate(a >> valueOf(TLog#(NumBytes)));
typedef TDiv#(SBBlockSz, MemDataSz) SBBlockNumMemData;
typedef Bit#(TLog#(SBBlockNumMemData)) SBBlockMemDataSel;
function SBBlockMemDataSel getSBBlockMemDataSel(Addr a);
return truncate(a >> valueOf(TLog#(MemDataBytes)));
endfunction
// store buffer entry
typedef struct {
SBBlockAddr addr;
SBByteEn byteEn;
SBBlock data;
CLine line;
} SBEntry deriving(Bits, Eq, FShow);
// result of searching (e.g. load byass)
typedef struct {
Maybe#(SBIndex) matchIdx;
Maybe#(Data) forwardData; // XXX data is not shifted to match load addr offset
Maybe#(MemTaggedData) forwardData; // XXX data is not shifted to match load addr offset
} SBSearchRes deriving(Bits, Eq, FShow);
interface StoreBuffer;
method Bool isEmpty;
method Maybe#(SBIndex) getEnqIndex(Addr paddr);
method Action enq(SBIndex idx, Addr paddr, ByteEn be, Data data);
method Action enq(SBIndex idx, Addr paddr, MemDataByteEn be, MemTaggedData data);
method ActionValue#(SBEntry) deq(SBIndex idx);
method ActionValue#(Tuple2#(SBIndex, SBEntry)) issue;
method SBSearchRes search(Addr paddr, ByteEn be); // load bypass/stall or atomic inst stall
method SBSearchRes search(Addr paddr, MemDataByteEn be); // load bypass/stall or atomic inst stall
// check no matching entry for AMO/Lr/Sc issue
// XXX assume BE has been shifted approriately for paddr offset
// (for load we need to do that before calling the methods)
method Bool noMatchLdQ(Addr paddr, ByteEn be);
method Bool noMatchStQ(Addr paddr, ByteEn be);
method Bool noMatchLdQ(Addr paddr, MemDataByteEn be);
method Bool noMatchStQ(Addr paddr, MemDataByteEn be);
endinterface
/////////////////
@@ -100,7 +99,7 @@ module mkStoreBufferEhr(StoreBuffer);
// entries with valid bit
Vector#(SBSize, Ehr#(2, SBEntry)) entry <- replicateM(mkEhr(?));
Vector#(SBSize, Ehr#(2, Bool)) valid <- replicateM(mkEhr(False));
// FIFO of entries to be issued to memory
FIFOF#(SBIndex) issueQ <- mkUGSizedFIFOF(valueOf(SBSize));
// FIFO of empty entries
@@ -129,19 +128,19 @@ module mkStoreBufferEhr(StoreBuffer);
endcase
endfunction
function Bool noMatch(Addr paddr, ByteEn be);
function Bool noMatch(Addr paddr, MemDataByteEn be);
// input BE has been shifted, just pack it
Bit#(NumBytes) ldBE = pack(be);
Bit#(MemDataBytes) ldBE = pack(be);
// data offset within block
SBBlockDataSel sel = getSBBlockDataSel(paddr);
SBBlockMemDataSel sel = getSBBlockMemDataSel(paddr);
// helper to extract byteEn from entry
function Bit#(NumBytes) getEntryBE(SBIndex idx);
Vector#(SBBlockNumData, ByteEn) byteEn = unpack(pack(entry[idx][searchPort].byteEn));
function Bit#(MemDataBytes) getEntryBE(SBIndex idx);
Vector#(SBBlockNumMemData, MemDataByteEn) byteEn = unpack(pack(entry[idx][searchPort].byteEn));
return pack(byteEn[sel]);
endfunction
// func to determine whether the load matches a store entry
function Bool matchEntry(Integer i);
// entry must be valid, addr should match, byte enable should overlap
@@ -179,28 +178,27 @@ module mkStoreBufferEhr(StoreBuffer);
end
endmethod
method Action enq(SBIndex idx, Addr paddr, ByteEn be, Data d) if(inited);
method Action enq(SBIndex idx, Addr paddr, MemDataByteEn be, MemTaggedData d) if(inited);
// get data offset
SBBlockDataSel sel = getSBBlockDataSel(paddr);
SBBlockMemDataSel sel = getSBBlockMemDataSel(paddr);
// check whether the entry already exists
if(valid[idx][enqPort]) begin
// existing entry: merge
doAssert(getSBBlockAddr(paddr) == entry[idx][enqPort].addr, "SB enq to existing entry addr should match");
// update data
Vector#(SBBlockNumData, Data) block = unpack(entry[idx][enqPort].data);
Vector#(NumBytes, Bit#(8)) origData = unpack(block[sel]);
Vector#(NumBytes, Bit#(8)) wrData = unpack(d);
function Bit#(8) getNewByte(Integer i) = be[i] ? wrData[i] : origData[i];
Vector#(NumBytes, Bit#(8)) newData = map(getNewByte, genVector);
block[sel] = pack(newData);
CLine block = entry[idx][enqPort].line;
block.data[sel] = mergeDataBE(block.data[sel], d.data, be);
// update tag
if (pack(be) == ~0) block.tag[sel] = d.tag;
else if (pack(be) != 0) block.tag[sel] = False;
// update byte enable
Vector#(SBBlockNumData, ByteEn) byteEn = unpack(pack(entry[idx][enqPort].byteEn));
Vector#(SBBlockNumMemData, MemDataByteEn) byteEn = unpack(pack(entry[idx][enqPort].byteEn));
byteEn[sel] = unpack(pack(byteEn[sel]) | pack(be));
// update entry
entry[idx][enqPort] <= SBEntry {
addr: getSBBlockAddr(paddr),
byteEn: unpack(pack(byteEn)),
data: pack(block)
line: block
};
// this entry must have been sent to issueQ
end
@@ -208,14 +206,16 @@ module mkStoreBufferEhr(StoreBuffer);
// new entry: set valid
valid[idx][enqPort] <= True;
// setup entry
Vector#(SBBlockNumData, Data) block = ?;
block[sel] = d;
Vector#(SBBlockNumData, ByteEn) byteEn = replicate(replicate(False));
CLine block = ?;
block.data[sel] = d.data;
if (pack(be) == ~0) block.tag[sel] = d.tag;
else if (pack(be) != 0) block.tag[sel] = False;
Vector#(SBBlockNumMemData, MemDataByteEn) byteEn = replicate(replicate(False));
byteEn[sel] = be;
entry[idx][enqPort] <= SBEntry {
addr: getSBBlockAddr(paddr),
byteEn: unpack(pack(byteEn)),
data: pack(block)
line: block
};
// send this entry to issueQ
doAssert(issueQ.notFull, "SB issueQ should not be full");
@@ -239,19 +239,19 @@ module mkStoreBufferEhr(StoreBuffer);
return tuple2(idx, entry[idx][issuePort]);
endmethod
method SBSearchRes search(Addr paddr, ByteEn be);
method SBSearchRes search(Addr paddr, MemDataByteEn be);
// input BE has been shifted, just pack it
Bit#(NumBytes) ldBE = pack(be);
Bit#(MemDataBytes) ldBE = pack(be);
// data offset within block
SBBlockDataSel sel = getSBBlockDataSel(paddr);
SBBlockMemDataSel sel = getSBBlockMemDataSel(paddr);
// helper to extract byteEn from entry
function Bit#(NumBytes) getEntryBE(SBIndex idx);
Vector#(SBBlockNumData, ByteEn) byteEn = unpack(pack(entry[idx][searchPort].byteEn));
function Bit#(MemDataBytes) getEntryBE(SBIndex idx);
Vector#(SBBlockNumMemData, MemDataByteEn) byteEn = unpack(pack(entry[idx][searchPort].byteEn));
return pack(byteEn[sel]);
endfunction
// func to determine whether the load matches a store entry
function Bool matchEntry(Integer i);
// entry must be valid, addr should match, byte enable should overlap
@@ -266,10 +266,11 @@ module mkStoreBufferEhr(StoreBuffer);
// check whether bytes reading are all covered by the entry
if((getEntryBE(idx) & ldBE) == ldBE) begin
// fully covered, forward data
Vector#(SBBlockNumData, Data) block = unpack(entry[idx][searchPort].data);
CLine block = entry[idx][searchPort].line;
return SBSearchRes {
matchIdx: Valid (idx),
forwardData: Valid (block[sel])
forwardData: Valid (MemTaggedData { tag: block.tag[sel]
, data: block.data[sel]})
};
end
else begin
@@ -297,7 +298,7 @@ endmodule
module mkDummyStoreBuffer(StoreBuffer);
method Bool isEmpty = True;
method Maybe#(SBIndex) getEnqIndex(Addr paddr) = Invalid;
method Action enq(SBIndex idx, Addr paddr, ByteEn be, Data data);
method Action enq(SBIndex idx, Addr paddr, MemDataByteEn be, MemTaggedData data);
doAssert(False, "enq should never be called)");
endmethod
method ActionValue#(SBEntry) deq(SBIndex idx);
@@ -308,9 +309,9 @@ module mkDummyStoreBuffer(StoreBuffer);
doAssert(False, "issue should never be called)");
return ?;
endmethod
method SBSearchRes search(Addr paddr, ByteEn be);
method SBSearchRes search(Addr paddr, MemDataByteEn be);
return SBSearchRes {matchIdx: Invalid, forwardData: Invalid};
endmethod
method Bool noMatchLdQ(Addr paddr, ByteEn be) = True;
method Bool noMatchStQ(Addr paddr, ByteEn be) = True;
method Bool noMatchLdQ(Addr paddr, MemDataByteEn be) = True;
method Bool noMatchStQ(Addr paddr, MemDataByteEn be) = True;
endmodule

View File

@@ -37,6 +37,56 @@ typedef Bit#(AddrSz) Addr;
typedef 64 DataSz;
typedef Bit#(DataSz) Data;
typedef TDiv#(DataSz, 8) DataBytes;
typedef Vector#(DataBytes, Bool) ByteEn;
typedef struct {
tag_t tag;
data_t data;
} TaggedData#(type tag_t, type data_t) deriving (Bits, FShow, Eq);
typedef Vector#(2, Data) MemData;
typedef Bool MemTag;
typedef SizeOf#(MemData) MemDataSz;
typedef TDiv#(MemDataSz, 8) MemDataBytes;
typedef SizeOf#(MemTag) MemTagSz;
typedef SizeOf#(MemTaggedData) MemTaggedDataSz;
typedef TaggedData#(MemTag, MemData) MemTaggedData;
instance Literal#(MemTaggedData);
function fromInteger(i);
Bit#(MemDataSz) val = fromInteger(i);
return MemTaggedData { tag: False, data: unpack(val) };
endfunction
function inLiteralRange(x, i) = i < 2**valueOf(MemDataSz);
endinstance
function data_res mergeDataBE(data_t0 oldData, data_t1 newData, be_t be)
provisos( Bits#(data_t0, data_sz), Bits#(data_t1, data_sz), Bits#(be_t, be_sz)
, Bits#(data_res, data_sz)
, Mul#(be_sz, 8, data_sz));
Vector#(be_sz, Bit#(8)) oldVec = unpack(pack(oldData));
Vector#(be_sz, Bit#(8)) newVec = unpack(pack(newData));
Vector#(be_sz, Bool) beVec = unpack(pack(be));
function Bit#(8) getNewByte(Integer i) = beVec[i] ? newVec[i] : oldVec[i];
Vector#(be_sz, Bit#(8)) finalVec = map(getNewByte, genVector);
return unpack(pack(finalVec));
endfunction
function MemTaggedData mergeMemTaggedDataBE( MemTaggedData oldItem
, MemTaggedData newItem
, be_t be)
provisos (Bits#(be_t, MemDataBytes)) =
MemTaggedData { tag : (pack(be) == ~0) ? newItem.tag : False
, data: mergeDataBE(oldItem.data, newItem.data, be)};
function MemData dataToMemData(Data x) = unpack(zeroExtend(x));
function MemDataByteEn dataBEToMemDataBE(ByteEn x) = unpack(zeroExtend(pack(x)));
function Data memDataToData(MemData x) = x[0];
function ByteEn memDataBEToDataBE(MemDataByteEn x) = unpack(truncate(pack(x)));
function MemTaggedData toMemTaggedData(t x)
provisos (Bits#(t, sz), Add#(sz, smthg, MemDataSz)) = MemTaggedData {
tag: False,
data: unpack(zeroExtend(pack(x)))
};
function MemTaggedData dataToMemTaggedData(Data x) = toMemTaggedData(x);
function t fromMemTaggedData(MemTaggedData x)
provisos (Bits#(t, sz), Add#(sz, smthg, MemDataSz)) =
unpack(truncate(pack(x.data)));
typedef 32 InstSz;
typedef Bit#(InstSz) Instruction;
@@ -48,30 +98,34 @@ typedef Bit #(Inst16_Sz) Instruction16;
typedef 0 AsidSz; // not really implement ASID
typedef Bit#(AsidSz) Asid;
typedef TDiv#(DataSz, 8) NumBytes;
typedef TLog#(NumBytes) IndxShamt;
typedef Vector#(NumBytes, Bool) ByteEn;
typedef TLog#(MemDataBytes) IndxShamt;
typedef Vector#(MemDataBytes, Bool) MemDataByteEn;
typedef TDiv#(DataSz, InstSz) DataSzInst;
typedef TLog#(DataSzInst) LgDataSzInst;
typedef Bit#(LgDataSzInst) DataInstOffset;
typedef TDiv#(MemDataSz, InstSz) MemDataSzInst;
typedef TLog#(MemDataSzInst) LgMemDataSzInst;
typedef Bit#(LgMemDataSzInst) MemDataInstOffset;
// These types show up in many places so they are defined here
typedef enum {Swap, Add, Xor, And, Or, Min, Max, Minu, Maxu, None} AmoFunc deriving(Bits, Eq, FShow, Bounded);
typedef enum {QWord, DWord, Word} AmoWidth deriving(Bits, Eq, FShow, Bounded);
typedef enum { Ld, St, Lr, Sc, Amo, Fence } MemFunc deriving(Bits, Eq, FShow);
typedef struct {
AmoFunc func;
Bool doubleWord;
Bool aq;
Bool rl;
AmoFunc func;
AmoWidth width;
Bool aq;
Bool rl;
} AmoInst deriving(Bits, Eq, FShow);
typedef struct {
MemFunc mem_func; // Ld, St, Lr, Sc, Amo
AmoFunc amo_func;
Bool unsignedLd;
ByteEn byteEn; // takes place of double word
Bool aq;
Bool rl;
MemFunc mem_func; // Ld, St, Lr, Sc, Amo
AmoFunc amo_func;
Bool unsignedLd;
MemDataByteEn byteEn; // takes place of double word
Bool aq;
Bool rl;
Bool reg_bounds;
} MemInst deriving(Bits, Eq, FShow);
`ifdef BSIM
@@ -81,7 +135,7 @@ function Action doAssert(Bool b, String s) = dynamicAssert(b, s);
`endif
`ifdef RVFI_DII
typedef Vector#(`sizeSup, Maybe#(RVFI_DII_Execution #(DataSz,DataSz))) Rvfi_Traces;
typedef Vector#(`sizeSup, Maybe#(RVFI_DII_Execution #(64, 64))) Rvfi_Traces;
typedef Vector#(`sizeSup, Maybe#(Dii_Id)) Dii_Ids;
typedef Vector#(`sizeSup, Maybe#(Bit#(32))) Dii_Insts;