From f6bd0b0e1bf99e99620447df944381d2f4aff6a4 Mon Sep 17 00:00:00 2001 From: Franz Fuchs Date: Tue, 11 May 2021 14:13:02 +0100 Subject: [PATCH 01/14] first attempts to fix inhibit mismatch --- src_Core/CPU/CsrFile.bsv | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index e6db11b..924e1ee 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -245,7 +245,7 @@ endfunction interface PerfCountersVec; interface Vector#(No_Of_Ctrs, Reg#(Data)) counter_vec; interface Vector#(No_Of_Ctrs, Reg#(Data)) event_vec; - interface Reg#(Data) inhibit; + interface Reg#(Bit#(No_Of_Ctrs)) inhibit; method Action send_performance_events (Vector #(No_Of_Evts, Bit#(Report_Width)) evts); endinterface (* synthesize *) @@ -283,8 +283,8 @@ module mkPerfCountersToooba (PerfCountersVec); interface counter_vec = counters; interface event_vec = events; interface inhibit = interface Reg; - method Action _write(Data x) = writeCounterInhibitFF.enq(truncate(x)); - method Data _read = zeroExtend(perf_counters.read_ctr_inhibit); + method Action _write(Bit#(No_Of_Ctrs) x) = writeCounterInhibitFF.enq(truncate(x)); + method Bit#(No_Of_Ctrs) _read = (perf_counters.read_ctr_inhibit); endinterface; method send_performance_events = perf_counters.send_performance_events; endmodule @@ -821,8 +821,19 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap); Ehr#(2, CapReg) mepcc_reg <- mkConfigEhr(defaultValue); +`ifdef PERFORMANCE_MONITORING + // Performance monitoring + Reg#(Bit#(1)) mcountinhibit_cy_reg <- mkReg(0); + Reg#(Bit#(1)) mcountinhibit_ir_reg <- mkReg(0); + Reg#(Data) mcountinhibit_reg = concatReg5(readOnlyReg(32'h00000000), perf_counters.inhibit, mcountinhibit_ir_reg, readOnlyReg(1'b0), mcountinhibit_cy_reg); +`endif + rule incCycle; +`ifdef PERFORMANCE_MONITORING + if(unpack(mcountinhibit_cy_reg)) mcycle_ehr[1] <= mcycle_ehr[1] + 1; +`else mcycle_ehr[1] <= mcycle_ehr[1] + 1; +`endif endrule // Function for getting a csr given an index @@ -880,7 +891,8 @@ module mkCsrFile #(Data hartid)(CsrFile); csrAddrMHARTID: mhartid_csr; csrAddrMCCSR: mccsr_csr; `ifdef PERFORMANCE_MONITORING - csrAddrMCOUNTERINHIBIT: perf_counters.inhibit; + //csrAddrMCOUNTERINHIBIT: perf_counters.inhibit; + csrAddrMCOUNTERINHIBIT: mcountinhibit_reg; `endif `ifdef SECURITY csrAddrMEVBASE: mevbase_csr; From fcea3a1f4e218ad401967a8c55ff7f676852424e Mon Sep 17 00:00:00 2001 From: Franz Fuchs Date: Tue, 11 May 2021 19:28:49 +0100 Subject: [PATCH 02/14] included suggestions from Peter (pdr32) --- src_Core/CPU/CsrFile.bsv | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 924e1ee..2441e38 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -283,7 +283,7 @@ module mkPerfCountersToooba (PerfCountersVec); interface counter_vec = counters; interface event_vec = events; interface inhibit = interface Reg; - method Action _write(Bit#(No_Of_Ctrs) x) = writeCounterInhibitFF.enq(truncate(x)); + method Action _write(Bit#(No_Of_Ctrs) x) = writeCounterInhibitFF.enq(x); method Bit#(No_Of_Ctrs) _read = (perf_counters.read_ctr_inhibit); endinterface; method send_performance_events = perf_counters.send_performance_events; @@ -823,14 +823,14 @@ module mkCsrFile #(Data hartid)(CsrFile); `ifdef PERFORMANCE_MONITORING // Performance monitoring - Reg#(Bit#(1)) mcountinhibit_cy_reg <- mkReg(0); - Reg#(Bit#(1)) mcountinhibit_ir_reg <- mkReg(0); + Reg#(Bit#(1)) mcountinhibit_cy_reg <- mkCsrReg(0); + Reg#(Bit#(1)) mcountinhibit_ir_reg <- mkCsrReg(0); Reg#(Data) mcountinhibit_reg = concatReg5(readOnlyReg(32'h00000000), perf_counters.inhibit, mcountinhibit_ir_reg, readOnlyReg(1'b0), mcountinhibit_cy_reg); `endif rule incCycle; `ifdef PERFORMANCE_MONITORING - if(unpack(mcountinhibit_cy_reg)) mcycle_ehr[1] <= mcycle_ehr[1] + 1; + if(!unpack(mcountinhibit_cy_reg)) mcycle_ehr[1] <= mcycle_ehr[1] + 1; `else mcycle_ehr[1] <= mcycle_ehr[1] + 1; `endif @@ -1373,7 +1373,11 @@ module mkCsrFile #(Data hartid)(CsrFile); }; method Action incInstret(SupCnt x); +`ifdef PERFORMANCE_MONITORING + if(!unpack(mcountinhibit_cy_reg)) minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x); +`else minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x); +`endif endmethod method Action setTime(Data t); From d78a2799d396f0f02ebeb900eee8f32e2de9db3c Mon Sep 17 00:00:00 2001 From: Franz Fuchs Date: Wed, 12 May 2021 10:46:07 +0100 Subject: [PATCH 03/14] Fixed small mistake pointed out by Peter(pdr32) --- src_Core/CPU/CsrFile.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 2441e38..77ca3a6 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -1374,7 +1374,7 @@ module mkCsrFile #(Data hartid)(CsrFile); method Action incInstret(SupCnt x); `ifdef PERFORMANCE_MONITORING - if(!unpack(mcountinhibit_cy_reg)) minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x); + if(!unpack(mcountinhibit_ir_reg)) minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x); `else minstret_ehr[1] <= minstret_ehr[1] + zeroExtend(x); `endif From abc70134b1d43f68bc4a405518cbac8d84473048 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Thu, 13 May 2021 21:38:01 +0100 Subject: [PATCH 04/14] Don't take load cap page faults if the authorising cap doesn't have load cap --- .../RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv | 14 ++++++-------- src_Core/RISCY_OOO/procs/lib/DTlb.bsv | 4 ++-- src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv | 6 +++--- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 85b7646..2869826 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -114,8 +114,7 @@ typedef struct { `endif Bool misaligned; Bool capStore; - Bool capWidthLoad; - Bool allowCap; + Bool allowCapLoad; Maybe#(CSR_XCapCause) capException; Maybe#(BoundsCheck) check; } MemExeToFinish deriving(Bits, FShow); @@ -168,7 +167,7 @@ module mkDTlbSynth(DTlbSynth); default: False; endcase), capStore: x.capStore, - capWidthLoad: x.capWidthLoad + potentialCapLoad: x.allowCapLoad }; endfunction let m <- mkDTlb(getTlbReq); @@ -578,8 +577,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); `endif misaligned: memAddrMisaligned(getAddr(vaddr), origBE), capStore: isValidCap(data) && origBE == DataMemAccess(unpack(~0)), - capWidthLoad: origBE == DataMemAccess(unpack(~0)), - allowCap: getHardPerms(x.rVal1).permitLoadCap, + allowCapLoad: getHardPerms(x.rVal1).permitLoadCap && origBE == DataMemAccess(unpack(~0)), capException: capChecksMem(x.rVal1, x.rVal2, x.cap_checks, x.mem_func, origBE), check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/, ddc, getAddr(vaddr), accessByteCount, x.cap_checks) @@ -676,7 +674,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // update LSQ LSQUpdateAddrResult updRes <- lsq.updateAddr( - x.ldstq_tag, cause, x.allowCap && allowCapPTE, paddr, isMMIO, x.shiftedBE + x.ldstq_tag, cause, x.allowCapLoad && allowCapPTE, paddr, isMMIO, x.shiftedBE ); // issue non-MMIO Ld which has no exception and is not waiting for @@ -1316,7 +1314,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // write reg file & set ROB as Executed & wake up rs if(lsqDeqSt.dst matches tagged Valid .dst) begin CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); - dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCap around. Can a cap be loaded this way (e.g. AMOSWAP?) + dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCapLoad around. Can a cap be loaded this way (e.g. AMOSWAP?) inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF @@ -1430,7 +1428,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // 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 CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); - dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCap around. Can a cap be loaded this way (e.g. AMOSWAP?) + dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCapLoad around. Can a cap be loaded this way (e.g. AMOSWAP?) inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF diff --git a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv index adbb6ff..ee99fda 100644 --- a/src_Core/RISCY_OOO/procs/lib/DTlb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/DTlb.bsv @@ -297,7 +297,7 @@ module mkDTlb#( en.level, r.write ? DataStore : DataLoad, r.capStore, - r.capWidthLoad); + r.potentialCapLoad); if (permCheck.allowed) begin // fill TLB, and record resp tlb.addEntry(en); @@ -487,7 +487,7 @@ module mkDTlb#( entry.level, r.write ? DataStore : DataLoad, r.capStore, - r.capWidthLoad); + r.potentialCapLoad); $display("Permission check output 2: ", fshow(permCheck)); if (permCheck.allowed) begin // update TLB replacement info diff --git a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv index 0ac2f7d..8c8330b 100644 --- a/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TlbTypes.bsv @@ -32,7 +32,7 @@ typedef struct{ Addr addr; Bool write; Bool capStore; - Bool capWidthLoad; + Bool potentialCapLoad; } TlbReq deriving(Eq, Bits, FShow); typedef Tuple3#(Addr, Maybe#(Exception), Bool) TlbResp; @@ -192,7 +192,7 @@ function TlbPermissionCheck hasVMPermission( PTEType pte_type, PTEUpperType pte_upper_type, Ppn ppn, PageWalkLevel level, TlbAccessType access, - Bool capStore, Bool capWidthLoad + Bool capStore, Bool potentialCapLoad ); // try to find any page fault Bool fault = False; @@ -249,7 +249,7 @@ function TlbPermissionCheck hasVMPermission( !(pte_type.executable && vm_info.exeReadable)) begin fault = True; end - if (capWidthLoad) begin + if (potentialCapLoad) begin if (!fault) excCode = excLoadCapPageFault; // load traps if page not cap readable and using cap_read_mod set if (!pte_upper_type.cap_readable && pte_upper_type.cap_read_mod) begin From 657124671cf033fb986613cbd6d87e650d90f1d6 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Thu, 13 May 2021 23:15:10 +0100 Subject: [PATCH 05/14] Support amoswap.c --- src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv | 4 ++-- src_Core/RISCY_OOO/procs/lib/Decode.bsv | 10 +++++++--- src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv | 10 +++++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv index 2869826..b625352 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/MemExePipeline.bsv @@ -1314,7 +1314,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // write reg file & set ROB as Executed & wake up rs if(lsqDeqSt.dst matches tagged Valid .dst) begin CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); - dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCapLoad around. Can a cap be loaded this way (e.g. AMOSWAP?) + dataUnpacked = setValidCap(dataUnpacked, lsqDeqSt.allowCapAmoLd && isValidCap(dataUnpacked)); inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF @@ -1428,7 +1428,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline); // 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 CapPipe dataUnpacked = fromMem(tuple2(resp.tag, pack(resp.data))); - dataUnpacked = setValidCap(dataUnpacked, False); // TODO no allowCapLoad around. Can a cap be loaded this way (e.g. AMOSWAP?) + dataUnpacked = setValidCap(dataUnpacked, lsqDeqSt.allowCapAmoLd && isValidCap(dataUnpacked)); inIfc.writeRegFile(dst.indx, dataUnpacked); inIfc.setRegReadyAggr_mem(dst.indx); `ifdef INCLUDE_TANDEM_VERIF diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index 4ff0195..f415631 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -92,6 +92,13 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst, Bool cap_mode); illegalInst = True; end + Bool capWidth = ((mem_func == St || mem_func == Amo) && funct3 == 3'b100) + || (opcode == opcMiscMem && funct3 == 3'b010); + + if (capWidth && amo_func != None && amo_func != Swap) begin + illegalInst = True; // Don't support atomic cap arithmetic + end + // unsignedLd // it doesn't matter if this is set to True for stores Bool unsignedLd = False; @@ -109,9 +116,6 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst, Bool cap_mode); unsignedLd = True; end - Bool capWidth = (mem_func == St && funct3 == 3'b100) - || (opcode == opcMiscMem && funct3 == 3'b010); - // byteEn // TODO: Some combinations of operations and byteEn's are illegal. // They should be detected here. diff --git a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv index ece0f03..24fa28c 100644 --- a/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SplitLSQ.bsv @@ -338,7 +338,7 @@ typedef struct { Bool isMMIO; MemDataByteEn shiftedBE; MemTaggedData stData; - Bool allowCap; + Bool allowCapAmoLd; Maybe#(Trap) fault; } StQDeqEntry deriving (Bits, Eq, FShow); @@ -857,6 +857,7 @@ module mkSplitLSQ(SplitLSQ); Vector#(StQSize, Ehr#(2, MemDataByteEn)) st_shiftedBE <- replicateM(mkEhr(?)); Vector#(StQSize, Ehr#(1, MemTaggedData)) st_stData <- replicateM(mkEhr(?)); Vector#(StQSize, Ehr#(2, Maybe#(Trap))) st_fault <- replicateM(mkEhr(?)); + Vector#(StQSize, Ehr#(2, Bool)) st_allowCapAmoLd <- replicateM(mkEhr(?)); Vector#(StQSize, Ehr#(2, Bool)) st_computed <- replicateM(mkEhr(?)); Vector#(StQSize, Ehr#(2, Bool)) st_verified <- replicateM(mkEhr(?)); Vector#(StQSize, Ehr#(2, SpecBits)) st_specBits <- replicateM(mkEhr(?)); @@ -896,6 +897,10 @@ module mkSplitLSQ(SplitLSQ); let st_fault_deqSt = getVEhrPort(st_fault, 1); let st_fault_enq = getVEhrPort(st_fault, 1); // write + let st_allowCapAmoLd_updAddr = getVEhrPort(st_allowCapAmoLd, 0); // write + let st_allowCapAmoLd_deqSt = getVEhrPort(st_allowCapAmoLd, 1); + let st_allowCapAmoLd_enq = getVEhrPort(st_allowCapAmoLd, 1); // write + let st_computed_verify = getVEhrPort(st_computed, 0); let st_computed_updAddr = getVEhrPort(st_computed, 0); // write let st_computed_issue = getVEhrPort(st_computed, 1); @@ -1544,6 +1549,7 @@ module mkSplitLSQ(SplitLSQ); st_rel[st_enqP] <= mem_inst.rl; st_dst[st_enqP] <= dst; st_fault_enq[st_enqP] <= Invalid; + st_allowCapAmoLd_enq[st_enqP] <= False; st_computed_enq[st_enqP] <= False; st_verified_enq[st_enqP] <= False; st_specBits_enq[st_enqP] <= spec_bits; @@ -1635,6 +1641,7 @@ module mkSplitLSQ(SplitLSQ); // write fault, computed paddr, shift be. NOTE computed is // true only when no fault. st_fault_updAddr[tag] <= fault; + st_allowCapAmoLd_updAddr[tag] <= allowCap; st_computed_updAddr[tag] <= !isValid(fault); st_paddr_updAddr[tag] <= pa; st_isMMIO_updAddr[tag] <= mmio; @@ -2174,6 +2181,7 @@ module mkSplitLSQ(SplitLSQ); isMMIO: st_isMMIO_deqSt[deqP], shiftedBE: st_shiftedBE_deqSt[deqP], stData: st_stData_deqSt[deqP], + allowCapAmoLd: st_allowCapAmoLd_deqSt[deqP], fault: st_fault_deqSt[deqP] }; endmethod From 6450d9c33cf5a72eaf9af85fc5e6552ff37469d7 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 14 Apr 2021 14:53:49 +0100 Subject: [PATCH 06/14] Make JAL and JALR mode-dependent --- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 1 + .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 6 +-- src_Core/RISCY_OOO/procs/lib/BrPred.bsv | 2 +- src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi | 1 + src_Core/RISCY_OOO/procs/lib/Decode.bsv | 26 +++++++-- src_Core/RISCY_OOO/procs/lib/Exec.bsv | 53 ++++++++++--------- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 2 +- .../RISCY_OOO/procs/lib/ReorderBuffer.bsv | 2 +- 8 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 5c58751..8f1185c 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -1184,6 +1184,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Auipc, Auipcc: auipcCnt = auipcCnt + 1; Br: brCnt = brCnt + 1; J : jmpCnt = jmpCnt + 1; + CJAL: jmpCnt = jmpCnt + 1; Jr: jrCnt = jrCnt + 1; CJALR: jrCnt = jrCnt + 1; Ld: begin diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 1e57e09..c819973 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -717,7 +717,7 @@ module mkFetchStage(FetchStage); CapMem push_addr = addPc(pc, ((in.inst_kind == Inst_32b) ? 4 : 2)); CapMem pop_addr = ras.ras[i].first; - if (dInst.iType == J && dst_link) begin + if ((dInst.iType == J || dInst.iType == CJAL) && dst_link) begin // rs1 is invalid, i.e., not link: push ras.ras[i].popPush(False, Valid (push_addr)); end @@ -821,7 +821,7 @@ module mkFetchStage(FetchStage); if(redirectInst matches tagged Valid .iType &&& doStats) begin case(iType) Br: decRedirectBrCnt.incr(1); - J : decRedirectJmpCnt.incr(1); + J, CJAL: decRedirectJmpCnt.incr(1); Jr: decRedirectJrCnt.incr(1); default: decRedirectOtherCnt.incr(1); endcase @@ -930,7 +930,7 @@ module mkFetchStage(FetchStage); CapMem pc, CapMem next_pc, IType iType, Bool taken, DirPredTrainInfo dpTrain, Bool mispred, Bool isCompressed ); - //if (iType == J || (iType == Br && next_pc < pc)) begin + //if (iType == J || iType == CJAL || (iType == Br && next_pc < pc)) begin // // Only train the next address predictor for jumps and backward branches // // next_pc != pc + 4 is a substitute for taken // nextAddrPred.update(pc, next_pc, taken); diff --git a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv index 5943f36..1ac9456 100644 --- a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv @@ -48,7 +48,7 @@ function Maybe#(CapMem) decodeBrPred( CapMem pc, DecodedInst dInst, Bool histTak Maybe#(CapMem) nextPc = tagged Invalid; CapPipe pcPipe = cast(pc); CapMem jTarget = cast(incOffset(pcPipe, imm_val).value); - if( dInst.iType == J ) begin + if( dInst.iType == J || dInst.iType == CJAL ) begin nextPc = tagged Valid jTarget; end else if( dInst.iType == Br ) begin if( histTaken ) begin diff --git a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi index 722ce39..018b513 100644 --- a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi @@ -6,6 +6,7 @@ `CAP_CHECK_FIELD(ddc_unsealed,"ddc_unsealed") `CAP_CHECK_FIELD(src1_unsealed,"src1_unsealed") `CAP_CHECK_FIELD(src1_unsealed_or_sentry,"src1_unsealed_or_sentry") +`CAP_CHECK_FIELD(src1_unsealed_or_imm_zero,"src1_unsealed_or_imm_zero") `CAP_CHECK_FIELD(src2_unsealed,"src2_unsealed") `CAP_CHECK_FIELD(src1_src2_types_match,"src1_src2_types_match") `CAP_CHECK_FIELD(src1_permit_ccall,"src1_permit_ccall") diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index f415631..28510fc 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -491,7 +491,13 @@ function DecodeResult decode(Instruction inst, Bool cap_mode); end opcJal: begin - dInst.iType = J; + if (cap_mode) begin + dInst.iType = CJAL; + end + else begin + dInst.iType = J; + end + regs.dst = Valid(tagged Gpr rd); regs.src1 = Invalid; regs.src2 = Invalid; @@ -506,18 +512,32 @@ function DecodeResult decode(Instruction inst, Bool cap_mode); end opcJalr: begin - dInst.iType = Jr; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Invalid; 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; + if (cap_mode) begin + dInst.iType = CJALR; + + dInst.capChecks.src1_tag = True; + dInst.capChecks.src1_permit_x = True; + dInst.capChecks.src1_unsealed_or_sentry = True; + dInst.capChecks.src1_unsealed_or_imm_zero = True; + + dInst.capChecks.check_authority_src = Src1; + end + else begin + dInst.iType = Jr; + + dInst.capChecks.check_authority_src = Pcc; + end end opcBranch: begin diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index e629b29..cfbfa2b 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -46,54 +46,56 @@ import ISA_Decls_CHERI::*; import CacheUtils::*; // For CLoadTags alignment (* noinline *) -function Maybe#(CSR_XCapCause) capChecksExec(CapPipe a, CapPipe b, CapPipe ddc, CapChecks toCheck, Bool cap_exact); +function Maybe#(CSR_XCapCause) capChecksExec(CapPipe a, CapPipe b, CapPipe ddc, CapChecks toCheck, Bool cap_exact, ImmData imm); 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: {1'b1, pack(scrAddrDDC)}, cheri_exc_code: e}); Maybe#(CSR_XCapCause) result = Invalid; - if (toCheck.ddc_tag && !isValidCap(ddc)) + if (toCheck.ddc_tag && !isValidCap(ddc)) result = eDDC(cheriExcTagViolation); - else if (toCheck.src1_tag && !isValidCap(a)) + else if (toCheck.src1_tag && !isValidCap(a)) result = e1(cheriExcTagViolation); - else if (toCheck.src2_tag && !isValidCap(b)) + else if (toCheck.src2_tag && !isValidCap(b)) result = e2(cheriExcTagViolation); - else if (toCheck.ddc_unsealed && isValidCap(ddc) && (getKind(ddc) != UNSEALED)) + else if (toCheck.ddc_unsealed && isValidCap(ddc) && (getKind(ddc) != UNSEALED)) result = eDDC(cheriExcSealViolation); - else if (toCheck.src1_unsealed && isValidCap(a) && (getKind(a) != UNSEALED)) + else if (toCheck.src1_unsealed && isValidCap(a) && (getKind(a) != UNSEALED)) result = e1(cheriExcSealViolation); - else if (toCheck.src1_unsealed_or_sentry && isValidCap(a) && (getKind(a) != UNSEALED) && (getKind(a) != SENTRY)) + else if (toCheck.src1_unsealed_or_sentry && isValidCap(a) && (getKind(a) != UNSEALED) && (getKind(a) != SENTRY)) result = e1(cheriExcSealViolation); - else if (toCheck.src2_unsealed && isValidCap(b) && (getKind(b) != UNSEALED)) + else if (toCheck.src1_unsealed_or_imm_zero && isValidCap(a) && (getKind(a) != UNSEALED) && (imm != 0)) + result = e1(cheriExcSealViolation); + else if (toCheck.src2_unsealed && isValidCap(b) && (getKind(b) != UNSEALED)) result = e2(cheriExcSealViolation); - else if (toCheck.src1_sealed_with_type && (getKind (a) matches tagged SEALED_WITH_TYPE .t ? False : True)) + else if (toCheck.src1_sealed_with_type && (getKind (a) matches tagged SEALED_WITH_TYPE .t ? False : True)) result = e1(cheriExcSealViolation); - else if (toCheck.src2_sealed_with_type && (getKind (b) matches tagged SEALED_WITH_TYPE .t ? False : True)) + else if (toCheck.src2_sealed_with_type && (getKind (b) matches tagged SEALED_WITH_TYPE .t ? False : True)) result = e2(cheriExcSealViolation); - else if (toCheck.src1_type_not_reserved && !validAsType(a, zeroExtend(getKind(a).SEALED_WITH_TYPE))) + else if (toCheck.src1_type_not_reserved && !validAsType(a, zeroExtend(getKind(a).SEALED_WITH_TYPE))) result = e1(cheriExcTypeViolation); - else if (toCheck.src1_src2_types_match && getKind(a).SEALED_WITH_TYPE != getKind(b).SEALED_WITH_TYPE) + else if (toCheck.src1_src2_types_match && getKind(a).SEALED_WITH_TYPE != getKind(b).SEALED_WITH_TYPE) result = e1(cheriExcTypeViolation); - else if (toCheck.src1_permit_ccall && !getHardPerms(a).permitCCall) + else if (toCheck.src1_permit_ccall && !getHardPerms(a).permitCCall) result = e1(cheriExcPermitCCallViolation); - else if (toCheck.src2_permit_ccall && !getHardPerms(b).permitCCall) + else if (toCheck.src2_permit_ccall && !getHardPerms(b).permitCCall) result = e2(cheriExcPermitCCallViolation); - else if (toCheck.src1_permit_x && !getHardPerms(a).permitExecute) + else if (toCheck.src1_permit_x && !getHardPerms(a).permitExecute) result = e1(cheriExcPermitXViolation); - else if (toCheck.src2_no_permit_x && getHardPerms(b).permitExecute) + else if (toCheck.src2_no_permit_x && getHardPerms(b).permitExecute) result = e2(cheriExcPermitXViolation); - else if (toCheck.src2_permit_unseal && !getHardPerms(b).permitUnseal) + else if (toCheck.src2_permit_unseal && !getHardPerms(b).permitUnseal) result = e2(cheriExcPermitUnsealViolation); - else if (toCheck.src2_permit_seal && !getHardPerms(b).permitSeal) + else if (toCheck.src2_permit_seal && !getHardPerms(b).permitSeal) result = e2(cheriExcPermitSealViolation); - else if (toCheck.src2_points_to_src1_type && getAddr(b) != zeroExtend(getKind(a).SEALED_WITH_TYPE)) + else if (toCheck.src2_points_to_src1_type && getAddr(b) != zeroExtend(getKind(a).SEALED_WITH_TYPE)) result = e2(cheriExcTypeViolation); - else if (toCheck.src2_addr_valid_type && !validAsType(b, truncate(getAddr(b)))) + else if (toCheck.src2_addr_valid_type && !validAsType(b, truncate(getAddr(b)))) result = e2(cheriExcLengthViolation); - else if (toCheck.src1_perm_subset_src2 && (getPerms(a) & getPerms(b)) != getPerms(a)) + else if (toCheck.src1_perm_subset_src2 && (getPerms(a) & getPerms(b)) != getPerms(a)) result = e2(cheriExcSoftwarePermViolation); - else if (toCheck.src1_derivable && !isDerivable(a)) + else if (toCheck.src1_derivable && !isDerivable(a)) result = e1(cheriExcLengthViolation); - else if (toCheck.cap_exact && !cap_exact) + else if (toCheck.cap_exact && !cap_exact) result = e1(cheriExcRepresentViolation); return result; endfunction @@ -358,7 +360,7 @@ function CapPipe brAddrCalc(CapPipe pc, CapPipe val, IType iType, Data imm, Bool jumpTarget = setAddrUnsafe(jumpTarget, {truncateLSB(getAddr(jumpTarget)), 1'b0}); jumpTarget = setKind(jumpTarget, UNSEALED); // It is checked elsewhere that we have an unsealed cap already, or sentry if permitted CapPipe targetAddr = (case (iType) - J : branchTarget; + J, CJAL : branchTarget; Jr,CCall,CJALR : jumpTarget; Br : (taken? branchTarget : pcPlusN); default : pcPlusN; @@ -407,7 +409,7 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C 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); - Maybe#(CSR_XCapCause) capException = capChecksExec(rVal1, aluVal2, nullCap, dInst.capChecks, cap_exact); + Maybe#(CSR_XCapCause) capException = capChecksExec(rVal1, aluVal2, nullCap, dInst.capChecks, cap_exact, dInst.imm.Valid); if (dInst.execFunc matches tagged Br .unused) begin rVal1 = cf.nextPc; if (!cf.taken) dInst.capChecks.check_enable = False; @@ -431,6 +433,7 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C Sc : rVal2; Amo : rVal2; J : nullWithAddr(getOffset(link_pcc)); + CJAL : setKind(link_pcc, SENTRY); CCall : cap_alu_result; CJALR : setKind(link_pcc, SENTRY); Jr : nullWithAddr(getOffset(link_pcc)); diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 21830b0..8708ad7 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -268,7 +268,7 @@ typedef enum { Alu, Ld, St, Lr, Sc, J, Jr, Br, - CCall, CJALR, Cap, + CCall, CJAL, CJALR, Cap, Auipc, Auipcc, Fpu, diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index 0fde3d8..ffbf123 100755 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -57,7 +57,7 @@ import Cur_Cycle :: *; // some parts of full_result are for verification // but some are truly used for execution -// ppc is only used by iType = BR/J/JR +// ppc is only used by iType = BR/J/CJAL/JR // csrData is only used by iType = Csr // vaddr is only used by mem inst in page fault typedef union tagged { From 913d14406edb14da961a94a4bf8a293a6d49c32a Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 14 Apr 2021 14:55:18 +0100 Subject: [PATCH 07/14] Add explicit PCC and cap JALRs --- src_Core/ISA/ISA_Decls_CHERI.bsv | 6 ++++-- src_Core/RISCY_OOO/procs/lib/Decode.bsv | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src_Core/ISA/ISA_Decls_CHERI.bsv b/src_Core/ISA/ISA_Decls_CHERI.bsv index 0cf2497..3dbd9dd 100755 --- a/src_Core/ISA/ISA_Decls_CHERI.bsv +++ b/src_Core/ISA/ISA_Decls_CHERI.bsv @@ -177,14 +177,16 @@ Bit #(5) f5rs2_cap_CRRL = 5'h08; Bit #(5) f5rs2_cap_CRAM = 5'h09; Bit #(5) f5rs2_cap_CMove = 5'h0a; Bit #(5) f5rs2_cap_CClearTag = 5'h0b; -Bit #(5) f5rs2_cap_CJALR = 5'h0c; +Bit #(5) f5rs2_cap_JALR_CAP = 5'h0c; Bit #(5) f5rs2_cap_CClearReg = 5'h0d; // 5'h0e unused Bit #(5) f5rs2_cap_CGetAddr = 5'h0f; Bit #(5) f5rs2_cap_CClearFPReg = 5'h10; Bit #(5) f5rs2_cap_CSealEntry = 5'h11; Bit #(5) f5rs2_cap_CLoadTags = 5'h12; -// 5'h13-5'h1f unused (5'h1f reserved for 1-reg instructions) +// 5'h13 unused +Bit #(5) f5rs2_cap_JALR_PCC = 5'h14; +// 5'h15-5'h1f unused (5'h1f reserved for 1-reg instructions) // ================================================================ // f7_cap_{Load, Store} opcode subdivision diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index 28510fc..401af3d 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -1365,7 +1365,7 @@ function DecodeResult decode(Instruction inst, Bool cap_mode); regs.src1 = Valid(tagged Gpr rs1); dInst.capFunc = CapInspect (GetPerm); end - f5rs2_cap_CJALR: begin + f5rs2_cap_JALR_CAP: begin dInst.capChecks.src1_tag = True; dInst.capChecks.src1_permit_x = True; dInst.capChecks.src1_unsealed_or_sentry = True; @@ -1380,7 +1380,19 @@ function DecodeResult decode(Instruction inst, Bool cap_mode); dInst.execFunc = tagged Br AT; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); - end + end + f5rs2_cap_JALR_PCC: begin + 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; + + dInst.iType = Jr; + dInst.execFunc = tagged Br AT; + regs.dst = Valid(tagged Gpr rd); + regs.src1 = Valid(tagged Gpr rs1); + end f5rs2_cap_CGetType: begin dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); From 88751cccba36a417a5e05ff404c5b73f1601b0bc Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 14 Apr 2021 14:55:57 +0100 Subject: [PATCH 08/14] Remove hardcoded field encodings for cap loads and stores --- src_Core/RISCY_OOO/procs/lib/Decode.bsv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index 401af3d..e2302c1 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -92,8 +92,8 @@ function Maybe#(MemInst) decodeMemInst(Instruction inst, Bool cap_mode); illegalInst = True; end - Bool capWidth = ((mem_func == St || mem_func == Amo) && funct3 == 3'b100) - || (opcode == opcMiscMem && funct3 == 3'b010); + Bool capWidth = ((mem_func == St || mem_func == Amo) && funct3 == f3_SQ) + || (opcode == opcMiscMem && funct3 == f3_LQ); if (capWidth && amo_func != None && amo_func != Swap) begin illegalInst = True; // Don't support atomic cap arithmetic From 1b5f4ee9e088a1f20b4ebeba34b90754d67fdf2a Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Wed, 14 Apr 2021 14:56:19 +0100 Subject: [PATCH 09/14] Add capability-aware compressed decoding --- src_Core/CPU/CPU_Decode_C.bsv | 422 ++++++++++-------- src_Core/ISA/ISA_Decls_C.bsv | 112 ++--- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 2 +- 3 files changed, 294 insertions(+), 242 deletions(-) diff --git a/src_Core/CPU/CPU_Decode_C.bsv b/src_Core/CPU/CPU_Decode_C.bsv index 5b3b04e..dbb9c79 100644 --- a/src_Core/CPU/CPU_Decode_C.bsv +++ b/src_Core/CPU/CPU_Decode_C.bsv @@ -38,71 +38,72 @@ export fv_decode_C; // ================================================================ // Project imports -import ISA_Decls :: *; +import ISA_Decls :: *; +import ISA_Decls_CHERI :: *; // ================================================================ -function Instr fv_decode_C (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Instr fv_decode_C (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); // ---------------- // Try each possible C instruction - match { .valid_C_LWSP, .i_C_LWSP } = fv_decode_C_LWSP (misa, xl, instr_C); - match { .valid_C_SWSP, .i_C_SWSP } = fv_decode_C_SWSP (misa, xl, instr_C); - match { .valid_C_LW, .i_C_LW } = fv_decode_C_LW (misa, xl, instr_C); - match { .valid_C_SW, .i_C_SW } = fv_decode_C_SW (misa, xl, instr_C); + match { .valid_C_LWSP, .i_C_LWSP } = fv_decode_C_LWSP (misa, xl, cap_enc, instr_C); + match { .valid_C_SWSP, .i_C_SWSP } = fv_decode_C_SWSP (misa, xl, cap_enc, instr_C); + match { .valid_C_LW, .i_C_LW } = fv_decode_C_LW (misa, xl, cap_enc, instr_C); + match { .valid_C_SW, .i_C_SW } = fv_decode_C_SW (misa, xl, cap_enc, instr_C); - match { .valid_C_J, .i_C_J } = fv_decode_C_J (misa, xl, instr_C); - match { .valid_C_JAL, .i_C_JAL } = fv_decode_C_JAL (misa, xl, instr_C); - match { .valid_C_JR, .i_C_JR } = fv_decode_C_JR (misa, xl, instr_C); - match { .valid_C_JALR, .i_C_JALR } = fv_decode_C_JALR (misa, xl, instr_C); - match { .valid_C_BEQZ, .i_C_BEQZ } = fv_decode_C_BEQZ (misa, xl, instr_C); - match { .valid_C_BNEZ, .i_C_BNEZ } = fv_decode_C_BNEZ (misa, xl, instr_C); - match { .valid_C_LI, .i_C_LI } = fv_decode_C_LI (misa, xl, instr_C); - match { .valid_C_LUI, .i_C_LUI } = fv_decode_C_LUI (misa, xl, instr_C); - match { .valid_C_ADDI, .i_C_ADDI } = fv_decode_C_ADDI (misa, xl, instr_C); - match { .valid_C_NOP, .i_C_NOP } = fv_decode_C_NOP (misa, xl, instr_C); - match { .valid_C_ADDIW, .i_C_ADDIW } = fv_decode_C_ADDIW (misa, xl, instr_C); - match { .valid_C_ADDI16SP, .i_C_ADDI16SP } = fv_decode_C_ADDI16SP (misa, xl, instr_C); - match { .valid_C_ADDI4SPN, .i_C_ADDI4SPN } = fv_decode_C_ADDI4SPN (misa, xl, instr_C); - match { .valid_C_SLLI, .i_C_SLLI } = fv_decode_C_SLLI (misa, xl, instr_C); - match { .valid_C_SRLI, .i_C_SRLI } = fv_decode_C_SRLI (misa, xl, instr_C); - match { .valid_C_SRAI, .i_C_SRAI } = fv_decode_C_SRAI (misa, xl, instr_C); - match { .valid_C_ANDI, .i_C_ANDI } = fv_decode_C_ANDI (misa, xl, instr_C); - match { .valid_C_MV, .i_C_MV } = fv_decode_C_MV (misa, xl, instr_C); - match { .valid_C_ADD, .i_C_ADD } = fv_decode_C_ADD (misa, xl, instr_C); - match { .valid_C_AND, .i_C_AND } = fv_decode_C_AND (misa, xl, instr_C); - match { .valid_C_OR, .i_C_OR } = fv_decode_C_OR (misa, xl, instr_C); - match { .valid_C_XOR, .i_C_XOR } = fv_decode_C_XOR (misa, xl, instr_C); - match { .valid_C_SUB, .i_C_SUB } = fv_decode_C_SUB (misa, xl, instr_C); - match { .valid_C_ADDW, .i_C_ADDW } = fv_decode_C_ADDW (misa, xl, instr_C); - match { .valid_C_SUBW, .i_C_SUBW } = fv_decode_C_SUBW (misa, xl, instr_C); - match { .valid_C_EBREAK, .i_C_EBREAK } = fv_decode_C_EBREAK (misa, xl, instr_C); + match { .valid_C_J, .i_C_J } = fv_decode_C_J (misa, xl, cap_enc, instr_C); + match { .valid_C_JAL, .i_C_JAL } = fv_decode_C_JAL (misa, xl, cap_enc, instr_C); + match { .valid_C_JR, .i_C_JR } = fv_decode_C_JR (misa, xl, cap_enc, instr_C); + match { .valid_C_JALR, .i_C_JALR } = fv_decode_C_JALR (misa, xl, cap_enc, instr_C); + match { .valid_C_BEQZ, .i_C_BEQZ } = fv_decode_C_BEQZ (misa, xl, cap_enc, instr_C); + match { .valid_C_BNEZ, .i_C_BNEZ } = fv_decode_C_BNEZ (misa, xl, cap_enc, instr_C); + match { .valid_C_LI, .i_C_LI } = fv_decode_C_LI (misa, xl, cap_enc, instr_C); + match { .valid_C_LUI, .i_C_LUI } = fv_decode_C_LUI (misa, xl, cap_enc, instr_C); + match { .valid_C_ADDI, .i_C_ADDI } = fv_decode_C_ADDI (misa, xl, cap_enc, instr_C); + match { .valid_C_NOP, .i_C_NOP } = fv_decode_C_NOP (misa, xl, cap_enc, instr_C); + match { .valid_C_ADDIW, .i_C_ADDIW } = fv_decode_C_ADDIW (misa, xl, cap_enc, instr_C); + match { .valid_C_ADDI16SP, .i_C_ADDI16SP } = fv_decode_C_ADDI16SP (misa, xl, cap_enc, instr_C); + match { .valid_C_CIncOffsetImm16CSP, .i_C_CIncOffsetImm16CSP } = fv_decode_C_CIncOffsetImm16CSP (misa, xl, cap_enc, instr_C); + match { .valid_C_ADDI4SPN, .i_C_ADDI4SPN } = fv_decode_C_ADDI4SPN (misa, xl, cap_enc, instr_C); + match { .valid_C_CIncOffsetImm4CSPN, .i_C_CIncOffsetImm4CSPN } = fv_decode_C_CIncOffsetImm4CSPN (misa, xl, cap_enc, instr_C); + match { .valid_C_SLLI, .i_C_SLLI } = fv_decode_C_SLLI (misa, xl, cap_enc, instr_C); + match { .valid_C_SRLI, .i_C_SRLI } = fv_decode_C_SRLI (misa, xl, cap_enc, instr_C); + match { .valid_C_SRAI, .i_C_SRAI } = fv_decode_C_SRAI (misa, xl, cap_enc, instr_C); + match { .valid_C_ANDI, .i_C_ANDI } = fv_decode_C_ANDI (misa, xl, cap_enc, instr_C); + match { .valid_C_MV, .i_C_MV } = fv_decode_C_MV (misa, xl, cap_enc, instr_C); + match { .valid_C_ADD, .i_C_ADD } = fv_decode_C_ADD (misa, xl, cap_enc, instr_C); + match { .valid_C_AND, .i_C_AND } = fv_decode_C_AND (misa, xl, cap_enc, instr_C); + match { .valid_C_OR, .i_C_OR } = fv_decode_C_OR (misa, xl, cap_enc, instr_C); + match { .valid_C_XOR, .i_C_XOR } = fv_decode_C_XOR (misa, xl, cap_enc, instr_C); + match { .valid_C_SUB, .i_C_SUB } = fv_decode_C_SUB (misa, xl, cap_enc, instr_C); + match { .valid_C_ADDW, .i_C_ADDW } = fv_decode_C_ADDW (misa, xl, cap_enc, instr_C); + match { .valid_C_SUBW, .i_C_SUBW } = fv_decode_C_SUBW (misa, xl, cap_enc, instr_C); + match { .valid_C_EBREAK, .i_C_EBREAK } = fv_decode_C_EBREAK (misa, xl, cap_enc, instr_C); + + match { .valid_C_LDSP, .i_C_LDSP } = fv_decode_C_LDSP (misa, xl, cap_enc, instr_C); + match { .valid_C_SDSP, .i_C_SDSP } = fv_decode_C_SDSP (misa, xl, cap_enc, instr_C); + match { .valid_C_LD, .i_C_LD } = fv_decode_C_LD (misa, xl, cap_enc, instr_C); + match { .valid_C_SD, .i_C_SD } = fv_decode_C_SD (misa, xl, cap_enc, instr_C); `ifdef RV64 - match { .valid_C_LDSP, .i_C_LDSP } = fv_decode_C_LDSP (misa, xl, instr_C); - match { .valid_C_SDSP, .i_C_SDSP } = fv_decode_C_SDSP (misa, xl, instr_C); - match { .valid_C_LD, .i_C_LD } = fv_decode_C_LD (misa, xl, instr_C); - match { .valid_C_SD, .i_C_SD } = fv_decode_C_SD (misa, xl, instr_C); -`endif - -`ifdef RV128 - match { .valid_C_LQSP, .i_C_LQSP } = fv_decode_C_LQSP (misa, xl, instr_C); - match { .valid_C_SQSP, .i_C_SQSP } = fv_decode_C_SQSP (misa, xl, instr_C); - match { .valid_C_LQ, .i_C_LQ } = fv_decode_C_LQ (misa, xl, instr_C); - match { .valid_C_SQ, .i_C_SQ } = fv_decode_C_SQ (misa, xl, instr_C); + match { .valid_C_LQSP, .i_C_LQSP } = fv_decode_C_LQSP (misa, xl, cap_enc, instr_C); + match { .valid_C_SQSP, .i_C_SQSP } = fv_decode_C_SQSP (misa, xl, cap_enc, instr_C); + match { .valid_C_LQ, .i_C_LQ } = fv_decode_C_LQ (misa, xl, cap_enc, instr_C); + match { .valid_C_SQ, .i_C_SQ } = fv_decode_C_SQ (misa, xl, cap_enc, instr_C); `endif `ifdef ISA_F - match { .valid_C_FLWSP, .i_C_FLWSP } = fv_decode_C_FLWSP (misa, xl, instr_C); - match { .valid_C_FSWSP, .i_C_FSWSP } = fv_decode_C_FSWSP (misa, xl, instr_C); - match { .valid_C_FLW, .i_C_FLW } = fv_decode_C_FLW (misa, xl, instr_C); - match { .valid_C_FSW, .i_C_FSW } = fv_decode_C_FSW (misa, xl, instr_C); + match { .valid_C_FLWSP, .i_C_FLWSP } = fv_decode_C_FLWSP (misa, xl, cap_enc, instr_C); + match { .valid_C_FSWSP, .i_C_FSWSP } = fv_decode_C_FSWSP (misa, xl, cap_enc, instr_C); + match { .valid_C_FLW, .i_C_FLW } = fv_decode_C_FLW (misa, xl, cap_enc, instr_C); + match { .valid_C_FSW, .i_C_FSW } = fv_decode_C_FSW (misa, xl, cap_enc, instr_C); `endif `ifdef ISA_D - match { .valid_C_FLDSP, .i_C_FLDSP } = fv_decode_C_FLDSP (misa, xl, instr_C); - match { .valid_C_FSDSP, .i_C_FSDSP } = fv_decode_C_FSDSP (misa, xl, instr_C); - match { .valid_C_FLD, .i_C_FLD } = fv_decode_C_FLD (misa, xl, instr_C); - match { .valid_C_FSD, .i_C_FSD } = fv_decode_C_FSD (misa, xl, instr_C); + match { .valid_C_FLDSP, .i_C_FLDSP } = fv_decode_C_FLDSP (misa, xl, cap_enc, instr_C); + match { .valid_C_FSDSP, .i_C_FSDSP } = fv_decode_C_FSDSP (misa, xl, cap_enc, instr_C); + match { .valid_C_FLD, .i_C_FLD } = fv_decode_C_FLD (misa, xl, cap_enc, instr_C); + match { .valid_C_FSD, .i_C_FSD } = fv_decode_C_FSD (misa, xl, cap_enc, instr_C); `endif // ---------------- @@ -110,64 +111,64 @@ function Instr fv_decode_C (MISA misa, Bit #(2) xl, Instr_C instr_C); Instr instr = ?; - if (valid_C_LWSP) instr = i_C_LWSP; - else if (valid_C_SWSP) instr = i_C_SWSP; - else if (valid_C_LW) instr = i_C_LW; - else if (valid_C_SW) instr = i_C_SW; + if (valid_C_LWSP) instr = i_C_LWSP; + else if (valid_C_SWSP) instr = i_C_SWSP; + else if (valid_C_LW) instr = i_C_LW; + else if (valid_C_SW) instr = i_C_SW; - else if (valid_C_J) instr = i_C_J; - else if (valid_C_JAL) instr = i_C_JAL; - else if (valid_C_JR) instr = i_C_JR; - else if (valid_C_JALR) instr = i_C_JALR; - else if (valid_C_BEQZ) instr = i_C_BEQZ; - else if (valid_C_BNEZ) instr = i_C_BNEZ; - else if (valid_C_LI) instr = i_C_LI; - else if (valid_C_LUI) instr = i_C_LUI; - else if (valid_C_ADDI) instr = i_C_ADDI; - else if (valid_C_NOP) instr = i_C_NOP; - else if (valid_C_ADDIW) instr = i_C_ADDIW; - else if (valid_C_ADDI16SP) instr = i_C_ADDI16SP; - else if (valid_C_ADDI4SPN) instr = i_C_ADDI4SPN; - else if (valid_C_SLLI) instr = i_C_SLLI; - else if (valid_C_SRLI) instr = i_C_SRLI; - else if (valid_C_SRAI) instr = i_C_SRAI; - else if (valid_C_ANDI) instr = i_C_ANDI; - else if (valid_C_MV) instr = i_C_MV; - else if (valid_C_ADD) instr = i_C_ADD; - else if (valid_C_AND) instr = i_C_AND; - else if (valid_C_OR) instr = i_C_OR; - else if (valid_C_XOR) instr = i_C_XOR; - else if (valid_C_SUB) instr = i_C_SUB; - else if (valid_C_ADDW) instr = i_C_ADDW; - else if (valid_C_SUBW) instr = i_C_SUBW; - else if (valid_C_EBREAK) instr = i_C_EBREAK; + else if (valid_C_J) instr = i_C_J; + else if (valid_C_JAL) instr = i_C_JAL; + else if (valid_C_JR) instr = i_C_JR; + else if (valid_C_JALR) instr = i_C_JALR; + else if (valid_C_BEQZ) instr = i_C_BEQZ; + else if (valid_C_BNEZ) instr = i_C_BNEZ; + else if (valid_C_LI) instr = i_C_LI; + else if (valid_C_LUI) instr = i_C_LUI; + else if (valid_C_ADDI) instr = i_C_ADDI; + else if (valid_C_NOP) instr = i_C_NOP; + else if (valid_C_ADDIW) instr = i_C_ADDIW; + else if (valid_C_ADDI16SP) instr = i_C_ADDI16SP; + else if (valid_C_CIncOffsetImm16CSP) instr = i_C_CIncOffsetImm16CSP; + else if (valid_C_ADDI4SPN) instr = i_C_ADDI4SPN; + else if (valid_C_CIncOffsetImm4CSPN) instr = i_C_CIncOffsetImm4CSPN; + else if (valid_C_SLLI) instr = i_C_SLLI; + else if (valid_C_SRLI) instr = i_C_SRLI; + else if (valid_C_SRAI) instr = i_C_SRAI; + else if (valid_C_ANDI) instr = i_C_ANDI; + else if (valid_C_MV) instr = i_C_MV; + else if (valid_C_ADD) instr = i_C_ADD; + else if (valid_C_AND) instr = i_C_AND; + else if (valid_C_OR) instr = i_C_OR; + else if (valid_C_XOR) instr = i_C_XOR; + else if (valid_C_SUB) instr = i_C_SUB; + else if (valid_C_ADDW) instr = i_C_ADDW; + else if (valid_C_SUBW) instr = i_C_SUBW; + else if (valid_C_EBREAK) instr = i_C_EBREAK; `ifdef RV64 - else if (valid_C_LDSP) instr = i_C_LDSP; - else if (valid_C_SDSP) instr = i_C_SDSP; - else if (valid_C_LD) instr = i_C_LD; - else if (valid_C_SD) instr = i_C_SD; + else if (valid_C_LDSP) instr = i_C_LDSP; + else if (valid_C_SDSP) instr = i_C_SDSP; + else if (valid_C_LD) instr = i_C_LD; + else if (valid_C_SD) instr = i_C_SD; `endif -`ifdef RV128 - else if (valid_C_LQSP) instr = i_C_LQSP; - else if (valid_C_SQSP) instr = i_C_SQSP; - else if (valid_C_LQ) instr = i_C_LQ; - else if (valid_C_SQ) instr = i_C_SQ; -`endif + else if (valid_C_LQSP) instr = i_C_LQSP; + else if (valid_C_SQSP) instr = i_C_SQSP; + else if (valid_C_LQ) instr = i_C_LQ; + else if (valid_C_SQ) instr = i_C_SQ; `ifdef ISA_F - else if (valid_C_FLWSP) instr = i_C_FLWSP; - else if (valid_C_FSWSP) instr = i_C_FSWSP; - else if (valid_C_FLW) instr = i_C_FLW; - else if (valid_C_FSW) instr = i_C_FSW; + else if (valid_C_FLWSP) instr = i_C_FLWSP; + else if (valid_C_FSWSP) instr = i_C_FSWSP; + else if (valid_C_FLW) instr = i_C_FLW; + else if (valid_C_FSW) instr = i_C_FSW; `endif `ifdef ISA_D - else if (valid_C_FLDSP) instr = i_C_FLDSP; - else if (valid_C_FSDSP) instr = i_C_FSDSP; - else if (valid_C_FLD) instr = i_C_FLD; - else if (valid_C_FSD) instr = i_C_FSD; + else if (valid_C_FLDSP) instr = i_C_FLDSP; + else if (valid_C_FSDSP) instr = i_C_FSDSP; + else if (valid_C_FLD) instr = i_C_FLD; + else if (valid_C_FSD) instr = i_C_FSD; `endif else @@ -180,7 +181,7 @@ endfunction // 'C' Extension Stack-Pointer-Based Loads // LWSP: expands into LW -function Tuple2 #(Bool, Instr) fv_decode_C_LWSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LWSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: I-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -198,9 +199,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LWSP (MISA misa, Bit #(2) xl, Instr end endfunction -`ifdef RV64 // LDSP: expands into LD -function Tuple2 #(Bool, Instr) fv_decode_C_LDSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LDSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: I-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -211,7 +211,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LDSP (MISA misa, Bit #(2) xl, Instr && (rd != 0) && (funct3 == funct3_C_LDSP) && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + || (cap_enc))); RegName rs1 = reg_sp; let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LD, rd, op_LOAD); @@ -219,11 +219,10 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LDSP (MISA misa, Bit #(2) xl, Instr return tuple2 (is_legal, instr); end endfunction -`endif -`ifdef RV128 +`ifdef RV64 // LQSP: expands into LQ -function Tuple2 #(Bool, Instr) fv_decode_C_LQSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LQSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: I-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -233,10 +232,11 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LQSP (MISA misa, Bit #(2) xl, Instr && (op == opcode_C2) && (rd != 0) && (funct3 == funct3_C_LQSP) - && (xl == misa_mxl_128)); + && (xl == misa_mxl_64) + && (cap_enc)); RegName rs1 = reg_sp; - let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LQ, rd, op_LOAD); + let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LQ, rd, op_MISC_MEM); return tuple2 (is_legal, instr); end @@ -245,7 +245,7 @@ endfunction `ifdef ISA_F // FLWSP: expands into FLW -function Tuple2 #(Bool, Instr) fv_decode_C_FLWSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FLWSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: I-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -254,7 +254,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FLWSP (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C2) && (funct3 == funct3_C_FLWSP) - && (misa.f == 1'b1)); + && (misa.f == 1'b1) + && (! cap_enc)); RegName rs1 = reg_sp; let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_FLW, rd, op_LOAD_FP); @@ -266,7 +267,7 @@ endfunction `ifdef ISA_D // FLDSP: expands into FLD -function Tuple2 #(Bool, Instr) fv_decode_C_FLDSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FLDSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: I-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -276,8 +277,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FLDSP (MISA misa, Bit #(2) xl, Inst && (op == opcode_C2) && (funct3 == funct3_C_FLDSP) && (misa.d == 1'b1) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && ( (xl == misa_mxl_32) + || (! cap_enc))); RegName rs1 = reg_sp; let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_FLD, rd, op_LOAD_FP); @@ -291,7 +292,7 @@ endfunction // 'C' Extension Stack-Pointer-Based Stores // SWSP: expands to SW -function Tuple2 #(Bool, Instr) fv_decode_C_SWSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SWSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CSS-type match { .funct3, .imm_at_12_7, .rs2, .op } = fv_ifields_CSS_type (instr_C); @@ -308,9 +309,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SWSP (MISA misa, Bit #(2) xl, Inst end endfunction -`ifdef RV64 // SDSP: expands to SD -function Tuple2 #(Bool, Instr) fv_decode_C_SDSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SDSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CSS-type match { .funct3, .imm_at_12_7, .rs2, .op } = fv_ifields_CSS_type (instr_C); @@ -320,7 +320,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SDSP (MISA misa, Bit #(2) xl, Inst && (op == opcode_C2) && (funct3 == funct3_C_SDSP) && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + || (cap_enc))); RegName rs1 = reg_sp; let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_SD, op_STORE); @@ -328,11 +328,10 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SDSP (MISA misa, Bit #(2) xl, Inst return tuple2 (is_legal, instr); end endfunction -`endif -`ifdef RV128 +`ifdef RV64 // SQSP: expands to SQ -function Tuple2 #(Bool, Instr) fv_decode_C_SQSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SQSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CSS-type match { .funct3, .imm_at_12_7, .rs2, .op } = fv_ifields_CSS_type (instr_C); @@ -341,7 +340,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SQSP (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C2) && (funct3 == funct3_C_SQSP) - && (xl == misa_mxl_128)); + && (xl == misa_mxl_64) + && (cap_enc)); RegName rs1 = reg_sp; let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_SQ, op_STORE); @@ -353,7 +353,7 @@ endfunction `ifdef ISA_F // FSWSP: expands to FSW -function Tuple2 #(Bool, Instr) fv_decode_C_FSWSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FSWSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CSS-type match { .funct3, .imm_at_12_7, .rs2, .op } = fv_ifields_CSS_type (instr_C); @@ -361,7 +361,9 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FSWSP (MISA misa, Bit #(2) xl, Ins Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C2) - && (funct3 == funct3_C_FSWSP)); + && (funct3 == funct3_C_FSWSP) + && (xl == misa_mxl_32) + && (! cap_enc)); RegName rs1 = reg_sp; let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_FSW, op_STORE_FP); @@ -373,7 +375,7 @@ endfunction `ifdef ISA_D // FSDSP: expands to FSD -function Tuple2 #(Bool, Instr) fv_decode_C_FSDSP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FSDSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CSS-type match { .funct3, .imm_at_12_7, .rs2, .op } = fv_ifields_CSS_type (instr_C); @@ -382,8 +384,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FSDSP (MISA misa, Bit #(2) xl, Ins Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C2) && (funct3 == funct3_C_FSDSP) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && ( (xl == misa_mxl_32) + || (! cap_enc))); RegName rs1 = reg_sp; let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_FSD, op_STORE_FP); @@ -397,7 +399,7 @@ endfunction // 'C' Extension Register-Based Loads // C_LW: expands to LW -function Tuple2 #(Bool, Instr) fv_decode_C_LW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CL-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rd, .op } = fv_ifields_CL_type (instr_C); @@ -413,9 +415,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LW (MISA misa, Bit #(2) xl, Instr end endfunction -`ifdef RV64 // C_LD: expands to LD -function Tuple2 #(Bool, Instr) fv_decode_C_LD (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LD (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CL-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rd, .op } = fv_ifields_CL_type (instr_C); @@ -425,18 +426,17 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LD (MISA misa, Bit #(2) xl, Instr && (op == opcode_C0) && (funct3 == funct3_C_LD) && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + || (cap_enc))); let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LD, rd, op_LOAD); return tuple2 (is_legal, instr); end endfunction -`endif -`ifdef RV128 +`ifdef RV64 // C_LQ: expands to LQ -function Tuple2 #(Bool, Instr) fv_decode_C_LQ (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LQ (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CL-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rd, .op } = fv_ifields_CL_type (instr_C); @@ -445,9 +445,10 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LQ (MISA misa, Bit #(2) xl, Instr Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) && (funct3 == funct3_C_LQ) - && (xl == misa_mxl_128)); + && (xl == misa_mxl_64) + && (cap_enc)); - let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LQ, rd, op_LOAD); + let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_LQ, rd, op_MISC_MEM); return tuple2 (is_legal, instr); end @@ -456,7 +457,7 @@ endfunction `ifdef ISA_F // C_FLW: expands to FLW -function Tuple2 #(Bool, Instr) fv_decode_C_FLW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FLW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CL-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rd, .op } = fv_ifields_CL_type (instr_C); @@ -464,7 +465,9 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FLW (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) - && (funct3 == funct3_C_FLW)); + && (funct3 == funct3_C_FLW) + && (xl == misa_mxl_32) + && (! cap_enc)); let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_FLW, rd, op_LOAD_FP); @@ -475,7 +478,7 @@ endfunction `ifdef ISA_D // C_FLD: expands to FLD -function Tuple2 #(Bool, Instr) fv_decode_C_FLD (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FLD (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CL-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rd, .op } = fv_ifields_CL_type (instr_C); @@ -484,8 +487,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FLD (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) && (funct3 == funct3_C_FLD) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && ( (xl == misa_mxl_32) + || (! cap_enc))); let instr = mkInstr_I_type (zeroExtend (offset), rs1, f3_FLD, rd, op_LOAD_FP); @@ -498,7 +501,7 @@ endfunction // 'C' Extension Register-Based Stores // C_SW: expands to SW -function Tuple2 #(Bool, Instr) fv_decode_C_SW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CS-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rs2, .op } = fv_ifields_CS_type (instr_C); @@ -514,9 +517,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SW (MISA misa, Bit #(2) xl, Instr end endfunction -`ifdef RV64 // C_SD: expands to SD -function Tuple2 #(Bool, Instr) fv_decode_C_SD (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SD (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CS-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rs2, .op } = fv_ifields_CS_type (instr_C); @@ -524,18 +526,19 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SD (MISA misa, Bit #(2) xl, Instr Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) - && (funct3 == funct3_C_SD)); + && (funct3 == funct3_C_SD) + && ( (xl == misa_mxl_64) + || (cap_enc))); let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_SD, op_STORE); return tuple2 (is_legal, instr); end endfunction -`endif -`ifdef RV128 +`ifdef RV64 // C_SQ: expands to SQ -function Tuple2 #(Bool, Instr) fv_decode_C_SQ (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SQ (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CS-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rs2, .op } = fv_ifields_CS_type (instr_C); @@ -543,7 +546,9 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SQ (MISA misa, Bit #(2) xl, Instr Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) - && (funct3 == funct3_C_SQ)); + && (funct3 == funct3_C_SQ) + && (xl == misa_mxl_64) + && (cap_enc)); let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_SQ, op_STORE); @@ -554,7 +559,7 @@ endfunction `ifdef ISA_F // C_FSW: expands to FSW -function Tuple2 #(Bool, Instr) fv_decode_C_FSW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FSW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CS-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rs2, .op } = fv_ifields_CS_type (instr_C); @@ -562,7 +567,9 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FSW (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) - && (funct3 == funct3_C_FSW)); + && (funct3 == funct3_C_FSW) + && (xl == misa_mxl_32) + && (! cap_enc)); let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_FSW, op_STORE_FP); @@ -573,7 +580,7 @@ endfunction `ifdef ISA_D // C_FSD: expands to FSD -function Tuple2 #(Bool, Instr) fv_decode_C_FSD (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_FSD (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CS-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_5, .rs2, .op } = fv_ifields_CS_type (instr_C); @@ -581,7 +588,9 @@ function Tuple2 #(Bool, Instr) fv_decode_C_FSD (MISA misa, Bit #(2) xl, Inst Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) - && (funct3 == funct3_C_FSD)); + && (funct3 == funct3_C_FSD) + && ( (xl == misa_mxl_32) + || (! cap_enc))); let instr = mkInstr_S_type (zeroExtend (offset), rs2, rs1, f3_FSD, op_STORE_FP); @@ -595,7 +604,7 @@ endfunction // C.J, C.JAL, C.JR, C.JALR, C.BEQZ, C.BNEZ // C.J: expands to JAL -function Tuple2 #(Bool, Instr) fv_decode_C_J (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_J (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CJ-type match { .funct3, .imm_at_12_2, .op } = fv_ifields_CJ_type (instr_C); @@ -622,7 +631,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_J (MISA misa, Bit #(2) xl, Instr_ endfunction // C.JAL: expands to JAL -function Tuple2 #(Bool, Instr) fv_decode_C_JAL (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_JAL (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CJ-type match { .funct3, .imm_at_12_2, .op } = fv_ifields_CJ_type (instr_C); @@ -650,7 +659,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_JAL (MISA misa, Bit #(2) xl, Inst endfunction // C.JR: expands to JALR -function Tuple2 #(Bool, Instr) fv_decode_C_JR (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_JR (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CR-type match { .funct4, .rs1, .rs2, .op } = fv_ifields_CR_type (instr_C); @@ -669,7 +678,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_JR (MISA misa, Bit #(2) xl, Instr endfunction // C.JALR: expands to JALR -function Tuple2 #(Bool, Instr) fv_decode_C_JALR (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_JALR (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CR-type match { .funct4, .rs1, .rs2, .op } = fv_ifields_CR_type (instr_C); @@ -689,7 +698,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_JALR (MISA misa, Bit #(2) xl, Ins endfunction // C.BEQZ: expands to BEQ -function Tuple2 #(Bool, Instr) fv_decode_C_BEQZ (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_BEQZ (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CB-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_2, .op } = fv_ifields_CB_type (instr_C); @@ -708,7 +717,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_BEQZ (MISA misa, Bit #(2) xl, Ins endfunction // C.BNEZ: expands to BNE -function Tuple2 #(Bool, Instr) fv_decode_C_BNEZ (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_BNEZ (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CB-type match { .funct3, .imm_at_12_10, .rs1, .imm_at_6_2, .op } = fv_ifields_CB_type (instr_C); @@ -730,7 +739,7 @@ endfunction // 'C' Extension Integer Constant-Generation // C.LI: expands to ADDI -function Tuple2 #(Bool, Instr) fv_decode_C_LI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -750,7 +759,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_LI (MISA misa, Bit #(2) xl, Instr endfunction // C.LUI: expands to LUI -function Tuple2 #(Bool, Instr) fv_decode_C_LUI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_LUI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -774,7 +783,7 @@ endfunction // 'C' Extension Integer Register-Immediate Operations // C.ADDI: expands to ADDI -function Tuple2 #(Bool, Instr) fv_decode_C_ADDI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADDI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -794,7 +803,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDI (MISA misa, Bit #(2) xl, Ins endfunction // C.NOP: expands to ADDI -function Tuple2 #(Bool, Instr) fv_decode_C_NOP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_NOP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -814,7 +823,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_NOP (MISA misa, Bit #(2) xl, Inst endfunction // C.ADDIW: expands to ADDIW -function Tuple2 #(Bool, Instr) fv_decode_C_ADDIW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADDIW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -824,8 +833,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDIW (MISA misa, Bit #(2) xl, In && (op == opcode_C1) && (funct3 == funct3_C_ADDIW) && (rd_rs1 != 0) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && (xl == misa_mxl_64)); Bit #(12) imm12 = signExtend (imm6); let instr = mkInstr_I_type (imm12, rd_rs1, f3_ADDIW, rd_rs1, op_OP_IMM_32); @@ -835,7 +843,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDIW (MISA misa, Bit #(2) xl, In endfunction // C.ADDI16SP: expands to ADDI -function Tuple2 #(Bool, Instr) fv_decode_C_ADDI16SP (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADDI16SP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -845,7 +853,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDI16SP (MISA misa, Bit #(2) xl, && (op == opcode_C1) && (funct3 == funct3_C_ADDI16SP) && (rd_rs1 == reg_sp) - && (nzimm10 != 0)); + && (nzimm10 != 0) + && (! cap_enc)); Bit #(12) imm12 = signExtend (nzimm10); let instr = mkInstr_I_type (imm12, rd_rs1, f3_ADDI, rd_rs1, op_OP_IMM); @@ -854,8 +863,29 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDI16SP (MISA misa, Bit #(2) xl, end endfunction +// C.CIncOffsetImm16CSP: expands to CIncOffsetImm +function Tuple2 #(Bool, Instr) fv_decode_C_CIncOffsetImm16CSP (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); + begin + // Instr fields: CI-type + match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); + Bit #(10) nzimm10 = { imm_at_12, imm_at_6_2 [2:1], imm_at_6_2 [3], imm_at_6_2 [0], imm_at_6_2 [4], 4'b0 }; + + Bool is_legal = ((misa.c == 1'b1) + && (op == opcode_C1) + && (funct3 == funct3_C_CIncOffsetImm16CSP) + && (rd_rs1 == reg_sp) + && (nzimm10 != 0) + && (cap_enc)); + + Bit #(12) imm12 = signExtend (nzimm10); + let instr = mkInstr_I_type (imm12, rd_rs1, f3_cap_CIncOffsetImmediate, rd_rs1, op_cap_Manip); + + return tuple2 (is_legal, instr); + end +endfunction + // C.ADDI4SPN: expands to ADDI -function Tuple2 #(Bool, Instr) fv_decode_C_ADDI4SPN (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADDI4SPN (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CIW-type match { .funct3, .imm_at_12_5, .rd, .op } = fv_ifields_CIW_type (instr_C); @@ -864,7 +894,8 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDI4SPN (MISA misa, Bit #(2) xl, Bool is_legal = ((misa.c == 1'b1) && (op == opcode_C0) && (funct3 == funct3_C_ADDI4SPN) - && (nzimm10 != 0)); + && (nzimm10 != 0) + && (! cap_enc)); RegName rs1 = reg_sp; Bit #(12) imm12 = zeroExtend (nzimm10); @@ -874,8 +905,29 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDI4SPN (MISA misa, Bit #(2) xl, end endfunction +// C.CIncOffsetImm4CSPN: expands to CIncOffsetImm +function Tuple2 #(Bool, Instr) fv_decode_C_CIncOffsetImm4CSPN (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); + begin + // Instr fields: CIW-type + match { .funct3, .imm_at_12_5, .rd, .op } = fv_ifields_CIW_type (instr_C); + Bit #(10) nzimm10 = { imm_at_12_5 [5:2], imm_at_12_5 [7:6], imm_at_12_5 [0], imm_at_12_5 [1], 2'b0 }; + + Bool is_legal = ((misa.c == 1'b1) + && (op == opcode_C0) + && (funct3 == funct3_C_CIncOffsetImm4CSPN) + && (nzimm10 != 0) + && (cap_enc)); + + RegName rs1 = reg_sp; + Bit #(12) imm12 = zeroExtend (nzimm10); + let instr = mkInstr_I_type (imm12, rs1, f3_cap_CIncOffsetImmediate, rd, op_cap_Manip); + + return tuple2 (is_legal, instr); + end +endfunction + // C.SLLI: expands to SLLI -function Tuple2 #(Bool, Instr) fv_decode_C_SLLI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SLLI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CI-type match { .funct3, .imm_at_12, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CI_type (instr_C); @@ -898,7 +950,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SLLI (MISA misa, Bit #(2) xl, Ins endfunction // C.SRLI: expands to SRLI -function Tuple2 #(Bool, Instr) fv_decode_C_SRLI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SRLI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CB-type match { .funct3, .imm_at_12_10, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CB_type (instr_C); @@ -924,7 +976,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SRLI (MISA misa, Bit #(2) xl, Ins endfunction // C.SRAI: expands to SRAI -function Tuple2 #(Bool, Instr) fv_decode_C_SRAI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SRAI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CB-type match { .funct3, .imm_at_12_10, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CB_type (instr_C); @@ -950,7 +1002,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SRAI (MISA misa, Bit #(2) xl, Ins endfunction // C.ANDI: expands to ANDI -function Tuple2 #(Bool, Instr) fv_decode_C_ANDI (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ANDI (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CB-type match { .funct3, .imm_at_12_10, .rd_rs1, .imm_at_6_2, .op } = fv_ifields_CB_type (instr_C); @@ -974,7 +1026,7 @@ endfunction // 'C' Extension Integer Register-Register Operations // C.MV: expands to ADD -function Tuple2 #(Bool, Instr) fv_decode_C_MV (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_MV (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin match { .funct4, .rd_rs1, .rs2, .op } = fv_ifields_CR_type (instr_C); @@ -992,7 +1044,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_MV (MISA misa, Bit #(2) xl, Instr endfunction // C.ADD: expands to ADD -function Tuple2 #(Bool, Instr) fv_decode_C_ADD (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADD (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin match { .funct4, .rd_rs1, .rs2, .op } = fv_ifields_CR_type (instr_C); @@ -1009,7 +1061,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADD (MISA misa, Bit #(2) xl, Inst endfunction // C.AND: expands to AND -function Tuple2 #(Bool, Instr) fv_decode_C_AND (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_AND (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1026,7 +1078,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_AND (MISA misa, Bit #(2) xl, Inst endfunction // C.OR: expands to OR -function Tuple2 #(Bool, Instr) fv_decode_C_OR (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_OR (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1043,7 +1095,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_OR (MISA misa, Bit #(2) xl, Instr endfunction // C.XOR: expands to XOR -function Tuple2 #(Bool, Instr) fv_decode_C_XOR (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_XOR (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1060,7 +1112,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_XOR (MISA misa, Bit #(2) xl, Inst endfunction // C.SUB: expands to SUB -function Tuple2 #(Bool, Instr) fv_decode_C_SUB (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SUB (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1077,7 +1129,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SUB (MISA misa, Bit #(2) xl, Inst endfunction // C.ADDW: expands to ADDW -function Tuple2 #(Bool, Instr) fv_decode_C_ADDW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_ADDW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1086,8 +1138,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDW (MISA misa, Bit #(2) xl, Ins && (op == opcode_C1) && (funct6 == funct6_C_ADDW) && (funct2 == funct2_C_ADDW) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && (xl == misa_mxl_64)); let instr = mkInstr_R_type (funct7_ADDW, rs2, rd_rs1, funct3_ADDW, rd_rs1, op_OP_32); @@ -1096,7 +1147,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_ADDW (MISA misa, Bit #(2) xl, Ins endfunction // C.SUBW: expands to SUBW -function Tuple2 #(Bool, Instr) fv_decode_C_SUBW (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_SUBW (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CA-type match { .funct6, .rd_rs1, .funct2, .rs2, .op } = fv_ifields_CA_type (instr_C); @@ -1105,8 +1156,7 @@ function Tuple2 #(Bool, Instr) fv_decode_C_SUBW (MISA misa, Bit #(2) xl, Ins && (op == opcode_C1) && (funct6 == funct6_C_SUBW) && (funct2 == funct2_C_SUBW) - && ( (xl == misa_mxl_64) - || (xl == misa_mxl_128))); + && ((xl == misa_mxl_64))); let instr = mkInstr_R_type (funct7_SUBW, rs2, rd_rs1, funct3_SUBW, rd_rs1, op_OP_32); @@ -1118,7 +1168,7 @@ endfunction // 'C' Extension EBREAK // C.EBREAK: expands to EBREAK -function Tuple2 #(Bool, Instr) fv_decode_C_EBREAK (MISA misa, Bit #(2) xl, Instr_C instr_C); +function Tuple2 #(Bool, Instr) fv_decode_C_EBREAK (MISA misa, Bit #(2) xl, Bool cap_enc, Instr_C instr_C); begin // Instr fields: CR-type match { .funct4, .rd_rs1, .rs2, .op } = fv_ifields_CR_type (instr_C); diff --git a/src_Core/ISA/ISA_Decls_C.bsv b/src_Core/ISA/ISA_Decls_C.bsv index 3b05822..b3bfbe6 100644 --- a/src_Core/ISA/ISA_Decls_C.bsv +++ b/src_Core/ISA/ISA_Decls_C.bsv @@ -15,85 +15,87 @@ Bit #(2) opcode_C0 = 2'b00; Bit #(2) opcode_C1 = 2'b01; Bit #(2) opcode_C2 = 2'b10; -Bit #(3) funct3_C_LWSP = 3'b_010; -Bit #(3) funct3_C_LDSP = 3'b_011; // RV64 and RV128 -Bit #(3) funct3_C_LQSP = 3'b_001; // RV128 -Bit #(3) funct3_C_FLWSP = 3'b_011; // RV32FC -Bit #(3) funct3_C_FLDSP = 3'b_001; // RV32DC, RV64DC +Bit #(3) funct3_C_LWSP = 3'b_010; +Bit #(3) funct3_C_LDSP = 3'b_011; // RV64 and RV128 +Bit #(3) funct3_C_LQSP = 3'b_001; // RV128 +Bit #(3) funct3_C_FLWSP = 3'b_011; // RV32FC +Bit #(3) funct3_C_FLDSP = 3'b_001; // RV32DC, RV64DC -Bit #(3) funct3_C_SWSP = 3'b_110; +Bit #(3) funct3_C_SWSP = 3'b_110; -Bit #(3) funct3_C_SQSP = 3'b_101; // RV128 -Bit #(3) funct3_C_FSDSP = 3'b_101; // RV32DC, RV64DC +Bit #(3) funct3_C_SQSP = 3'b_101; // RV128 +Bit #(3) funct3_C_FSDSP = 3'b_101; // RV32DC, RV64DC -Bit #(3) funct3_C_SDSP = 3'b_111; // RV64 and RV128 -Bit #(3) funct3_C_FSWSP = 3'b_111; // RV32FC +Bit #(3) funct3_C_SDSP = 3'b_111; // RV64 and RV128 +Bit #(3) funct3_C_FSWSP = 3'b_111; // RV32FC -Bit #(3) funct3_C_LQ = 3'b_001; // RV128 -Bit #(3) funct3_C_FLD = 3'b_001; // RV32DC, RV64DC +Bit #(3) funct3_C_LQ = 3'b_001; // RV128 +Bit #(3) funct3_C_FLD = 3'b_001; // RV32DC, RV64DC -Bit #(3) funct3_C_LW = 3'b_010; +Bit #(3) funct3_C_LW = 3'b_010; -Bit #(3) funct3_C_LD = 3'b_011; // RV64 and RV128 -Bit #(3) funct3_C_FLW = 3'b_011; // RV32FC +Bit #(3) funct3_C_LD = 3'b_011; // RV64 and RV128 +Bit #(3) funct3_C_FLW = 3'b_011; // RV32FC -Bit #(3) funct3_C_FSD = 3'b_101; // RV32DC, RV64DC -Bit #(3) funct3_C_SQ = 3'b_101; // RV128 +Bit #(3) funct3_C_FSD = 3'b_101; // RV32DC, RV64DC +Bit #(3) funct3_C_SQ = 3'b_101; // RV128 -Bit #(3) funct3_C_SW = 3'b_110; +Bit #(3) funct3_C_SW = 3'b_110; -Bit #(3) funct3_C_SD = 3'b_111; // RV64 and RV128 -Bit #(3) funct3_C_FSW = 3'b_111; // RV32FC +Bit #(3) funct3_C_SD = 3'b_111; // RV64 and RV128 +Bit #(3) funct3_C_FSW = 3'b_111; // RV32FC -Bit #(3) funct3_C_JAL = 3'b_001; // RV32 -Bit #(3) funct3_C_J = 3'b_101; -Bit #(3) funct3_C_BEQZ = 3'b_110; -Bit #(3) funct3_C_BNEZ = 3'b_111; +Bit #(3) funct3_C_JAL = 3'b_001; // RV32 +Bit #(3) funct3_C_J = 3'b_101; +Bit #(3) funct3_C_BEQZ = 3'b_110; +Bit #(3) funct3_C_BNEZ = 3'b_111; -Bit #(4) funct4_C_JR = 4'b_1000; -Bit #(4) funct4_C_JALR = 4'b_1001; +Bit #(4) funct4_C_JR = 4'b_1000; +Bit #(4) funct4_C_JALR = 4'b_1001; -Bit #(3) funct3_C_LI = 3'b_010; -Bit #(3) funct3_C_LUI = 3'b_011; // RV64 and RV128 +Bit #(3) funct3_C_LI = 3'b_010; +Bit #(3) funct3_C_LUI = 3'b_011; // RV64 and RV128 -Bit #(3) funct3_C_NOP = 3'b_000; -Bit #(3) funct3_C_ADDI = 3'b_000; -Bit #(3) funct3_C_ADDIW = 3'b_001; -Bit #(3) funct3_C_ADDI16SP = 3'b_011; -Bit #(3) funct3_C_ADDI4SPN = 3'b_000; -Bit #(3) funct3_C_SLLI = 3'b_000; +Bit #(3) funct3_C_NOP = 3'b_000; +Bit #(3) funct3_C_ADDI = 3'b_000; +Bit #(3) funct3_C_ADDIW = 3'b_001; +Bit #(3) funct3_C_ADDI16SP = 3'b_011; +Bit #(3) funct3_C_CIncOffsetImm16CSP = 3'b_011; +Bit #(3) funct3_C_ADDI4SPN = 3'b_000; +Bit #(3) funct3_C_CIncOffsetImm4CSPN = 3'b_000; +Bit #(3) funct3_C_SLLI = 3'b_000; -Bit #(3) funct3_C_SRLI = 3'b_100; -Bit #(2) funct2_C_SRLI = 2'b_00; +Bit #(3) funct3_C_SRLI = 3'b_100; +Bit #(2) funct2_C_SRLI = 2'b_00; -Bit #(3) funct3_C_SRAI = 3'b_100; -Bit #(2) funct2_C_SRAI = 2'b_01; +Bit #(3) funct3_C_SRAI = 3'b_100; +Bit #(2) funct2_C_SRAI = 2'b_01; -Bit #(3) funct3_C_ANDI = 3'b_100; -Bit #(2) funct2_C_ANDI = 2'b_10; +Bit #(3) funct3_C_ANDI = 3'b_100; +Bit #(2) funct2_C_ANDI = 2'b_10; -Bit #(4) funct4_C_MV = 4'b_1000; -Bit #(4) funct4_C_ADD = 4'b_1001; +Bit #(4) funct4_C_MV = 4'b_1000; +Bit #(4) funct4_C_ADD = 4'b_1001; -Bit #(6) funct6_C_AND = 6'b_100_0_11; -Bit #(2) funct2_C_AND = 2'b_11; +Bit #(6) funct6_C_AND = 6'b_100_0_11; +Bit #(2) funct2_C_AND = 2'b_11; -Bit #(6) funct6_C_OR = 6'b_100_0_11; -Bit #(2) funct2_C_OR = 2'b_10; +Bit #(6) funct6_C_OR = 6'b_100_0_11; +Bit #(2) funct2_C_OR = 2'b_10; -Bit #(6) funct6_C_XOR = 6'b_100_0_11; -Bit #(2) funct2_C_XOR = 2'b_01; +Bit #(6) funct6_C_XOR = 6'b_100_0_11; +Bit #(2) funct2_C_XOR = 2'b_01; -Bit #(6) funct6_C_SUB = 6'b_100_0_11; -Bit #(2) funct2_C_SUB = 2'b_00; +Bit #(6) funct6_C_SUB = 6'b_100_0_11; +Bit #(2) funct2_C_SUB = 2'b_00; -Bit #(6) funct6_C_ADDW = 6'b_100_1_11; -Bit #(2) funct2_C_ADDW = 2'b_01; +Bit #(6) funct6_C_ADDW = 6'b_100_1_11; +Bit #(2) funct2_C_ADDW = 2'b_01; -Bit #(6) funct6_C_SUBW = 6'b_100_1_11; -Bit #(2) funct2_C_SUBW = 2'b_00; +Bit #(6) funct6_C_SUBW = 6'b_100_1_11; +Bit #(2) funct2_C_SUBW = 2'b_00; -Bit #(4) funct4_C_EBREAK = 4'b_1001; +Bit #(4) funct4_C_EBREAK = 4'b_1001; // ================================================================ // Functions to extract instruction fields from 'C' (compressed) instructions diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index c819973..e04b216 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -626,7 +626,7 @@ module mkFetchStage(FetchStage); end end else if (is_16b_inst(frag.inst_frag)) begin // 16-bit instruction new_pick = tagged Valid fetch3_2_instC(frag, - fv_decode_C (misa, misa_mxl_64, frag.inst_frag), + fv_decode_C (misa, misa_mxl_64, getFlags(decompressPc(frag.pc))==1, frag.inst_frag), zeroExtend(frag.inst_frag)); end end From f909d886c9c56771327ca8e650aea87fb926e408 Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Thu, 27 May 2021 14:45:15 +0100 Subject: [PATCH 10/14] Add a copyright --- src_Core/CPU/CPU_Decode_C.bsv | 1 + 1 file changed, 1 insertion(+) diff --git a/src_Core/CPU/CPU_Decode_C.bsv b/src_Core/CPU/CPU_Decode_C.bsv index dbb9c79..d242c73 100644 --- a/src_Core/CPU/CPU_Decode_C.bsv +++ b/src_Core/CPU/CPU_Decode_C.bsv @@ -3,6 +3,7 @@ // RVFI_DII + CHERI modifications: // Copyright (c) 2020 Jessica Clarke // Copyright (c) 2020 Jonathan Woodruff +// Copyright (c) 2020 Peter Rugg // All rights reserved. // // This software was developed by SRI International and the University of From afd636a0f57e80333030ebc98a79a3e4d57ff071 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Fri, 28 May 2021 02:32:04 +0100 Subject: [PATCH 11/14] mkXBar: Fix bias towards earlier sources In the case where the prioritised round-robin source does not have a request, this was always picking the earliest source that had one, which means if some sources are making more requests than others (e.g. there is lots of D$ churn but the I$ has a high hit rate) then, whilst the cycles where srcRR[dst] prioritises a source that is making requests are fair, the cycles where it prioritises a source that is not making requests is not fair, since then the earlier sources will be prioritised. Instead, make the fallback priority similarly dynamic so we cycle through the order we look at the sources in. --- src_Core/RISCY_OOO/coherence/src/CrossBar.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv index e43f2e5..492c87a 100644 --- a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv @@ -108,7 +108,7 @@ module mkXBar#( end else begin // otherwise just get one valid src - Vector#(srcNum, srcIdxT) srcIdxVec = genWith(fromInteger); + Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), unpack(srcRR[dst])); whichSrc = searchIndex(isFromSrc, srcIdxVec); end if(whichSrc matches tagged Valid .src) begin From 46b1519cb0a319850f6eddaf3b0321ee4ead8fec Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Fri, 28 May 2021 02:57:12 +0100 Subject: [PATCH 12/14] mkXBar: Simplify as fallback case handles priority case correctly The first element in the vector will be srcRR[dst], so the special case is unnecessary. --- src_Core/RISCY_OOO/coherence/src/CrossBar.bsv | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv index 492c87a..3eae2ae 100644 --- a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv @@ -101,16 +101,9 @@ module mkXBar#( return False; end endfunction - Maybe#(srcIdxT) whichSrc = Invalid; // the src to select - if(isFromSrc(srcRR[dst])) begin - // first check the src with priority - whichSrc = Valid (srcRR[dst]); - end - else begin - // otherwise just get one valid src - Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), unpack(srcRR[dst])); - whichSrc = searchIndex(isFromSrc, srcIdxVec); - end + // find the first valid source starting at srcRR[dst] + Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), unpack(srcRR[dst])); + Maybe#(srcIdxT) whichSrc = searchIndex(isFromSrc, srcIdxVec); // the src to select if(whichSrc matches tagged Valid .src) begin // can do enq & deq deqSrcByDst[dst] = whichSrc; From bf911326e3a3aa90f0a5d91e66e96eb6185ab86b Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Fri, 28 May 2021 12:36:06 +0100 Subject: [PATCH 13/14] Fix some arbitration bugs --- src_Core/RISCY_OOO/coherence/src/CrossBar.bsv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv index 3eae2ae..dba7565 100644 --- a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv @@ -102,8 +102,8 @@ module mkXBar#( end endfunction // find the first valid source starting at srcRR[dst] - Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), unpack(srcRR[dst])); - Maybe#(srcIdxT) whichSrc = searchIndex(isFromSrc, srcIdxVec); // the src to select + Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), -unpack(srcRR[dst])); + Maybe#(srcIdxT) whichSrc = fmap(select(srcIdxVec), searchIndex(isFromSrc, srcIdxVec)); // the src to select if(whichSrc matches tagged Valid .src) begin // can do enq & deq deqSrcByDst[dst] = whichSrc; From 10f0807a9b69963084b2219600a178a4d7f901cf Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Fri, 28 May 2021 14:37:24 +0100 Subject: [PATCH 14/14] Fix arbitration for non-power-of-two numbers of sources --- src_Core/RISCY_OOO/coherence/src/CrossBar.bsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv index dba7565..4e1bb86 100644 --- a/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv +++ b/src_Core/RISCY_OOO/coherence/src/CrossBar.bsv @@ -102,7 +102,7 @@ module mkXBar#( end endfunction // find the first valid source starting at srcRR[dst] - Vector#(srcNum, srcIdxT) srcIdxVec = rotateBy(genWith(fromInteger), -unpack(srcRR[dst])); + Vector#(srcNum, srcIdxT) srcIdxVec = reverse(rotateBy(reverse(genWith(fromInteger)), unpack(srcRR[dst]))); // Double reverse to achieve rotateBy left, since it's not provided by Bluespec Maybe#(srcIdxT) whichSrc = fmap(select(srcIdxVec), searchIndex(isFromSrc, srcIdxVec)); // the src to select if(whichSrc matches tagged Valid .src) begin // can do enq & deq