diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 292fca69b3..b7d8d399a4 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/chipsalliance/riscv-dv - rev: 08b12066b34c9728f706e45098ba502a36d7ca59 + rev: 71666ebacd69266b1abb7cdbad5e1897ce5884e6 } } diff --git a/vendor/google_riscv-dv/.github/scripts/code_fixup.py b/vendor/google_riscv-dv/.github/scripts/code_fixup.py new file mode 100644 index 0000000000..cd982544dd --- /dev/null +++ b/vendor/google_riscv-dv/.github/scripts/code_fixup.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +import argparse +import re + +# ============================================================================= + +class AssemblyLine: + """ + Simple assembly line representation + """ + + RE_INSTR = re.compile(r"(?P\S+)\s+(?P.*)") + + def __init__(self, text): + self.text = text + self.mnemonic = None + self.operands = None + + # Strip label if any + if ":" in text: + text = text.split(":", maxsplit=1)[1] + + # Strip comment if any + if "#" in text: + text = text.split("#", maxsplit=1)[0] + + # Get instruction and operands + m = self.RE_INSTR.match(text.strip()) + if m is not None: + + if m.group("mnemonic")[0] == ".": + return + + self.mnemonic = m.group("mnemonic").lower() + self.operands = [op.strip() for op in m.group("operands").split()] + + def __str__(self): + return self.text + +# ============================================================================= + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + type=str, + required=True, + help="Input assembly file" + ) + parser.add_argument( + "-o", + type=str, + required=True, + help="Output assembly file" + ) + + args = parser.parse_args() + + max_nops = 10 + + # Read and parse + with open(args.i, "r") as fp: + inp_lines = [AssemblyLine(l) for l in fp.readlines()] + + # Identify a delayed write instruction followed by another one which writes + # to the same register + out_lines = [] + for i in range(len(inp_lines)): + line = inp_lines[i] + out_lines.append(line) + + # Bypass + if not line.mnemonic: + continue + + # Check if it is a delayed write. If not then bypass + is_delayed = line.mnemonic in ["div", "divu", "rem", "remu", "lw"] + if not is_delayed: + continue + + # Get next 2 instructions + following = [] + for j in range(i+1, len(inp_lines)): + if inp_lines[j].mnemonic is not None: + following.append(inp_lines[j]) + if len(following) >= 2: + break + + # If any of the instructions targets the same register insert NOPs + dst = line.operands[0] + for j, l in enumerate(following): + if l.operands and l.operands[0] == dst: + nops = max(0, max_nops - j) + for _ in range(nops): + out_lines.append(" " * 18 + "nop # FIXME: A fixup not to make VeeR cancel a delayed write\n") + break + + # Write + with open(args.o, "w") as fp: + for l in out_lines: + fp.write(str(l)) + + +if __name__ == "__main__": + main() diff --git a/vendor/google_riscv-dv/.github/scripts/parse_testlist.py b/vendor/google_riscv-dv/.github/scripts/parse_testlist.py new file mode 100644 index 0000000000..9b36c5594e --- /dev/null +++ b/vendor/google_riscv-dv/.github/scripts/parse_testlist.py @@ -0,0 +1,26 @@ +import sys +from json import dumps +from yaml import load, Loader +from typing import Generator + + +def parse_yaml(path: str) -> Generator[str, None, None]: + with open(path, 'rb') as fd: + tests = load(fd, Loader=Loader) + for test in tests: + if 'import' in test: + import_path = test['import'].split('/', 1)[1] + yield from parse_yaml(import_path) + elif 'test' in test: + yield test['test'] + + +if __name__ == "__main__": + if len(sys.argv) == 2: + testlist = parse_yaml(f'target/{sys.argv[1]}/testlist.yaml') + else: + testlist = parse_yaml('yaml/base_testlist.yaml') + testlist = list(testlist) + # remove, will cause incomplete sim, need customized RTL + testlist.remove("riscv_csr_test") + print(dumps(testlist)) diff --git a/vendor/google_riscv-dv/.github/workflows/build-spike.yml b/vendor/google_riscv-dv/.github/workflows/build-spike.yml new file mode 100644 index 0000000000..442e825e82 --- /dev/null +++ b/vendor/google_riscv-dv/.github/workflows/build-spike.yml @@ -0,0 +1,63 @@ +# https://github.com/chipsalliance/Cores-VeeR-EL2/blob/774510e43f5408ec2b818db8f865027bc9be97b8/.github/workflows/build-spike.yml + +name: Spike Build + +on: + workflow_call: + +jobs: + verilator: + name: Build Spike + runs-on: ubuntu-latest + env: + TOOL_NAME: spike + TOOL_VERSION: d70ea67d + DEBIAN_FRONTEND: "noninteractive" + + steps: + - name: Setup Cache Metadata + id: cache_metadata + run: | + cache_date=$(date +"%Y_%m_%d") + cache_name=cache_${{ env.TOOL_NAME }}_${{ env.TOOL_VERSION }} + echo "Cache date: "$cache_date + echo "Cache name: "$cache_name + echo "cache_date=$cache_date" >> "$GITHUB_ENV" + echo "cache_name=$cache_name" >> "$GITHUB_ENV" + + - name: Setup cache + uses: actions/cache@v3 + id: cache + timeout-minutes: 60 + with: + path: | + /opt/spike + /opt/spike/.cache + key: ${{ env.cache_name }}_${{ env.cache_date }} + restore-keys: ${{ env.cache_name }}_ + + - name: Install prerequisities + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + run: | + sudo apt -qqy update && sudo apt -qqy --no-install-recommends install \ + git build-essential cmake ccache device-tree-compiler + + - name: Build Spike + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + run: | + export CCACHE_DIR=/opt/spike/.cache + ccache --show-config | grep cache_dir + git clone https://github.com/riscv-software-src/riscv-isa-sim spike + export CC="ccache gcc" + export CXX="ccache g++" + pushd spike + git checkout ${{ env.TOOL_VERSION }} + mkdir build + cd build + ../configure --prefix=/opt/spike + make -j`nproc` + make install + popd + rm -rf /opt/spike/include # Remove include and lib to save space + rm -rf /opt/spike/lib + diff --git a/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml b/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml deleted file mode 100644 index de92648eff..0000000000 --- a/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml +++ /dev/null @@ -1,27 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: metrics-regress - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch -on: - push: - branches: [ master ] -# pull_request_target: -# branches: [ master ] - -# If you fork this repository, you must create a new Metrics project for your fork -# and set the environment variable $METRICS_PROJECT_ID accordingly -jobs: - metrics-regression: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run: ./scripts/metrics-regress.py $METRICS_REGRESSION_NAME $METRICS_PROJECT_ID - env: - METRICS_CI_TOKEN: ${{ secrets.METRICS_CI_TOKEN }} - METRICS_REGRESSION_NAME: riscv-dv_regression - METRICS_PROJECT_ID: ${{ secrets.METRICS_PROJECT_ID }} - PR_NUMBER: ${{ github.event.pull_request.number }} - shell: bash - diff --git a/vendor/google_riscv-dv/.github/workflows/run-tests.yml b/vendor/google_riscv-dv/.github/workflows/run-tests.yml new file mode 100644 index 0000000000..dd93d0cf63 --- /dev/null +++ b/vendor/google_riscv-dv/.github/workflows/run-tests.yml @@ -0,0 +1,182 @@ +name: run-tests + +on: + push: + pull_request: + +env: + RISCV_TARGET: rv32imc + +jobs: + build-spike: + uses: ./.github/workflows/build-spike.yml + + generate-config: + runs-on: ubuntu-latest + outputs: + test-types: ${{ steps.test-types.outputs.tests }} + hash: ${{ steps.hash.outputs.files-hash }} + steps: + - uses: actions/checkout@v4 + - id: test-types + name: Prepare test types + run: | + python3 -m pip install pyyaml + echo "tests=$(python3 .github/scripts/parse_testlist.py $RISCV_TARGET)" | tee -a $GITHUB_OUTPUT + - id: hash + name: Prepare files' hash + run: | + echo "files-hash=$(sha256sum **/*.sv **/*.py **/*.yml **/*.yaml | cut -d\ -f1 | sha256sum | cut -d\ -f1)" | tee -a $GITHUB_OUTPUT + + + generate-code: + runs-on: [ self-hosted, Linux, X64, gcp-custom-runners ] + container: centos:8 + needs: generate-config + strategy: + fail-fast: false + matrix: + test: ${{ fromJSON(needs.generate-config.outputs.test-types) }} + version: [ uvm ] + include: + - test: riscv_arithmetic_basic_test + version: pyflow + env: + GHA_EXTERNAL_DISK: additional-tools + CACHE_HASH: ${{ needs.generate-config.outputs.hash }} + steps: + - uses: actions/checkout@v3 + + - name: Setup Cache Metadata + id: cache_metadata + run: | + cache_code=cache_${{ matrix.test }}_${{ matrix.version }} + echo "cache_code=${cache_code}_${{ env.CACHE_HASH }}" | tee -a "$GITHUB_ENV" + + - name: Cache Code + uses: actions/cache@v3 + id: cache-code + timeout-minutes: 60 + with: + path: test/asm_test + key: ${{ env.cache_code }} + + - name: Prepare Environment + if: steps.cache-code.outputs.cache-hit != 'true' + run: _secret_environment + + - name: Setup Python 3.9 + if: steps.cache-code.outputs.cache-hit != 'true' + run: | + yum update -y + yum install -y python39 + python3.9 -m pip install -r requirements.txt + + - name: Generate UVM Tests + if: steps.cache-code.outputs.cache-hit != 'true' && matrix.version == 'uvm' + run: _secret_riscv + env: + RISCV_TEST: ${{ matrix.test }} + RISCV_TARGET: ${{ env.RISCV_TARGET }} + + - name: Generate PyFlow Tests + if: steps.cache-code.outputs.cache-hit != 'true' && matrix.version == 'pyflow' + run: | + set -eo pipefail + python3 run.py --simulator pyflow \ + --test ${{ matrix.test }} --iss spike \ + --start_seed 999 --iterations 1 --batch_size 1 \ + --isa $RISCV_TARGET --mabi ilp32 --steps gen -v -o test 2>&1 | tee test/generate.log + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + if: always() + with: + path: | + test/asm_test/*.S + + + run-tests: + runs-on: ubuntu-latest + needs: [ build-spike, generate-code, generate-config ] + strategy: + fail-fast: false + matrix: + test: ${{ fromJSON(needs.generate-config.outputs.test-types) }} + version: + - uvm + include: + - test: riscv_arithmetic_basic_test + version: pyflow + env: + TOOL_VERSION: d70ea67d + CACHE_HASH: ${{ needs.generate-config.outputs.hash }} + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: sudo apt-get -qqy update && sudo apt-get -qqy install gcc-riscv64-unknown-elf device-tree-compiler + + - name: Setup python + # python dependencies cannot be properly downloaded with new versions of python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Install python dependencies + run: python3 -m pip install -r requirements.txt + + - name: Setup Cache Metadata + id: cache_metadata + run: | + date=$(date +"%Y_%m_%d") + time=$(date +"%Y%m%d_%H%M%S_%N") + cache_spike_restore_key=cache_spike_ + cache_spike_key=${cache_spike_restore_key}${{ env.TOOL_VERSION }}_${date} + cache_code=cache_${{ matrix.test }}_${{ matrix.version }} + + echo "cache_spike_restore_key=$cache_spike_restore_key" | tee -a "$GITHUB_ENV" + echo "cache_spike_key=$cache_spike_key" | tee -a "$GITHUB_ENV" + echo "cache_code=${cache_code}_${{ env.CACHE_HASH }}" | tee -a "$GITHUB_ENV" + + - name: Restore Spike cache + id: cache-spike-restore + uses: actions/cache/restore@v3 + with: + path: | + /opt/spike + /opt/spike/.cache + key: ${{ env.cache_spike_key }} + restore-keys: ${{ env.cache_spike_restore_key }} + + - name: Set variables + run: | + echo "RISCV_GCC=riscv64-unknown-elf-gcc" >> $GITHUB_ENV + echo "RISCV_OBJCOPY=riscv64-unknown-elf-objcopy" >> $GITHUB_ENV + echo "SPIKE_PATH=/opt/spike/bin" >> $GITHUB_ENV + echo "PYTHONPATH=pygen" >> $GITHUB_ENV + + - name: Cache Code Restore + uses: actions/cache/restore@v3 + id: cache-code-restore + timeout-minutes: 60 + with: + path: test/asm_test + key: ${{ env.cache_code }} + + - name: Run Tests + run: | + set -eo pipefail + python3 run.py --simulator pyflow \ + --test ${{ matrix.test }} --iss spike --iss_timeout 60 \ + --start_seed 999 --iterations 1 --batch_size 1 \ + --isa $RISCV_TARGET --mabi ilp32 --steps gcc_compile,iss_sim -v -o test 2>&1 | tee -a test/generate.log + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + if: always() + with: + path: | + test/asm_test/*.log + test/*.log diff --git a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_asm_program_gen.d b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_asm_program_gen.d index 98324ac4f7..abfb638dd4 100644 --- a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_asm_program_gen.d +++ b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_asm_program_gen.d @@ -736,7 +736,7 @@ class riscv_asm_program_gen : uvm_object } // get a random double precision floating value - ubvec!XLEN get_rand_dpf_value() { + ubvec!64 get_rand_dpf_value() { ubvec!64 value; int randint = urandom(0,6); diff --git a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_load_store_instr_lib.d b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_load_store_instr_lib.d index 4694ce4d7a..a5308ed286 100644 --- a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_load_store_instr_lib.d +++ b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_load_store_instr_lib.d @@ -670,11 +670,11 @@ class riscv_vector_load_store_instr_stream : riscv_mem_access_stream add_mixed_instr(num_mixed_instr); add_rs1_init_la_instr(rs1_reg, data_page_id, base); if (address_mode == address_mode_e.STRIDED) { - this.append_instr(get_init_gpr_instr(rs2_reg, toubvec!64(stride_byte_offset))); + this.append_instr(get_init_gpr_instr(rs2_reg, toubvec!XLEN(stride_byte_offset))); } else if (address_mode == address_mode_e.INDEXED) { // TODO: Support different index address for each element - add_init_vector_gpr_instr(vs2_reg, toubvec!64(index_addr)); + add_init_vector_gpr_instr(vs2_reg, toubvec!XLEN(index_addr)); } super.post_randomize(); } diff --git a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_page_table_entry.d b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_page_table_entry.d index cc1ae5de0c..308526d733 100644 --- a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_page_table_entry.d +++ b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_page_table_entry.d @@ -161,7 +161,7 @@ class riscv_page_table_entry(satp_mode_t MODE = satp_mode_t.SV39) : uvm_object void pack_entry() { switch (MODE) { case satp_mode_t.SV32: - bits = ppn1 ~ ppn0 ~ rsw ~ d ~ a ~ g ~ u ~ xwr ~ v; + bits = cast(ubvec!XLEN) (ppn1 ~ ppn0 ~ rsw ~ d ~ a ~ g ~ u ~ xwr ~ v); break; case satp_mode_t.SV39: bits = cast(ubvec!XLEN) (rsvd ~ ppn2 ~ ppn1 ~ ppn0 ~ rsw ~ d ~ a ~ g ~ u ~ xwr ~ v); diff --git a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_privileged_common_seq.d b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_privileged_common_seq.d index 8b41a9166e..64e7a1987c 100644 --- a/vendor/google_riscv-dv/euvm/riscv/gen/riscv_privileged_common_seq.d +++ b/vendor/google_riscv-dv/euvm/riscv/gen/riscv_privileged_common_seq.d @@ -123,16 +123,18 @@ class riscv_privileged_common_seq : uvm_sequence!(uvm_sequence_item,uvm_sequence mstatus.set_field("TW", cfg.set_mstatus_tw); mstatus.set_field("FS", cfg.mstatus_fs); mstatus.set_field("VS", cfg.mstatus_vs); - if (!(canFind(supported_privileged_mode, privileged_mode_t.SUPERVISOR_MODE) && (XLEN != 32))) { - mstatus.set_field("SXL", toubvec!2(0b00)); - } - else if (XLEN == 64) { - mstatus.set_field("SXL", toubvec!2(0b10)); - } - if (!(canFind(supported_privileged_mode, privileged_mode_t.USER_MODE) && (XLEN != 32))) { - mstatus.set_field("UXL", toubvec!2(0b00)); - } else if (XLEN == 64) { - mstatus.set_field("UXL", toubvec!2(0b10)); + if (XLEN != 32) { + if (!(canFind(supported_privileged_mode, privileged_mode_t.SUPERVISOR_MODE))) { + mstatus.set_field("SXL", toubvec!2(0b00)); + } + else if (XLEN == 64) { + mstatus.set_field("SXL", toubvec!2(0b10)); + } + if (!(canFind(supported_privileged_mode, privileged_mode_t.USER_MODE))) { + mstatus.set_field("UXL", toubvec!2(0b00)); + } else if (XLEN == 64) { + mstatus.set_field("UXL", toubvec!2(0b10)); + } } mstatus.set_field("XS", 0); mstatus.set_field("SD", 0); diff --git a/vendor/google_riscv-dv/requirements.txt b/vendor/google_riscv-dv/requirements.txt index 49934ea5cf..6fbc7060ce 100644 --- a/vendor/google_riscv-dv/requirements.txt +++ b/vendor/google_riscv-dv/requirements.txt @@ -1,5 +1,5 @@ PyYAML -bitstring +bitstring==3.1.9 Sphinx Pallets-Sphinx-Themes sphinxcontrib-log-cabinet diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index 9acf6dcfae..872752f001 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -109,6 +109,7 @@ def run_cmd(cmd, timeout_s=999, exit_on_error=1, check_return_code=True, executable='/bin/bash', universal_newlines=True, start_new_session=True, + env=os.environ, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: diff --git a/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv b/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv index 147f13ed3e..e256178388 100644 --- a/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv +++ b/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv @@ -764,15 +764,26 @@ class riscv_pmp_cfg extends uvm_object; // if counter < pmp_num_regions => branch to beginning of loop, // otherwise jump to the end of the loop $sformatf("ble x%0d, x%0d, 19f", scratch_reg[1], scratch_reg[0]), - $sformatf("j 0b"), - // If we reach here, it means that no PMP entry has matched the request. - // We must immediately jump to since the CPU is taking a PMP exception, - // but this routine is unable to find a matching PMP region for the faulting access - - // there is a bug somewhere. - // In case of MMWP mode this is expected behavior, we should try to continue. - $sformatf("19: csrr x%0d, 0x%0x", scratch_reg[0], MSECCFG), - $sformatf("andi x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]), - $sformatf("bnez x%0d, 27f", scratch_reg[0]), + $sformatf("j 0b") + }; + + // If we reach here, it means that no PMP entry has matched the request. + // We must immediately jump to since the CPU is taking a PMP exception, + // but this routine is unable to find a matching PMP region for the faulting access - + // there is a bug somewhere. + // In case of MMWP mode this is expected behavior, we should try to continue. + if (riscv_instr_pkg::support_epmp) begin + instr = {instr, + $sformatf("19: csrr x%0d, 0x%0x", scratch_reg[0], MSECCFG), + $sformatf("andi x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]), + $sformatf("bnez x%0d, 27f", scratch_reg[0]) + }; + end else begin + instr = {instr, + $sformatf("19: nop") + }; + end + instr = {instr, $sformatf("la x%0d, test_done", scratch_reg[0]), $sformatf("jalr x0, x%0d, 0", scratch_reg[0]) }; @@ -839,16 +850,24 @@ class riscv_pmp_cfg extends uvm_object; // If masked_fault_addr != masked_pmpaddr[i] : mismatch, so continue looping $sformatf("bne x%0d, x%0d, 18b", scratch_reg[0], scratch_reg[4]), $sformatf("j 26f") - }; + }; // Sub-section that is common to the address modes deciding what to do what to do when hitting // a locked region + if (riscv_instr_pkg::support_epmp) begin + instr = {instr, + // If we get here there is an address match. + // First check whether we are in MML mode. + $sformatf("26: csrr x%0d, 0x%0x", scratch_reg[4], MSECCFG), + $sformatf("andi x%0d, x%0d, 1", scratch_reg[4], scratch_reg[4]), + $sformatf("bnez x%0d, 27f", scratch_reg[4]) + }; + end else begin + instr = {instr, + $sformatf("26: nop") + }; + end instr = {instr, - // If we get here there is an address match. - // First check whether we are in MML mode. - $sformatf("26: csrr x%0d, 0x%0x", scratch_reg[4], MSECCFG), - $sformatf("andi x%0d, x%0d, 1", scratch_reg[4], scratch_reg[4]), - $sformatf("bnez x%0d, 27f", scratch_reg[4]), // Then check whether the lock bit is set. $sformatf("andi x%0d, x%0d, 128", scratch_reg[4], scratch_reg[3]), $sformatf("bnez x%0d, 27f", scratch_reg[4]), diff --git a/vendor/google_riscv-dv/yaml/simulator.yaml b/vendor/google_riscv-dv/yaml/simulator.yaml index 01f8b1acc4..76dd6f1e64 100644 --- a/vendor/google_riscv-dv/yaml/simulator.yaml +++ b/vendor/google_riscv-dv/yaml/simulator.yaml @@ -22,6 +22,7 @@ - "vcs -file /vcs.compile.option.f +incdir+ +incdir+ + +vcs+lic+wait -f /files.f -full64 -l /compile.log -LDFLAGS '-Wl,--no-as-needed'