diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index d5f652dd..d1152a11 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: d23da3862f95954e6374aaec787e0fb0c1878a16 + rev: a655f34eb5058da442b38ca010b0d008291c11b5 } } diff --git a/vendor/google_riscv-dv/README.md b/vendor/google_riscv-dv/README.md index 4de78724..5d12da48 100644 --- a/vendor/google_riscv-dv/README.md +++ b/vendor/google_riscv-dv/README.md @@ -16,20 +16,9 @@ processor verification. It currently supports the following features: - Supports mixing directed instructions with random instruction stream - Debug mode support, with fully randomized debug ROM - Instruction generation coverage model -- Communication of information to any integrated SV testbench -- Co-simulation with multiple ISS : spike, riscv-ovpsim - -A CSR test generation script written in Python is also provided, to generate a -directed test suite that stresses all CSR instructions on all of the CSRs that -the core implements. - -## External contributions and collaborations - -This repository is still under active development. We hope the RISC-V processor -verification platform development to be a collaborative effort of the RISC-V -community. Free feel to submit issues, feature requests, pull requests through -Github. You can also send your private collaboration request to [riscv_dv_dev@google.com](riscv_dv_dev@google.com). -Please refer to CONTRIBUTING.md for license related questions. +- Handshake communication with testbench +- Support handcoded assembly test +- Co-simulation with multiple ISS : spike, riscv-ovpsim, whisper, sail-riscv ## Getting Started @@ -73,533 +62,18 @@ run --help cov --help ``` -### Setup RISCV-GCC compiler toolchain +## Document -- Install [riscv-gcc](https://github.com/riscv/riscv-gcc) toolchain -- Set environment variable RISCV_GCC to the RISC-V gcc executable - executable. (example: /bin/riscv32-unknown-elf-gcc) -- Set environment variable RISCV_OBJCOPY to RISC-v objcopy executable - executable. (example: /bin/riscv32-unknown-elf-objcopy) +To understand how to setup and customize the generator, please check the full document under docs directory. You can use the makefile to generate the document. [HTML preview](https://htmlpreview.github.io/?https://github.com/google/riscv-dv/blob/master/docs/build/singlehtml/index.html#document-index) -```bash -# Sample .bashrc setup -export RISCV_TOOLCHAIN= -export RISCV_GCC="$RISCV_TOOLCHAIN/bin/riscv32-unknown-elf-gcc" -export RISCV_OBJCOPY="$RISCV_TOOLCHAIN/bin/riscv32-unknown-elf-objcopy" -``` +## External contributions and collaborations -### Setup ISS (instruction set simulator) +This repository is still under active development. We hope the RISC-V processor +verification platform development to be a collaborative effort of the RISC-V +community. Free feel to submit issues, feature requests, pull requests through +Github. You can also send your private collaboration request to [riscv_dv_dev@google.com](riscv_dv_dev@google.com). +Please refer to CONTRIBUTING.md for license related questions. -Currently three ISS are supported, the default ISS is spike. You can install any -one of below to run ISS simulation. - -- [spike](https://github.com/riscv/riscv-isa-sim#) setup - - Follow the [steps](https://github.com/riscv/riscv-isa-sim#build-steps) to build spike - - Build spike with "--enable-commitlog" - - Set environment variable SPIKE_PATH to the directory of the spike binary -- [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim) setup - - Download the riscv-ovpsim binary - - Set environment variable OVPSIM_PATH to the directory of the ovpsim binary -- [whisper(swerv-ISS)](https://github.com/westerndigitalcorporation/swerv-ISS) setup - - Follow the instruction to install the ISS, and set WHISPER_ISS to the - whisper binary -- [sail-riscv](https://github.com/rems-project/sail-riscv) setup - - Follow the [steps](https://github.com/rems-project/sail-riscv/blob/master/README.md) to install sail-riscv - - Set environment variable SAIL_RISCV to the path of sail-riscv binary - -```bash -export SPIKE_PATH=$RISCV_TOOLCHAIN/bin -export SAIL_RISCV="xx/xxx/ocaml_emulator" -export OVPSIM_PATH=/xx/xxx/riscv-ovpsim/bin/Linux64 -export WHISPER_ISS="xx/xxx/swerv-ISS/build-Linux/whisper" -``` - -## Running the generator - -A simple script "run.py" is provided for you to run a single test or a regression. - -You can use --help to get the complete command reference: - -```bash -run --help -``` - -Here is the command to run a single test: - -```bash -run --test=riscv_arithmetic_basic_test -``` -You can specify the simulator by "-simulator" option - -```bash -run --test riscv_arithmetic_basic_test --simulator ius -run --test riscv_arithmetic_basic_test --simulator vcs -run --test riscv_arithmetic_basic_test --simulator questa -run --test riscv_arithmetic_basic_test --simulator dsim -run --test riscv_arithmetic_basic_test --simulator qrun -``` -The complete test list can be found in [yaml/base_testlist.yaml](https://github.com/google/riscv-dv/blob/master/yaml/base_testlist.yaml). To run a full -regression, simply use below command - -```bash -run -``` - -You can also run multiple generator jobs in parallel through LSF - -```bash -run --lsf_cmd="bsub -Is" -``` - -Here's a few more examples of the run command: - -```bash -# Run a single test 10 times -run --test riscv_arithmetic_basic_test --iterations 10 - -# Run multiple tests -run --test riscv_arithmetic_basic_test,riscv_rand_instr_test - -# Run a test with verbose logging -run --test riscv_arithmetic_basic_test --verbose - -# Run a test with a specified seed -run --test riscv_arithmetic_basic_test --seed 123 - -# Skip the generation, run ISS simulation with previously generated program -run --test riscv_arithmetic_basic_test --steps iss_sim - -# Run the generator only, do not compile and simluation with ISS -run --test riscv_arithmetic_basic_test --steps gen - -# Compile the generator only, do not simulate -run --test riscv_arithmetic_basic_test --co - -.... -``` - -### Run ISS simulation - -You can use -iss to run with different ISS. - -```bash -# Run ISS with spike -run --test riscv_arithmetic_basic_test --iss spike - -# Run ISS with riscv-ovpsim -run --test riscv_rand_instr_test --iss ovpsim - -# Run ISS with whisper (swerv-ISS) -run --test riscv_rand_instr_test --iss whisper - -# Run ISS with sail-riscv -run --test riscv_rand_instr_test --iss sail -``` - -To run with ISS simulation for RV32IMC, you can specify ISA and ABI from command -line like this: - -```bash -# Run a full regression with RV32IMC -run --isa rv32imc --mabi ilp32 -``` - -We have added a flow to run ISS simulation with both spike and riscv-ovpsim, -the instruction trace from these runs will be cross compared. This could greatly -speed up your development of new test without the need to simulate against a -real RISC-V processor. - -```bash -run --test=riscv_rand_instr_test --iss=spike,ovpsim -run --test=riscv_rand_instr_test --iss=ovpsim,whisper -run --test=riscv_rand_instr_test --iss=spike,sail -``` -### Run directed assembly tests - -Sometimes it might be useful to run some hand-coded assembly tests to hit some -corner cases: - -```bash -# Run a single/multiple assembly test -run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2/asm_test2.S - -# Run regression with all assembly tests(*.S) under a given directory -run --asm_tests asm_test_path1,asm_test_path2 - -# Run mix between the assembly test and assembly tests under a directory -run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2 -``` - -You could also use this approach to integrate the assembly tests -from other sources to riscv-dv flow. - -## Configuration - -### Configure the generator to match your processor features - -The default configuration of the instruction generator is **RV32IMC** (machine -mode only). A few pre-defined configurations can be found under "target" directory, -you can run with these targets if it matches your processor specification. - -```bash -run # Default target rv32imc -run --target rv32i # rv32i, machine mode only -run --target rv32imc # rv32imc, machine mode only -run --target rv64imc # rv64imc, machine mode only -run --target rv64gc # rv64gc, SV39, M/S/U mode -``` - -If you want to have a custom setting for your processor, you can make a copy of -existing target directory as the template, and modify riscv_core_setting.sv to -match your processor capability. - -```verilog -// Bit width of RISC-V GPR -parameter int XLEN = 64; - -// Parameter for SATP mode, set to BARE if address translation is not supported -parameter satp_mode_t SATP_MODE = SV39; - -// Supported Privileged mode -privileged_mode_t supported_privileged_mode[] = {USER_MODE, - SUPERVISOR_MODE, - MACHINE_MODE}; - -// Unsupported instructions -riscv_instr_name_t unsupported_instr[] = {}; - -// ISA supported by the processor -riscv_instr_group_t supported_isa[] = {RV32I, RV32M, RV64I, RV64M}; - -... -``` - -You can then run the generator with "--custom_target " - -```bash -# You need to manually specify isa and mabi for your custom target -run --custom_target --isa --mabi -... -``` - -### Setup the memory map - -Here's a few cases that you might want to allocate the instruction and data -sections to match the actual memory map -- The processor has internal memories, and you want to test load/store from - various internal/externel memory regions -- The processor implments the PMP feature, and you want to configure the memory - map to match PMP setting. -- Virtual address translation is implmented and you want to test load/store from - sparse memory locations to verify data TLB replacement logic. - -You can configure the memory map in [riscv_instr_gen_config.sv](https://github.com/google/riscv-dv/blob/master/src/riscv_instr_gen_config.sv) - -```verilog - mem_region_t mem_region[$] = '{ - '{name:"region_0", size_in_bytes: 4096, xwr: 3'b111}, - '{name:"region_1", size_in_bytes: 4096 * 4, xwr: 3'b111}, - '{name:"region_2", size_in_bytes: 4096 * 2, xwr: 3'b111}, - '{name:"region_3", size_in_bytes: 512, xwr: 3'b111}, - '{name:"region_4", size_in_bytes: 4096, xwr: 3'b111} - }; -``` - -Each memory region belongs to a separate section in the generated assembly -program. You can modify the link script to link each section to the target -memory location. Please avoid setting a large memory range as it could takes a -long time to randomly initializing the memory. You can break down a large memory -region to a few representative small regions which covers all the boundary -conditions for the load/store testing. - -### Setup regression test list - -[Test list in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml) - -```yaml -# 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 simulation (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 log comparison (Optional) -# compare_opts : Options for the RTL & ISS trace comparison - -- test: riscv_arithmetic_basic_test - description: > - Arithmetic instruction test, no load/store/branch instructions - gen_opts: > - +instr_cnt=10000 - +num_of_sub_program=0 - +no_fence=1 - +no_data_page=1'b1 - +no_branch_jump=1'b1 - +boot_mode=m - iterations: 2 - gen_test: riscv_instr_base_test - rtl_test: core_base_test - -- test: riscv_csr_test - description: > - Stress CSR accesses on all implemented CSRs - iterations: 2 - no_iss: 1 - rtl_test: core_base_test - no_post_compare: 1 - -- test: riscv_directed_asm_test - description: > - Hand-coded assembly test to test corner case - iterations: 1 - asm_tests: - rtl_test: core_base_test - -``` - -Note: To automatically generate CSR stress tests without having to explicitly run the -script, include a test entry `riscv_csr_test` in the testlist as shown in the -example YAML file above. - - -The generation flow now supports inclusion of handcoded assembly tests into the -overall regression. To do this, simply create a YAML entry in the appropriate -testlist as shown above in `riscv_directed_asm_test`, using the `asm_tests` -field to point to the location of the assembly test file or directory. -The run flow will then locate these file(s) and include them into the overall -regression run. These directed test targets can also be run individually from -the python script, as shown below: - -```bash - -# Run directed assembly test 10 times -python3 run.py --test riscv_directed_asm_test --iterations 10 - -``` - -Note: when using the `asm_tests` field to specify some directed/handcoded -assembly tests to the flow, make sure that the `gen_test` field is not defined, -as this will cause the flow to throw an error. - - -### Runtime options of the generator - -| Option | Description | Default | -|:---------------------------:|:-------------------------------------------------:|:-------:| -| num_of_tests | Number of assembly tests to be generated | 1 | -| num_of_sub_program | Number of sub-program in one test | 5 | -| instr_cnt | Instruction count per test | 200 | -| enable_page_table_exception | Enable page table exception | 0 | -| enable_unaligned_load_store | Enable unaligned memory operations | 0 | -| no_ebreak | Disable ebreak instruction | 1 | -| no_wfi | Disable WFI instruction | 1 | -| no_dret | Disable dret instruction | 1 | -| no_branch_jump | Disable branch/jump instruction | 0 | -| no_load_store | Disable load/store instruction | 0 | -| no_csr_instr | Disable CSR instruction | 0 | -| no_fence | Disable fence instruction | 0 | -| illegal_instr_ratio | Number of illegal instructions every 1000 instr | 0 | -| hint_instr_ratio | Number of HINT instructions every 1000 instr | 0 | -| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode | m | -| no_directed_instr | Disable directed instruction stream | 0 | -| require_signature_addr | Set to 1 if test needs to talk to testbench | 0 | -| signature_addr | Write to this addr to send data to testbench | 0 | -| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 | -| gen_debug_section | Disables randomized debug_rom section | 0 | -| num_debug_sub_program | Number of debug sub-programs in test | 0 | -| enable_ebreak_in_debug_rom | Generate ebreak instructions inside debug ROM | 0 | -| set_dcsr_ebreak | Randomly enable dcsr.ebreak(m/s/u) | 0 | -| randomize_csr | Fully randomize main CSRs (xSTATUS, xIE) | 0 | - - -### Setup Privileged CSR description (optional) - -This YAML description file of all CSRs is only required for the privileged CSR -test. All other standard tests do not use this description. - -[CSR descriptions in YAML -format](https://github.com/google/riscv-dv/blob/master/yaml/csr_template.yaml) - -```yaml -- csr: CSR_NAME - description: > - BRIEF_DESCRIPTION - address: 0x### - privilege_mode: MODE (D/M/S/H/U) - rv32: - - MSB_FIELD_NAME: - - description: > - BRIEF_DESCRIPTION - - type: TYPE (WPRI/WLRL/WARL/R) - - reset_val: RESET_VAL - - msb: MSB_POS - - lsb: LSB_POS - - ... - - ... - - LSB_FIELD_NAME: - - description: ... - - type: ... - - ... - rv64: - - MSB_FIELD_NAME: - - description: > - BRIEF_DESCRIPTION - - type: TYPE (WPRI/WLRL/WARL/R) - - reset_val: RESET_VAL - - msb: MSB_POS - - lsb: LSB_POS - - ... - - ... - - LSB_FIELD_NAME: - - description: ... - - type: ... - - ... -``` - -To specify what ISA width should be generated in the test, simply include the -matching rv32/rv64/rv128 entry and fill in the appropriate CSR field entries. - -### Privileged CSR Test Generation (optional) - -The CSR generation script is located at -[scripts/gen_csr_test.py](https://github.com/google/riscv-dv/blob/master/scripts/gen_csr_test.py). -The CSR test code that this script generates will execute every CSR instruction -on every processor implemented CSR, writing values to the CSR and then using a -prediction function to calculate a reference value that will be written into -another GPR. The reference value will then be compared to the value actually -stored in the CSR to determine whether to jump to the failure condition or -continue executing, allowing it to be completely self checking. This script has -been integrated with run.py. If you want to run it separately, you can get the -command reference with --help: - -```bash -python3 scripts/gen_csr_test.py --help -``` - -### Adding new instruction stream and test - -Please refer to src/src/riscv_load_store_instr_lib.sv for an example on how to -add a new instruction stream. -After the new instruction stream is created, you can use a runtime option to mix -it with random instructions - -```bash -//+directed_instr_n=instr_sequence_name,frequency(number of insertions per 1000 instructions) -+directed_instr_5=riscv_multi_page_load_store_instr_stream,4 - -// An alternative command line options for directed instruction stream -+stream_name_0=riscv_multi_page_load_store_instr_stream -+stream_freq_0=4 -``` - -## Integrate a new ISS - -You can add a new entry in [iss.yaml](https://github.com/google/riscv-dv/blob/master/yaml/iss.yaml) - -```yaml -- iss: new_iss_name - path_var: ISS_PATH - cmd: > - /iss_executable --isa= -l -``` - -Simulate with the new ISS - -```bash -run --test riscv_arithmetic_basic_test --iss new_iss_name -``` - -## End-to-end RTL and ISS co-simulation flow - -We have collaborated with LowRISC to apply this flow for [IBEX RISC-V core -verification](https://github.com/lowRISC/ibex/blob/master/doc/verification.rst). You can use -it as a reference to setup end-to-end co-simulation flow. -This repo is still under active development, this is the recommended approach to -customize the instruction generator while keeping the effort of merging -upstream changes to a minimum. -- Do not modify the upstream classes directly. When possible, extend from - the upstream classses and implement your own functionalities. -- Add your extensions under user_extension directory, and add the files to - user_extension/user_extension.svh. If you prefer to put your extensions in a - different directory, you can use "-ext " to override the - user extension path. -- Create a new target directory and customize the setting and testlist -- Run the generator with `--custom_target --isa --mabi ` -- Use command line type override to use your extended classes. - `--sim_opts="+uvm_set_type_override=,"` -- If extending `riscv_asm_program_gen` class is desired, must use this command - line override: - `--sim_opts="+uvm_set_inst_override=riscv_asm_program_gen,,'uvm_test_top.asm_gen'"` - -You can refer to [riscv-dv extension for ibex](https://github.com/lowRISC/ibex/blob/master/dv/uvm/Makefile#L68) for a working example. - -We have plan to open-source the end-to-end environments of other advanced RISC-V -processors. Stay tuned! - -## Handshaking Mechanism - -This mechanism allows the generator to generate small, directed sequences of -instructions that write critical information to a specified address in memory, -that the testbench monitors for write accesses to. -This allows for more in-depth verification of scenarios that involve external -stimulus to the core, such as interrupts and debug requests. - -For more information, detailed documentation of this mechanism can be found in -[HANDSHAKE.md](./HANDSHAKE.md). - -## Functional coverage (work in progress) - -This flow extracts functional coverage information from the -instruction trace generated by ISS. It's independent of the instruction generation -flow and does not require a tracer implementation in the RTL. You can use this -flow as long as your program can be run with an ISS supported in this flow. The -flow parses the instruction trace log and converts it to a CSV trace format. After -that, a SV test is run to process the CSV trace files and sample functional -coverage from there. - -The functional covergroup is defined in [riscv_instr_cover_group.sv](https://github.com/google/riscv-dv/blob/master/src/riscv_instr_cover_group.sv). It includes below major categories: -- Cover all operands for each instruction -- Hazard conditions -- Corner cases like overflow, underflow, divide by zero -- Aligned/unaligned load/store -- Positive/negative immediate value -- Forward/backward branches, branch hit history -- Hint instruction -- Illegal instruction -- All compressed and non-compressed opcode -- Access to all implemened privileged CSR -- Exception and interrupt - -The functional covergroup is still under active development. Please feel free to -add anything you are interested or file a bug for any feature request. - -Before start, please check the you have modified [riscv_core_setting.sv](https://github.com/google/riscv-dv/blob/master/setting/riscv_core_setting.sv) to reflect your processor capabilities. The covergroup is selectively instantiated based on this setting so that you don't need to deal with excluding unrelated coverpoints later. You also need to get the Spike ISS or riscvOVPsim ISS (riscv-ovpsim) setup before running this flow. - - -```bash -# Process spike simulation log and collect functional coverage -cov --dir out/spike_sim - -# Get the command reference -cov --help - -# Run the coverage flow with predefined targets -cov --dir out/spike_sim --target rv32imc -``` - -The coverage sampling from the CSV could be time consuming if you have a large -number of log to process. You can split them to small batches and run with LSF -in parallel. - -``` -# Split the run to process 5 CSV at a time, and run with LSF -cov --dir out/spike_sim --lsf_cmd "bsub ....." -bz 5 -``` ## Supporting model Please file an issue under this repository for any bug report / integration diff --git a/vendor/google_riscv-dv/cov.py b/vendor/google_riscv-dv/cov.py index ab44e1e9..b49178bc 100644 --- a/vendor/google_riscv-dv/cov.py +++ b/vendor/google_riscv-dv/cov.py @@ -53,7 +53,7 @@ def build_cov(out, cfg, cwd, opts_vec, opts_cov): build_cmd += (" --custom_target %s" % argv.custom_target) if argv.stop_on_first_error: build_cmd += (" --stop_on_first_error") - run_cmd(build_cmd) + run_cmd(build_cmd, debug_cmd = argv.debug) def sim_cov(out, cfg, cwd, opts_vec, opts_cov, csv_list): """Simulation the coverage collection @@ -101,7 +101,7 @@ def sim_cov(out, cfg, cwd, opts_vec, opts_cov, csv_list): sim_cmd += (" --log_suffix _%d" % file_idx) if argv.lsf_cmd == "": logging.info("Processing batch %0d/%0d" % (file_idx+1, batch_cnt)) - run_cmd(sim_cmd) + run_cmd(sim_cmd, debug_cmd = argv.debug) else: sim_cmd += (" --lsf_cmd \"%s\"" % argv.lsf_cmd) sim_cmd_list.append(sim_cmd) @@ -127,8 +127,9 @@ def collect_cov(out, cfg, cwd): sys.exit(RET_FAIL) logging.info("Processing trace log under %s" % argv.dir) if not os.path.isdir(argv.dir) or not os.listdir(argv.dir): - logging.error("Cannot find %s directory, or it is empty", argv.dir) - sys.exit(RET_FAIL) + if not argv.debug: + logging.error("Cannot find %s directory, or it is empty", argv.dir) + sys.exit(RET_FAIL) if argv.core: """ If functional coverage is being collected from an RTL core implementation, @@ -239,6 +240,8 @@ def setup_parser(): help="Controlling coverage coverpoints") parser.add_argument("--exp", action="store_true", default=False, help="Run generator with experimental features") + parser.add_argument("-d", "--debug", type=str, default="", + help="Generate debug command log file") return parser def load_config(args, cwd): @@ -250,6 +253,8 @@ def load_config(args, cwd): Returns: Loaded configuration dictionary. """ + if args.debug: + args.debug = open(args.debug, "w") if args.verbose: args.opts += "-v" diff --git a/vendor/google_riscv-dv/docs/make.bat b/vendor/google_riscv-dv/docs/make.bat index 6247f7e2..2f8439d1 100644 --- a/vendor/google_riscv-dv/docs/make.bat +++ b/vendor/google_riscv-dv/docs/make.bat @@ -9,6 +9,7 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR=source set BUILDDIR=build +set SPHINXOPTS="-html_theme classic" if "%1" == "" goto help diff --git a/vendor/google_riscv-dv/docs/source/appendix.rst b/vendor/google_riscv-dv/docs/source/appendix.rst new file mode 100644 index 00000000..6d6028e6 --- /dev/null +++ b/vendor/google_riscv-dv/docs/source/appendix.rst @@ -0,0 +1,49 @@ +Appendix +======== + +Trace CSV format +---------------- + +A standard CSV format is defined for the instruction execution trace. It's used for co-simulation result comparison and functional coverage collection. + +.. image:: trace_csv.png + +**The CSV format includes the following fields:** + +- pc : Program counter (instruction memory address) +- instr: Instruction name +- gpr: General purpose register updated by the instruction (rd, fd, vd etc.) + + - Format: : + - GPR can be any integer/floating point/vector register + - If more than one general purpose registers are updated, separate them with semicolon +- csr: Privileged CSR updated by the instruction + + - The same format as the GPR field +- binary: Instruction binary +- instr_str: Instruction in assmebly format +- operand: Instruction operands +- pad: Unused + +**Here's a sample of the CSV trace file:** + +.. code-block:: verilog + + pc,instr,gpr,csr,binary,mode,instr_str,operand,pad + ffffffff8000000c,c.addi,ra:daab700e,,000000b9,3,"c.addi ra, 14","ra,14", + ffffffff8000000e,lui,sp:ff8e6000,,ff8e6137,3,"lui sp, 0xff8e6","sp,0xff8e6", + ffffffff80000012,addi,sp:ff8e6541,,54110113,3,"addi sp, sp, 1345","sp,sp,1345", + ffffffff80000016,c.li,gp:00000000,,00004181,3,"c.li gp, 0","gp,0", + ffffffff80000018,lui,tp:80000000,,80000237,3,"lui tp, 0x80000","tp,0x80000", + ffffffff8000001c,lui,t0:f999d000,,f999d2b7,3,"lui t0, 0xf999d","t0,0xf999d", + ffffffff80000020,addi,t0:f999cbf0,,bf028293,3,"addi t0, t0, -1040","t0,t0,-1040", + ffffffff80000024,lui,t1:0416b000,,0416b337,3,"lui t1, 0x416b","t1,0x416b", + ffffffff80000028,addi,t1:0416b6ee,,6ee30313,3,"addi t1, t1, 1774","t1,t1,1774", + ffffffff8000002c,lui,t2:e6420000,,e64203b7,3,"lui t2, 0xe6420","t2,0xe6420", + ... + +To integrate a new ISS or processor with the co-simualtion or coverage flow, user must implement a +python script to convert the custom trace log format to this CSV format. You can find a sample +script `here`_. + +.. _here: https://github.com/google/riscv-dv/blob/master/scripts/spike_log_to_trace_csv.py diff --git a/vendor/google_riscv-dv/docs/source/conf.py b/vendor/google_riscv-dv/docs/source/conf.py index ec91d3eb..f2711670 100644 --- a/vendor/google_riscv-dv/docs/source/conf.py +++ b/vendor/google_riscv-dv/docs/source/conf.py @@ -14,6 +14,7 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) from pallets_sphinx_themes import ProjectLink +import sphinx_rtd_theme # -- Project information ----------------------------------------------------- @@ -35,6 +36,7 @@ extensions = [ "sphinxcontrib.log_cabinet", "sphinx_issues", "rst2pdf.pdfbuilder", + 'sphinx_rtd_theme', ] # Add any paths that contain templates here, relative to this directory. @@ -51,20 +53,20 @@ exclude_patterns = [] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "jinja" -html_theme_options = {"index_sidebar_logo": False} - -html_context = { - "project_links": [ - ProjectLink("Source Code", "https://github.com/google/riscv-dv.git"), - ProjectLink("Issue Tracker", "https://github.com/google/riscv-dv/issues"), - ] -} - -html_sidebars = { - "index": ["project.html", "localtoc.html", "searchbox.html"], - "**": ["localtoc.html", "relations.html", "searchbox.html"], -} +html_theme = "sphinx_rtd_theme" +#html_theme_options = {"index_sidebar_logo": False} +# +#html_context = { +# "project_links": [ +# ProjectLink("Source Code", "https://github.com/google/riscv-dv.git"), +# ProjectLink("Issue Tracker", "https://github.com/google/riscv-dv/issues"), +# ] +#} +# +#html_sidebars = { +# "index": ["project.html", "localtoc.html", "searchbox.html"], +# "**": ["localtoc.html", "relations.html", "searchbox.html"], +#} # -- For PDF output --------------------------------------------------------- pdf_documents = [('index', u'riscv-dv', u'RISCV-DV', u'Google, Inc'),] diff --git a/vendor/google_riscv-dv/docs/source/configuration.rst b/vendor/google_riscv-dv/docs/source/configuration.rst index 1cd3038b..3c4e481d 100644 --- a/vendor/google_riscv-dv/docs/source/configuration.rst +++ b/vendor/google_riscv-dv/docs/source/configuration.rst @@ -108,7 +108,7 @@ Test list in `YAML format`_ gen_test: riscv_instr_base_test rtl_test: core_base_test -.. _YAML format: https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml +.. _YAML format: https://github.com/google/riscv-dv/blob/master/yaml/base_testlist.yaml .. note:: To automatically generate CSR tests without having to explicitly run the script, include `riscv_csr_test` in the testlist as shown in the example YAML diff --git a/vendor/google_riscv-dv/docs/source/customize_extend_generator.rst b/vendor/google_riscv-dv/docs/source/customize_extend_generator.rst index 7bd3a4fb..59e846ac 100644 --- a/vendor/google_riscv-dv/docs/source/customize_extend_generator.rst +++ b/vendor/google_riscv-dv/docs/source/customize_extend_generator.rst @@ -1,2 +1,29 @@ Customize and Extend Generator ============================== + +Add custom instructions +----------------------- + +1. Add the new instruction enum to `riscv_custom_instr_enum.sv`_ + +.. code-block:: verilog + + CUSTOM_ADD, + CUSTOM_SUB, + ... + +2. Add custom instruction definition to `rv32x_instr.sv`_/`rv64x_instr.sv`_ + +.. code-block:: verilog + + `DEFINE_CUSTOM_INSTR(CUSTOM_ADD, R_FORMAT, ARITHMETIC, RV32X) + `DEFINE_CUSTOM_INSTR(CUSTOM_SUB, R_FORMAT, ARITHMETIC, RV32X) + ... + +3. Extend `riscv_custom_instr.sv`_ and implement key functions like get_instr_name, convert2asm +4. Add RV32X/RV64X to supported_isa in riscv_core_setting.sv + +.. _riscv_custom_instr_enum.sv: https://github.com/google/riscv-dv/blob/master/src/isa/custom/riscv_custom_instr_enum.sv +.. _riscv_custom_instr.sv: https://github.com/google/riscv-dv/blob/master/src/isa/custom/riscv_custom_instr.sv +.. _rv32x_instr.sv: https://github.com/google/riscv-dv/blob/master/src/isa/custom/rv32x_instr.sv +.. _rv64x_instr.sv: https://github.com/google/riscv-dv/blob/master/src/isa/custom/rv64x_instr.sv diff --git a/vendor/google_riscv-dv/docs/source/index.rst b/vendor/google_riscv-dv/docs/source/index.rst index 332fb6c1..1a9dc612 100644 --- a/vendor/google_riscv-dv/docs/source/index.rst +++ b/vendor/google_riscv-dv/docs/source/index.rst @@ -19,6 +19,7 @@ Welcome to riscv-dv's documentation! customize_extend_generator class_reference cmd_line_reference + appendix diff --git a/vendor/google_riscv-dv/docs/source/trace_csv.png b/vendor/google_riscv-dv/docs/source/trace_csv.png new file mode 100644 index 00000000..f694a96d Binary files /dev/null and b/vendor/google_riscv-dv/docs/source/trace_csv.png differ diff --git a/vendor/google_riscv-dv/requirements.txt b/vendor/google_riscv-dv/requirements.txt index 57100e4c..e616e982 100644 --- a/vendor/google_riscv-dv/requirements.txt +++ b/vendor/google_riscv-dv/requirements.txt @@ -4,4 +4,5 @@ Sphinx Pallets-Sphinx-Themes sphinxcontrib-log-cabinet sphinx-issues +sphinx_rtd_theme rst2pdf diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index b5c0c91b..8cc6fb4f 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -33,7 +33,7 @@ from types import SimpleNamespace LOGGER = logging.getLogger() -def get_generator_cmd(simulator, simulator_yaml, cov, exp): +def get_generator_cmd(simulator, simulator_yaml, cov, exp, debug_cmd): """ Setup the compile and simulation command for the generator Args: @@ -41,6 +41,7 @@ def get_generator_cmd(simulator, simulator_yaml, cov, exp): simulator_yaml : RTL simulator configuration file in YAML format cov : Enable functional coverage exp : Use experimental version + debug_cmd : Produce the debug cmd log without running Returns: compile_cmd : RTL simulator command to compile the instruction generator @@ -69,14 +70,15 @@ def get_generator_cmd(simulator, simulator_yaml, cov, exp): if 'env_var' in entry: for env_var in entry['env_var'].split(','): for i in range(len(compile_cmd)): - compile_cmd[i] = re.sub("<"+env_var+">", get_env_var(env_var), compile_cmd[i]) - sim_cmd = re.sub("<"+env_var+">", get_env_var(env_var), sim_cmd) + compile_cmd[i] = re.sub("<"+env_var+">", get_env_var(env_var, debug_cmd = debug_cmd), + compile_cmd[i]) + sim_cmd = re.sub("<"+env_var+">", get_env_var(env_var, debug_cmd = debug_cmd), sim_cmd) return compile_cmd, sim_cmd logging.error("Cannot find RTL simulator %0s" % simulator) sys.exit(RET_FAIL) -def parse_iss_yaml(iss, iss_yaml, isa, setting_dir): +def parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd): """Parse ISS YAML to get the simulation command Args: @@ -84,6 +86,7 @@ def parse_iss_yaml(iss, iss_yaml, isa, setting_dir): iss_yaml : ISS configuration file in YAML format isa : ISA variant passed to the ISS setting_dir : Generator setting directory + debug_cmd : Produce the debug cmd log without running Returns: cmd : ISS run command @@ -95,7 +98,7 @@ def parse_iss_yaml(iss, iss_yaml, isa, setting_dir): if entry['iss'] == iss: logging.info("Found matching ISS: %s" % entry['iss']) cmd = entry['cmd'].rstrip() - cmd = re.sub("\", get_env_var(entry['path_var']), cmd) + cmd = re.sub("\", get_env_var(entry['path_var'], debug_cmd = debug_cmd), cmd) m = re.search(r"rv(?P[0-9]+?)(?P[a-z]+?)$", isa) if m: cmd = re.sub("\", m.group('xlen'), cmd) @@ -130,7 +133,8 @@ def get_iss_cmd(base_cmd, elf, log): cmd += (" &> %s" % log) return cmd -def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmp_opts, output_dir): +def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, + cmp_opts, output_dir, debug_cmd): """Compile the instruction generator Args: @@ -141,6 +145,7 @@ def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmp_opts, ext_dir : User extension directory cmd_opts : Compile options for the generator output_dir : Output directory of the ELF files + debug_cmd : Produce the debug cmd log without running """ if (not((len(test_list) == 1) and (test_list[0]['test'] == 'riscv_csr_test'))): logging.info("Building RISC-V instruction generator") @@ -155,10 +160,10 @@ def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmp_opts, cmd = re.sub("", cmp_opts, cmd) logging.debug("Compile command: %s" % cmd) - run_cmd(cmd) + run_cmd(cmd, debug_cmd = debug_cmd) def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, - end_signature_addr, timeout_s, output_dir): + end_signature_addr, timeout_s, output_dir, debug_cmd): """Run CSR test It calls a separate python script to generate directed CSR test code, located at scripts/gen_csr_test.py. @@ -172,11 +177,11 @@ def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, if lsf_cmd: cmd_list.append(cmd) else: - run_cmd(cmd, timeout_s) + run_cmd(cmd, timeout_s, debug_cmd = debug_cmd) def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, isa, end_signature_addr, lsf_cmd, timeout_s, log_suffix, - batch_size, output_dir, verbose, check_return_code): + batch_size, output_dir, verbose, check_return_code, debug_cmd): """Run the instruction generator Args: @@ -195,6 +200,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, batch_size : Number of tests to generate per run output_dir : Output directory of the ELF files check_return_code : Check return code of the command + debug_cmd : Produce the debug cmd log without running """ cmd_list = [] sim_cmd = re.sub("", os.path.abspath(output_dir), sim_cmd) @@ -212,7 +218,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, # Running a CSR test if test['test'] == 'riscv_csr_test': run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, - end_signature_addr, timeout_s, output_dir) + end_signature_addr, timeout_s, output_dir, debug_cmd) else: batch_cnt = 1 if batch_size > 0: @@ -247,12 +253,13 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, else: logging.info("Running %s, batch %0d/%0d, test_cnt:%0d" % (test['test'], i+1, batch_cnt, test_cnt)) - run_cmd(cmd, timeout_s, check_return_code = check_return_code) + run_cmd(cmd, timeout_s, check_return_code = check_return_code, debug_cmd = debug_cmd) if sim_seed: with open(('%s/seed.yaml' % os.path.abspath(output_dir)) , 'w') as outfile: yaml.dump(sim_seed, outfile, default_flow_style=False) if lsf_cmd: - run_parallel_cmd(cmd_list, timeout_s, check_return_code = check_return_code) + run_parallel_cmd(cmd_list, timeout_s, check_return_code = check_return_code, + debug_cmd = debug_cmd) def gen(test_list, cfg, output_dir, cwd): @@ -281,19 +288,20 @@ def gen(test_list, cfg, output_dir, cwd): # Setup the compile and simulation command for the generator compile_cmd = [] sim_cmd = "" - compile_cmd, sim_cmd = get_generator_cmd(argv.simulator, argv.simulator_yaml, argv.cov, argv.exp); + compile_cmd, sim_cmd = get_generator_cmd(argv.simulator, argv.simulator_yaml, argv.cov, + argv.exp, argv.debug); # Compile the instruction generator if not argv.so: do_compile(compile_cmd, test_list, argv.core_setting_dir, cwd, argv.user_extension_dir, - argv.cmp_opts, output_dir) + argv.cmp_opts, output_dir, argv.debug) # Run the instruction generator if not argv.co: do_simulate(sim_cmd, test_list, cwd, argv.sim_opts, argv.seed_yaml, argv.seed, argv.csr_yaml, argv.isa, argv.end_signature_addr, argv.lsf_cmd, argv.gen_timeout, argv.log_suffix, - argv.batch_size, output_dir, argv.verbose, check_return_code) + argv.batch_size, output_dir, argv.verbose, check_return_code, argv.debug) -def gcc_compile(test_list, output_dir, isa, mabi, opts): +def gcc_compile(test_list, output_dir, isa, mabi, opts, debug_cmd): """Use riscv gcc toolchain to compile the assembly program Args: @@ -301,6 +309,7 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): output_dir : Output directory of the ELF files isa : ISA variant passed to GCC mabi : MABI variant passed to GCC + debug_cmd : Produce the debug cmd log without running """ cwd = os.path.dirname(os.path.realpath(__file__)) for test in test_list: @@ -312,7 +321,7 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): elf = prefix + ".o" binary = prefix + ".bin" test_isa = isa - if not os.path.isfile(asm): + if not os.path.isfile(asm) and not debug_cmd: logging.error("Cannot find assembly test: %s\n", asm) sys.exit(RET_FAIL) # gcc comilation @@ -321,7 +330,7 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): -nostartfiles %s \ -I%s/user_extension \ -T%s/scripts/link.ld %s -o %s " % \ - (get_env_var("RISCV_GCC"), asm, cwd, cwd, opts, elf)) + (get_env_var("RISCV_GCC", debug_cmd = debug_cmd), asm, cwd, cwd, opts, elf)) if 'gcc_opts' in test: cmd += test['gcc_opts'] if 'gen_opts' in test: @@ -335,15 +344,16 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): if not re.search('mabi', cmd): cmd += (" -mabi=%s" % mabi) logging.info("Compiling %s" % asm) - run_cmd_output(cmd.split()) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) # Convert the ELF to plain binary, used in RTL sim logging.info("Converting to %s" % binary) - cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY"), elf, binary)) - run_cmd_output(cmd.split()) + cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY", debug_cmd = debug_cmd), + elf, binary)) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) def run_assembly(asm_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, - setting_dir): + setting_dir, debug_cmd): """Run a directed assembly test with ISS Args: @@ -355,6 +365,7 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, iss_opts : Instruction set simulators output_dir : Output directory of compiled test files setting_dir : Generator setting directory + debug_cmd : Produce the debug cmd log without running """ if not asm_test.endswith(".S"): logging.error("%s is not an assembly .S file" % asm_test) @@ -377,30 +388,31 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, -nostartfiles %s \ -I%s/user_extension \ -T%s/scripts/link.ld %s -o %s " % \ - (get_env_var("RISCV_GCC"), asm_test, cwd, cwd, gcc_opts, elf)) + (get_env_var("RISCV_GCC", debug_cmd = debug_cmd), asm_test, cwd, + cwd, gcc_opts, elf)) cmd += (" -march=%s" % isa) cmd += (" -mabi=%s" % mabi) - run_cmd_output(cmd.split()) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) # Convert the ELF to plain binary, used in RTL sim logging.info("Converting to %s" % binary) - cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY"), elf, binary)) - run_cmd_output(cmd.split()) + cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY", debug_cmd = debug_cmd), elf, binary)) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) log_list = [] # ISS simulation for iss in iss_list: run_cmd("mkdir -p %s/%s_sim" % (output_dir, iss)) log = ("%s/%s_sim/%s.log" % (output_dir, iss, asm)) log_list.append(log) - base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir) + base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd) logging.info("[%0s] Running ISS simulation: %s" % (iss, elf)) cmd = get_iss_cmd(base_cmd, elf, log) - run_cmd(cmd, 10) + run_cmd(cmd, 10, debug_cmd = debug_cmd) logging.info("[%0s] Running ISS simulation: %s ...done" % (iss, elf)) if len(iss_list) == 2: compare_iss_log(iss_list, log_list, report) def run_assembly_from_dir(asm_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, - output_dir, setting_dir): + output_dir, setting_dir, debug_cmd): """Run a directed assembly test from a directory with spike Args: @@ -412,6 +424,7 @@ def run_assembly_from_dir(asm_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, iss : Instruction set simulators output_dir : Output directory of compiled test files setting_dir : Generator setting directory + debug_cmd : Produce the debug cmd log without running """ result = run_cmd("find %s -name \"*.S\"" % asm_test_dir) if result: @@ -420,14 +433,102 @@ def run_assembly_from_dir(asm_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, (len(asm_list), asm_test_dir)) for asm_file in asm_list: run_assembly(asm_file, iss_yaml, isa, mabi, gcc_opts, iss, output_dir, - setting_dir) + setting_dir, debug_cmd) if "," in iss: report = ("%s/iss_regr.log" % output_dir).rstrip() save_regr_report(report) else: logging.error("No assembly test(*.S) found under %s" % asm_test_dir) -def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, setting_dir, timeout_s): +def run_c(c_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, + setting_dir, debug_cmd): + """Run a directed c test with ISS + + Args: + c_test : C test file + iss_yaml : ISS configuration file in YAML format + isa : ISA variant passed to the ISS + mabi : MABI variant passed to GCC + gcc_opts : User-defined options for GCC compilation + iss_opts : Instruction set simulators + output_dir : Output directory of compiled test files + setting_dir : Generator setting directory + debug_cmd : Produce the debug cmd log without running + """ + if not c_test.endswith(".c"): + logging.error("%s is not a .c file" % c_test) + return + cwd = os.path.dirname(os.path.realpath(__file__)) + c_test = os.path.expanduser(c_test) + report = ("%s/iss_regr.log" % output_dir).rstrip() + c = re.sub(r"^.*\/", "", c_test) + c = re.sub(r"\.c$", "", c) + prefix = ("%s/directed_c_tests/%s" % (output_dir, c)) + elf = prefix + ".o" + binary = prefix + ".bin" + iss_list = iss_opts.split(",") + run_cmd("mkdir -p %s/directed_c_tests" % output_dir) + logging.info("Compiling c test : %s" % c_test) + + # gcc compilation + cmd = ("%s -mcmodel=medany -nostdlib \ + -nostartfiles %s \ + -I%s/user_extension \ + -T%s/scripts/link.ld %s -o %s " % \ + (get_env_var("RISCV_GCC", debug_cmd = debug_cmd), c_test, cwd, + cwd, gcc_opts, elf)) + cmd += (" -march=%s" % isa) + cmd += (" -mabi=%s" % mabi) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) + # Convert the ELF to plain binary, used in RTL sim + logging.info("Converting to %s" % binary) + cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY", debug_cmd = debug_cmd), elf, binary)) + run_cmd_output(cmd.split(), debug_cmd = debug_cmd) + log_list = [] + # ISS simulation + for iss in iss_list: + run_cmd("mkdir -p %s/%s_sim" % (output_dir, iss)) + log = ("%s/%s_sim/%s.log" % (output_dir, iss, c)) + log_list.append(log) + base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd) + logging.info("[%0s] Running ISS simulation: %s" % (iss, elf)) + cmd = get_iss_cmd(base_cmd, elf, log) + run_cmd(cmd, 10, debug_cmd = debug_cmd) + logging.info("[%0s] Running ISS simulation: %s ...done" % (iss, elf)) + if len(iss_list) == 2: + compare_iss_log(iss_list, log_list, report) + +def run_c_from_dir(c_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, + output_dir, setting_dir, debug_cmd): + """Run a directed assembly test from a directory with spike + + Args: + c_test_dir : C test file directory + iss_yaml : ISS configuration file in YAML format + isa : ISA variant passed to the ISS + mabi : MABI variant passed to GCC + gcc_opts : User-defined options for GCC compilation + iss : Instruction set simulators + output_dir : Output directory of compiled test files + setting_dir : Generator setting directory + debug_cmd : Produce the debug cmd log without running + """ + result = run_cmd("find %s -name \"*.c\"" % c_test_dir) + if result: + c_list = result.splitlines() + logging.info("Found %0d c tests under %s" % + (len(c_list), c_test_dir)) + for c_file in c_list: + run_c(c_file, iss_yaml, isa, mabi, gcc_opts, iss, output_dir, + setting_dir, debug_cmd) + if "," in iss: + report = ("%s/iss_regr.log" % output_dir).rstrip() + save_regr_report(report) + else: + logging.error("No c test(*.c) found under %s" % c_test_dir) + +def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, + setting_dir, timeout_s, debug_cmd): """Run ISS simulation with the generated test program Args: @@ -438,10 +539,11 @@ def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, setting_dir, timeout isa : ISA variant passed to the ISS setting_dir : Generator setting directory timeout_s : Timeout limit in seconds + debug_cmd : Produce the debug cmd log without running """ for iss in iss_list.split(","): log_dir = ("%s/%s_sim" % (output_dir, iss)) - base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir) + base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd) logging.info("%s sim log dir: %s" % (iss, log_dir)) run_cmd_output(["mkdir", "-p", log_dir]) for test in test_list: @@ -455,13 +557,13 @@ def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, setting_dir, timeout cmd = get_iss_cmd(base_cmd, elf, log) logging.info("Running %s sim: %s" % (iss, elf)) if iss == "ovpsim": - run_cmd(cmd, timeout_s, check_return_code=False) + run_cmd(cmd, timeout_s, check_return_code=False, debug_cmd = debug_cmd) else: - run_cmd(cmd, timeout_s) + run_cmd(cmd, timeout_s, debug_cmd = debug_cmd) logging.debug(cmd) -def iss_cmp(test_list, iss, output_dir, stop_on_first_error, exp): +def iss_cmp(test_list, iss, output_dir, stop_on_first_error, exp, debug_cmd): """Compare ISS simulation reult Args: @@ -470,7 +572,10 @@ def iss_cmp(test_list, iss, output_dir, stop_on_first_error, exp): output_dir : Output directory of the ELF files stop_on_first_error : will end run on first error detected exp : Use experimental version + debug_cmd : Produce the debug cmd log without running """ + if debug_cmd: + return iss_list = iss.split(",") if len(iss_list) != 2: return @@ -593,6 +698,8 @@ def setup_parser(): help="Path for the user extension directory") parser.add_argument("--asm_tests", type=str, default="", help="Directed assembly tests") + parser.add_argument("--c_tests", type=str, default="", + help="Directed c tests") parser.add_argument("--log_suffix", type=str, default="", help="Simulation log name suffix") parser.add_argument("--exp", action="store_true", default=False, @@ -605,6 +712,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("-d", "--debug", type=str, default="", + help="Generate debug command log file") return parser def load_config(args, cwd): @@ -615,6 +724,8 @@ def load_config(args, cwd): Returns: Loaded configuration dictionary. """ + if args.debug: + args.debug = open(args.debug, "w") if not args.csr_yaml: args.csr_yaml = cwd + "/yaml/csr_template.yaml" @@ -687,11 +798,31 @@ def main(): # path_asm_test is a directory if os.path.isdir(full_path): run_assembly_from_dir(full_path, args.iss_yaml, args.isa, args.mabi, - args.gcc_opts, args.iss, output_dir, args.core_setting_dir) + args.gcc_opts, args.iss, output_dir, + args.core_setting_dir, args.debug) # path_asm_test is an assembly file - elif os.path.isfile(full_path): + elif os.path.isfile(full_path) or args.debug: run_assembly(full_path, args.iss_yaml, args.isa, args.mabi, args.gcc_opts, - args.iss, output_dir, args.core_setting_dir) + args.iss, output_dir, args.core_setting_dir, args.debug) + else: + logging.error('%s does not exist' % full_path) + sys.exit(RET_FAIL) + return + + # Run any handcoded/directed c tests specified by args.c_tests + if args.c_tests != "": + c_test = args.c_tests.split(',') + for path_c_test in c_test: + full_path = os.path.expanduser(path_c_test) + # path_c_test is a directory + if os.path.isdir(full_path): + run_c_from_dir(full_path, args.iss_yaml, args.isa, args.mabi, + args.gcc_opts, args.iss, output_dir, + args.core_setting_dir, args.debug) + # path_c_test is a c file + elif os.path.isfile(full_path) or args.debug: + run_c(full_path, args.iss_yaml, args.isa, args.mabi, args.gcc_opts, + args.iss, output_dir, args.core_setting_dir, args.debug) else: logging.error('%s does not exist' % full_path) sys.exit(RET_FAIL) @@ -729,30 +860,34 @@ def main(): # path_asm_test is a directory if os.path.isdir(path_asm_test): run_assembly_from_dir(path_asm_test, args.iss_yaml, args.isa, args.mabi, - gcc_opts, args.iss, output_dir, args.core_setting_dir) + gcc_opts, args.iss, output_dir, + args.core_setting_dir, args.debug) # path_asm_test is an assembly file elif os.path.isfile(path_asm_test): run_assembly(path_asm_test, args.iss_yaml, args.isa, args.mabi, gcc_opts, - args.iss, output_dir, args.core_setting_dir) + args.iss, output_dir, args.core_setting_dir, args.debug) else: - logging.error('%s does not exist' % path_asm_test) - sys.exit(RET_FAIL) + if not args.debug: + logging.error('%s does not exist' % path_asm_test) + sys.exit(RET_FAIL) # Run remaining tests using the instruction generator gen(matched_list, cfg, output_dir, cwd) if not args.co: # Compile the assembly program to ELF, convert to plain binary if args.steps == "all" or re.match(".*gcc_compile.*", args.steps): - gcc_compile(matched_list, output_dir, args.isa, args.mabi, args.gcc_opts) + gcc_compile(matched_list, output_dir, args.isa, args.mabi, + args.gcc_opts, args.debug) # Run ISS simulation if args.steps == "all" or re.match(".*iss_sim.*", args.steps): iss_sim(matched_list, output_dir, args.iss, args.iss_yaml, - args.isa, args.core_setting_dir, args.iss_timeout) + args.isa, args.core_setting_dir, args.iss_timeout, args.debug) # Compare ISS simulation result if args.steps == "all" or re.match(".*iss_cmp.*", args.steps): - iss_cmp(matched_list, args.iss, output_dir, args.stop_on_first_error, args.exp) + iss_cmp(matched_list, args.iss, output_dir, args.stop_on_first_error, + args.exp, args.debug) sys.exit(RET_SUCCESS) except KeyboardInterrupt: diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index df70b528..b9746371 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -65,7 +65,7 @@ def read_yaml(yaml_file): return yaml_data -def get_env_var(var): +def get_env_var(var, debug_cmd = None): """Get the value of environment variable Args: @@ -77,8 +77,11 @@ def get_env_var(var): try: val = os.environ[var] except KeyError: - logging.warning("Please set the environment variable %0s" % var) - sys.exit(RET_FAIL) + if debug_cmd: + return var + else: + logging.warning("Please set the environment variable %0s" % var) + sys.exit(RET_FAIL) return val @@ -96,7 +99,7 @@ def get_seed(seed): return random.getrandbits(32) -def run_cmd(cmd, timeout_s = 999, exit_on_error = 1, check_return_code = True): +def run_cmd(cmd, timeout_s = 999, exit_on_error = 1, check_return_code = True, debug_cmd = None): """Run a command and return output Args: @@ -106,6 +109,10 @@ def run_cmd(cmd, timeout_s = 999, exit_on_error = 1, check_return_code = True): command output """ logging.debug(cmd) + if debug_cmd: + debug_cmd.write(cmd) + debug_cmd.write("\n\n") + return try: ps = subprocess.Popen("exec " + cmd, shell=True, @@ -135,7 +142,8 @@ def run_cmd(cmd, timeout_s = 999, exit_on_error = 1, check_return_code = True): return output -def run_parallel_cmd(cmd_list, timeout_s = 999, exit_on_error = 0, check_return_code = True): +def run_parallel_cmd(cmd_list, timeout_s = 999, exit_on_error = 0, + check_return_code = True, debug_cmd = None): """Run a list of commands in parallel Args: @@ -144,6 +152,11 @@ def run_parallel_cmd(cmd_list, timeout_s = 999, exit_on_error = 0, check_return_ Returns: command output """ + if debug_cmd: + for cmd in cmd_list: + debug_cmd.write(cmd) + debug_cmd.write("\n\n") + return children = [] for cmd in cmd_list: ps = subprocess.Popen("exec " + cmd, @@ -174,12 +187,16 @@ def run_parallel_cmd(cmd_list, timeout_s = 999, exit_on_error = 0, check_return_ os.system("stty sane") logging.debug(output) -def run_cmd_output(cmd): +def run_cmd_output(cmd, debug_cmd = None): """Run a command and return output Args: cmd : Command line to execute """ logging.debug(" ".join(cmd)) + if debug_cmd: + debug_cmd.write(" ".join(cmd)) + debug_cmd.write("\n\n") + return try: output = subprocess.check_output(cmd) except subprocess.CalledProcessError as exc: diff --git a/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr.sv b/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr.sv new file mode 100644 index 00000000..5669005d --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr.sv @@ -0,0 +1,51 @@ +/* + * Copyright 2020 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. + */ + +// Custom instruction class + +class riscv_custom_instr extends riscv_instr; + + // TODO: Add custom operands here, example: + // rand riscv_reg_t rs3; + + `uvm_object_utils(riscv_custom_instr) + `uvm_object_new + + virtual function string get_instr_name(); + get_instr_name = instr_name.name(); + // TODO: Add custom instruction name encoding here + return get_instr_name; + endfunction : get_instr_name + + // Convert the instruction to assembly code + virtual function string convert2asm(string prefix = ""); + string asm_str; + asm_str = format_string("nop", MAX_INSTR_STR_LEN); + /* TODO: Convert custom instruction to assembly format. Example: + asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN); + case (instr_name) + CUSTOM_1: asm_str = $sformatf("%0s %0s, (%0s)", asm_str, rd.name(), rs1.name()); + CUSTOM_2: asm_str = $sformatf("%0s %0s", asm_str, r3.name()); + endcase + */ + comment = {get_instr_name(), " ", comment}; + if (comment != "") begin + asm_str = {asm_str, " #",comment}; + end + return asm_str.tolower(); + endfunction : convert2asm + +endclass : riscv_custom_instr diff --git a/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr_enum.sv b/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr_enum.sv new file mode 100644 index 00000000..53410915 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/custom/riscv_custom_instr_enum.sv @@ -0,0 +1,2 @@ +// TODO: Add custom instruction name enum +CUSTOM_1, diff --git a/vendor/google_riscv-dv/src/isa/custom/rv32x_instr.sv b/vendor/google_riscv-dv/src/isa/custom/rv32x_instr.sv new file mode 100644 index 00000000..87572365 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/custom/rv32x_instr.sv @@ -0,0 +1,18 @@ +/* + * Copyright 2020 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. + */ + +// TODO: Add custom RV32X instruction. Example: +`DEFINE_CUSTOM_INSTR(CUSTOM_1, R_FORMAT, ARITHMETIC, RV32X) diff --git a/vendor/google_riscv-dv/src/isa/custom/rv64x_instr.sv b/vendor/google_riscv-dv/src/isa/custom/rv64x_instr.sv new file mode 100644 index 00000000..4ff4ffc6 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/custom/rv64x_instr.sv @@ -0,0 +1,18 @@ +/* + * Copyright 2020 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. + */ + +// TODO: Add custom RV32X instruction. Example: +// `DEFINE_CUSTOM_INSTR(CUSTOM1, R_FORMAT, LOAD, RV64X) diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index 6a84cbef..821ae8d9 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -362,6 +362,7 @@ class riscv_asm_program_gen extends uvm_object; 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; + RV32X, RV64X : misa[MISA_EXT_X] = 1'b1; default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported", supported_isa[i].name())) endcase @@ -820,21 +821,6 @@ class riscv_asm_program_gen extends uvm_object; for (int i = 1; i < max_interrupt_vector_num; i++) begin string intr_handler[$]; push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, intr_handler); - // If nested interrupts are enabled, set xSTATUS.xIE in the interrupt handler - // to re-enable interrupt handling capabilities - if (cfg.enable_nested_interrupt) begin - case (status) - MSTATUS: begin - intr_handler.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 8)); - end - SSTATUS: begin - intr_handler.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 2)); - end - USTATUS: begin - intr_handler.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 1)); - end - endcase - end gen_signature_handshake(.instr(intr_handler), .signature_type(CORE_STATUS), .core_status(HANDLING_IRQ)); intr_handler = {intr_handler, $sformatf("csrr x%0d, 0x%0x # %0s", cfg.gpr[0], cause, cause.name()), @@ -845,7 +831,7 @@ class riscv_asm_program_gen extends uvm_object; gen_signature_handshake(.instr(intr_handler), .signature_type(WRITE_CSR), .csr(cause)); gen_signature_handshake(.instr(intr_handler), .signature_type(WRITE_CSR), .csr(ie)); gen_signature_handshake(.instr(intr_handler), .signature_type(WRITE_CSR), .csr(ip)); - // Jump to commmon interrupt handling routine + // Jump to commmon interrupt handling routine intr_handler = {intr_handler, $sformatf("j %0smode_intr_handler", mode), "1: j test_done"}; @@ -1022,6 +1008,25 @@ class riscv_asm_program_gen extends uvm_object; end default: `uvm_fatal(get_full_name(), $sformatf("Unsupported mode: %0s", mode.name())) endcase + // If nested interrupts are enabled, set xSTATUS.xIE in the interrupt handler + // to re-enable interrupt handling capabilities + if (cfg.enable_nested_interrupt) begin + interrupt_handler_instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], scratch)); + interrupt_handler_instr.push_back($sformatf("bgtz x%0d, 1f", cfg.gpr[0])); + interrupt_handler_instr.push_back($sformatf("csrwi 0x%0x, 0x1", scratch)); + case (status) + MSTATUS: begin + interrupt_handler_instr.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 8)); + end + SSTATUS: begin + interrupt_handler_instr.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 2)); + end + USTATUS: begin + interrupt_handler_instr.push_back($sformatf("csrsi 0x%0x, 0x%0x", status, 1)); + end + endcase + interrupt_handler_instr.push_back($sformatf("1: csrwi 0x%0x,0", scratch)); + end // Read back interrupt related privileged CSR // The value of these CSR are checked by comparing with spike simulation result. interrupt_handler_instr = { diff --git a/vendor/google_riscv-dv/src/riscv_defines.svh b/vendor/google_riscv-dv/src/riscv_defines.svh index f46f2e60..e423f76e 100644 --- a/vendor/google_riscv-dv/src/riscv_defines.svh +++ b/vendor/google_riscv-dv/src/riscv_defines.svh @@ -93,3 +93,8 @@ `define DEFINE_VA_INSTR(instr_n, instr_format, instr_category, instr_group, vav = {}, imm_tp = IMM) \ class riscv_``instr_n``_instr extends riscv_vector_instr; \ `VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, imm_tp) + +// Custom extension instruction +`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) diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index ca1cccd0..e2cfee5f 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -90,7 +90,9 @@ package riscv_instr_pkg; RV32V, RV32B, RV64V, - RV64B + RV64B, + RV32X, + RV64X } riscv_instr_group_t; typedef enum { @@ -491,6 +493,8 @@ package riscv_instr_pkg; SRET, WFI, SFENCE_VMA, + // Custom instructions + `include "isa/custom/riscv_custom_instr_enum.sv" // You can add other instructions here INVALID_INSTR } riscv_instr_name_t; @@ -1106,6 +1110,9 @@ package riscv_instr_pkg; `include "isa/rv64m_instr.sv" `include "isa/rv128c_instr.sv" `include "isa/rv32v_instr.sv" + `include "isa/custom/riscv_custom_instr.sv" + `include "isa/custom/rv32x_instr.sv" + `include "isa/custom/rv64x_instr.sv" `endif `include "riscv_pseudo_instr.sv" diff --git a/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv index 2321908c..15ea4c64 100644 --- a/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv @@ -31,7 +31,7 @@ riscv_instr_name_t unsupported_instr[]; // ISA supported by the processor riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C, RV32A, RV64A, - RV32F, RV64F, RV32D, RV64D}; + RV32F, RV64F, RV32D, RV64D, RV32X}; // Interrupt mode support mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};