Merge pull request #887 from davidharrishmc/dev

Fully decode decompressed instructions, including hints and illegal registers/immediates
This commit is contained in:
Rose Thompson 2024-07-19 09:23:36 -05:00 committed by GitHub
commit e751fbe865
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 115 additions and 177 deletions

View File

@ -11,6 +11,7 @@
# #
################################## ##################################
import sys,os,shutil import sys,os,shutil
import argparse
import multiprocessing import multiprocessing
from collections import namedtuple from collections import namedtuple
from multiprocessing import Pool, TimeoutError from multiprocessing import Pool, TimeoutError
@ -320,13 +321,16 @@ coveragesim = "questa" # Questa is required for code/functional coverage
#defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready
defaultsim = "verilator" # Default simulator for all other tests defaultsim = "verilator" # Default simulator for all other tests
ccov = '--ccov' in sys.argv parser = argparse.ArgumentParser()
fp = '--fp' in sys.argv parser.add_argument("--ccov", help="Code Coverage", action="store_true")
nightly = '--nightly' in sys.argv parser.add_argument("--fcov", help="Functional Coverage", action="store_true")
testfloat = '--testfloat' in sys.argv parser.add_argument("--nightly", help="Run large nightly regression", action="store_true")
buildroot = '--buildroot' in sys.argv parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true")
parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true")
parser.add_argument("--fp", help="Include floating-point tests in coverage (slower runtime)", action="store_true")
args = parser.parse_args()
if (nightly): if (args.nightly):
nightMode = "--nightly"; nightMode = "--nightly";
# sims = [defaultsim] # uncomment to use only the default simulator # sims = [defaultsim] # uncomment to use only the default simulator
sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators
@ -334,7 +338,7 @@ else:
nightMode = "" nightMode = ""
sims = [defaultsim] sims = [defaultsim]
if (ccov): # only run RV64GC tests in coverage mode if (args.ccov): # only run RV64GC tests in coverage mode
coverStr = '--ccov' coverStr = '--ccov'
else: else:
coverStr = '' coverStr = ''
@ -353,24 +357,24 @@ configs = [
# run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests # run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests
if (buildroot): if (args.buildroot):
# addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours # addTests(tests_buildrootboot, defaultsim) # non-lockstep with Verilator runs in about 2 hours
addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight
if (ccov): # only run RV64GC tests on Questa in code coverage mode if (args.ccov): # only run RV64GC tests on Questa in code coverage mode
addTests(tests64gc_nofp, "questa") addTests(tests64gc_nofp, "questa")
if (fp): if (args.fp):
addTests(tests64gc_fp, "questa") addTests(tests64gc_fp, "questa")
else: else:
for sim in sims: for sim in sims:
if (not (buildroot and sim == defaultsim)): # skip shot buildroot sim if running long one if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one
addTests(tests_buildrootshort, sim) addTests(tests_buildrootshort, sim)
addTests(tests, sim) addTests(tests, sim)
addTests(tests64gc_nofp, sim) addTests(tests64gc_nofp, sim)
addTests(tests64gc_fp, sim) addTests(tests64gc_fp, sim)
# run derivative configurations and lockstep tests in nightly regression # run derivative configurations and lockstep tests in nightly regression
if (nightly): if (args.nightly):
addTests(derivconfigtests, defaultsim) addTests(derivconfigtests, defaultsim)
sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log" sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log"
tc = TestCase( tc = TestCase(
@ -391,9 +395,9 @@ if (nightly):
configs.append(tc) configs.append(tc)
# testfloat tests # testfloat tests
if (testfloat): # for testfloat alone, just run testfloat tests if (args.testfloat): # for testfloat alone, just run testfloat tests
configs = [] configs = []
if (testfloat or nightly): # for nightly, run testfloat along with others if (args.testfloat or args.nightly): # for nightly, run testfloat along with others
testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved testfloatsim = "questa" # change to Verilator when Issue #707 about testfloat not running Verilator is resolved
testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"] testfloatconfigs = ["fdqh_ieee_rv64gc", "fdq_ieee_rv64gc", "fdh_ieee_rv64gc", "fd_ieee_rv64gc", "fh_ieee_rv64gc", "f_ieee_rv64gc", "fdqh_ieee_rv32gc", "f_ieee_rv32gc"]
for config in testfloatconfigs: for config in testfloatconfigs:
@ -458,7 +462,7 @@ if (testfloat or nightly): # for nightly, run testfloat along with others
def main(): def main():
"""Run the tests and count the failures""" """Run the tests and count the failures"""
global configs, ccov global configs, args
os.chdir(regressionDir) os.chdir(regressionDir)
dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"] dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"]
for d in dirs: for d in dirs:
@ -467,17 +471,12 @@ def main():
os.mkdir(d) os.mkdir(d)
except: except:
pass pass
if args.ccov:
if '--makeTests' in sys.argv:
os.chdir(regressionDir)
os.system('./make-tests.sh | tee ./logs/make-tests.log')
elif '--ccov' in sys.argv:
TIMEOUT_DUR = 20*60 # seconds TIMEOUT_DUR = 20*60 # seconds
os.system('rm -f questa/cov/*.ucdb') os.system('rm -f questa/cov/*.ucdb')
elif '--nightly' in sys.argv: elif args.nightly in sys.argv:
TIMEOUT_DUR = 60*1440 # 1 day TIMEOUT_DUR = 60*1440 # 1 day
elif '--testfloat' in sys.argv: elif args.testfloat in sys.argv:
TIMEOUT_DUR = 30*60 # seconds TIMEOUT_DUR = 30*60 # seconds
else: else:
TIMEOUT_DUR = 10*60 # seconds TIMEOUT_DUR = 10*60 # seconds
@ -497,7 +496,7 @@ def main():
print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR)) print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR))
# Coverage report # Coverage report
if ccov: if args.ccov:
os.system('make QuestaCodeCoverage') os.system('make QuestaCodeCoverage')
# Count the number of failures # Count the number of failures
if num_fail: if num_fail:

View File

@ -27,7 +27,7 @@ parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilat
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true") parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true")
parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="")
parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true")
parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true")

View File

@ -32,13 +32,15 @@ module decompress import cvw::*; #(parameter cvw_t P) (
output logic [31:0] InstrD, // Decompressed instruction output logic [31:0] InstrD, // Decompressed instruction
output logic IllegalCompInstrD // Invalid decompressed instruction output logic IllegalCompInstrD // Invalid decompressed instruction
); );
logic [32:0] LInstrD; // decompressed instruction with illegal flag in [32]
logic [15:0] instr16; logic [15:0] instr16;
logic [4:0] rds1, rs2, rs1p, rs2p, rds1p, rdp; logic [4:0] rds1, rs2, rs1p, rs2p, rds1p, rdp;
logic [11:0] immCILSP, immCILSPD, immCSS, immCSSD, immCL, immCLD, immCI, immCS, immCSD, immCB, immCIASP, immCIW; logic [11:0] immCILSP, immCILSPD, immCSS, immCSSD, immCL, immCLD, immCI, immCS, immCSD, immCB, immCIASP, immCIW;
logic [19:0] immCJ, immCILUI; logic [19:0] immCJ, immCILUI;
logic [5:0] immSH; logic [5:0] immSH;
logic [1:0] op; logic [1:0] op;
logic LegalCompInstrD;
// Extract op and register source/destination fields // Extract op and register source/destination fields
assign instr16 = InstrRawD[15:0]; // instruction is already aligned assign instr16 = InstrRawD[15:0]; // instruction is already aligned
@ -62,10 +64,10 @@ module decompress import cvw::*; #(parameter cvw_t P) (
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}}; assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]}; assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
assign immCI = {{7{instr16[12]}}, instr16[6:2]}; assign immCI = {{7{instr16[12]}}, instr16[6:2]};
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; // c.lui
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; // c.addi16sp
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00}; assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
assign immSH = {instr16[12], instr16[6:2]}; assign immSH = {instr16[12], instr16[6:2]}; // c. shift instructions: c.srli, c.srai, c.slli
// only for RV128 // only for RV128
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000}; // assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
@ -75,173 +77,110 @@ module decompress import cvw::*; #(parameter cvw_t P) (
always_comb always_comb
if (op == 2'b11) begin // noncompressed instruction if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD; LInstrD = {1'b1, InstrRawD};
IllegalCompInstrD = '0;
end else begin // convert compressed instruction into uncompressed end else begin // convert compressed instruction into uncompressed
IllegalCompInstrD = '0; LInstrD = {1'b0, 16'b0, instr16}; // if a legal instruction is not decoded, default to illegal and preserve 16-bit value for mtval
case ({op, instr16[15:13]}) case ({op, instr16[15:13]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn 5'b00000: if (immCIW != 0) LInstrD = {1'b1, immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction 5'b00001: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
IllegalCompInstrD = 1'b1; 5'b00010: LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b00011: if (P.XLEN==32) begin
end if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
5'b00001: if (P.ZCD_SUPPORTED) end else LInstrD = {1'b1, immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
else begin // unsupported instruction
IllegalCompInstrD = 1'b1;
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 (P.XLEN==32)
if (P.ZCF_SUPPORTED)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else begin
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00100: if (P.ZCB_SUPPORTED) 5'b00100: if (P.ZCB_SUPPORTED)
if (instr16[12:10] == 3'b000) if (instr16[12:10] == 3'b000) LInstrD = {1'b1, 10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
InstrD = {10'b0, instr16[5], instr16[6], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
else if (instr16[12:10] == 3'b001) begin else if (instr16[12:10] == 3'b001) begin
if (instr16[6]) if (instr16[6]) LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh else LInstrD = {1'b1, 10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
else
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
end else if (instr16[12:10] == 3'b010) end else if (instr16[12:10] == 3'b010)
InstrD = {7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[5], instr16[6], 7'b0100011}; // c.sb
else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0) 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'b0100011}; // c.sh LInstrD = {1'b1, 7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0100011}; // c.sh
else begin 5'b00101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
IllegalCompInstrD = 1'b1; 5'b00110: LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b00111: if (P.XLEN==32) begin
end if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else begin end else LInstrD = {1'b1, immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; // c.sd
IllegalCompInstrD = 1'b1; 5'b01000: if (rds1 != 5'b0)
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (immCI[5:0] != 0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
end else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.addi with imm = 0 is a HINT, treated as nop
5'b00101: if (P.ZCD_SUPPORTED) else if (immCI[5:0] == 6'b0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop = addi x0, x0, 0
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.nop with imm != 0 is a HINT, treated as nop
else begin // unsupported instruction 5'b01001: if (P.XLEN==32) LInstrD = {1'b1, immCJ, 5'b00001, 7'b1101111}; // c.jal
IllegalCompInstrD = 1'b1; else if (rds1 != 5'b0) LInstrD = {1'b1, immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap 5'b01010: if (rds1 != 5'b0) LInstrD = {1'b1, immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
end else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.li with rd = 0 is a HINT, treated as nop
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw 5'b01011: if (rds1 == 5'b00010) begin
5'b00111: if (P.XLEN==32) if (immCIASP[9:4] != 6'b0) LInstrD = {1'b1, immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
if (P.ZCF_SUPPORTED) end else if (immCILUI[5:0] != 0)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw if (rds1 != 5'b0) LInstrD = {1'b1, immCILUI, rds1, 7'b0110111}; // c.lui
else begin else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.lui with rd = 0, imm!=0 is a HINT, treated as nop
IllegalCompInstrD = 1'b1; 5'b01100: if (instr16[11:10] == 2'b00) begin
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli; shamt[5] must be 0 in RV32C
end end else if (instr16[11:10] == 2'b01) begin
else if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai; shamt[5] must be 0 in RV32C
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd end else if (instr16[11:10] == 2'b10) LInstrD = {1'b1, immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi else if (instr16[12:10] == 3'b011) begin
5'b01001: if (P.XLEN==32) if (instr16[6:5] == 2'b00) LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal else if (instr16[6:5] == 2'b01) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else else if (instr16[6:5] == 2'b10) LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw else LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li end else begin // (instr16[12:10] == 3'b111)
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
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 begin // (instr16[12:10] == 3'b111)
if (instr16[6:5] == 2'b00 & P.XLEN > 32) if (instr16[6:5] == 2'b00 & P.XLEN > 32)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw LInstrD = {1'b1, 7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01 & P.XLEN > 32) else if (instr16[6:5] == 2'b01 & P.XLEN > 32)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw LInstrD = {1'b1, 7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED) 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 LInstrD = {1'b1, 12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255
else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11001 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b LInstrD = {1'b1, 12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b
else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h LInstrD = {1'b1, 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 & P.ZBB_SUPPORTED) else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED & P.ZBB_SUPPORTED)
InstrD = {12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h LInstrD = {1'b1, 12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h
else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED) else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED)
InstrD = {12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori LInstrD = {1'b1, 12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori
else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32) else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.ZBA_SUPPORTED & P.XLEN > 32)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0 LInstrD = {1'b1, 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 & P.ZMMUL_SUPPORTED) else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED & P.ZMMUL_SUPPORTED)
InstrD = {7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul LInstrD = {1'b1, 7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul
else begin // reserved
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
/** end else begin // illegal instruction
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap **/
end end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j 5'b01101: LInstrD = {1'b1, 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'b01110: LInstrD = {1'b1, 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'b01111: LInstrD = {1'b1, 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'b10000: if (rds1 != 5'b0) begin
if (P.XLEN > 32 | ~immSH[5]) LInstrD = {1'b1, 6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli; shamt[5] must be 0 in RV32C
end else if (immSH != 0) LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.slli with rd = 0, immm != 0 is a HINT, treated as nop
5'b10001: if (P.ZCD_SUPPORTED) 5'b10001: if (P.ZCD_SUPPORTED)
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
else begin // unsupported instruction 5'b10010: if (rds1 != 5'b0) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
IllegalCompInstrD = 1'b1; 5'b10011: if (P.XLEN == 32) begin
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
end end else if (rds1 != 5'b0) LInstrD = {1'b1, immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (P.XLEN == 32)
if (P.ZCF_SUPPORTED)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else begin
IllegalCompInstrD = 1'b1;
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) 5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000) if (rs2 == 5'b00000) begin
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
else end else
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv if (rds1 != 5'b0) LInstrD = {1'b1, 7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.mv with rd = 0 is a HINT, treated as nop
else else
if (rs2 == 5'b00000) if (rs2 == 5'b00000) begin
if (rds1 == 5'b00000) if (rds1 == 5'b00000) LInstrD = {1'b1, 12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak else if (rds1 != 5'b0) LInstrD = {1'b1, 12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else end else
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr if (rds1 != 0) LInstrD = {1'b1, 7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
else else LInstrD = {1'b1, 25'b0, 7'b0010011}; // c.add with rd = 0 is a HINT, treated as nop, even if it is a C.NTL
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add 5'b10101: if (P.ZCD_SUPPORTED) LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
5'b10101: if (P.ZCD_SUPPORTED) 5'b10110: LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp 5'b10111: if (P.XLEN==32) begin
else begin // unsupported instruction if (P.ZCF_SUPPORTED) LInstrD = {1'b1, immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
IllegalCompInstrD = 1'b1; end else LInstrD = {1'b1, immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap default: ; // illegal instruction
end
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (P.XLEN==32)
if (P.ZCF_SUPPORTED)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else begin
IllegalCompInstrD = 1'b1;
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
IllegalCompInstrD = 1'b1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
endcase endcase
end end
// extract instruction and illegal from LInstrD
assign {LegalCompInstrD, InstrD} = LInstrD;
assign IllegalCompInstrD = ~LegalCompInstrD;
endmodule endmodule