From 28752303be0b8a0386aaa7a99ad64baba8700824 Mon Sep 17 00:00:00 2001 From: David Harris Date: Wed, 4 Oct 2023 12:28:12 -0700 Subject: [PATCH] Added ZCA/ZCF/ZCD/ZCB support. Doesn't break regression, but not tested. Need to get tests for Zcb. Draft tests are in riscv-arch-test but not yet committed there --- config/buildroot/config.vh | 6 ++ config/fpga/config.vh | 6 ++ config/rv32e/config.vh | 6 ++ config/rv32gc/config.vh | 6 ++ config/rv32i/config.vh | 6 ++ config/rv32imc/config.vh | 6 ++ config/rv64fpquad/config.vh | 6 ++ config/rv64gc/config.vh | 6 ++ config/rv64i/config.vh | 6 ++ config/shared/parameter-defs.vh | 4 + src/cvw.sv | 6 ++ src/ifu/decompress.sv | 116 ++++++++++++++++++++++------ src/ifu/ifu.sv | 4 +- testbench/common/riscvassertions.sv | 5 ++ 14 files changed, 163 insertions(+), 26 deletions(-) diff --git a/config/buildroot/config.vh b/config/buildroot/config.vh index 79ee99f3c..b25e8fe9c 100644 --- a/config/buildroot/config.vh +++ b/config/buildroot/config.vh @@ -158,6 +158,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 1; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/fpga/config.vh b/config/fpga/config.vh index 27903d0be..2508b557e 100644 --- a/config/fpga/config.vh +++ b/config/fpga/config.vh @@ -171,6 +171,12 @@ localparam ZBB_SUPPORTED = 1; localparam ZBC_SUPPORTED = 1; localparam ZBS_SUPPORTED = 1; +// New compressed instructions +localparam ZCB_SUPPORTED = 1; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index c67e71c13..35e85003d 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -159,6 +159,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 0; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index de966b1f2..06be2e01b 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -171,6 +171,12 @@ localparam ZBB_SUPPORTED = 1; localparam ZBC_SUPPORTED = 1; localparam ZBS_SUPPORTED = 1; +// New compressed instructions +localparam ZCB_SUPPORTED = 1; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index a31e034df..5e03d3e93 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -159,6 +159,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 0; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index 61eea7325..cb031d2db 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -158,6 +158,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 0; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv64fpquad/config.vh b/config/rv64fpquad/config.vh index d8bf3e6fc..63a35c7f5 100644 --- a/config/rv64fpquad/config.vh +++ b/config/rv64fpquad/config.vh @@ -161,6 +161,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 0; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index 36d99020e..f17761e33 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -164,6 +164,12 @@ localparam ZBB_SUPPORTED = 1; localparam ZBC_SUPPORTED = 1; localparam ZBS_SUPPORTED = 1; +// New compressed instructions +localparam ZCB_SUPPORTED = 1; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 6add96e78..d87708c18 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -161,6 +161,12 @@ localparam ZBB_SUPPORTED = 0; localparam ZBC_SUPPORTED = 0; localparam ZBS_SUPPORTED = 0; +// New compressed instructions +localparam ZCB_SUPPORTED = 0; +localparam ZCA_SUPPORTED = 0; +localparam ZCF_SUPPORTED = 0; +localparam ZCD_SUPPORTED = 0; + // Memory synthesis configuration localparam USE_SRAM = 0; diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 4921f6a3d..f3f216062 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -96,6 +96,10 @@ localparam cvw_t P = '{ ZBB_SUPPORTED : ZBB_SUPPORTED, ZBC_SUPPORTED : ZBC_SUPPORTED, ZBS_SUPPORTED : ZBS_SUPPORTED, + ZCA_SUPPORTED : ZCA_SUPPORTED, + ZCB_SUPPORTED : ZCB_SUPPORTED, + ZCD_SUPPORTED : ZCD_SUPPORTED, + ZCF_SUPPORTED : ZCF_SUPPORTED, USE_SRAM : USE_SRAM, M_MODE : M_MODE, S_MODE : S_MODE, diff --git a/src/cvw.sv b/src/cvw.sv index f64618574..01e0d6376 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -161,6 +161,12 @@ typedef struct packed { logic ZBC_SUPPORTED; logic ZBS_SUPPORTED; +// compressed + logic ZCA_SUPPORTED; + logic ZCB_SUPPORTED; + logic ZCD_SUPPORTED; + logic ZCF_SUPPORTED; + // Memory synthesis configuration logic USE_SRAM; diff --git a/src/ifu/decompress.sv b/src/ifu/decompress.sv index 1605ed039..5c4395a12 100644 --- a/src/ifu/decompress.sv +++ b/src/ifu/decompress.sv @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////// -module decompress #(parameter XLEN)( +module decompress import cvw::*; #(parameter cvw_t P) ( input logic [31:0] InstrRawD, // 32-bit instruction or raw compressed 16-bit instruction in bottom half output logic [31:0] InstrD, // Decompressed instruction output logic IllegalCompInstrD // Invalid decompressed instruction @@ -88,20 +88,60 @@ module decompress #(parameter XLEN)( IllegalCompInstrD = 1; InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap end - 5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld + 5'b00001: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED) + InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld + else begin // unsupported instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end 5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw - 5'b00011: if (XLEN==32) - InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + 5'b00011: if (P.XLEN==32) + if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED) + InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end else InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld; - 5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd + 5'b00100: if (P.ZCB_SUPPORTED) + if (instr16[12:10] == 3'b000) + InstrD = {10'b0, instr16[6:5], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu + else if (instr16[12:10] == 3'b001) begin + if (instr16[6]) + InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh + else + InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu + end else if (instr16[12:10] == 3'b010) + InstrD = {7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[6:5], 7'b0000011}; // c.sb + else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) + InstrD = {7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0000011}; // c.sh + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end + 5'b00101: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED) + InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd + else begin // unsupported instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end 5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw - 5'b00111: if (XLEN==32) - InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw + 5'b00111: if (P.XLEN==32) + if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED) + InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end else InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd 5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi - 5'b01001: if (XLEN==32) + 5'b01001: if (P.XLEN==32) InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal else InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw @@ -125,33 +165,51 @@ module decompress #(parameter XLEN)( InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or else // if (instr16[6:5] == 2'b11) InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and - else if (XLEN > 32) //if (instr16[12:10] == 3'b111) full truth table no need to check [12:10] - if (instr16[6:5] == 2'b00) + else if (instr16[12:10] == 3'b111) begin + if (instr16[6:5] == 2'b00 & P.XLEN > 32) InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw - else if (instr16[6:5] == 2'b01) + else if (instr16[6:5] == 2'b01 & P.XLEN > 32) InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw + else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) + InstrD = {12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255 + else if (instr16[6:2] == 5'b10101 & P.ZCB_SUPPORTED) + InstrD = {12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b + else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED) + InstrD = {7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h + else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED) + InstrD = {12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h + else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) + InstrD = {12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori + else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.XLEN > 32) + InstrD = {7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 + else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED) + InstrD = {7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul else begin // reserved IllegalCompInstrD = 1; InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap end - // coverage off - // are excluding this branch from coverage because in rv64gc XLEN is always 64 and thus greater than 32 bits - // This branch will only be taken if instr16[12:10] == 3'b111 and 'XLEN !> 32, because all other - // possible values for instr16[12:10] are covered by branches above. XLEN !> 32 - // will never occur in rv64gc so this branch can not be covered - else begin // illegal instruction + end else begin // illegal instruction IllegalCompInstrD = 1; InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap end - // coverage on 5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j 5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz 5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez 5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli - 5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + 5'b10001: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED) + InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp + else begin // unsupported instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end 5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp - 5'b10011: if (XLEN == 32) - InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + 5'b10011: if (P.XLEN == 32) + if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED) + InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end else InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp 5'b10100: if (instr16[12] == 0) @@ -167,10 +225,20 @@ module decompress #(parameter XLEN)( InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr else InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add - 5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp + 5'b10101: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED) + InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp + else begin // unsupported instruction + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end 5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp - 5'b10111: if (XLEN==32) - InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + 5'b10111: if (P.XLEN==32) + if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED) + InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp + else begin + IllegalCompInstrD = 1; + InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap + end else InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp default: begin // illegal instruction diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index d63a987b2..af6f70898 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -353,9 +353,9 @@ module ifu import cvw::*; #(parameter cvw_t P) ( flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD); // expand 16-bit compressed instructions to 32 bits - if (P.C_SUPPORTED) begin + if (P.C_SUPPORTED | P.ZCA_SUPPORTED) begin logic IllegalCompInstrD; - decompress #(P.XLEN) decomp(.InstrRawD, .InstrD, .IllegalCompInstrD); + decompress #(P) decomp(.InstrRawD, .InstrD, .IllegalCompInstrD); assign IllegalIEUInstrD = IllegalBaseInstrD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr end else begin assign InstrD = InstrRawD; diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index a6cee910e..815478390 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -63,6 +63,11 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP requires DCACHE_SUPPORTED"); assert ((P.SVPBMT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVPBMT requires VIRTMEM_SUPPORTED and RV64"); assert ((P.SVNAPOT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVNAPOT requires VIRTMEM_SUPPORTED and RV64"); + assert ((P.ZCB_SUPPORTED == 0) || (P.M_SUPPORTED == 1 && (P.ZBA_SUPPORTED == 1 || P.XLEN == 32) && P.ZBB_SUPPORTED == 1)) else $error("ZCB requires M and ZBB (and also ZBA for RV64)"); + assert ((P.C_SUPPORTED == 0) || (P.ZCA_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0 && P.ZCD_SUPPORTED == 0)) else $error("C and ZCA/ZCD/ZCF cannot simultaneously be supported"); + assert ((P.ZCA_SUPPORTED == 1) || (P.ZCD_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0)) else $error("ZCF or ZCD requires ZCA"); + assert ((P.ZCF_SUPPORTED == 0) || (P.F_SUPPORTED == 1)) else $error("ZCF requires F"); + assert ((P.ZCD_SUPPORTED == 0) || (P.D_SUPPORTED == 1)) else $error("ZCD requires D"); end endmodule