Update google_riscv-dv to google/riscv-dv@5baf82a (#723)

Update code from upstream repository https://github.com/google/riscv-
dv to revision 5baf82a24347dae3cb71c8ab66a66494666d2291

* Fix illegal func3/func7 instruction generation for B-extension
  (google/riscv-dv#525) (taoliug)
* more tightly constrain pmpaddr values (google/riscv-dv#524)
  (udinator)
* Update style check (Weicai Yang)
* Bump verible (Tomasz Gorochowik)
* Add target for B-extension (google/riscv-dv#521) (taoliug)
* [cov] tag coverage database directories with <test_id> (Udi
  Jonnalagadda)
* Add bit manipulation (google/riscv-dv#518) (weicaiyang)
* Don't change input file in spike_log_to_trace_csv.py (google/riscv-
  dv#504) (Rupert Swarbrick)
* Fix ius constraint solver failure (google/riscv-dv#515) (taoliug)
* Fix AMO sequence address generation issue (google/riscv-dv#514)
  (taoliug)
* Remove alignment constraint (google/riscv-dv#513) (taoliug)
* Add section for each data region (google/riscv-dv#512) (taoliug)

Signed-off-by: Udi <udij@google.com>
This commit is contained in:
udinator 2020-03-23 13:33:38 -07:00 committed by GitHub
parent 3af3e72b2f
commit 2c198383a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1292 additions and 138 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 3f584adef07b7f04edda8a6ba1dfc01a14df5d98
rev: 5baf82a24347dae3cb71c8ab66a66494666d2291
}
}

View file

@ -250,6 +250,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file,
if verbose:
cmd += "+UVM_VERBOSITY=UVM_HIGH "
cmd = re.sub("<seed>", str(rand_seed), cmd)
cmd = re.sub("<test_id>", test_id, cmd)
sim_seed[test_id] = str(rand_seed)
if "gen_opts" in test:
cmd += test['gen_opts']
@ -730,6 +731,8 @@ def setup_parser():
help="Stop on detecting first error")
parser.add_argument("--noclean", action="store_true", default=True,
help="Do not clean the output of the previous runs")
parser.add_argument("--verilog_style_check", action="store_true", default=False,
help="Run verilog style check")
parser.add_argument("-d", "--debug", type=str, default="",
help="Generate debug command log file")
return parser
@ -772,6 +775,9 @@ def load_config(args, cwd):
elif args.target == "multi_harts":
args.mabi = "ilp32"
args.isa = "rv32gc"
elif args.target == "rv32imcb":
args.mabi = "ilp32"
args.isa = "rv32imcb"
elif args.target == "rv32i":
args.mabi = "ilp32"
args.isa = "rv32i"
@ -813,6 +819,11 @@ def main():
# Create output directory
output_dir = create_output(args.o, args.noclean)
if args.verilog_style_check:
logging.debug("Run style check")
style_err = run_cmd("verilog_style/run.sh")
if style_err: logging.info("Found style error: \nERROR: " + style_err)
# Run any handcoded/directed assembly tests specified by args.asm_tests
if args.asm_tests != "":
asm_test = args.asm_tests.split(',')

View file

@ -34,70 +34,6 @@ ILLE_RE = re.compile(r"trap_illegal_instruction")
LOGGER = logging.getLogger()
def process_spike_sim_log(spike_log, csv, full_trace = 0):
"""Process SPIKE simulation log.
Extract instruction and affected register information from spike simulation
log and save to a list.
"""
logging.info("Processing spike log : %s" % spike_log)
instr_cnt = 0
spike_instr = ""
# Remove all the init spike boot instructions
cmd = ("sed -i '/core.*0x0000000000001010/,$!d' %s" % spike_log)
os.system(cmd)
# Remove all instructions after ecall (end of program excecution)
cmd = ("sed -i '/ecall/q' %s" % spike_log)
os.system(cmd)
with open(spike_log, "r") as f, open(csv, "w") as csv_fd:
trace_csv = RiscvInstructionTraceCsv(csv_fd)
trace_csv.start_new_trace()
for line in f:
# Extract instruction infromation
m = CORE_RE.search(line)
if m:
instr_cnt += 1
spike_instr = m.group("instr").replace("pc + ", "")
spike_instr = spike_instr.replace("pc - ", "-")
rv_instr_trace = RiscvInstructionTraceEntry()
rv_instr_trace.pc = m.group("addr")
rv_instr_trace.instr_str = spike_instr
rv_instr_trace.binary = m.group("bin")
if full_trace:
rv_instr_trace.instr = spike_instr.split(" ")[0]
rv_instr_trace.operand = spike_instr[len(rv_instr_trace.instr):]
rv_instr_trace.operand = rv_instr_trace.operand.replace(" ", "")
rv_instr_trace.instr, rv_instr_trace.operand = convert_pseudo_instr(
rv_instr_trace.instr, rv_instr_trace.operand, rv_instr_trace.binary)
process_instr(rv_instr_trace)
if spike_instr == "wfi":
trace_csv.write_trace_entry(rv_instr_trace)
continue
nextline = f.readline()
if nextline != "":
if ILLE_RE.search(nextline):
if full_trace:
logging.debug("Illegal instruction: %s, opcode:%s" %
(rv_instr_trace.instr_str, rv_instr_trace.binary))
trace_csv.write_trace_entry(rv_instr_trace)
continue
m = RD_RE.search(nextline)
if m:
# Extract RD information
rv_instr_trace.gpr.append(
gpr_to_abi(m.group("reg").replace(" ","")) + ":" + m.group("val"))
rv_instr_trace.mode = m.group("pri")
else:
# If full trace is not enabled, skip the entry that doesn't have
# architectural state update.
if not full_trace:
continue
trace_csv.write_trace_entry(rv_instr_trace)
logging.info("Processed instruction count : %d" % instr_cnt)
logging.info("CSV saved to : %s" % csv)
def process_instr(trace):
if trace.instr == "jal":
@ -113,6 +49,171 @@ def process_instr(trace):
trace.operand = trace.operand.replace(")", "")
def read_spike_instr(match, full_trace):
'''Unpack a regex match for CORE_RE to a RiscvInstructionTraceEntry
If full_trace is true, extract operand data from the disassembled
instruction.
'''
# Extract the disassembled instruction.
disasm = match.group('instr')
# Spike's disassembler shows a relative jump as something like "j pc +
# 0x123" or "j pc - 0x123". We just want the relative offset.
disasm = disasm.replace('pc + ', '').replace('pc - ', '-')
instr = RiscvInstructionTraceEntry()
instr.pc = match.group('addr')
instr.instr_str = disasm
instr.binary = match.group('bin')
if full_trace:
opcode = disasm.split(' ')[0]
operand = disasm[len(opcode):].replace(' ', '')
instr.instr, instr.operand = \
convert_pseudo_instr(opcode, operand, instr.binary)
process_instr(instr)
return instr
def read_spike_trace(path, full_trace):
'''Read a Spike simulation log at <path>, yielding executed instructions.
This assumes that the log was generated with the -l and --log-commits options
to Spike.
If full_trace is true, extract operands from the disassembled instructions.
Since Spike has a strange trampoline that always runs at the start, we skip
instructions up to and including the one at PC 0x1010 (the end of the
trampoline). At the end of a DV program, there's an ECALL instruction, which
we take as a signal to stop checking, so we ditch everything that follows
that instruction.
This function yields instructions as it parses them as tuples of the form
(entry, illegal). entry is a RiscvInstructionTraceEntry. illegal is a
boolean, which is true if the instruction caused an illegal instruction trap.
'''
# This loop is a simple FSM with states TRAMPOLINE, INSTR, EFFECT. The idea
# is that we're in state TRAMPOLINE until we get to the end of Spike's
# trampoline, then we switch between INSTR (where we expect to read an
# instruction) and EFFECT (where we expect to read commit information).
#
# We yield a RiscvInstructionTraceEntry object each time we leave EFFECT
# (going back to INSTR), we loop back from INSTR to itself, or we get to the
# end of the file and have an instruction in hand.
#
# On entry to the loop body, we are in state TRAMPOLINE if in_trampoline is
# true. Otherwise, we are in state EFFECT if instr is not None, otherwise we
# are in state INSTR.
end_trampoline_re = re.compile(r'core.*: 0x0*1010 ')
in_trampoline = True
instr = None
with open(path, 'r') as handle:
for line in handle:
if in_trampoline:
# The TRAMPOLINE state
if end_trampoline_re.match(line):
in_trampoline = False
continue
if instr is None:
# The INSTR state. We expect to see a line matching CORE_RE. We'll
# discard any other lines.
instr_match = CORE_RE.match(line)
if not instr_match:
continue
instr = read_spike_instr(instr_match, full_trace)
# If instr.instr_str is 'ecall', we should stop.
if instr.instr_str == 'ecall':
break
continue
# The EFFECT state. If the line matches CORE_RE, we should have been in
# state INSTR, so we yield the instruction we had, read the new
# instruction and continue. As above, if the new instruction is 'ecall',
# we need to stop immediately.
instr_match = CORE_RE.match(line)
if instr_match:
yield (instr, False)
instr = read_spike_instr(instr_match, full_trace)
if instr.instr_str == 'ecall':
break
continue
# The line doesn't match CORE_RE, so we are definitely on a follow-on
# line in the log. First, check for illegal instructions
if 'trap_illegal_instruction' in line:
yield (instr, True)
instr = None
continue
# The instruction seems to have been fine. Do we have commit data (from
# the --log-commits Spike option)?
commit_match = RD_RE.match(line)
if commit_match:
instr.gpr.append(gpr_to_abi(commit_match.group('reg')
.replace(' ', '')) +
':' + commit_match.group('val'))
instr.mode = commit_match.group('pri')
# At EOF, we might have an instruction in hand. Yield it if so.
if instr is not None:
yield (instr, False)
def process_spike_sim_log(spike_log, csv, full_trace = 0):
"""Process SPIKE simulation log.
Extract instruction and affected register information from spike simulation
log and write the results to a CSV file at csv. Returns the number of
instructions written.
"""
logging.info("Processing spike log : %s" % spike_log)
instrs_in = 0
instrs_out = 0
with open(csv, "w") as csv_fd:
trace_csv = RiscvInstructionTraceCsv(csv_fd)
trace_csv.start_new_trace()
for (entry, illegal) in read_spike_trace(spike_log, full_trace):
instrs_in += 1
if illegal and full_trace:
logging.debug("Illegal instruction: {}, opcode:{}"
.format(entry.instr_str, entry.binary))
# Instructions that cause no architectural update (which includes illegal
# instructions) are ignored if full_trace is false.
#
# We say that an instruction caused an architectural update if either we
# saw a commit line (in which case, entry.gpr will contain a single
# entry) or the instruction was 'wfi' or 'ecall'.
if not (full_trace or entry.gpr or entry.instr_str in ['wfi', 'ecall']):
continue
trace_csv.write_trace_entry(entry)
instrs_out += 1
logging.info("Processed instruction count : %d" % instrs_in)
logging.info("CSV saved to : %s" % csv)
return instrs_out
def main():
# Parse input arguments
parser = argparse.ArgumentParser()

View file

@ -0,0 +1,459 @@
/*
* Copyright 2019 Google LLC
* Copyright 2019 Mellanox Technologies Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class riscv_b_instr extends riscv_instr;
rand riscv_reg_t rs3;
bit has_rs3 = 1'b0;
`uvm_object_utils(riscv_b_instr)
function new(string name = "");
super.new(name);
endfunction
virtual function void set_rand_mode();
super.set_rand_mode();
has_rs3 = 1'b0;
case (format) inside
R4_FORMAT: begin
has_imm = 1'b0;
has_rs3 = 1'b1;
end
I_FORMAT: begin
has_rs2 = 1'b0;
if (instr_name inside {FSRI, FSRIW}) begin
has_rs3 = 1'b1;
end
end
endcase
endfunction
function void pre_randomize();
super.pre_randomize();
rs3.rand_mode(has_rs3);
endfunction
virtual function void set_imm_len();
if (format inside {I_FORMAT}) begin
if (category inside {SHIFT, LOGICAL}) begin
imm_len = 7;
if (group == RV64B) begin
imm_len = 5;
if (instr_name inside {SLLIU_W}) begin
imm_len = 6;
end
end
if ((group == RV32B) && (imm_type == UIMM)) begin
imm_len = 6;
end
end
if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
imm_len = 5;
end
if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
imm_len = 12;
end
end
imm_mask = imm_mask << imm_len;
endfunction
// Convert the instruction to assembly code
virtual function string convert2asm(string prefix = "");
string asm_str_super, asm_str;
asm_str_super = super.convert2asm(prefix);
asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN);
case (format)
I_FORMAT: begin
if (instr_name inside {FSRI, FSRIW}) begin // instr rd,rs1,rs3,imm
asm_str_super = $sformatf("%0s%0s, %0s, %0s, %0s", asm_str, rd.name(), rs1.name(),
rs3.name(), get_imm());
end
end
R_FORMAT: begin //instr rd rs1
if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP}) begin
asm_str_super = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
end
if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D,
CRC32C_D}) begin
asm_str_super = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
end
end
R4_FORMAT: begin // instr rd,rs1,rs2,rs3
asm_str_super = $sformatf("%0s%0s, %0s, %0s, %0s", asm_str, rd.name(), rs1.name(),
rs2.name(), rs3.name());
end
default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
endcase
if (comment != "") begin
asm_str = {asm_str, " #", comment};
return asm_str.tolower();
end
return asm_str_super.tolower();
endfunction
function bit [6:0] get_opcode();
case (instr_name) inside
ANDN, ORN, XNOR, GORC, SLO, SRO, ROL, ROR, SBCLR, SBSET, SBINV, SBEXT,
GREV: get_opcode = 7'b0110011;
SLOI, SROI, RORI, SBCLRI, SBSETI, SBINVI, SBEXTI, GORCI, GREVI, CMIX, CMOV,
FSL: get_opcode = 7'b0010011;
FSR, FSRI, CLZ, CTZ, PCNT, BMATFLIP, SEXT_B, SEXT_H, CRC32_B, CRC32_H, CRC32_W, CRC32C_B,
CRC32C_H: get_opcode = 7'b0010011;
CRC32C_W, CRC32_D, CRC32C_D: get_opcode = 7'b0010011;
CLMUL, CLMULR, CLMULH, MIN, MAX, MINU, MAXU, SHFL, UNSHFL, BDEP, BEXT, PACK, PACKU, BMATOR,
BMATXOR, PACKH, BFP: get_opcode = 7'b0110011;
SHFLI, UNSHFLI: get_opcode = 7'b0010011;
ADDIWU, SLLIU_W: get_opcode = 7'b0011011;
ADDWU, SUBWU, ADDU_W, SUBU_W, SLOW, SROW, ROLW, RORW, SBCLRW, SBSETW, SBINVW, SBEXTW, GORCW,
GREVW: get_opcode = 7'b0111011;
SLOIW, SROIW, RORIW, SBCLRIW, SBSETIW, SBINVIW, GORCIW, GREVIW: get_opcode = 7'b0011011;
FSLW, FSRW: get_opcode = 7'b0111011;
FSRIW, CLZW, CTZW, PCNTW: get_opcode = 7'b0011011;
CLMULW, CLMULRW, CLMULHW, SHFLW, UNSHFLW, BDEPW, BEXTW, PACKW, PACKUW,
BFPW: get_opcode = 7'b0111011;
default: get_opcode = super.get_opcode();
endcase
endfunction
virtual function bit [2:0] get_func3();
case (instr_name) inside
ANDN: get_func3 = 3'b111;
ORN: get_func3 = 3'b110;
XNOR: get_func3 = 3'b100;
GORC: get_func3 = 3'b101;
SLO: get_func3 = 3'b001;
SRO: get_func3 = 3'b101;
ROL: get_func3 = 3'b001;
ROR: get_func3 = 3'b101;
SBCLR: get_func3 = 3'b001;
SBSET: get_func3 = 3'b001;
SBINV: get_func3 = 3'b001;
SBEXT: get_func3 = 3'b101;
GREV: get_func3 = 3'b101;
SLOI: get_func3 = 3'b001;
SROI: get_func3 = 3'b101;
RORI: get_func3 = 3'b101;
SBCLRI: get_func3 = 3'b001;
SBSETI: get_func3 = 3'b001;
SBINVI: get_func3 = 3'b001;
SBEXTI: get_func3 = 3'b101;
GORCI: get_func3 = 3'b101;
GREVI: get_func3 = 3'b101;
CMIX: get_func3 = 3'b001;
CMOV: get_func3 = 3'b101;
FSL: get_func3 = 3'b001;
FSR: get_func3 = 3'b101;
FSRI: get_func3 = 3'b101;
CLZ: get_func3 = 3'b001;
CTZ: get_func3 = 3'b001;
PCNT: get_func3 = 3'b001;
BMATFLIP: get_func3 = 3'b001;
SEXT_B: get_func3 = 3'b001;
SEXT_H: get_func3 = 3'b001;
CRC32_B: get_func3 = 3'b001;
CRC32_H: get_func3 = 3'b001;
CRC32_W: get_func3 = 3'b001;
CRC32C_B: get_func3 = 3'b001;
CRC32C_H: get_func3 = 3'b001;
CRC32C_W: get_func3 = 3'b001;
CRC32_D: get_func3 = 3'b001;
CRC32C_D: get_func3 = 3'b001;
CLMUL: get_func3 = 3'b001;
CLMULR: get_func3 = 3'b010;
CLMULH: get_func3 = 3'b011;
MIN: get_func3 = 3'b100;
MAX: get_func3 = 3'b101;
MINU: get_func3 = 3'b110;
MAXU: get_func3 = 3'b111;
SHFL: get_func3 = 3'b001;
UNSHFL: get_func3 = 3'b101;
BDEP: get_func3 = 3'b110;
BEXT: get_func3 = 3'b110;
PACK: get_func3 = 3'b100;
PACKU: get_func3 = 3'b100;
BMATOR: get_func3 = 3'b011;
BMATXOR: get_func3 = 3'b011;
PACKH: get_func3 = 3'b111;
BFP: get_func3 = 3'b111;
SHFLI: get_func3 = 3'b001;
UNSHFLI: get_func3 = 3'b101;
ADDIWU: get_func3 = 3'b100;
SLLIU_W: get_func3 = 3'b001;
ADDWU: get_func3 = 3'b000;
SUBWU: get_func3 = 3'b000;
ADDU_W: get_func3 = 3'b000;
SUBU_W: get_func3 = 3'b000;
SLOW: get_func3 = 3'b001;
SROW: get_func3 = 3'b101;
ROLW: get_func3 = 3'b001;
RORW: get_func3 = 3'b101;
SBCLRW: get_func3 = 3'b001;
SBSETW: get_func3 = 3'b001;
SBINVW: get_func3 = 3'b001;
SBEXTW: get_func3 = 3'b101;
GORCW: get_func3 = 3'b101;
GREVW: get_func3 = 3'b101;
SLOIW: get_func3 = 3'b001;
SROIW: get_func3 = 3'b101;
RORIW: get_func3 = 3'b101;
SBCLRIW: get_func3 = 3'b001;
SBSETIW: get_func3 = 3'b001;
SBINVIW: get_func3 = 3'b001;
GORCIW: get_func3 = 3'b101;
GREVIW: get_func3 = 3'b101;
FSLW: get_func3 = 3'b001;
FSRW: get_func3 = 3'b101;
FSRIW: get_func3 = 3'b101;
CLZW: get_func3 = 3'b001;
CTZW: get_func3 = 3'b001;
PCNTW: get_func3 = 3'b001;
CLMULW: get_func3 = 3'b001;
CLMULRW: get_func3 = 3'b010;
CLMULHW: get_func3 = 3'b011;
SHFLW: get_func3 = 3'b001;
UNSHFLW: get_func3 = 3'b101;
BDEPW: get_func3 = 3'b110;
BEXTW: get_func3 = 3'b110;
PACKW: get_func3 = 3'b100;
PACKUW: get_func3 = 3'b100;
BFPW: get_func3 = 3'b111;
default: get_func3 = super.get_func3();
endcase
;
endfunction
function bit [6:0] get_func7();
case (instr_name) inside
ANDN: get_func7 = 7'b0100000;
ORN: get_func7 = 7'b0100000;
XNOR: get_func7 = 7'b0100000;
GORC: get_func7 = 7'b0010100;
SLO: get_func7 = 7'b0010000;
SRO: get_func7 = 7'b0010000;
ROL: get_func7 = 7'b0110000;
ROR: get_func7 = 7'b0110000;
SBCLR: get_func7 = 7'b0100100;
SBSET: get_func7 = 7'b0010100;
SBINV: get_func7 = 7'b0110100;
SBEXT: get_func7 = 7'b0100100;
GREV: get_func7 = 7'b0110100;
CLZ: get_func7 = 7'b0110000;
CTZ: get_func7 = 7'b0110000;
PCNT: get_func7 = 7'b0110000;
BMATFLIP: get_func7 = 7'b0110000;
SEXT_B: get_func7 = 7'b0110000;
SEXT_H: get_func7 = 7'b0110000;
CRC32_B: get_func7 = 7'b0110000;
CRC32_H: get_func7 = 7'b0110000;
CRC32_W: get_func7 = 7'b0110000;
CRC32C_B: get_func7 = 7'b0110000;
CRC32C_H: get_func7 = 7'b0110000;
CRC32C_W: get_func7 = 7'b0110000;
CRC32_D: get_func7 = 7'b0110000;
CRC32C_D: get_func7 = 7'b0110000;
CLMUL: get_func7 = 7'b0000101;
CLMULR: get_func7 = 7'b0000101;
CLMULH: get_func7 = 7'b0000101;
MIN: get_func7 = 7'b0000101;
MAX: get_func7 = 7'b0000101;
MINU: get_func7 = 7'b0000101;
MAXU: get_func7 = 7'b0000101;
SHFL: get_func7 = 7'b0000100;
UNSHFL: get_func7 = 7'b0000100;
BDEP: get_func7 = 7'b0100100;
BEXT: get_func7 = 7'b0000100;
PACK: get_func7 = 7'b0000100;
PACKU: get_func7 = 7'b0100100;
BMATOR: get_func7 = 7'b0000100;
BMATXOR: get_func7 = 7'b0100100;
PACKH: get_func7 = 7'b0000100;
BFP: get_func7 = 7'b0100100;
ADDWU: get_func7 = 7'b0000101;
SUBWU: get_func7 = 7'b0100101;
ADDU_W: get_func7 = 7'b0000100;
SUBU_W: get_func7 = 7'b0100100;
SLOW: get_func7 = 7'b0010000;
SROW: get_func7 = 7'b0010000;
ROLW: get_func7 = 7'b0110000;
RORW: get_func7 = 7'b0110000;
SBCLRW: get_func7 = 7'b0100100;
SBSETW: get_func7 = 7'b0010100;
SBINVW: get_func7 = 7'b0110100;
SBEXTW: get_func7 = 7'b0100100;
GORCW: get_func7 = 7'b0010100;
GREVW: get_func7 = 7'b0110100;
SLOIW: get_func7 = 7'b0010000;
SROIW: get_func7 = 7'b0010000;
RORIW: get_func7 = 7'b0110000;
SBCLRIW: get_func7 = 7'b0100100;
SBSETIW: get_func7 = 7'b0010100;
SBINVIW: get_func7 = 7'b0110100;
GORCIW: get_func7 = 7'b0010100;
GREVIW: get_func7 = 7'b0110100;
CLZW: get_func7 = 7'b0110000;
CTZW: get_func7 = 7'b0110000;
PCNTW: get_func7 = 7'b0110000;
CLMULW: get_func7 = 7'b0000101;
CLMULRW: get_func7 = 7'b0000101;
CLMULHW: get_func7 = 7'b0000101;
SHFLW: get_func7 = 7'b0000100;
UNSHFLW: get_func7 = 7'b0000100;
BDEPW: get_func7 = 7'b0100100;
BEXTW: get_func7 = 7'b0000100;
PACKW: get_func7 = 7'b0000100;
PACKUW: get_func7 = 7'b0100100;
BFPW: get_func7 = 7'b0100100;
default: get_func7 = super.get_func7();
endcase
endfunction
function bit [4:0] get_func5();
case (instr_name) inside
SLOI: get_func5 = 5'b00100;
SROI: get_func5 = 5'b00100;
RORI: get_func5 = 5'b01100;
SBCLRI: get_func5 = 5'b01001;
SBSETI: get_func5 = 5'b01001;
SBINVI: get_func5 = 5'b01101;
SBEXTI: get_func5 = 5'b01001;
GORCI: get_func5 = 5'b00101;
GREVI: get_func5 = 5'b01101;
CLZW: get_func5 = 5'b00000;
CTZW: get_func5 = 5'b00001;
PCNTW: get_func5 = 5'b00010;
CRC32_B: get_func5 = 5'b10000;
CRC32_H: get_func5 = 5'b10001;
CRC32_W: get_func5 = 5'b10010;
CRC32C_B: get_func5 = 5'b11000;
CRC32C_H: get_func5 = 5'b11001;
CRC32C_W: get_func5 = 5'b11010;
CRC32_D: get_func5 = 5'b10011;
CRC32C_D: get_func5 = 5'b11011;
CLZ: get_func5 = 5'b00000;
CTZ: get_func5 = 5'b00001;
PCNT: get_func5 = 5'b00010;
BMATFLIP: get_func5 = 5'b00011;
SEXT_B: get_func5 = 5'b00100;
SEXT_H: get_func5 = 5'b00101;
default: `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
endcase
endfunction
function bit [1:0] get_func2();
case (instr_name) inside
CMIX: get_func2 = 2'b11;
CMOV: get_func2 = 2'b11;
FSL: get_func2 = 2'b10;
FSR: get_func2 = 2'b10;
FSLW: get_func2 = 2'b10;
FSRW: get_func2 = 2'b10;
FSRIW: get_func2 = 2'b10;
default: `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
endcase
endfunction
// Convert the instruction to assembly code
virtual function string convert2bin(string prefix = "");
string binary = "";
case (format)
R_FORMAT: begin
if ((category inside {LOGICAL}) && (group == RV32B)) begin
if (instr_name inside {SEXT_B, SEXT_H}) begin
binary =
$sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
end
end
if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CLZ, CTZ,
PCNT}) begin
binary =
$sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
end
end
if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
if (instr_name inside {CLZW, CTZW, PCNTW, CRC32_D, CRC32C_D, BMATFLIP}) begin
binary =
$sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()});
end
end
end
I_FORMAT: begin
if ((category inside {SHIFT, LOGICAL}) && (group == RV32B)) begin
binary = $sformatf("%8h", {get_func5(), imm[6:0], rs1, get_func3(), rd, get_opcode()});
end else if ((category inside {SHIFT, LOGICAL}) && (group == RV64B)) begin
binary = $sformatf("%8h", {get_func7(), imm[4:0], rs1, get_func3(), rd, get_opcode()});
if (instr_name == SLLIU_W)
binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()});
end
if (instr_name inside {FSRI}) begin
binary = $sformatf("%8h", {rs3, 1'b1, imm[5:0], rs1, get_func3(), rd, get_opcode()});
end
if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
binary = $sformatf("%8h", {6'b00_0010, imm[5:0], rs1, get_func3(), rd, get_opcode()});
end
if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
binary = $sformatf("%8h", {imm[11:0], rs1, get_func3(), rd, get_opcode()});
end
end
R4_FORMAT: begin
binary = $sformatf("%8h", {rs3, get_func2(), rs2, rs1, get_func3(), rd, get_opcode()});
end
default: begin
if (binary == "") binary = super.convert2bin(prefix);
end
endcase
return {prefix, binary};
endfunction
virtual function void do_copy(uvm_object rhs);
riscv_b_instr rhs_;
super.copy(rhs);
assert($cast(rhs_, rhs));
this.rs3 = rhs_.rs3;
this.has_rs3 = rhs_.has_rs3;
endfunction : do_copy
endclass

View file

@ -217,6 +217,7 @@ class riscv_compressed_instr extends riscv_instr;
end
CJ_FORMAT:
asm_str = $sformatf("%0s%0s", asm_str, get_imm());
default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
endcase
end else begin
// For EBREAK,C.EBREAK, making sure pc+4 is a valid instruction boundary

View file

@ -138,6 +138,7 @@ class riscv_floating_point_instr extends riscv_instr;
has_fs1 = 1'b0;
has_fd = 1'b0;
end
default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
endcase
endfunction

View file

@ -123,7 +123,9 @@ class riscv_instr extends uvm_object;
!(cfg.disable_compressed_instr &&
(instr_inst.group inside {RV32C, RV64C, RV32DC, RV32FC, RV128C})) &&
!(!cfg.enable_floating_point &&
(instr_inst.group inside {RV32F, RV64F, RV32D, RV64D}))) begin
(instr_inst.group inside {RV32F, RV64F, RV32D, RV64D})) &&
!(!cfg.enable_b_extension &&
(instr_inst.group inside {RV32B, RV64B}))) begin
instr_category[instr_inst.category].push_back(instr_name);
instr_group[instr_inst.group].push_back(instr_name);
instr_names.push_back(instr_name);
@ -374,6 +376,8 @@ class riscv_instr extends uvm_object;
end else begin
asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported format %0s [%0s]",
format.name(), instr_name.name()))
endcase
end else begin
// For EBREAK,C.EBREAK, making sure pc+4 is a valid instruction boundary
@ -580,6 +584,7 @@ class riscv_instr extends uvm_object;
else
binary = $sformatf("%8h", {get_func7(), rs2, rs1, get_func3(), rd, get_opcode()});
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported format %0s", format.name()))
endcase
return {prefix, binary};
endfunction

View file

@ -103,6 +103,7 @@ class riscv_vector_instr extends riscv_floating_point_instr;
VV: asm_str = $sformatf("vmv.v.v %s,%s", vd.name(), vs1.name());
VX: asm_str = $sformatf("vmv.v.x %s,%s", vd.name(), rs1.name());
VI: asm_str = $sformatf("vmv.v.i %s,%s", vd.name(), imm_str);
default: `uvm_info(`gfn, $sformatf("Unsupported va_variant %0s", va_variant), UVM_LOW)
endcase
end else if (instr_name == VFMV) begin
asm_str = $sformatf("vfmv.v.f %s,%s", vd.name(), fs1.name());
@ -156,6 +157,7 @@ class riscv_vector_instr extends riscv_floating_point_instr;
end
end
end
default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
endcase
if(comment != "") begin
asm_str = {asm_str, " #",comment};

78
vendor/google_riscv-dv/src/isa/rv32b_instr.sv vendored Executable file
View file

@ -0,0 +1,78 @@
/*
* Copyright 2019 Google LLC
* Copyright 2019 Mellanox Technologies Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// LOGICAL instructions
`DEFINE_B_INSTR(SEXT_B, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(SEXT_H, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(ANDN, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(ORN , R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(XNOR, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(GORC, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(GORCI, I_FORMAT, LOGICAL, RV32B, UIMM)
`DEFINE_B_INSTR(CMIX, R4_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(CMOV, R4_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(PACK, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(PACKU, R_FORMAT, LOGICAL, RV32B)
`DEFINE_B_INSTR(PACKH, R_FORMAT, LOGICAL, RV32B)
// SHIFT intructions
`DEFINE_B_INSTR(SLO, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(SRO, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(ROL, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(ROR, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(SBCLR, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(SBSET, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(SBINV, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(SBEXT, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(GREV, R_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(GREVI, I_FORMAT, SHIFT, RV32B , UIMM)
`DEFINE_B_INSTR(SLOI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(SROI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(RORI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(SBCLRI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(SBSETI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(SBINVI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(SBEXTI , I_FORMAT, SHIFT, RV32B ,UIMM)
`DEFINE_B_INSTR(FSL, R4_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(FSR, R4_FORMAT, SHIFT, RV32B)
`DEFINE_B_INSTR(FSRI, I_FORMAT, SHIFT, RV32B ,UIMM)
// ARITHMETIC intructions
`DEFINE_B_INSTR(CLZ, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CTZ, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(PCNT, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32_B, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32_H, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32_W, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32C_B, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32C_H, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CRC32C_W, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CLMUL, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(MIN, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(MAX, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(MINU, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(MAXU, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(SHFL, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(UNSHFL, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(BDEP, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(BEXT, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(BMATOR, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(BMATXOR, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(BFP, R_FORMAT, ARITHMETIC, RV32B)
`DEFINE_B_INSTR(SHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)
`DEFINE_B_INSTR(UNSHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM)

66
vendor/google_riscv-dv/src/isa/rv64b_instr.sv vendored Executable file
View file

@ -0,0 +1,66 @@
/*
* Copyright 2019 Google LLC
* Copyright 2019 Mellanox Technologies Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ARITHMETIC intructions
`DEFINE_B_INSTR(BMATFLIP, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CRC32_D, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CRC32C_D, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(ADDIWU, I_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(ADDWU, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(SUBWU, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(ADDU_W, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(SUBU_W, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CLZW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CTZW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(PCNTW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CLMULW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CLMULRW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(CLMULHW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(SHFLW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(UNSHFLW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(BDEPW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(BEXTW, R_FORMAT, ARITHMETIC, RV64B)
`DEFINE_B_INSTR(BFPW, R_FORMAT, ARITHMETIC, RV64B)
// SHIFT intructions
`DEFINE_B_INSTR(SLLIU_W, I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SLOW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SROW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(ROLW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(RORW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SBCLRW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SBSETW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SBINVW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SBEXTW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(GREVW, R_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(SLOIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SROIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(RORIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SBCLRIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SBSETIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(SBINVIW , I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(GREVIW, I_FORMAT, SHIFT, RV64B, UIMM)
`DEFINE_B_INSTR(FSLW, R4_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(FSRW, R4_FORMAT, SHIFT, RV64B)
`DEFINE_B_INSTR(FSRIW, I_FORMAT, SHIFT, RV64B, UIMM)
// LOGICAL instructions
`DEFINE_B_INSTR(GORCW, R_FORMAT, LOGICAL, RV64B)
`DEFINE_B_INSTR(GORCIW, I_FORMAT, LOGICAL, RV64B, UIMM)
`DEFINE_B_INSTR(PACKW, R_FORMAT, LOGICAL, RV64B)
`DEFINE_B_INSTR(PACKUW, R_FORMAT, LOGICAL, RV64B)

View file

@ -19,60 +19,72 @@ class riscv_amo_base_instr_stream extends riscv_mem_access_stream;
rand int unsigned num_amo;
rand int unsigned num_mixed_instr;
rand int base;
rand riscv_reg_t rs1_reg;
rand int unsigned data_page_id;
rand int max_load_store_offset;
rand int offset[];
rand riscv_reg_t rs1_reg[];
rand int num_of_rs1_reg;
int unsigned data_page_id;
int unsigned max_offset;
// User can specify a small group of available registers to generate various hazard condition
rand riscv_reg_t avail_regs[];
`uvm_object_utils(riscv_amo_base_instr_stream)
constraint num_of_rs1_reg_c {
num_of_rs1_reg == 1;
}
constraint rs1_c {
!(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
solve num_of_rs1_reg before rs1_reg;
rs1_reg.size() == num_of_rs1_reg;
offset.size() == num_of_rs1_reg;
foreach (rs1_reg[i]) {
!(rs1_reg[i] inside {cfg.reserved_regs, reserved_rd, ZERO});
}
unique {rs1_reg};
}
constraint addr_range_c {
data_page_id < max_data_page_id;
base inside {[0 : max_load_store_offset-1]};
}
constraint aligned_amo_c {
if (XLEN == 32) {
base % 4 == 0;
} else {
base % 8 == 0;
foreach (offset[i]) {
offset[i] inside {[0 : max_offset - 1]};
}
}
function new(string name = "");
super.new(name);
endfunction
constraint aligned_amo_c {
foreach (offset[i]) {
if (XLEN == 32) {
offset[i] % 4 == 0;
} else {
offset[i] % 8 == 0;
}
}
}
`uvm_object_utils(riscv_amo_base_instr_stream)
`uvm_object_new
function void pre_randomize();
data_page = cfg.amo_region;
max_data_page_id = data_page.size();
data_page_id = $urandom_range(0, max_data_page_id - 1);
max_offset = data_page[data_page_id].size_in_bytes;
endfunction
// Use "la" instruction to initialize the base regiseter
virtual function void add_rs1_init_la_instr(riscv_reg_t gpr, int id, int base = 0);
riscv_pseudo_instr la_instr;
la_instr = riscv_pseudo_instr::type_id::create("la_instr");
la_instr.pseudo_instr_name = LA;
la_instr.rd = gpr;
la_instr.imm_str = $sformatf("%0s+%0d", cfg.amo_region[id].name, base);
instr_list.push_front(la_instr);
// Use "la" instruction to initialize the offset regiseter
virtual function void init_offset_reg();
foreach (rs1_reg[i]) begin
riscv_pseudo_instr la_instr;
la_instr = riscv_pseudo_instr::type_id::create("la_instr");
la_instr.pseudo_instr_name = LA;
la_instr.rd = rs1_reg[i];
la_instr.imm_str = $sformatf("%0s+%0d", cfg.amo_region[data_page_id].name, offset[i]);
instr_list.push_front(la_instr);
end
endfunction
function void post_randomize();
gen_amo_instr();
// rs1 cannot be modified by other instructions
if(!(rs1_reg inside {reserved_rd})) begin
reserved_rd = {reserved_rd, rs1_reg};
end
reserved_rd = {reserved_rd, rs1_reg};
add_mixed_instr(num_mixed_instr);
add_rs1_init_la_instr(rs1_reg, data_page_id);
init_offset_reg();
super.post_randomize();
endfunction
@ -113,24 +125,24 @@ class riscv_lr_sc_instr_stream extends riscv_amo_base_instr_stream;
lr_instr = riscv_instr::get_rand_instr(.include_instr({allowed_lr_instr}));
sc_instr = riscv_instr::get_rand_instr(.include_instr({allowed_sc_instr}));
`DV_CHECK_RANDOMIZE_WITH_FATAL(lr_instr,
rs1 == rs1_reg;
rs1 == rs1_reg[0];
if (reserved_rd.size() > 0) {
!(rd inside {reserved_rd});
}
if (cfg.reserved_regs.size() > 0) {
!(rd inside {cfg.reserved_regs});
}
rd != rs1_reg;
rd != rs1_reg[0];
)
`DV_CHECK_RANDOMIZE_WITH_FATAL(sc_instr,
rs1 == rs1_reg;
rs1 == rs1_reg[0];
if (reserved_rd.size() > 0) {
!(rd inside {reserved_rd});
}
if (cfg.reserved_regs.size() > 0) {
!(rd inside {cfg.reserved_regs});
}
rd != rs1_reg;
rd != rs1_reg[0];
)
instr_list.push_back(lr_instr);
instr_list.push_back(sc_instr);
@ -144,8 +156,14 @@ class riscv_amo_instr_stream extends riscv_amo_base_instr_stream;
constraint reasonable_c {
solve num_amo before num_mixed_instr;
num_amo inside {[1:10]};
num_mixed_instr inside {[0:2*num_amo]};
num_amo inside {[1 : 10]};
num_mixed_instr inside {[0 : num_amo]};
}
constraint num_of_rs1_reg_c {
solve num_amo before num_of_rs1_reg;
num_of_rs1_reg inside {[1 : num_amo]};
num_of_rs1_reg < 5;
}
`uvm_object_utils(riscv_amo_instr_stream)
@ -162,8 +180,8 @@ class riscv_amo_instr_stream extends riscv_amo_base_instr_stream;
if (cfg.reserved_regs.size() > 0) {
!(rd inside {cfg.reserved_regs});
}
rs1 == rs1_reg;
rd != rs1_reg;
rs1 inside {rs1_reg};
!(rd inside {rs1_reg});
)
instr_list.push_front(amo_instr[i]);
end

View file

@ -106,7 +106,8 @@ class riscv_asm_program_gen extends uvm_object;
`DV_CHECK_RANDOMIZE_FATAL(main_program[hart])
main_program[hart].gen_instr(.is_main_program(1), .no_branch(cfg.no_branch_jump));
// Setup jump instruction among main program and sub programs
gen_callstack(main_program[hart], sub_program[hart], sub_program_name, cfg.num_of_sub_program);
gen_callstack(main_program[hart], sub_program[hart], sub_program_name,
cfg.num_of_sub_program);
`uvm_info(`gfn, "Generating callstack...done", UVM_LOW)
main_program[hart].post_process_instr();
`uvm_info(`gfn, "Post-processing main program...done", UVM_LOW)
@ -128,8 +129,10 @@ class riscv_asm_program_gen extends uvm_object;
// Program end
gen_program_end(hart);
if (!cfg.bare_program_mode) begin
// Privileged mode switch routine
gen_privileged_mode_switch_routine(hart);
if (!riscv_instr_pkg::support_pmp) begin
// Privileged mode switch routine
gen_privileged_mode_switch_routine(hart);
end
// Generate debug rom section
if (riscv_instr_pkg::support_debug_mode) begin
gen_debug_rom(hart);
@ -165,7 +168,12 @@ class riscv_asm_program_gen extends uvm_object;
// Generate kernel program/data/stack sections
//---------------------------------------------------------------------------------------
virtual function void gen_kernel_sections(int hart);
instr_stream.push_back(get_label("kernel_instr_start: .align 12", hart));
if (SATP_MODE != BARE) begin
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
instr_stream.push_back(get_label("kernel_instr_start:", hart));
instr_stream.push_back(".text");
// Kernel programs
if (cfg.virtual_addr_translation_on) begin
@ -189,8 +197,13 @@ class riscv_asm_program_gen extends uvm_object;
// User stack and data pages may not be accessible when executing trap handling programs in
// machine/supervisor mode. Generate separate kernel data/stack sections to solve it.
if (cfg.virtual_addr_translation_on) begin
if (SATP_MODE != BARE) begin
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
// Kernel data pages
instr_stream.push_back(get_label("kernel_data_start: .align 12", hart));
instr_stream.push_back(get_label("kernel_data_start:", hart));
if(!cfg.no_data_page) begin
// Data section
gen_data_page(hart, 1'b1);
@ -347,8 +360,15 @@ class riscv_asm_program_gen extends uvm_object;
if (cfg.use_push_data_section) begin
instr_stream.push_back($sformatf(".pushsection .%0suser_stack,\"aw\",@progbits;",
hart_prefix(hart)));
end else begin
instr_stream.push_back($sformatf(".section .%0suser_stack,\"aw\",@progbits;",
hart_prefix(hart)));
end
if (SATP_MODE != BARE) begin
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
instr_stream.push_back(".align 12");
instr_stream.push_back(get_label("user_stack_start:", hart));
instr_stream.push_back($sformatf(".rept %0d", cfg.stack_len - 1));
instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8));
@ -365,8 +385,15 @@ class riscv_asm_program_gen extends uvm_object;
if (cfg.use_push_data_section) begin
instr_stream.push_back($sformatf(".pushsection .%0skernel_stack,\"aw\",@progbits;",
hart_prefix(hart)));
end else begin
instr_stream.push_back($sformatf(".section .%0skernel_stack,\"aw\",@progbits;",
hart_prefix(hart)));
end
if (SATP_MODE != BARE) begin
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
instr_stream.push_back(".align 12");
instr_stream.push_back(get_label("kernel_stack_start:", hart));
instr_stream.push_back($sformatf(".rept %0d", cfg.kernel_stack_len - 1));
instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8));
@ -414,6 +441,7 @@ class riscv_asm_program_gen extends uvm_object;
RV32I, RV64I, RV128I : misa[MISA_EXT_I] = 1'b1;
RV32M, RV64M : misa[MISA_EXT_M] = 1'b1;
RV32A, RV64A : misa[MISA_EXT_A] = 1'b1;
RV32B, RV64B : misa[MISA_EXT_B] = 1'b1;
RV32F, RV64F, RV32FC : misa[MISA_EXT_F] = 1'b1;
RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1;
RV32V, RV64V : misa[MISA_EXT_V] = 1'b1;
@ -591,6 +619,12 @@ class riscv_asm_program_gen extends uvm_object;
end
// Setup mepc register, jump to init entry
setup_epc(hart);
// Move privileged mode support to the "safe" section of the program
// if PMP is supported
if (riscv_instr_pkg::support_pmp) begin
// Privileged mode switch routine
gen_privileged_mode_switch_routine(hart);
end
endfunction
virtual function void gen_privileged_mode_switch_routine(int hart);
@ -623,6 +657,8 @@ class riscv_asm_program_gen extends uvm_object;
.csr(USTATUS));
gen_signature_handshake(.instr(csr_handshake), .signature_type(WRITE_CSR), .csr(UIE));
end
default: `uvm_info(`gfn, $sformatf("Unsupported privileged_mode %0s",
riscv_instr_pkg::supported_privileged_mode[i]), UVM_LOW)
endcase
// Write M-mode CSRs to testbench by default, as these should be implemented
gen_signature_handshake(.instr(csr_handshake), .signature_type(WRITE_CSR), .csr(MSTATUS));
@ -636,7 +672,7 @@ class riscv_asm_program_gen extends uvm_object;
// Setup EPC before entering target privileged mode
virtual function void setup_epc(int hart);
string instr[];
string instr[$];
string mode_name;
instr = {$sformatf("la x%0d, %0sinit", cfg.gpr[0], hart_prefix(hart))};
if(cfg.virtual_addr_translation_on) begin
@ -648,10 +684,10 @@ class riscv_asm_program_gen extends uvm_object;
$sformatf("srli x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN - 12)};
end
mode_name = cfg.init_privileged_mode.name();
instr = {instr,
$sformatf("csrw mepc, x%0d", cfg.gpr[0]),
$sformatf("j %0sinit_%0s", hart_prefix(hart), mode_name.tolower())
};
instr.push_back($sformatf("csrw mepc, x%0d", cfg.gpr[0]));
if (!riscv_instr_pkg::support_pmp) begin
instr.push_back($sformatf("j %0sinit_%0s", hart_prefix(hart), mode_name.tolower()));
end
gen_section(get_label("mepc_setup", hart), instr);
endfunction
@ -723,6 +759,8 @@ class riscv_asm_program_gen extends uvm_object;
MACHINE_MODE: trap_vec_reg = MTVEC;
SUPERVISOR_MODE: trap_vec_reg = STVEC;
USER_MODE: trap_vec_reg = UTVEC;
default: `uvm_info(`gfn, $sformatf("Unsupported privileged_mode %0s",
riscv_instr_pkg::supported_privileged_mode[i]), UVM_LOW)
endcase
// Skip utvec init if trap delegation to u_mode is not supported
if ((riscv_instr_pkg::supported_privileged_mode[i] == USER_MODE) &&
@ -796,6 +834,8 @@ class riscv_asm_program_gen extends uvm_object;
gen_trap_handler_section(hart, "u", UCAUSE, UTVEC, UTVAL,
UEPC, USCRATCH, USTATUS, UIE, UIP);
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported privileged_mode %0s",
riscv_instr_pkg::supported_privileged_mode[i]))
endcase
end
endfunction
@ -834,7 +874,11 @@ class riscv_asm_program_gen extends uvm_object;
end
// The trap handler will occupy one 4KB page, it will be allocated one entry in the page table
// with a specific privileged mode.
instr_stream.push_back(".align 12");
if (SATP_MODE != BARE) begin
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
tvec_name = tvec.name();
gen_section(get_label($sformatf("%0s_handler", tvec_name.tolower()), hart), instr);
// Exception handler
@ -1059,6 +1103,9 @@ class riscv_asm_program_gen extends uvm_object;
if (cfg.use_push_data_section) begin
instr_stream.push_back($sformatf(".pushsection .%0spage_table,\"aw\",@progbits;",
hart_prefix(hart)));
end else begin
instr_stream.push_back($sformatf(".section .%0spage_table,\"aw\",@progbits;",
hart_prefix(hart)));
end
foreach(page_table_list.page_table[i]) begin
page_table_list.page_table[i].gen_page_table_section(page_table_section);
@ -1129,6 +1176,7 @@ class riscv_asm_program_gen extends uvm_object;
USTATUS: begin
interrupt_handler_instr.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 1));
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported status %0s", status))
endcase
interrupt_handler_instr.push_back($sformatf("1: csrwi 0x%0x,0", scratch));
end
@ -1150,8 +1198,12 @@ class riscv_asm_program_gen extends uvm_object;
interrupt_handler_instr = {interrupt_handler_instr,
$sformatf("%0sret;", mode_prefix)
};
// The interrupt handler will use one 4KB page
instr_stream.push_back(".align 12");
if (SATP_MODE != BARE) begin
// The interrupt handler will use one 4KB page
instr_stream.push_back(".align 12");
end else begin
instr_stream.push_back(".align 2");
end
gen_section(get_label($sformatf("%0smode_intr_handler", mode_prefix), hart),
interrupt_handler_instr);
endfunction

View file

@ -75,12 +75,18 @@ class riscv_data_page_gen extends uvm_object;
if (cfg.use_push_data_section) begin
data_page_str.push_back($sformatf(".pushsection .%0s,\"aw\",@progbits;",
mem_region_setting[i].name));
end else begin
data_page_str.push_back($sformatf(".section .%0s,\"aw\",@progbits;",
mem_region_setting[i].name));
end
data_page_str.push_back($sformatf("%0s:", mem_region_setting[i].name));
end else begin
if (cfg.use_push_data_section) begin
data_page_str.push_back($sformatf(".pushsection .%0s,\"aw\",@progbits;",
{hart_prefix(hart_id), mem_region_setting[i].name}));
end else begin
data_page_str.push_back($sformatf(".section .%0s,\"aw\",@progbits;",
{hart_prefix(hart_id), mem_region_setting[i].name}));
end
data_page_str.push_back($sformatf("%0s:",
{hart_prefix(hart_id), mem_region_setting[i].name}));

View file

@ -98,3 +98,9 @@
`define DEFINE_CUSTOM_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
class riscv_``instr_n``_instr extends riscv_custom_instr; \
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
//B-extension instruction
`define DEFINE_B_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
class riscv_``instr_n``_instr extends riscv_b_instr; \
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)

View file

@ -165,6 +165,14 @@ class riscv_illegal_instr extends uvm_object;
c_op != 2'b11;
}
// Avoid generating illegal func3/func7 errors for opcode used by B-extension
constraint b_extension_c {
if (RV32B inside {supported_isa}) {
if (exception inside {kIllegalFunc3, kIllegalFunc7}) {
!(opcode inside {7'b0011011, 7'b0010011, 7'b0111011});
}
}
}
constraint illegal_compressed_op_c {
if (exception == kIllegalCompressedOpcode) {

View file

@ -197,7 +197,7 @@ class riscv_instr_gen_config extends uvm_object;
bit disable_compressed_instr;
// "Memory mapped" address that when written to will indicate some event to
// the testbench - testbench will take action based on the value written
int signature_addr = 32'hdead_beef;
bit [XLEN - 1 : 0] signature_addr = 32'hdead_beef;
bit require_signature_addr = 1'b0;
// Enable a full or empty debug_rom section.
// Full debug_rom will contain random instruction streams.
@ -232,6 +232,8 @@ class riscv_instr_gen_config extends uvm_object;
bit enable_floating_point;
// Vector extension support
bit enable_vector_extension;
// Bit manipulation extension support
bit enable_b_extension;
//-----------------------------------------------------------------------------
// Command line options for instruction distribution control
@ -396,7 +398,7 @@ class riscv_instr_gen_config extends uvm_object;
constraint addr_translaction_rnd_order_c {
solve init_privileged_mode before virtual_addr_translation_on;
}
constraint addr_translaction_c {
if ((init_privileged_mode != MACHINE_MODE) && (SATP_MODE != BARE)) {
virtual_addr_translation_on == 1'b1;
@ -474,6 +476,7 @@ class riscv_instr_gen_config extends uvm_object;
`uvm_field_int(max_directed_instr_stream_seq, UVM_DEFAULT)
`uvm_field_int(enable_floating_point, UVM_DEFAULT)
`uvm_field_int(enable_vector_extension, UVM_DEFAULT)
`uvm_field_int(enable_b_extension, UVM_DEFAULT)
`uvm_field_int(use_push_data_section, UVM_DEFAULT)
`uvm_object_utils_end
@ -527,6 +530,7 @@ class riscv_instr_gen_config extends uvm_object;
get_bool_arg_value("+set_mstatus_tw=", set_mstatus_tw);
get_bool_arg_value("+enable_floating_point=", enable_floating_point);
get_bool_arg_value("+enable_vector_extension=", enable_vector_extension);
get_bool_arg_value("+enable_b_extension=", enable_b_extension);
if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
`uvm_info(get_full_name(), $sformatf(
"Got boot mode option - %0s", boot_mode_opts), UVM_LOW)
@ -566,6 +570,7 @@ class riscv_instr_gen_config extends uvm_object;
vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg");
pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg");
pmp_cfg.rand_mode(pmp_cfg.pmp_randomize);
pmp_cfg.initialize(require_signature_addr);
setup_instr_distribution();
get_invalid_priv_lvl_csr();
endfunction
@ -642,7 +647,8 @@ class riscv_instr_gen_config extends uvm_object;
bit support_64b;
bit support_128b;
foreach (riscv_instr_pkg::supported_isa[i]) begin
if (riscv_instr_pkg::supported_isa[i] inside {RV64I, RV64M, RV64A, RV64F, RV64D, RV64C}) begin
if (riscv_instr_pkg::supported_isa[i] inside {RV64I, RV64M, RV64A, RV64F, RV64D, RV64C,
RV64B}) begin
support_64b = 1'b1;
end else if (riscv_instr_pkg::supported_isa[i] inside {RV128I, RV128C}) begin
support_128b = 1'b1;

View file

@ -147,6 +147,108 @@ package riscv_instr_pkg;
CSRRWI,
CSRRSI,
CSRRCI,
// RV32B instructions
ANDN,
ORN,
XNOR,
GORC,
SLO,
SRO,
ROL,
ROR,
SBCLR,
SBSET,
SBINV,
SBEXT,
GREV,
SLOI,
SROI,
RORI,
SBCLRI,
SBSETI,
SBINVI,
SBEXTI,
GORCI,
GREVI,
CMIX,
CMOV,
FSL,
FSR,
FSRI,
CLZ,
CTZ,
PCNT,
SEXT_B,
SEXT_H,
CRC32_B,
CRC32_H,
CRC32_W,
CRC32C_B,
CRC32C_H,
CRC32C_W,
CLMUL,
CLMULR,
CLMULH,
MIN,
MAX,
MINU,
MAXU,
SHFL,
UNSHFL,
BDEP,
BEXT,
PACK,
PACKU,
BMATOR,
BMATXOR,
PACKH,
BFP,
SHFLI,
UNSHFLI,
//RV64B instructions
ADDIWU,
SLLIU_W,
ADDWU,
SUBWU,
BMATFLIP,
CRC32_D,
CRC32C_D,
ADDU_W,
SUBU_W,
SLOW,
SROW,
ROLW,
RORW,
SBCLRW,
SBSETW,
SBINVW,
SBEXTW,
GORCW,
GREVW,
SLOIW,
SROIW,
RORIW,
SBCLRIW,
SBSETIW,
SBINVIW,
GORCIW,
GREVIW,
FSLW,
FSRW,
FSRIW,
CLZW,
CTZW,
PCNTW,
CLMULW,
CLMULRW,
CLMULHW,
SHFLW,
UNSHFLW,
BDEPW,
BEXTW,
PACKW,
PACKUW,
BFPW,
// RV32M instructions
MUL,
MULH,
@ -1124,7 +1226,8 @@ package riscv_instr_pkg;
endfunction
// Get a hex argument from command line
function automatic void get_hex_arg_value(string cmdline_str, ref int val);
function automatic void get_hex_arg_value(string cmdline_str,
ref bit [XLEN - 1 : 0] val);
string s;
if(inst.get_arg_value(cmdline_str, s)) begin
val = s.atohex();
@ -1148,6 +1251,7 @@ package riscv_instr_pkg;
`include "riscv_instr_gen_config.sv"
`include "isa/riscv_instr.sv"
`include "isa/riscv_amo_instr.sv"
`include "isa/riscv_b_instr.sv"
`include "isa/riscv_floating_point_instr.sv"
`include "isa/riscv_vector_instr.sv"
`include "isa/riscv_compressed_instr.sv"
@ -1158,8 +1262,10 @@ package riscv_instr_pkg;
`include "isa/rv32fc_instr.sv"
`include "isa/rv32f_instr.sv"
`include "isa/rv32i_instr.sv"
`include "isa/rv32b_instr.sv"
`include "isa/rv32m_instr.sv"
`include "isa/rv64a_instr.sv"
`include "isa/rv64b_instr.sv"
`include "isa/rv64c_instr.sv"
`include "isa/rv64d_instr.sv"
`include "isa/rv64f_instr.sv"

View file

@ -305,6 +305,7 @@ class riscv_instr_sequence extends uvm_sequence;
C_JALR : str = {prefix, $sformatf("c.jalr x%0d", ra)};
C_JR : str = {prefix, $sformatf("c.jr x%0d", ra)};
JALR : str = {prefix, $sformatf("jalr x%0d, x%0d, 0", ra, ra)};
default: `uvm_fatal(`gfn, $sformatf("Unsupported jump_instr %0s", jump_instr[i]))
endcase
instr_string_list.push_back(str);
endfunction

View file

@ -146,6 +146,7 @@ class riscv_page_table_entry#(satp_mode_t MODE = SV39) extends uvm_object;
1 : return PPN0_WIDTH;
2 : return PPN0_WIDTH + PPN1_WIDTH;
3 : return PPN0_WIDTH + PPN1_WIDTH + PPN2_WIDTH;
default: `uvm_fatal(`gfn, $sformatf("Unsupported page_level %0x", page_level))
endcase
endfunction

View file

@ -25,8 +25,11 @@ class riscv_pmp_cfg extends uvm_object;
// pmp CSR configurations
rand pmp_cfg_reg_t pmp_cfg[];
// PMP maximum address - used to set defaults
// TODO(udinator) - make this address configurable?
bit [XLEN - 1 : 0] pmp_max_address = {XLEN{1'b1}};
// PMP "minimum" address - the address written to pmpaddr0
// to create a "safe region", which contains important setup code,
// and cannot throw a PMP fault
bit [XLEN - 1 : 0] pmp_min_address = 0;
// used to parse addr_mode configuration from cmdline
typedef uvm_enum_wrapper#(pmp_addr_mode_t) addr_mode_wrapper;
@ -64,6 +67,7 @@ class riscv_pmp_cfg extends uvm_object;
get_bool_arg_value("+pmp_randomize=", pmp_randomize);
get_int_arg_value("+pmp_granularity=", pmp_granularity);
get_int_arg_value("+pmp_num_regions=", pmp_num_regions);
get_hex_arg_value("+pmp_max_address=", pmp_max_address);
pmp_cfg = new[pmp_num_regions];
// As per privileged spec, the top 10 bits of a rv64 PMP address are all 0.
if (XLEN == 64) begin
@ -75,6 +79,21 @@ class riscv_pmp_cfg extends uvm_object;
end
endfunction
function void initialize(bit require_signature_addr);
// We want to set the "minimum" pmp address to just after the location of the <main>
// section of the program to allow all initialization routines to not be interrupted
// by PMP faults.
// The location of <main> itself will change depending on whether the handshaking
// mechanism is enabled or disabled, so we check if it is enabled and then
// round up the address of <main>.
pmp_min_address = (require_signature_addr) ? 'h80002910 : 'h80001580;
if (!pmp_randomize) begin
set_defaults();
setup_pmp();
end
endfunction
// This will only get called if pmp_randomize is set, in which case we apply command line
// arguments after randomization
function void post_randomize();
@ -88,13 +107,16 @@ class riscv_pmp_cfg extends uvm_object;
pmp_cfg[i].x = 1'b1;
pmp_cfg[i].w = 1'b1;
pmp_cfg[i].r = 1'b1;
pmp_cfg[i].addr = assign_default_addr(pmp_num_regions, i + 1);
pmp_cfg[i].addr = (i == 0) ? pmp_min_address : assign_default_addr(pmp_num_regions, i);
end
endfunction
// Helper function to break down
function bit [XLEN - 1 : 0] assign_default_addr(int num_regions, int index);
return pmp_max_address / num_regions * index;
bit [XLEN - 1 : 0] total_addr_space, offset;
total_addr_space = pmp_max_address - pmp_min_address;
offset = total_addr_space / (num_regions - 1) * index;
return pmp_min_address + offset;
endfunction
function void setup_pmp();
@ -163,6 +185,7 @@ class riscv_pmp_cfg extends uvm_object;
64: begin
return {10'b0, shifted_addr[XLEN - 11 : 0]};
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported XLEN %0s", XLEN))
endcase
endfunction
@ -177,7 +200,7 @@ class riscv_pmp_cfg extends uvm_object;
// CSR, this function waits until it has reached this maximum to write to the physical CSR to
// save some extraneous instructions from being performed.
function void gen_pmp_instr(ref string instr[$], riscv_reg_t scratch_reg);
int cfg_per_csr = XLEN / 4;
int cfg_per_csr = XLEN / 8;
bit [XLEN - 1 : 0] pmp_word;
bit [XLEN - 1 : 0] cfg_bitmask;
bit [7 : 0] cfg_byte;
@ -195,7 +218,7 @@ class riscv_pmp_cfg extends uvm_object;
pmp_word = pmp_word | cfg_bitmask;
`uvm_info(`gfn, $sformatf("pmp_word: 0x%0x", pmp_word), UVM_DEBUG)
cfg_bitmask = 0;
`uvm_info(`gfn, $sformatf("pmp_addr: 0x%0x", pmp_cfg[i].addr), UVM_DEBUG)
`uvm_info(`gfn, $sformatf("pmp_addr_%d: 0x%0x", i, pmp_cfg[i].addr), UVM_DEBUG)
instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg, pmp_cfg[i].addr));
instr.push_back($sformatf("csrw 0x%0x, x%0d", base_pmp_addr + i, scratch_reg));
// short circuit if end of list

View file

@ -72,10 +72,10 @@
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+instr_cnt=5000
+num_of_sub_program=5
+directed_instr_0=riscv_lr_sc_instr_stream,10
+directed_instr_1=riscv_amo_instr_stream,10
+instr_cnt=2000
+num_of_sub_program=2
+directed_instr_0=riscv_lr_sc_instr_stream,50
+directed_instr_1=riscv_amo_instr_stream,50
rtl_test: core_base_test

View file

@ -0,0 +1,22 @@
# riscOVPsim configuration file converted from YAML
--variant RV32I
--override iscvOVPsim/cpu/add_Extensions=MCB
--override riscvOVPsim/cpu/misa_MXL=1
--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0
--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0
--override riscvOVPsim/cpu/unaligned=T
--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0
--override riscvOVPsim/cpu/user_version=2.3
--override riscvOVPsim/cpu/priv_version=1.11
--override riscvOVPsim/cpu/mvendorid=0
--override riscvOVPsim/cpu/marchid=0
--override riscvOVPsim/cpu/mimpid=0
--override riscvOVPsim/cpu/mhartid=0
--override riscvOVPsim/cpu/cycle_undefined=F
--override riscvOVPsim/cpu/instret_undefined=F
--override riscvOVPsim/cpu/time_undefined=T
--override riscvOVPsim/cpu/reset_address=0x80000000
--override riscvOVPsim/cpu/simulateexceptions=T
--override riscvOVPsim/cpu/defaultsemihost=F
--override riscvOVPsim/cpu/wfi_is_nop=T
--exitonsymbol _exit

View file

@ -0,0 +1,118 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//-----------------------------------------------------------------------------
// Processor feature configuration
//-----------------------------------------------------------------------------
// XLEN
parameter int XLEN = 32;
// Parameter for SATP mode, set to BARE if address translation is not supported
parameter satp_mode_t SATP_MODE = BARE;
// Supported Privileged mode
privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
// Unsupported instructions
riscv_instr_name_t unsupported_instr[];
// ISA supported by the processor
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32B};
// Interrupt mode support
mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is
// supported
int max_interrupt_vector_num = 16;
// Physical memory protection support
bit support_pmp = 0;
// Debug mode support
bit support_debug_mode = 0;
// Support delegate trap to user mode
bit support_umode_trap = 0;
// Support sfence.vma instruction
bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Number of harts
parameter int NUM_HARTS = 1;
// ----------------------------------------------------------------------------
// Previleged CSR implementation
// ----------------------------------------------------------------------------
// Implemented previlieged CSR list
`ifdef DSIM
privileged_reg_t implemented_csr[] = {
`else
parameter privileged_reg_t implemented_csr[] = {
`endif
// Machine mode mode CSR
MVENDORID, // Vendor ID
MARCHID, // Architecture ID
MIMPID, // Implementation ID
MHARTID, // Hardware thread ID
MSTATUS, // Machine status
MISA, // ISA and extensions
MIE, // Machine interrupt-enable register
MTVEC, // Machine trap-handler base address
MCOUNTEREN, // Machine counter enable
MSCRATCH, // Scratch register for machine trap handlers
MEPC, // Machine exception program counter
MCAUSE, // Machine trap cause
MTVAL, // Machine bad address or instruction
MIP // Machine interrupt pending
};
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
`ifdef DSIM
interrupt_cause_t implemented_interrupt[] = {
`else
parameter interrupt_cause_t implemented_interrupt[] = {
`endif
M_SOFTWARE_INTR,
M_TIMER_INTR,
M_EXTERNAL_INTR
};
`ifdef DSIM
exception_cause_t implemented_exception[] = {
`else
parameter exception_cause_t implemented_exception[] = {
`endif
INSTRUCTION_ACCESS_FAULT,
ILLEGAL_INSTRUCTION,
BREAKPOINT,
LOAD_ADDRESS_MISALIGNED,
LOAD_ACCESS_FAULT,
ECALL_MMODE
};

View file

@ -0,0 +1,66 @@
# Copyright Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ================================================================================
# Regression test list format
# --------------------------------------------------------------------------------
# test : Assembly test name
# description : Description of this test
# gen_opts : Instruction generator options
# iterations : Number of iterations of this test
# no_iss : Enable/disable ISS simulator (Optional)
# gen_test : Test name used by the instruction generator
# asm_tests : Path to directed, hand-coded assembly test file or directory
# rtl_test : RTL simulation test name
# cmp_opts : Compile options passed to the instruction generator
# sim_opts : Simulation options passed to the instruction generator
# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional)
# compare_opts : Options for the RTL & ISS trace comparison
# gcc_opts : gcc compile options
# --------------------------------------------------------------------------------
- import: <riscv_dv_root>/yaml/base_testlist.yaml
- test: riscv_non_compressed_instr_test
description: >
Random instruction test without compressed instructions
iterations: 1
gen_test: riscv_rand_instr_test
gen_opts: >
+disable_compressed_instr=1
rtl_test: core_base_test
- test: riscv_hint_instr_test
description: >
HINT instruction test, verify the processor can detect HINT instruction
treat it as NOP. No illegal instruction exception is expected
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+hint_instr_ratio=5
rtl_test: core_base_test
- test: riscv_pmp_test
description: >
Provide some PMP configuration parameters, and setup PMP CSRs appropriately
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+pmp_randomize=0
+pmp_num_regions=1
+pmp_granularity=1
+pmp_region_0=L:0,A:NAPOT,X:1,W:1,R:1,ADDR:FFFFFFFF
rtl_test: core_base_test

View file

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
VERIBLE_VERSION=03c7102ab8ed63037159f479ce17b3487401f082
VERIBLE_VERSION=751d4d8e57741ab22806f91982f59c71ecf37d9d
INSTALL_DIR=/tools/verible
# this requires the bazel build system and GCC7

View file

@ -5,6 +5,3 @@ riscv_instr_cover_group.sv
riscv_instr_pkg.sv
# tool does not support included file very well. Issue at github.com/google/verible/issues/178
riscv_custom_instr_enum.sv
# tool bug. Issue at github.com/google/verible/issues/172
riscv_instr_stream.sv
riscv_reg.sv

View file

@ -29,7 +29,7 @@
cmd: >
<out>/vcs_simv +vcs+lic+wait <sim_opts> +ntb_random_seed=<seed> <cov_opts>
cov_opts: >
-cm_dir <out>/test.vdb -cm_log /dev/null -cm_name test_<seed>
-cm_dir <out>/test.vdb -cm_log /dev/null -cm_name test_<seed>_<test_id>
- tool: ius
compile: