|
|
|
@@ -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
|
|
|
|
|