3 Commits

Author SHA1 Message Date
9f7aa79b99 saving current changes 2026-01-25 14:24:20 +00:00
f2cc45d169 other changes 2026-01-20 18:05:54 +00:00
b9b318b4f5 added compilable TLB bypass need to fix assert
run time error
2026-01-20 18:04:13 +00:00
2 changed files with 176 additions and 96 deletions

View File

@@ -8,11 +8,11 @@ ARCH ?= RV64ACDFIMSUxCHERI
BSC_COMPILATION_FLAGS += -verbose BSC_COMPILATION_FLAGS += -verbose
# Default ISA test # Default ISA test
# TEST ?= rv64ui-p-add TEST ?= rv64ui-p-add
# TEST ?= rv64um-v-mulw # TEST ?= rv64um-v-mulw
# TEST ?= Page # TEST ?= Page
# TEST ?= PageReadWrite # TEST ?= PageReadWrite
TEST ?= CheriPage # TEST ?= CheriPage
#================================================================ #================================================================
# Parameter settings for MIT RISCY, setup paths etc. for Include_Common # Parameter settings for MIT RISCY, setup paths etc. for Include_Common

View File

@@ -320,7 +320,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// pipeline fifos // pipeline fifos
let dispToRegQ <- mkMemDispToRegFifo; let dispToRegQ <- mkMemDispToRegFifo;
let regToExeQ <- mkMemRegToExeFifo; let regToExeQ <- mkMemRegToExeFifo;
// let trollToExeQ <- mkMemRegToExeFifo; let trollToExeQ <- mkMemRegToExeFifo;
// wire to recv bypass // wire to recv bypass
Vector#(TMul#(2, AluExeNum), RWire#(Tuple2#(PhyRIndx, CapPipe))) bypassWire <- replicateM(mkRWire); Vector#(TMul#(2, AluExeNum), RWire#(Tuple2#(PhyRIndx, CapPipe))) bypassWire <- replicateM(mkRWire);
@@ -603,81 +603,154 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
let x = regToExe.data; let x = regToExe.data;
// trollToExeQ.enq(regToExe); // trollToExeQ.enq(regToExe);
// ============================== // ==============================
if(verbose) $display("%t : [doExeMem] ", $time, fshow(regToExe)); // if(verbose) $display("%t : [doExeMem] ", $time, fshow(regToExe));
let shiftBE = DataMemAccess(x.shiftBEData); // // Moved to the next stage
if (x.origBE == TagMemAccess) begin // // 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 = dTlb.Invalid;
let allowCapPTE = True;
if(verbose) $display("%t : [doFinishMem] ", $time, fshow(regToExe));
// Moved to the next stage
let shiftBE = DataMemAccess(lol.shiftBEData);
if (lol.origBE == TagMemAccess) begin
shiftBE = TagMemAccess; shiftBE = TagMemAccess;
end end
CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC)); CapPipe ddc = cast(inIfc.scaprf_rd(scrAddrDDC));
// get size of the access // get size of the access
Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(x.origBE.DataMemAccess)))); // Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(x.origBE.DataMemAccess))));
if (x.origBE == TagMemAccess) begin // if (x.origBE == TagMemAccess) begin
accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes)); // accessByteCount = fromInteger(valueOf(CacheUtils::CLineNumMemDataBytes));
end // end
`ifdef KONATA `ifdef KONATA
$display("KONATAE\t%0d\t%0d\t0\tMem2", cur_cycle, x.u_id); $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); $display("KONATAS\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id);
$fflush; $fflush;
`endif `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; // Capability checks computed early over instead of the previous stage
// trollToExeQ.deq; // This will resolve:
// let regToExe = trollToExeQ.first; // - .check
// let lol = regToExe.data; // - .capException
// ============================= // - .allowCapLoad
dTlb.deqProcResp; // - .capStore
let dTlbResp = dTlb.procResp;
let x = dTlbResp.inst; // get access byte count
let {paddr, expCause, allowCapPTE} = dTlbResp.resp; // get size of the access
// paddr = getAddr(lol.vaddr); Bit#(TAdd#(CacheUtils::LogCLineNumMemDataBytes,1)) accessByteCount = zeroExtend(pack(countOnes(pack(lol.origBE.DataMemAccess))));
// expCause = False; if (lol.origBE == TagMemAccess) begin
// allowCapPTE = True; 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
Maybe#(Trap) cause = Invalid; 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 = ?; Data store_data = ?;
ByteEn store_data_BE = ?; ByteEn store_data_BE = ?;
`ifdef INCLUDE_TANDEM_VERIF // `ifdef INCLUDE_TANDEM_VERIF
store_data = x.store_data; // store_data = tlbresp.store_data;
store_data_BE = x.store_data_BE; // store_data_BE = tlbresp.store_data_BE;
`endif // `endif
let misaligned = memAddrMisaligned(getAddr(lol.vaddr), lol.origBE);
// check misalignment // check misalignment
if(!isValid(cause) && x.misaligned) begin if(!isValid(cause) && misaligned) begin
case(x.mem_func) case(lol.mem_func)
Ld, Lr: begin Ld, Lr: begin
cause = Valid(Exception(excLoadAddrMisaligned)); cause = Valid(Exception(excLoadAddrMisaligned));
end end
@@ -687,25 +760,25 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
endcase endcase
end end
`ifdef RVFI_DII // `ifdef RVFI_DII
// TestRIG expects us throw an access fault for any memory access outside of a 8 MiB memory at 0x8000000. // // 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 // if (!isValid(cause) && (paddr < 'h80000000 || paddr >= 'h80800000)) begin
case(x.mem_func) // case(tlbresp.mem_func)
Ld, Lr: begin // Ld, Lr: begin
cause = Valid(Exception(excLoadAccessFault)); // cause = Valid(Exception(excLoadAccessFault));
end // end
default: begin // default: begin
cause = Valid(Exception(excStoreAccessFault)); // cause = Valid(Exception(excStoreAccessFault));
end // end
endcase // endcase
end // end
`endif // `endif
// check if addr is MMIO (only valid in case of no page fault) // check if addr is MMIO (only valid in case of no page fault)
Bool isMMIO = inIfc.isMMIOAddr(paddr); Bool isMMIO = inIfc.isMMIOAddr(paddr);
// raise access fault in case of MMIO Lr/Sc // raise access fault in case of MMIO Lr/Sc
if(!isValid(cause) && isMMIO) begin if(!isValid(cause) && isMMIO) begin
case(x.mem_func) case(lol.mem_func)
Lr: begin Lr: begin
cause = Valid(Exception(excLoadAccessFault)); cause = Valid(Exception(excLoadAccessFault));
end end
@@ -717,40 +790,42 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
// update ROB (access at commit and non-mmio st done can only be true // update ROB (access at commit and non-mmio st done can only be true
// when there is no exceptio) // when there is no exceptio)
Bool isLrScAmo = (case(x.mem_func) Bool isLrScAmo = (case(lol.mem_func)
Lr, Sc, Amo: True; Lr, Sc, Amo: True;
default: False; default: False;
endcase); 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) && if (!( (check.check_low >= check.authority_base) &&
(check.check_inclusive ? (check.check_high <= check.authority_top ) (check.check_inclusive ? (check.check_high <= check.authority_top )
: (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 end
if (x.capException matches tagged Valid .c) cause = Valid(CapException(c)); if (capException matches tagged Valid .c) cause = Valid(CapException(c));
Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo); Bool access_at_commit = !isValid(cause) && (isMMIO || isLrScAmo);
Bool non_mmio_st_done = !isValid(cause) && !isMMIO && x.mem_func == St; // Bool access_at_commit = True;
inIfc.rob_setExecuted_doFinishMem(x.tag, getAddr(x.vaddr), Bool non_mmio_st_done = !isValid(cause) && !isMMIO && lol.mem_func == St;
`ifdef INCLUDE_TANDEM_VERIF // Bool non_mmio_st_done = !isMMIO && lol.mem_func == St;
store_data, store_data_BE, inIfc.rob_setExecuted_doFinishMem(lol.tag, getAddr(lol.vaddr),
`endif // `ifdef INCLUDE_TANDEM_VERIF
// store_data, store_data_BE,
// `endif
access_at_commit, non_mmio_st_done access_at_commit, non_mmio_st_done
`ifdef RVFI `ifdef RVFI
, ExtraTraceBundle{ // , ExtraTraceBundle{
regWriteData: memData[pack(x.ldstq_tag)], // regWriteData: memData[pack(tlbresp.ldstq_tag)],
memByteEn: unpack(truncate(pack(x.shiftedBE.DataMemAccess) >> getAddr(x.vaddr)[3:0])) // memByteEn: unpack(truncate(pack(tlbresp.shiftedBE.DataMemAccess) >> getAddr(tlbresp.vaddr)[3:0]))
} // }
`endif // `endif
); );
let pc = inIfc.rob_getPC(x.tag); let pc = inIfc.rob_getPC(lol.tag);
`ifdef PERFORMANCE_MONITORING `ifdef PERFORMANCE_MONITORING
`ifdef CONTRACTS_VERIFY `ifdef CONTRACTS_VERIFY
function Bool is_16b_inst (Bit #(n) inst); function Bool is_16b_inst (Bit #(n) inst);
return (inst [1:0] != 2'b11); return (inst [1:0] != 2'b11);
endfunction endfunction
let ppc = inIfc.rob_getPredPC(x.tag); let ppc = inIfc.rob_getPredPC(lol.tag);
let inst = inIfc.rob_getOrig_Inst(x.tag); let inst = inIfc.rob_getOrig_Inst(lol.tag);
let validPc = is_16b_inst(inst) ? addPc(pc,2) : addPc(pc,4); let validPc = is_16b_inst(inst) ? addPc(pc,2) : addPc(pc,4);
if(cause matches tagged Valid .c &&& (ppc != validPc)) begin if(cause matches tagged Valid .c &&& (ppc != validPc)) begin
EventsTransExe events_trans = unpack(0); EventsTransExe events_trans = unpack(0);
@@ -760,28 +835,33 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
`endif `endif
`endif `endif
`ifdef KONATA // `ifdef KONATA
$display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, x.u_id); // $display("KONATAE\t%0d\t%0d\t0\tMem3", cur_cycle, tlbresp.u_id);
$display("KONATAS\t%0d\t%0d\t0\tMem4", cur_cycle, x.u_id); // $display("KONATAS\t%0d\t%0d\t0\tMem4", cur_cycle, tlbresp.u_id);
$fflush; // $fflush;
`endif // `endif
// Try me! // Try me!
// if (x.mem_func == St) begin // if (x.mem_func == St) begin
// paddr = 256; // paddr = 256;
// end // end
// update LSQ // update LSQ
// Important bit that updates memory ?
// LSQUpdateAddrResult updRes <- lsq.updateAddr(
// lol.ldstq_tag, cause, allowCapLoad && allowCapPTE, paddr, isMMIO, shiftBE
// );
LSQUpdateAddrResult updRes <- lsq.updateAddr( 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 // issue non-MMIO Ld which has no exception and is not waiting for
// wrong path resp // wrong path resp
if (x.mem_func == Ld && !isMMIO && if (lol.mem_func == Ld && !isMMIO &&
!isValid(cause) && !updRes.waitWPResp !isValid(cause) && !updRes.waitWPResp
&& !updRes.delayIssue) begin && !updRes.delayIssue) begin
LdQTag ldTag = ?; LdQTag ldTag = ?;
if(x.ldstq_tag matches tagged Ld .t) begin if(lol.ldstq_tag matches tagged Ld .t) begin
ldTag = t; ldTag = t;
end end
else begin else begin
@@ -790,7 +870,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
issueLd.wset(LSQIssueLdInfo { issueLd.wset(LSQIssueLdInfo {
tag: ldTag, tag: ldTag,
paddr: paddr, paddr: paddr,
shiftedBE: x.shiftedBE, shiftedBE: shiftBE,
pcHash: hash(getAddr(pc)) pcHash: hash(getAddr(pc))
}); });
end end