diff --git a/config/buildroot/config.vh b/config/buildroot/config.vh index 35d20e169..e183d9cbd 100644 --- a/config/buildroot/config.vh +++ b/config/buildroot/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 1; localparam ZICBOP_SUPPORTED = 1; localparam ZICCLSM_SUPPORTED = 1; +localparam ZICOND_SUPPORTED = 1; localparam SVPBMT_SUPPORTED = 1; localparam SVNAPOT_SUPPORTED = 1; localparam SVINVAL_SUPPORTED = 1; diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index 1db72cad7..8906bb571 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index a5af5f608..67855c817 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -47,6 +47,7 @@ localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 1; localparam ZICBOP_SUPPORTED = 1; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 1; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index 13e3d2f66..2f90656f2 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index ba0c455e3..ecb7b8f78 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -45,6 +45,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; diff --git a/config/rv64fpquad/config.vh b/config/rv64fpquad/config.vh index fb6e500fa..11feba734 100644 --- a/config/rv64fpquad/config.vh +++ b/config/rv64fpquad/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index bf2f36827..a8b7f1b05 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 1; localparam ZICBOP_SUPPORTED = 1; localparam ZICCLSM_SUPPORTED = 1; +localparam ZICOND_SUPPORTED = 1; localparam SVPBMT_SUPPORTED = 1; localparam SVNAPOT_SUPPORTED = 1; localparam SVINVAL_SUPPORTED = 1; diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 0a355f1e3..1908f900f 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -46,6 +46,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam ZICCLSM_SUPPORTED = 0; +localparam ZICOND_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 7e5a19619..ec6fc7ec5 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -24,6 +24,7 @@ localparam cvw_t P = '{ ZICBOZ_SUPPORTED : ZICBOZ_SUPPORTED, ZICBOP_SUPPORTED : ZICBOP_SUPPORTED, ZICCLSM_SUPPORTED : ZICCLSM_SUPPORTED, + ZICOND_SUPPORTED : ZICOND_SUPPORTED, SVPBMT_SUPPORTED : SVPBMT_SUPPORTED, SVNAPOT_SUPPORTED : SVNAPOT_SUPPORTED, SVINVAL_SUPPORTED : SVINVAL_SUPPORTED, diff --git a/sim/imperas.ic b/sim/imperas.ic index 1382f4d63..f3c620b96 100644 --- a/sim/imperas.ic +++ b/sim/imperas.ic @@ -19,6 +19,7 @@ # More extensions --override cpu/Zcb=T +--override cpu/Zicond=T # Cache block operations --override cpu/Zicbom=T diff --git a/sim/regression-wally b/sim/regression-wally index b2a1ad424..ea453d2c9 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -78,7 +78,7 @@ for test in tests64i: configs.append(tc) tests32gcimperas = ["imperas32i", "imperas32f", "imperas32m", "imperas32c"] # unused -tests32gc = ["arch32f", "arch32d", "arch32f_fma", "arch32d_fma", "arch32i", "arch32priv", "arch32c", "arch32m", "arch32a", "arch32zifencei", "arch32zba", "arch32zbb", "arch32zbc", "arch32zbs", "wally32a", "wally32priv", "wally32periph"] +tests32gc = ["arch32f", "arch32d", "arch32f_fma", "arch32d_fma", "arch32i", "arch32priv", "arch32c", "arch32m", "arch32a", "arch32zifencei", "arch32zicond", "arch32zba", "arch32zbb", "arch32zbc", "arch32zbs", "wally32a", "wally32priv", "wally32periph"] #tests32gc = ["arch32f", "arch32d", "arch32f_fma", "arch32d_fma", "arch32i", "arch32priv", "arch32c", "arch32m", "arch32a", "arch32zifencei", "arch32zba", "arch32zbb", "arch32zbc", "arch32zbs", "arch32zicboz", "arch32zcb", "wally32a", "wally32priv", "wally32periph"] for test in tests32gc: tc = TestCase( @@ -127,13 +127,13 @@ for test in ahbTests: configs.append(tc) tests64gc = ["arch64f", "arch64d", "arch64f_fma", "arch64d_fma", "arch64i", "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", - "arch64priv", "arch64c", "arch64m", "arch64a", "arch64zifencei", "wally64a", "wally64periph", "wally64priv"] + "arch64priv", "arch64c", "arch64m", "arch64a", "arch64zifencei", "arch64zicond", "wally64a", "wally64periph", "wally64priv"] #tests64gc = ["arch64f", "arch64d", "arch64f_fma", "arch64d_fma", "arch64i", "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", # "arch64priv", "arch64c", "arch64m", "arch64a", "arch64zifencei", "wally64a", "wally64periph", "wally64priv", "arch64zicboz", "arch64zcb"] if (coverage): # delete all but 64gc tests when running coverage configs = [] tests64gc = ["coverage64gc", "arch64i", "arch64priv", "arch64c", "arch64m", - "arch64zifencei", "arch64a", "wally64a", "wally64periph", "wally64priv", + "arch64zifencei", "arch64zicond", "arch64a", "wally64a", "wally64periph", "wally64priv", "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs"] # add when working: "arch64zicboz", "arch64zcb", if (fp): tests64gc.append("arch64f") diff --git a/src/cvw.sv b/src/cvw.sv index e237dd56c..53cbb5a70 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -59,6 +59,7 @@ typedef struct packed { logic ZICBOZ_SUPPORTED; logic ZICBOP_SUPPORTED; logic ZICCLSM_SUPPORTED; + logic ZICOND_SUPPORTED; logic SVPBMT_SUPPORTED; logic SVNAPOT_SUPPORTED; logic SVINVAL_SUPPORTED; diff --git a/src/ieu/alu.sv b/src/ieu/alu.sv index b8a0933dc..b13c3a65c 100644 --- a/src/ieu/alu.sv +++ b/src/ieu/alu.sv @@ -29,25 +29,27 @@ module alu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] A, B, // Operands - input logic W64, // W64-type instruction - input logic SubArith, // Subtraction or arithmetic shift - input logic [2:0] ALUSelect, // ALU mux select signal - input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction - input logic [2:0] ZBBSelect, // ZBB mux select signal - input logic [2:0] Funct3, // For BMU decoding - input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage - input logic BMUActiveE, // Bit manipulation instruction being executed + input logic W64, // W64-type instruction + input logic SubArith, // Subtraction or arithmetic shift + input logic [2:0] ALUSelect, // ALU mux select signal + input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction + input logic [2:0] ZBBSelect, // ZBB mux select signal + input logic [2:0] Funct3, // For BMU decoding + input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage + input logic BMUActive, // Bit manipulation instruction being executed + input logic [1:0] CZero, // {czero.nez, czero.eqz} instructions active output logic [P.XLEN-1:0] ALUResult, // ALU result output logic [P.XLEN-1:0] Sum); // Sum of operands // CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction. // FullResult = ALU result before adjusting for a RV64 w-suffix instruction. - logic [P.XLEN-1:0] CondMaskInvB, Shift, FullResult, PreALUResult; // Intermediate Signals - logic [P.XLEN-1:0] CondMaskB; // Result of B mask select mux - logic [P.XLEN-1:0] CondShiftA; // Result of A shifted select mux - logic Carry, Neg; // Flags: carry out, negative - logic LT, LTU; // Less than, Less than unsigned - logic Asign, Bsign; // Sign bits of A, B + logic [P.XLEN-1:0] CondMaskInvB, Shift, FullResult, PreALUResult; // Intermediate Signals + logic [P.XLEN-1:0] CondMaskB; // Result of B mask select mux + logic [P.XLEN-1:0] CondShiftA; // Result of A shifted select mux + logic [P.XLEN-1:0] ZeroCondMaskInvB; // B input to AND gate, accounting for czero.* instructions + logic Carry, Neg; // Flags: carry out, negative + logic LT, LTU; // Less than, Less than unsigned + logic Asign, Bsign; // Sign bits of A, B // Addition // CondMaskB is B for add/sub, or a masked version of B for certain bit manipulation instructions @@ -71,24 +73,24 @@ module alu import cvw::*; #(parameter cvw_t P) ( // Select appropriate ALU Result always_comb case (ALUSelect) - 3'b000: FullResult = Sum; // add or sub (including address generation) - 3'b001: FullResult = Shift; // sll, sra, or srl + 3'b000: FullResult = Sum; // add or sub (including address generation) + 3'b001: FullResult = Shift; // sll, sra, or srl 3'b010: FullResult = {{(P.XLEN-1){1'b0}}, LT}; // slt 3'b011: FullResult = {{(P.XLEN-1){1'b0}}, LTU}; // sltu - 3'b100: FullResult = A ^ CondMaskInvB; // xor, xnor, binv + 3'b100: FullResult = A ^ CondMaskInvB; // xor, xnor, binv 3'b101: FullResult = (P.ZBS_SUPPORTED | P.ZBB_SUPPORTED) ? {{(P.XLEN-1){1'b0}},{|(A & CondMaskB)}} : Shift; // bext (or IEU shift when BMU not supported) - 3'b110: FullResult = A | CondMaskInvB; // or, orn, bset - 3'b111: FullResult = A & CondMaskInvB; // and, bclr + 3'b110: FullResult = A | CondMaskInvB; // or, orn, bset + 3'b111: FullResult = A & ZeroCondMaskInvB; // and, bclr, czero.* endcase // Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits if (P.XLEN == 64) assign PreALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; else assign PreALUResult = FullResult; - // Final Result B instruction select mux + // Bit manipulation muxing if (P.ZBC_SUPPORTED | P.ZBS_SUPPORTED | P.ZBA_SUPPORTED | P.ZBB_SUPPORTED) begin : bitmanipalu bitmanipalu #(P) balu( - .A, .B, .W64, .BSelect, .ZBBSelect, .BMUActiveE, + .A, .B, .W64, .BSelect, .ZBBSelect, .BMUActive, .Funct3, .LT,.LTU, .BALUControl, .PreALUResult, .FullResult, .CondMaskB, .CondShiftA, .ALUResult); end else begin @@ -96,4 +98,14 @@ module alu import cvw::*; #(parameter cvw_t P) ( assign CondMaskB = B; assign CondShiftA = A; end + + // Zicond block + if (P.ZICOND_SUPPORTED) begin: zicond + logic BZero, KillB; + assign BZero = (B == 0); // check if rs2 = 0 + // Create a signal that is 0 when czero.* instruction should clear result + // If B = 0 for czero.eqz or if B != 0 for czero.nez + assign KillB = BZero & CZero[0] | ~BZero & CZero[1]; + assign ZeroCondMaskInvB = |CZero ? {P.XLEN{~KillB}} : CondMaskInvB; // extend to full width + end else assign ZeroCondMaskInvB = CondMaskInvB; // no masking if Zicond is not supported endmodule diff --git a/src/ieu/bmu/bitmanipalu.sv b/src/ieu/bmu/bitmanipalu.sv index 44c66f795..4a5b4bfab 100644 --- a/src/ieu/bmu/bitmanipalu.sv +++ b/src/ieu/bmu/bitmanipalu.sv @@ -29,14 +29,14 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] A, B, // Operands - input logic W64, // W64-type instruction - input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction - input logic [2:0] ZBBSelect, // ZBB mux select signal - input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform - input logic LT, // less than flag - input logic LTU, // less than unsigned flag - input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage - input logic BMUActiveE, // Bit manipulation instruction being executed + input logic W64, // W64-type instruction + input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction + input logic [2:0] ZBBSelect, // ZBB mux select signal + input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform + input logic LT, // less than flag + input logic LTU, // less than unsigned flag + input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage + input logic BMUActive, // Bit manipulation instruction being executed input logic [P.XLEN-1:0] PreALUResult, FullResult,// PreALUResult, FullResult signals output logic [P.XLEN-1:0] CondMaskB, // B is conditionally masked for ZBS instructions output logic [P.XLEN-1:0] CondShiftA, // A is conditionally shifted for ShAdd instructions @@ -45,16 +45,16 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] ZBBResult, ZBCResult; // ZBB, ZBC Result logic [P.XLEN-1:0] MaskB; // BitMask of B logic [P.XLEN-1:0] RevA; // Bit-reversed A - logic Rotate; // Indicates if it is Rotate instruction - logic Mask; // Indicates if it is ZBS instruction - logic PreShift; // Inidicates if it is sh1add, sh2add, sh3add instruction - logic [1:0] PreShiftAmt; // Amount to Pre-Shift A + logic Rotate; // Indicates if it is Rotate instruction + logic Mask; // Indicates if it is ZBS instruction + logic PreShift; // Inidicates if it is sh1add, sh2add, sh3add instruction + logic [1:0] PreShiftAmt; // Amount to Pre-Shift A logic [P.XLEN-1:0] CondZextA; // A Conditional Extend Intermediary Signal logic [P.XLEN-1:0] ABMU, BBMU; // Gated data inputs to reduce BMU activity // gate data inputs to BMU to only operate when BMU is active - assign ABMU = A & {P.XLEN{BMUActiveE}}; - assign BBMU = B & {P.XLEN{BMUActiveE}}; + assign ABMU = A & {P.XLEN{BMUActive}}; + assign BBMU = B & {P.XLEN{BMUActive}}; // Extract control signals from bitmanip ALUControl. assign {Mask, PreShift} = BALUControl[1:0]; diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index ab4ba414a..3507ec3e9 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -65,6 +65,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic [2:0] ZBBSelectE, // ZBB mux select signal in Execute stage output logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage output logic BMUActiveE, // Bit manipulation instruction being executed + output logic [1:0] CZeroE, // {czero.nez, czero.eqz} instructions active output logic MDUActiveE, // Mul/Div instruction being executed output logic [3:0] CMOpM, // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero output logic IFUPrefetchE, // instruction prefetch @@ -137,6 +138,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic IntDivM; // Integer divide instruction logic [1:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage logic [2:0] ZBBSelectD; // ZBB Mux Select Signal + logic [1:0] CZeroD; logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions logic FLSFunctD; // Detect floating-point loads and stores @@ -147,6 +149,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic RWFunctD, MWFunctD; // detect RW/MW instructions logic PFunctD, CSRFunctD; // detect privileged / CSR instruction logic FenceM; // Fence.I or sfence.VMA instruction in memory stage + logic [2:0] PreALUSelectD; // ALU Output selection mux control (before possible Zicond logic) logic [2:0] ALUSelectD; // ALU Output selection mux control logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions logic [3:0] CMOpD, CMOpE; // which CMO instruction 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero @@ -156,8 +159,8 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read logic StoreStallD; // load after store hazard + logic FunctCZeroD; // Funct7 and Funct3 indicate czero.* (not including Op check) - // Extract fields assign OpD = InstrD[6:0]; assign Funct3D = InstrD[14:12]; @@ -167,21 +170,22 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign RdD = InstrD[11:7]; // Funct 7 checking - // Be rigorous about detecting illegal instructions if CSRs or bit manipulation is supported + // Be rigorous about detecting illegal instructions if CSRs or bit manipulation or conditional ops are supported // otherwise be cheap - if (P.ZICSR_SUPPORTED | P.ZBA_SUPPORTED | P.ZBB_SUPPORTED | P.ZBC_SUPPORTED | P.ZBS_SUPPORTED) begin:legalcheck // Exact integer decoding + if (P.ZICSR_SUPPORTED | P.ZBA_SUPPORTED | P.ZBB_SUPPORTED | P.ZBC_SUPPORTED | P.ZBS_SUPPORTED | P.ZICOND_SUPPORTED) begin:legalcheck // Exact integer decoding logic Funct7ZeroD, Funct7b5D, IShiftD, INoShiftD; logic Funct7ShiftZeroD, Funct7Shiftb5D; assign Funct7ZeroD = (Funct7D == 7'b0000000); // most R-type instructions assign Funct7b5D = (Funct7D == 7'b0100000); // srai, sub + assign FunctCZeroD = (Funct3D == 3'b101 | Funct3D == 3'b111) & (Funct7D == 7'b0000111) & P.ZICOND_SUPPORTED; // czero.eqz or czero.nez assign Funct7ShiftZeroD = (P.XLEN==64) ? (Funct7D[6:1] == 6'b000000) : Funct7ZeroD; assign Funct7Shiftb5D = (P.XLEN==64) ? (Funct7D[6:1] == 6'b010000) : Funct7b5D; assign IShiftD = (Funct3D == 3'b001 & Funct7ShiftZeroD) | (Funct3D == 3'b101 & (Funct7ShiftZeroD | Funct7Shiftb5D)); // slli, srli, srai, or w forms assign INoShiftD = ((Funct3D != 3'b001) & (Funct3D != 3'b101)); assign IFunctD = IShiftD | INoShiftD; - assign RFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) | Funct7ZeroD; + assign RFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) | FunctCZeroD | Funct7ZeroD; assign MFunctD = (Funct7D == 7'b0000001) & (P.M_SUPPORTED | (P.ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv assign LFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b100 | Funct3D == 3'b101 | ((P.XLEN == 64) & (Funct3D == 3'b011 | Funct3D == 3'b110)); @@ -321,7 +325,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( bmuctrl #(P) bmuctrl(.clk, .reset, .StallD, .FlushD, .InstrD, .ALUOpD, .BSelectD, .ZBBSelectD, .BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE, - .ALUSelectD, .BSelectE, .ZBBSelectE, .BRegWriteE, .BALUControlE, .BMUActiveE); + .ALUSelectD(PreALUSelectD), .BSelectE, .ZBBSelectE, .BRegWriteE, .BALUControlE, .BMUActiveE); if (P.ZBA_SUPPORTED) begin // ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw assign sltD = (Funct3D == 3'b010 & (~(Funct7D[4]) | ~OpD[5])) ; @@ -337,7 +341,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign SubArithD = BaseSubArithD | BSubArithD; // TRUE If BMU or R-type instruction involves inverted operand end else begin: bitmanipi - assign ALUSelectD = ALUOpD ? Funct3D : 3'b000; // add for address generation when not doing ALU operation + assign PreALUSelectD = ALUOpD ? Funct3D : 3'b000; // add for address generation when not doing ALU operation assign sltD = (Funct3D == 3'b010); assign IllegalBaseInstrD = ControlsD[0] | IllegalERegAdrD ; assign RegWriteD = BaseRegWriteD; @@ -353,6 +357,16 @@ module controller import cvw::*; #(parameter cvw_t P) ( assign BMUActiveE = 1'b0; end + if (P.ZICOND_SUPPORTED) begin: Zicond + logic SomeCZeroD; // instruction is czero.* + assign SomeCZeroD = FunctCZeroD & (OpD == 7'b0110011); + assign CZeroD = {SomeCZeroD & (Funct3D == 3'b111), SomeCZeroD & (Funct3D == 3'b101)}; // {czero.nez, czero.eqz} + assign ALUSelectD = SomeCZeroD ? 3'b111 : PreALUSelectD; // perform AND operation for czero.* instructions + end else begin + assign CZeroD = 2'b00; // Zicond not supported + assign ALUSelectD = PreALUSelectD; + end + // Fences // Ordinary fence is presently a nop // fence.i flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented @@ -402,12 +416,12 @@ module controller import cvw::*; #(parameter cvw_t P) ( flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); // Execute stage pipeline control register and logic - flopenrc #(35) controlregE(clk, reset, FlushE, ~StallE, - {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, InstrValidD}, - {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, InstrValidE}); - flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); - flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); - flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); + flopenrc #(37) controlregE(clk, reset, FlushE, ~StallE, + {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, CMOpD, IFUPrefetchD, LSUPrefetchD, CZeroD, InstrValidD}, + {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, CMOpE, IFUPrefetchE, LSUPrefetchE, CZeroE, InstrValidE}); + flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); + flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); + flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); // Branch Logic // The comparator handles both signed and unsigned branches using BranchSignedE @@ -429,13 +443,13 @@ module controller import cvw::*; #(parameter cvw_t P) ( flopenrc #(25) controlregM(clk, reset, FlushM, ~StallM, {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE, CMOpE, LSUPrefetchE}, {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM}); - flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM); + flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM); // Writeback stage pipeline control register flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW, {RegWriteM, ResultSrcM, IntDivM}, {RegWriteW, ResultSrcW, IntDivW}); - flopenrc #(5) RdWReg(clk, reset, FlushW, ~StallW, RdM, RdW); + flopenrc #(5) RdWReg(clk, reset, FlushW, ~StallW, RdM, RdW); // Flush F, D, and E stages on a CSR write or Fence.I or SFence.VMA assign CSRWriteFenceM = CSRWriteM | FenceM; diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index 126410238..c2bcaf8c3 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -50,6 +50,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( input logic [2:0] ZBBSelectE, // ZBB mux select signal input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage input logic BMUActiveE, // Bit manipulation instruction being executed + input logic [1:0] CZeroE, // {czero.nez, czero.eqz} instructions active output logic [1:0] FlagsE, // Comparison flags ({eq, lt}) output logic [P.XLEN-1:0] IEUAdrE, // Address computed by ALU output logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B @@ -107,7 +108,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( comparator #(P.XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE); mux2 #(P.XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE); mux2 #(P.XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE); - alu #(P) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, BALUControlE, BMUActiveE, ALUResultE, IEUAdrE); + alu #(P) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, BALUControlE, BMUActiveE, CZeroE, ALUResultE, IEUAdrE); mux2 #(P.XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE); mux2 #(P.XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE); diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index b8b3c200d..870a37963 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -101,6 +101,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( logic BranchSignedE; // Branch does signed comparison on operands logic MDUE; // Multiply/divide instruction logic BMUActiveE; // Bit manipulation instruction being executed + logic [1:0] CZeroE; // {czero.nez, czero.eqz} instructions active controller #(P) c( .clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD, @@ -109,7 +110,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .StallE, .FlushE, .FlagsE, .FWriteIntE, .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE, .Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, - .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .MDUActiveE, + .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .MDUActiveE, .FCvtIntE, .ForwardAE, .ForwardBE, .CMOpM, .IFUPrefetchE, .LSUPrefetchM, .StallM, .FlushM, .MemRWE, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, @@ -119,7 +120,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( datapath #(P) dp( .clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE, .Funct3E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .JumpE, .BranchSignedE, - .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, + .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW, .StallW, .FlushW, .RegWriteW, .IntDivW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW, .CSRReadValW, .MDUResultW, .FIntDivResultW, .RdW); diff --git a/testbench/common/instrNameDecTB.sv b/testbench/common/instrNameDecTB.sv index 8f6fbe869..96ef6d67f 100644 --- a/testbench/common/instrNameDecTB.sv +++ b/testbench/common/instrNameDecTB.sv @@ -161,6 +161,7 @@ module instrNameDecTB( else if (funct7 == 7'b0000101) name = "MINU"; else if (funct7 == 7'b0110000) name = "ROR"; else if (funct7 == 7'b0100100) name = "BEXT"; + else if (funct7 == 7'b0000111) name = "CZERO.EQZ"; else name = "ILLEGAL"; 10'b0110011_110: if (funct7 == 7'b0000000) name = "OR"; else if (funct7 == 7'b0000001) name = "REM"; @@ -172,6 +173,7 @@ module instrNameDecTB( else if (funct7 == 7'b0000001) name = "REMU"; else if (funct7 == 7'b0000101) name = "MAXU"; else if (funct7 == 7'b0100000) name = "ANDN"; + else if (funct7 == 7'b0000111) name = "CZERO.NEZ"; else name = "ILLEGAL"; 10'b0110111_???: name = "LUI"; 10'b1100011_000: name = "BEQ"; diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 3910c1cfd..e68b01b48 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -105,6 +105,7 @@ module testbench; "arch64f_fma": if (P.F_SUPPORTED) tests = arch64f_fma; "arch64d_fma": if (P.D_SUPPORTED) tests = arch64d_fma; "arch64zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch64zifencei; + "arch64zicond": if (P.ZICOND_SUPPORTED) tests = arch64zicond; "imperas64i": tests = imperas64i; "imperas64f": if (P.F_SUPPORTED) tests = imperas64f; "imperas64d": if (P.D_SUPPORTED) tests = imperas64d; @@ -142,6 +143,7 @@ module testbench; "arch32f_fma": if (P.F_SUPPORTED) tests = arch32f_fma; "arch32d_fma": if (P.D_SUPPORTED) tests = arch32d_fma; "arch32zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch32zifencei; + "arch32zicond": if (P.ZICOND_SUPPORTED) tests = arch32zicond; "imperas32i": tests = imperas32i; "imperas32f": if (P.F_SUPPORTED) tests = imperas32f; "imperas32m": if (P.M_SUPPORTED) tests = imperas32m; diff --git a/testbench/tests.vh b/testbench/tests.vh index e6adb0330..39b4ecc41 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -904,6 +904,12 @@ string imperas32f[] = '{ "rv64i_m/Zifencei/src/Fencei.S" }; + string arch64zicond[] = '{ + `RISCVARCHTEST, + "rv64i_m/Zicond/src/czero.eqz-01.S", + "rv64i_m/Zicond/src/czero.nez-01.S" + }; + string arch32a[] = '{ `RISCVARCHTEST, "rv32i_m/A/src/amoadd.w-01.S", @@ -923,6 +929,12 @@ string imperas32f[] = '{ "rv32i_m/Zifencei/src/Fencei.S" }; + string arch32zicond[] = '{ + `RISCVARCHTEST, + "rv32i_m/Zicond/src/czero.eqz-01.S", + "rv32i_m/Zicond/src/czero.nez-01.S" + }; + string arch32zba[] = '{ `RISCVARCHTEST, "rv32i_m/B/src/sh1add-01.S", diff --git a/tests/riscof/spike/riscof_spike.py b/tests/riscof/spike/riscof_spike.py index 6b2e6267d..61b556932 100644 --- a/tests/riscof/spike/riscof_spike.py +++ b/tests/riscof/spike/riscof_spike.py @@ -111,6 +111,8 @@ class spike(pluginTemplate): self.isa += 'c' if "Zicsr" in ispec["ISA"]: self.isa += '_Zicsr' + if "Zicond" in ispec["ISA"]: + self.isa += '_Zicond' if "Zicboz" in ispec["ISA"]: self.isa += '_Zicboz' if "Zca" in ispec["ISA"]: diff --git a/tests/riscof/spike/spike_rv32gc_isa.yaml b/tests/riscof/spike/spike_rv32gc_isa.yaml index b7bba15d5..ae314fa76 100644 --- a/tests/riscof/spike/spike_rv32gc_isa.yaml +++ b/tests/riscof/spike/spike_rv32gc_isa.yaml @@ -1,6 +1,6 @@ hart_ids: [0] hart0: - ISA: RV32IMAFDCZicsr_Zifencei_Zba_Zbb_Zbc_Zbs + ISA: RV32IMAFDCZicsr_Zicond_Zifencei_Zba_Zbb_Zbc_Zbs # ISA: RV32IMAFDCZicsr_Zicboz_Zifencei_Zca_Zba_Zbb_Zbc_Zbs # _Zbkb_Zcb physical_addr_sz: 32 User_Spec_Version: '2.3' diff --git a/tests/riscof/spike/spike_rv64gc_isa.yaml b/tests/riscof/spike/spike_rv64gc_isa.yaml index c7fefa587..df5e7cb2b 100644 --- a/tests/riscof/spike/spike_rv64gc_isa.yaml +++ b/tests/riscof/spike/spike_rv64gc_isa.yaml @@ -2,7 +2,7 @@ hart_ids: [0] hart0: # ISA: RV64IMAFDCSUZicsr_Zicboz_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb # ISA: RV64IMAFDCSUZicsr_Zifencei_Zca_Zcb_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb - ISA: RV64IMAFDCSUZicsr_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb + ISA: RV64IMAFDCSUZicsr_Zicond_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb physical_addr_sz: 56 User_Spec_Version: '2.3' supported_xlen: [64]