diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index f1efa12..d207a3e 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -320,7 +320,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // pipeline fifos let dispToRegQ <- mkMemDispToRegFifo; let regToExeQ <- mkMemRegToExeFifo; - // let trollToExeQ <- mkMemRegToExeFifo; + let trollToExeQ <- mkMemRegToExeFifo; // wire to recv bypass Vector#(TMul#(2, AluExeNum), RWire#(Tuple2#(PhyRIndx, CapPipe))) bypassWire <- replicateM(mkRWire); @@ -603,154 +603,231 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); let x = regToExe.data; // trollToExeQ.enq(regToExe); // ============================== - if(verbose) $display("%t : [doExeMem] ", $time, fshow(regToExe)); +// if(verbose) $display("%t : [doExeMem] ", $time, fshow(regToExe)); - let shiftBE = DataMemAccess(x.shiftBEData); - if (x.origBE == TagMemAccess) begin - shiftBE = TagMemAccess; - end +// // Moved to the next stage +// // let shiftBE = DataMemAccess(x.shiftBEData); +// // if (x.origBE == TagMemAccess) begin +// // shiftBE = TagMemAccess; +// // end + +// CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC)); + +// // get size of the access +// Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(x.origBE.DataMemAccess)))); +// if (x.origBE == TagMemAccess) begin +// accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes)); +// end + +// `ifdef KONATA +// $display("KONATAE\t%0d\t%0d\t0\tMem2", cur_cycle, x.u_id); +// $display("KONATAS\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id); +// $fflush; +// `endif + // Make our own versions where this is passed as a queue to + // the next stage and processed there: + // We only need + // - x.mem_func(Maybe to see if it's a load ?) + // - x (We can get the hardware permissions, cap_mem permission, prepareBoundsCheck) + // - We will assume a one on one mapping with offset with a delta value of 1 (Hardcoded + // for just testing) + trollToExeQ.enq(regToExe); + + // go to next stage by sending to TLB +// dTlb.procReq(DTlbReq { +// inst: MemExeToFinish { +// mem_func: x.mem_func, +// tag: x.tag, +// ldstq_tag: x.ldstq_tag, +// shiftedBE: shiftBE, +// vaddr: x.vaddr, +// `ifdef INCLUDE_TANDEM_VERIF +// store_data: x.rVal2, +// store_data_BE: origBE, +// `endif +// misaligned: memAddrMisaligned(getAddr(x.vaddr), x.origBE), +// capStore: isValidCap(x.rVal2) && x.origBE == DataMemAccess(unpack(~0)), +// allowCapLoad: getHardPerms(x.rVal1).permitLoadCap && x.origBE == DataMemAccess(unpack(~0)), +// capException: capChecksMem(x.rVal1, x.rVal2, x.cap_checks, x.mem_func, x.origBE), +// check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/, +// ddc, getAddr(x.vaddr), accessByteCount, x.cap_checks) +// `ifdef KONATA +// , u_id: x.u_id +// `endif +// }, +// specBits: regToExe.spec_bits +// }); + + // When the DTLB proq request is called + // Could be only 1 at a time but let's assume there are plenty + // We assume there is queue of requests (|,|,|,|), We assume these run while other instructions + // are getting executed (When Proq response is called one by one from the queue responses with + // physical addresses are being executed to be stored or read from memory). + + endrule + + rule doFinishMem; + // Over here we are reducing the tracing surface area to ensure + // It's easier to write a TLB bypasser. + let regToExe = trollToExeQ.first; + // Let's check if lol access data can be found in the + // the previous stage. + let lol = regToExe.data; + // ============================= + // dTlb.deqProcResp; + // let dTlbResp = dTlb.procResp; + // Assumtion instruction related can be passed on + // from the previous stage. + // let tlbresp = dTlbResp.inst; + // let {paddr, expCause, allowCapPTE} = dTlbResp.resp; + // Assuming physcial address is virtual address just for testing + let paddr = getAddr(lol.vaddr); + // These are just assumtions for testing + let expCause = False; + let allowCapPTE = True; + + if(verbose) $display("%t : [doFinishMem] ", $time, fshow(regToExe)); + + // Moved to the next stage + // let shiftBE = DataMemAccess(x.shiftBEData); + // if (x.origBE == TagMemAccess) begin + // shiftBE = TagMemAccess; + // end CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC)); // get size of the access - Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(x.origBE.DataMemAccess)))); - if (x.origBE == TagMemAccess) begin - accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes)); - end + // Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(x.origBE.DataMemAccess)))); + // if (x.origBE == TagMemAccess) begin + // accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes)); + // end `ifdef KONATA $display("KONATAE\t%0d\t%0d\t0\tMem2", cur_cycle, x.u_id); $display("KONATAS\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id); $fflush; `endif - // go to next stage by sending to TLB - dTlb.procReq(DTlbReq { - inst: MemExeToFinish { - mem_func: x.mem_func, - tag: x.tag, - ldstq_tag: x.ldstq_tag, - shiftedBE: shiftBE, - vaddr: x.vaddr, -`ifdef INCLUDE_TANDEM_VERIF - store_data: x.rVal2, - store_data_BE: origBE, -`endif - misaligned: memAddrMisaligned(getAddr(x.vaddr), x.origBE), - capStore: isValidCap(x.rVal2) && x.origBE == DataMemAccess(unpack(~0)), - allowCapLoad: getHardPerms(x.rVal1).permitLoadCap && x.origBE == DataMemAccess(unpack(~0)), - capException: capChecksMem(x.rVal1, x.rVal2, x.cap_checks, x.mem_func, x.origBE), - check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/, - ddc, getAddr(x.vaddr), accessByteCount, x.cap_checks) -`ifdef KONATA - , u_id: x.u_id -`endif - }, - specBits: regToExe.spec_bits - }); - endrule - rule doFinishMem; - // trollToExeQ.deq; - // let regToExe = trollToExeQ.first; - // let lol = regToExe.data; - // ============================= - dTlb.deqProcResp; - let dTlbResp = dTlb.procResp; - let x = dTlbResp.inst; - let {paddr, expCause, allowCapPTE} = dTlbResp.resp; - // paddr = getAddr(lol.vaddr); - // expCause = False; - // allowCapPTE = True; + // Capability checks computed early over instead of the previous stage + // This will resolve: + // - .check + // - .capException + // - .allowCapLoad + // - .capStore + + // get access byte count + // get size of the access + Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(lol.origBE.DataMemAccess)))); + if (lol.origBE == TagMemAccess) begin + accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes)); + end + let check = prepareBoundsCheck(lol.rVal1, lol.rVal2, almightyCap/*ToDo: pcc*/,ddc, getAddr(lol.vaddr), accessByteCount, lol.cap_checks); + + let capException = capChecksMem(lol.rVal1, lol.rVal2, lol.cap_checks, lol.mem_func, lol.origBE); + + let allowCapLoad = getHardPerms(lol.rVal1).permitLoadCap && lol.origBE == DataMemAccess(unpack(~0)); + + // (TODO) Still need to pass the: + // (done) tag + // (done) ldstq_tag + // (done) shiftedBE + let shiftBE = DataMemAccess(lol.shiftBEData); + if (lol.origBE == TagMemAccess) begin + shiftBE = TagMemAccess; + end Maybe#(Trap) cause = Invalid; - if (expCause matches tagged Valid .c) cause = Valid(Exception(c)); + // if (expCause matches tagged Valid .c) cause = Valid(Exception(c)); - if(verbose) $display("%t : [doFinishMem] ", $time, fshow(dTlbResp)); - if(isValid(cause) && verbose) $display(" [doFinishMem - dTlb response] PAGEFAULT!"); + // if(verbose) $display("%t : [doFinishMem] ", $time, fshow(dTlbResp)); + $display("Bypassing TLB"); + // if(isValid(cause) && verbose) $display(" [doFinishMem - dTlb response] PAGEFAULT!"); Data store_data = ?; ByteEn store_data_BE = ?; -`ifdef INCLUDE_TANDEM_VERIF - store_data = x.store_data; - store_data_BE = x.store_data_BE; -`endif +// `ifdef INCLUDE_TANDEM_VERIF +// store_data = tlbresp.store_data; +// store_data_BE = tlbresp.store_data_BE; +// `endif // check misalignment - if(!isValid(cause) && x.misaligned) begin - case(x.mem_func) - Ld, Lr: begin - cause = Valid(Exception(excLoadAddrMisaligned)); - end - default: begin - cause = Valid(Exception(excStoreAddrMisaligned)); - end - endcase - end + // if(!isValid(cause) && x.misaligned) begin + // case(x.mem_func) + // Ld, Lr: begin + // cause = Valid(Exception(excLoadAddrMisaligned)); + // end + // default: begin + // cause = Valid(Exception(excStoreAddrMisaligned)); + // end + // endcase + // end -`ifdef RVFI_DII - // TestRIG expects us throw an access fault for any memory access outside of a 8 MiB memory at 0x8000000. - if (!isValid(cause) && (paddr < 'h80000000 || paddr >= 'h80800000)) begin - case(x.mem_func) - Ld, Lr: begin - cause = Valid(Exception(excLoadAccessFault)); - end - default: begin - cause = Valid(Exception(excStoreAccessFault)); - end - endcase - end -`endif +// `ifdef RVFI_DII +// // TestRIG expects us throw an access fault for any memory access outside of a 8 MiB memory at 0x8000000. +// if (!isValid(cause) && (paddr < 'h80000000 || paddr >= 'h80800000)) begin +// case(tlbresp.mem_func) +// Ld, Lr: begin +// cause = Valid(Exception(excLoadAccessFault)); +// end +// default: begin +// cause = Valid(Exception(excStoreAccessFault)); +// end +// endcase +// end +// `endif // check if addr is MMIO (only valid in case of no page fault) Bool isMMIO = inIfc.isMMIOAddr(paddr); // raise access fault in case of MMIO Lr/Sc - if(!isValid(cause) && isMMIO) begin - case(x.mem_func) - Lr: begin - cause = Valid(Exception(excLoadAccessFault)); - end - Sc: begin - cause = Valid(Exception(excStoreAccessFault)); - end - endcase - end + // if(!isValid(cause) && isMMIO) begin + // case(lol.mem_func) + // Lr: begin + // cause = Valid(Exception(excLoadAccessFault)); + // end + // Sc: begin + // cause = Valid(Exception(excStoreAccessFault)); + // end + // endcase + // end // update ROB (access at commit and non-mmio st done can only be true // when there is no exceptio) - Bool isLrScAmo = (case(x.mem_func) + Bool isLrScAmo = (case(lol.mem_func) Lr, Sc, Amo: True; default: False; endcase); - if (x.check matches tagged Valid .check &&& x.capException matches tagged Invalid) begin + if (check matches tagged Valid .check &&& 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: cheriExcLengthViolation}); + capException = Valid(CSR_XCapCause{cheri_exc_reg: check.authority_idx, cheri_exc_code: cheriExcLengthViolation}); end - if (x.capException matches tagged Valid .c) cause = Valid(CapException(c)); - Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo); - Bool non_mmio_st_done = !isValid(cause) && !isMMIO && x.mem_func == St; - inIfc.rob_setExecuted_doFinishMem(x.tag, getAddr(x.vaddr), -`ifdef INCLUDE_TANDEM_VERIF - store_data, store_data_BE, -`endif + // if (capException matches tagged Valid .c) cause = Valid(CapException(c)); + // Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo); + Bool access_at_commit = True; + // Bool non_mmio_st_done = !isValid(cause) && !isMMIO && lol.mem_func == St; + Bool non_mmio_st_done = !isMMIO && lol.mem_func == St; + inIfc.rob_setExecuted_doFinishMem(lol.tag, getAddr(lol.vaddr), +// `ifdef INCLUDE_TANDEM_VERIF +// store_data, store_data_BE, +// `endif access_at_commit, non_mmio_st_done -`ifdef RVFI - , ExtraTraceBundle{ - regWriteData: memData[pack(x.ldstq_tag)], - memByteEn: unpack(truncate(pack(x.shiftedBE.DataMemAccess) >> getAddr(x.vaddr)[3:0])) - } -`endif +// `ifdef RVFI +// , ExtraTraceBundle{ +// regWriteData: memData[pack(tlbresp.ldstq_tag)], +// memByteEn: unpack(truncate(pack(tlbresp.shiftedBE.DataMemAccess) >> getAddr(tlbresp.vaddr)[3:0])) +// } +// `endif ); - let pc = inIfc.rob_getPC(x.tag); + let pc = inIfc.rob_getPC(lol.tag); `ifdef PERFORMANCE_MONITORING `ifdef CONTRACTS_VERIFY function Bool is_16b_inst (Bit #(n) inst); return (inst [1:0] != 2'b11); endfunction - let ppc = inIfc.rob_getPredPC(x.tag); - let inst = inIfc.rob_getOrig_Inst(x.tag); + let ppc = inIfc.rob_getPredPC(lol.tag); + let inst = inIfc.rob_getOrig_Inst(lol.tag); let validPc = is_16b_inst(inst) ? addPc(pc,2) : addPc(pc,4); if(cause matches tagged Valid .c &&& (ppc != validPc)) begin EventsTransExe events_trans = unpack(0); @@ -760,28 +837,33 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif `endif -`ifdef KONATA - $display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id); - $display("KONATAS\t%0d\t%0d\t0\tMem4", cur_cycle, x.u_id); - $fflush; -`endif +// `ifdef KONATA +// $display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, tlbresp.u_id); +// $display("KONATAS\t%0d\t%0d\t0\tMem4", cur_cycle, tlbresp.u_id); +// $fflush; +// `endif // Try me! // if (x.mem_func == St) begin // paddr = 256; // end // update LSQ + // Important bit that updates memory ? + // LSQUpdateAddrResult updRes <- lsq.updateAddr( + // lol.ldstq_tag, cause, allowCapLoad && allowCapPTE, paddr, isMMIO, shiftBE + // ); LSQUpdateAddrResult updRes <- lsq.updateAddr( - x.ldstq_tag, cause, x.allowCapLoad && allowCapPTE, paddr, isMMIO, x.shiftedBE + lol.ldstq_tag, cause, allowCapLoad && allowCapPTE, paddr, isMMIO, shiftBE ); + // issue non-MMIO Ld which has no exception and is not waiting for // wrong path resp - if (x.mem_func == Ld && !isMMIO && + if (lol.mem_func == Ld && !isMMIO && !isValid(cause) && !updRes.waitWPResp && !updRes.delayIssue) begin LdQTag ldTag = ?; - if(x.ldstq_tag matches tagged Ld .t) begin + if(lol.ldstq_tag matches tagged Ld .t) begin ldTag = t; end else begin @@ -790,7 +872,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); issueLd.wset(LSQIssueLdInfo { tag: ldTag, paddr: paddr, - shiftedBE: x.shiftedBE, + shiftedBE: shiftBE, pcHash: hash(getAddr(pc)) }); end