diff --git a/README.md b/README.md index e8d0850..b03c45e 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/libs/cheri-cap-lib b/libs/cheri-cap-lib index dd24b76..3bb13f1 160000 --- a/libs/cheri-cap-lib +++ b/libs/cheri-cap-lib @@ -1 +1 @@ -Subproject commit dd24b7672b1b7479a9a665915d7682cb75e84e60 +Subproject commit 3bb13f1c87c78c7e3d6fe73c3d7b66786c300f3c diff --git a/src_Core/CHERI/ScrFile.bsv b/src_Core/CHERI/ScrFile.bsv deleted file mode 100644 index e69de29..0000000 diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index ffeb6ab..70c1f3d 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -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; diff --git a/src_Core/CPU/LLC_AXI4_Adapter.bsv b/src_Core/CPU/LLC_AXI4_Adapter.bsv index 521c3b3..23a12af 100644 --- a/src_Core/CPU/LLC_AXI4_Adapter.bsv +++ b/src_Core/CPU/LLC_AXI4_Adapter.bsv @@ -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); diff --git a/src_Core/CPU/MMIOPlatform.bsv b/src_Core/CPU/MMIOPlatform.bsv index b0840a2..4ae94d4 100644 --- a/src_Core/CPU/MMIOPlatform.bsv +++ b/src_Core/CPU/MMIOPlatform.bsv @@ -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 diff --git a/src_Core/CPU/MMIO_AXI4_Adapter.bsv b/src_Core/CPU/MMIO_AXI4_Adapter.bsv index 257dffe..5ec606a 100644 --- a/src_Core/CPU/MMIO_AXI4_Adapter.bsv +++ b/src_Core/CPU/MMIO_AXI4_Adapter.bsv @@ -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", diff --git a/src_Core/ISA/ISA_Decls_CHERI.bsv b/src_Core/ISA/ISA_Decls_CHERI.bsv index ce3e87c..63450e9 100755 --- a/src_Core/ISA/ISA_Decls_CHERI.bsv +++ b/src_Core/ISA/ISA_Decls_CHERI.bsv @@ -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)}; diff --git a/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv b/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv index f2f5f21..0f44b20 100644 --- a/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CCTypes.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/coherence/src/IBank.bsv b/src_Core/RISCY_OOO/coherence/src/IBank.bsv index 41e5c3b..6615bc5 100644 --- a/src_Core/RISCY_OOO/coherence/src/IBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/IBank.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv index 9116e86..2e1fbbe 100644 --- a/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/L1Bank.bsv @@ -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) diff --git a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv index ff4af5f..c8f4ae9 100644 --- a/src_Core/RISCY_OOO/coherence/src/LLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/LLBank.bsv @@ -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) diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvIBank.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvIBank.bsv index 73c063d..45c0c45 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvIBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvIBank.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvL1Bank.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvL1Bank.bsv index b00ebce..ffc25fe 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvL1Bank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvL1Bank.bsv @@ -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 { diff --git a/src_Core/RISCY_OOO/coherence/src/SelfInvLLBank.bsv b/src_Core/RISCY_OOO/coherence/src/SelfInvLLBank.bsv index 089b2c0..50c7245 100644 --- a/src_Core/RISCY_OOO/coherence/src/SelfInvLLBank.bsv +++ b/src_Core/RISCY_OOO/coherence/src/SelfInvLLBank.bsv @@ -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) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index a4ec801..c3b2b41 100755 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 4c31d52..939f8b4 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 3f255fa..50bc8d0 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index b41bc64..7a1ffb5 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index b7867ef..2d593d8 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -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, diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/ReservationStationMem.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/ReservationStationMem.bsv index 8bbf195..d5f05d0 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/ReservationStationMem.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/ReservationStationMem.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/Amo.bsv b/src_Core/RISCY_OOO/procs/lib/Amo.bsv index 3b36ad9..5ed8a4b 100644 --- a/src_Core/RISCY_OOO/procs/lib/Amo.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Amo.bsv @@ -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 ); diff --git a/src_Core/RISCY_OOO/procs/lib/CacheUtils.bsv b/src_Core/RISCY_OOO/procs/lib/CacheUtils.bsv index a443bb3..d5dfbba 100644 --- a/src_Core/RISCY_OOO/procs/lib/CacheUtils.bsv +++ b/src_Core/RISCY_OOO/procs/lib/CacheUtils.bsv @@ -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); diff --git a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi index 77a3aa6..d2aad26 100644 --- a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi @@ -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") diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index e4e5199..2d7d8ae 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index 9787fc7..79d7e38 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/FP_Utils.bsv b/src_Core/RISCY_OOO/procs/lib/FP_Utils.bsv index db5fe71..3e0dab1 100644 --- a/src_Core/RISCY_OOO/procs/lib/FP_Utils.bsv +++ b/src_Core/RISCY_OOO/procs/lib/FP_Utils.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv index 8c39764..229c376 100644 --- a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv +++ b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv @@ -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); diff --git a/src_Core/RISCY_OOO/procs/lib/MMIOCore.bsv b/src_Core/RISCY_OOO/procs/lib/MMIOCore.bsv index 7f89a8d..0864791 100644 --- a/src_Core/RISCY_OOO/procs/lib/MMIOCore.bsv +++ b/src_Core/RISCY_OOO/procs/lib/MMIOCore.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/MemLoader.bsv b/src_Core/RISCY_OOO/procs/lib/MemLoader.bsv index 06ac097..22141d2 100644 --- a/src_Core/RISCY_OOO/procs/lib/MemLoader.bsv +++ b/src_Core/RISCY_OOO/procs/lib/MemLoader.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/MemoryTypes.bsv b/src_Core/RISCY_OOO/procs/lib/MemoryTypes.bsv index 4a524cd..60692bb 100644 --- a/src_Core/RISCY_OOO/procs/lib/MemoryTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/MemoryTypes.bsv @@ -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; - diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index c4f5a06..bb865ca 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -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; diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index 7d42921..93c533e 100755 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index 03654f7..966ea72 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -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); diff --git a/src_Core/RISCY_OOO/procs/lib/StoreBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/StoreBuffer.bsv index 75e3769..a99d4bb 100644 --- a/src_Core/RISCY_OOO/procs/lib/StoreBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/StoreBuffer.bsv @@ -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 diff --git a/src_Core/RISCY_OOO/procs/lib/Types.bsv b/src_Core/RISCY_OOO/procs/lib/Types.bsv index 58ffc2b..db21dc2 100644 --- a/src_Core/RISCY_OOO/procs/lib/Types.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Types.bsv @@ -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;