├── .clang-format ├── .github └── workflows │ └── reuse.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── .pre-commit-config.yaml ├── .pylintrc ├── .style.yapf ├── LICENSES └── Apache-2.0.txt ├── README.md ├── hammer.cpp ├── hammer.h ├── hammer_enums.h ├── hammer_pybind.cpp ├── meson.build ├── meson_options.txt ├── native-file.txt ├── pytests ├── meson.build ├── pytest000.input.S ├── pytest000.py ├── pytest001.input.S ├── pytest001.py ├── pytest002.input.S ├── pytest002.py ├── pytest003.input.S ├── pytest003.py └── testinput.link.ld └── tests ├── meson.build ├── test000.cpp ├── test000.input.S ├── test001.cpp ├── test001.input.S ├── test002.cpp ├── test002.input.S ├── test003.cpp ├── test003.input.S └── testinput.link.ld /.clang-format: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # Based off Open Titan's 6 | BasedOnStyle: Google 7 | AllowShortIfStatementsOnASingleLine: false 8 | AllowShortLoopsOnASingleLine: false 9 | DerivePointerAlignment: false 10 | PointerAlignment: Right 11 | 12 | # Rivos 13 | ColumnLimit: 100 14 | UseTab: Never 15 | SortIncludes: false 16 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | name: reuse 6 | 7 | on: [push, pull_request] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: reuse Compliance Check 15 | uses: fsfe/reuse-action@v1 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | .vscode 6 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | include: 6 | # https://gitlab.ba.rivosinc.com/rv/group_gitlab_config/raw/rivos/main/ci_includes/pre-commit-lint.yml 7 | - project: 'rv/group_gitlab_config' 8 | ref: rivos/main 9 | file: '/ci_includes/pre-commit-lint.yml' 10 | 11 | stages: 12 | - prebuild 13 | - build 14 | 15 | variables: 16 | GIT_STRATEGY: clone 17 | GIT_SUBMODULE_STRATEGY: recursive 18 | 19 | default: 20 | before_script: 21 | - module load rivos/init 22 | # Below doesn't work. Only way to work is relative URL in .gitmodules: https://gitlab.com/gitlab-org/gitlab/-/issues/35649 23 | # - git config url."https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.ba.rivosinc.com".insteadOf git@gitlab.ba.rivosinc.com 24 | tags: [shell] 25 | 26 | build-and-test: 27 | stage: build 28 | rules: 29 | # run if MR or periodic to check if infra change breaks something 30 | - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "schedule" 31 | script: 32 | - meson setup builddir --native-file native-file.txt --buildtype release 33 | - echo "BUILDING HAMMER" 34 | - meson compile -C builddir 35 | - echo "TESTING" 36 | - meson test -C builddir 37 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rivosinc/hammer/6d9fac96407149a1a533cdd3f63f6bbd96614ffa/.gitmodules -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | repos: 6 | # pull mirror from: https://github.com/pre-commit/pre-commit-hooks 7 | - repo: https://gitlab.ba.rivosinc.com/pub/it/pre-commit-hooks.git 8 | rev: v4.1.0 9 | hooks: 10 | - id: check-added-large-files 11 | - id: check-ast 12 | - id: check-builtin-literals 13 | - id: check-case-conflict 14 | - id: check-docstring-first 15 | - id: check-executables-have-shebangs 16 | - id: check-json 17 | - id: check-merge-conflict 18 | - id: check-shebang-scripts-are-executable 19 | - id: check-symlinks 20 | - id: check-toml 21 | - id: check-xml 22 | - id: check-yaml 23 | - id: debug-statements 24 | - id: detect-private-key 25 | - id: forbid-new-submodules 26 | - id: end-of-file-fixer 27 | - id: trailing-whitespace 28 | args: [--markdown-linebreak-ext=md] 29 | exclude: ".patch" 30 | 31 | # - repo: https://github.com/PyCQA/isort 32 | - repo: https://gitlab.ba.rivosinc.com/pub/it/isort 33 | rev: "5.10.1" 34 | hooks: 35 | - id: isort 36 | args: 37 | - --profile 38 | - google 39 | - --filter-files 40 | 41 | # pull mirror from: https://github.com/google/yapf 42 | - repo: https://gitlab.ba.rivosinc.com/pub/it/yapf 43 | rev: v0.31.0 44 | hooks: 45 | - id: yapf 46 | 47 | # pull mirror of https://github.com/fsfe/reuse-tool (slightly modified) 48 | - repo: https://github.com/rivosinc/reuse-tool 49 | rev: '3a95909a30d51467575a95b8cabdc7949bb8e7bd' 50 | hooks: 51 | # Add copyright/license header 52 | - id: reuse-annotate 53 | args: 54 | - -c=Rivos Inc. 55 | - -l=Apache-2.0 56 | - --skip-unrecognised 57 | # Check compliance 58 | - id: reuse 59 | 60 | # pull mirror from: https://github.com/jumanjihouse/pre-commit-hooks.git 61 | - repo: https://gitlab.ba.rivosinc.com/pub/it/jumanjihouse_pre-commit-hooks 62 | rev: 2.1.5 63 | hooks: 64 | - id: shellcheck 65 | - id: shfmt 66 | args: 67 | - -i 2 68 | - -ci 69 | 70 | # pull mirror of https://github.com/ikamensh/flynt/ 71 | - repo: https://gitlab.ba.rivosinc.com/pub/it/flynt 72 | rev: '0.76' 73 | hooks: 74 | - id: flynt 75 | 76 | # pull mirror of https://github.com/asottile/pyupgrade 77 | - repo: https://gitlab.ba.rivosinc.com/pub/it/pyupgrade 78 | rev: v2.31.0 79 | hooks: 80 | - id: pyupgrade 81 | 82 | # mirror of https://github.com/pre-commit/mirrors-clang-format 83 | - repo: https://gitlab.ba.rivosinc.com/pub/it/mirrors-clang-format 84 | rev: v13.0.1 85 | hooks: 86 | - id: clang-format 87 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | [MESSAGES CONTROL] 6 | 7 | disable= 8 | W0511, 9 | C0301, 10 | W1203, 11 | -------------------------------------------------------------------------------- /.style.yapf: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | [style] 6 | # lowRISC style is basically pep8 7 | based_on_style = pep8 8 | 9 | # But we don't like the split before operators 10 | split_before_bitwise_operator = False 11 | split_before_logical_operator = False 12 | 13 | # Rivos SV line length is 100 so making python the same 14 | column_limit=100 15 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Hammer 8 | 9 | [![REUSE status](https://api.reuse.software/badge/github.com/rivosinc/hammer)](https://api.reuse.software/info/github.com/rivosinc/hammer) 10 | 11 | Infrastructure to drive Spike (RISC-V ISA Simulator) in cosim mode. Hammer provides a C++ and Python interface to interact with Spike. 12 | 13 | ## Dependencies 14 | 15 | * `python3` 16 | * `meson` is the build infrastructure. 17 | * `pybind11` Python module: 18 | ``` 19 | python3 -m pip install pybind11 20 | ``` 21 | * Libraries and headers from Spike 22 | 23 | In the Spike repo run: 24 | 25 | ``` 26 | mkdir build 27 | cd build/ 28 | ../configure --with-isa=RV64GCV --without-boost --without-boost-asio --without-boost-regex --prefix 29 | make 30 | make install 31 | ``` 32 | 33 | The SHA of the last tested Spike version is included in the name of the patch file. 34 | 35 | ## Building Hammer and Running Tests 36 | 37 | ``` 38 | meson setup builddir --native-file native-file.txt --buildtype release -Dspike_install_dir= 39 | meson compile -C builddir 40 | meson test -C builddir 41 | ``` 42 | 43 | *NOTE: Finish the compile step before running the pytests.* 44 | 45 | The pytests require the compile step be complete before being run because 46 | they depend on the `hammer.pylib` being built. I couldn't figure out a way to add 47 | a dependency between the pylib and the pytests in meson. 48 | 49 | ### Release procedure 50 | 51 | ``` 52 | meson setup builddir --native-file native-file.txt -Dspike_install_dir= --buildtype release --prefix 53 | meson compile -C builddir 54 | meson install -C builddir 55 | ``` 56 | -------------------------------------------------------------------------------- /hammer.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | #include "fesvr/option_parser.h" 8 | #include "riscv/cachesim.h" 9 | #include "riscv/decode.h" 10 | 11 | #include 12 | 13 | // FIXME: This function exists in Spike as a static function. We shouldn't have to 14 | // copy it out here but sim_t requires it as an argument. 15 | static std::vector> make_mems(const std::vector &layout) { 16 | std::vector> mems; 17 | mems.reserve(layout.size()); 18 | for (const auto &cfg : layout) { 19 | mems.push_back(std::make_pair(cfg.get_base(), new mem_t(cfg.get_size()))); 20 | } 21 | return mems; 22 | } 23 | 24 | Hammer::Hammer(const char *isa, const char *privilege_levels, const char *vector_arch, 25 | std::vector hart_ids, std::vector memory_layout, 26 | const std::string target_binary, const std::optional start_pc) { 27 | // Expose these only if needed 28 | std::vector> plugin_devices; 29 | debug_module_config_t dm_config = {.progbufsize = 2, 30 | .max_sba_data_width = 0, 31 | .require_authentication = false, 32 | .abstract_rti = 0, 33 | .support_hasel = true, 34 | .support_abstract_csr_access = true, 35 | .support_haltgroups = true, 36 | .support_impebreak = true}; 37 | const char *log_path = nullptr; 38 | const char *dtb_file = nullptr; 39 | FILE *cmd_file = nullptr; 40 | 41 | std::pair initrd_bounds{0, 0}; 42 | const char *bootargs = nullptr; 43 | bool real_time_clint = false; 44 | bool misaligned = false; 45 | 46 | reg_t trigger_count = 4; 47 | 48 | reg_t num_pmpregions = 16; 49 | 50 | endianness_t endinaness = endianness_little; 51 | 52 | cfg_t cfg = cfg_t(initrd_bounds, bootargs, isa, privilege_levels, vector_arch, misaligned, endinaness, num_pmpregions, memory_layout, 53 | hart_ids, real_time_clint, trigger_count); 54 | 55 | if (start_pc.has_value()) { 56 | cfg.start_pc = start_pc.value(); 57 | } 58 | 59 | std::vector> mems = make_mems(memory_layout); 60 | 61 | std::vector htif_args; 62 | htif_args.push_back(target_binary); 63 | 64 | bool halted = false; 65 | bool dtb_enabled = true; 66 | bool socket_enabled = false; 67 | 68 | simulator = new sim_t(&cfg, halted, mems, plugin_devices, htif_args, dm_config, log_path, 69 | dtb_enabled, dtb_file, socket_enabled, cmd_file); 70 | 71 | // Initializes everything 72 | simulator->start(); 73 | } 74 | 75 | Hammer::~Hammer() { delete simulator; } 76 | 77 | reg_t Hammer::get_gpr(uint8_t hart_id, uint8_t gpr_id) { 78 | assert(gpr_id < NXPR); 79 | 80 | processor_t *hart = simulator->get_core(hart_id); 81 | state_t *hart_state = hart->get_state(); 82 | 83 | return hart_state->XPR[gpr_id]; 84 | } 85 | 86 | void Hammer::set_gpr(uint8_t hart_id, uint8_t gpr_id, reg_t new_gpr_value) { 87 | assert(gpr_id < NXPR); 88 | 89 | processor_t *hart = simulator->get_core(hart_id); 90 | state_t *hart_state = hart->get_state(); 91 | 92 | hart_state->XPR.write(gpr_id, new_gpr_value); 93 | } 94 | 95 | uint64_t Hammer::get_fpr(uint8_t hart_id, uint8_t fpr_id) { 96 | assert(fpr_id < NFPR); 97 | 98 | processor_t *hart = simulator->get_core(hart_id); 99 | state_t *hart_state = hart->get_state(); 100 | freg_t fpr_value = hart_state->FPR[fpr_id]; 101 | 102 | return fpr_value.v[0]; 103 | } 104 | 105 | reg_t Hammer::get_PC(uint8_t hart_id) { 106 | processor_t *hart = simulator->get_core(hart_id); 107 | state_t *hart_state = hart->get_state(); 108 | 109 | return hart_state->pc; 110 | } 111 | 112 | void Hammer::set_PC(uint8_t hart_id, reg_t new_pc_value) { 113 | processor_t *hart = simulator->get_core(hart_id); 114 | state_t *hart_state = hart->get_state(); 115 | 116 | hart_state->pc = new_pc_value; 117 | } 118 | 119 | reg_t Hammer::get_csr(uint8_t hart_id, uint32_t csr_id) { 120 | processor_t *hart = simulator->get_core(hart_id); 121 | return hart->get_csr(csr_id); 122 | } 123 | 124 | void Hammer::single_step(uint8_t hart_id) { 125 | processor_t *hart = simulator->get_core(hart_id); 126 | hart->step(1); 127 | } 128 | 129 | uint32_t Hammer::get_flen(uint8_t hart_id) { 130 | processor_t *hart = simulator->get_core(hart_id); 131 | return hart->get_flen(); 132 | } 133 | 134 | reg_t Hammer::get_vlen(uint8_t hart_id) { 135 | processor_t *hart = simulator->get_core(hart_id); 136 | return hart->VU.get_vlen(); 137 | } 138 | 139 | reg_t Hammer::get_elen(uint8_t hart_id) { 140 | processor_t *hart = simulator->get_core(hart_id); 141 | return hart->VU.get_elen(); 142 | } 143 | 144 | std::vector Hammer::get_vector_reg(uint8_t hart_id, uint8_t vector_reg_id) { 145 | assert(vector_reg_id < NVPR); 146 | 147 | processor_t *hart = simulator->get_core(hart_id); 148 | uint32_t vlen = hart->VU.get_vlen(); 149 | 150 | std::vector vector_reg_value; 151 | 152 | for (uint32_t i = 0; i < (vlen / 64); ++i) { 153 | vector_reg_value.push_back(hart->VU.elt(vector_reg_id, i)); 154 | } 155 | 156 | return vector_reg_value; 157 | } 158 | 159 | -------------------------------------------------------------------------------- /hammer.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #pragma once 6 | 7 | #include "hammer_enums.h" 8 | #include "riscv/mmu.h" 9 | #include "riscv/sim.h" 10 | 11 | #include 12 | 13 | class Hammer { 14 | public: 15 | Hammer(const char *isa, const char *privilege_levels, const char *vector_arch, 16 | std::vector hart_ids, std::vector memory_layout, 17 | const std::string target_binary, const std::optional start_pc = std::nullopt); 18 | ~Hammer(); 19 | 20 | reg_t get_gpr(uint8_t hart_id, uint8_t gpr_id); 21 | void set_gpr(uint8_t hart_id, uint8_t gpr_id, reg_t new_gpr_value); 22 | 23 | uint64_t get_fpr(uint8_t hart_id, uint8_t fpr_id); 24 | 25 | reg_t get_PC(uint8_t hart_id); 26 | void set_PC(uint8_t hart_id, reg_t new_pc_value); 27 | 28 | reg_t get_csr(uint8_t hart_id, uint32_t csr_id); 29 | 30 | void single_step(uint8_t hart_id); 31 | 32 | uint32_t get_flen(uint8_t hart_id); 33 | 34 | reg_t get_vlen(uint8_t hart_id); 35 | reg_t get_elen(uint8_t hart_id); 36 | 37 | std::vector get_vector_reg(uint8_t hart_id, uint8_t vector_reg_id); 38 | 39 | template 40 | std::optional> get_memory_at_VA(uint8_t hart_id, uint64_t virtual_address, 41 | size_t num_bytes_to_read) { 42 | if (num_bytes_to_read % sizeof(T)) 43 | return std::nullopt; 44 | mmu_t *mmu = simulator->get_core(hart_id)->get_mmu(); 45 | std::vector data; 46 | try { 47 | for (size_t i = 0; i < num_bytes_to_read; i += sizeof(T)) 48 | data.push_back(mmu->load(virtual_address + i)); 49 | } catch (trap_t &t) { 50 | return std::nullopt; 51 | } 52 | return data; 53 | } 54 | 55 | template 56 | int set_memory_at_VA(uint8_t hart_id, uint64_t virtual_address, 57 | const std::vector &memory_contents) { 58 | mmu_t *mmu = simulator->get_core(hart_id)->get_mmu(); 59 | try { 60 | for (auto &i : memory_contents) { 61 | mmu->store(virtual_address, i); 62 | virtual_address += sizeof(T); 63 | } 64 | } catch (trap_t &t) { 65 | return -EFAULT; 66 | } 67 | return 0; 68 | } 69 | 70 | void hello_world() { printf("Hammer: Hello World.\n"); } 71 | 72 | private: 73 | sim_t *simulator; 74 | }; 75 | -------------------------------------------------------------------------------- /hammer_enums.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "riscv/encoding.h" 6 | #include "riscv/platform.h" 7 | 8 | enum PlatformDefines { 9 | DefaultRstVec = DEFAULT_RSTVEC, 10 | ClintBase = CLINT_BASE, 11 | ClintSize = CLINT_SIZE, 12 | ExtIOBase = EXT_IO_BASE, 13 | DramBase = DRAM_BASE 14 | }; 15 | 16 | enum CsrDefines { 17 | FFLAGS_CSR = CSR_FFLAGS, 18 | FRM_CSR = CSR_FRM, 19 | FCSR_CSR = CSR_FCSR, 20 | VSTART_CSR = CSR_VSTART, 21 | VXSAT_CSR = CSR_VXSAT, 22 | VXRM_CSR = CSR_VXRM, 23 | VCSR_CSR = CSR_VCSR, 24 | SEED_CSR = CSR_SEED, 25 | CYCLE_CSR = CSR_CYCLE, 26 | TIME_CSR = CSR_TIME, 27 | INSTRET_CSR = CSR_INSTRET, 28 | HPMCOUNTER3_CSR = CSR_HPMCOUNTER3, 29 | HPMCOUNTER4_CSR = CSR_HPMCOUNTER4, 30 | HPMCOUNTER5_CSR = CSR_HPMCOUNTER5, 31 | HPMCOUNTER6_CSR = CSR_HPMCOUNTER6, 32 | HPMCOUNTER7_CSR = CSR_HPMCOUNTER7, 33 | HPMCOUNTER8_CSR = CSR_HPMCOUNTER8, 34 | HPMCOUNTER9_CSR = CSR_HPMCOUNTER9, 35 | HPMCOUNTER10_CSR = CSR_HPMCOUNTER10, 36 | HPMCOUNTER11_CSR = CSR_HPMCOUNTER11, 37 | HPMCOUNTER12_CSR = CSR_HPMCOUNTER12, 38 | HPMCOUNTER13_CSR = CSR_HPMCOUNTER13, 39 | HPMCOUNTER14_CSR = CSR_HPMCOUNTER14, 40 | HPMCOUNTER15_CSR = CSR_HPMCOUNTER15, 41 | HPMCOUNTER16_CSR = CSR_HPMCOUNTER16, 42 | HPMCOUNTER17_CSR = CSR_HPMCOUNTER17, 43 | HPMCOUNTER18_CSR = CSR_HPMCOUNTER18, 44 | HPMCOUNTER19_CSR = CSR_HPMCOUNTER19, 45 | HPMCOUNTER20_CSR = CSR_HPMCOUNTER20, 46 | HPMCOUNTER21_CSR = CSR_HPMCOUNTER21, 47 | HPMCOUNTER22_CSR = CSR_HPMCOUNTER22, 48 | HPMCOUNTER23_CSR = CSR_HPMCOUNTER23, 49 | HPMCOUNTER24_CSR = CSR_HPMCOUNTER24, 50 | HPMCOUNTER25_CSR = CSR_HPMCOUNTER25, 51 | HPMCOUNTER26_CSR = CSR_HPMCOUNTER26, 52 | HPMCOUNTER27_CSR = CSR_HPMCOUNTER27, 53 | HPMCOUNTER28_CSR = CSR_HPMCOUNTER28, 54 | HPMCOUNTER29_CSR = CSR_HPMCOUNTER29, 55 | HPMCOUNTER30_CSR = CSR_HPMCOUNTER30, 56 | HPMCOUNTER31_CSR = CSR_HPMCOUNTER31, 57 | VL_CSR = CSR_VL, 58 | VTYPE_CSR = CSR_VTYPE, 59 | VLENB_CSR = CSR_VLENB, 60 | SSTATUS_CSR = CSR_SSTATUS, 61 | SEDELEG_CSR = CSR_SEDELEG, 62 | SIDELEG_CSR = CSR_SIDELEG, 63 | SIE_CSR = CSR_SIE, 64 | STVEC_CSR = CSR_STVEC, 65 | SCOUNTEREN_CSR = CSR_SCOUNTEREN, 66 | SENVCFG_CSR = CSR_SENVCFG, 67 | SSCRATCH_CSR = CSR_SSCRATCH, 68 | SEPC_CSR = CSR_SEPC, 69 | SCAUSE_CSR = CSR_SCAUSE, 70 | STVAL_CSR = CSR_STVAL, 71 | SIP_CSR = CSR_SIP, 72 | SATP_CSR = CSR_SATP, 73 | SCONTEXT_CSR = CSR_SCONTEXT, 74 | VSSTATUS_CSR = CSR_VSSTATUS, 75 | VSIE_CSR = CSR_VSIE, 76 | VSTVEC_CSR = CSR_VSTVEC, 77 | VSSCRATCH_CSR = CSR_VSSCRATCH, 78 | VSEPC_CSR = CSR_VSEPC, 79 | VSCAUSE_CSR = CSR_VSCAUSE, 80 | VSTVAL_CSR = CSR_VSTVAL, 81 | VSIP_CSR = CSR_VSIP, 82 | VSATP_CSR = CSR_VSATP, 83 | HSTATUS_CSR = CSR_HSTATUS, 84 | HEDELEG_CSR = CSR_HEDELEG, 85 | HIDELEG_CSR = CSR_HIDELEG, 86 | HIE_CSR = CSR_HIE, 87 | HTIMEDELTA_CSR = CSR_HTIMEDELTA, 88 | HCOUNTEREN_CSR = CSR_HCOUNTEREN, 89 | HGEIE_CSR = CSR_HGEIE, 90 | HENVCFG_CSR = CSR_HENVCFG, 91 | HTVAL_CSR = CSR_HTVAL, 92 | HIP_CSR = CSR_HIP, 93 | HVIP_CSR = CSR_HVIP, 94 | HTINST_CSR = CSR_HTINST, 95 | HGATP_CSR = CSR_HGATP, 96 | HCONTEXT_CSR = CSR_HCONTEXT, 97 | HGEIP_CSR = CSR_HGEIP, 98 | UTVT_CSR = CSR_UTVT, 99 | UNXTI_CSR = CSR_UNXTI, 100 | UINTSTATUS_CSR = CSR_UINTSTATUS, 101 | USCRATCHCSW_CSR = CSR_USCRATCHCSW, 102 | USCRATCHCSWL_CSR = CSR_USCRATCHCSWL, 103 | STVT_CSR = CSR_STVT, 104 | SNXTI_CSR = CSR_SNXTI, 105 | SINTSTATUS_CSR = CSR_SINTSTATUS, 106 | SSCRATCHCSW_CSR = CSR_SSCRATCHCSW, 107 | SSCRATCHCSWL_CSR = CSR_SSCRATCHCSWL, 108 | MTVT_CSR = CSR_MTVT, 109 | MNXTI_CSR = CSR_MNXTI, 110 | MINTSTATUS_CSR = CSR_MINTSTATUS, 111 | MSCRATCHCSW_CSR = CSR_MSCRATCHCSW, 112 | MSCRATCHCSWL_CSR = CSR_MSCRATCHCSWL, 113 | MSTATUS_CSR = CSR_MSTATUS, 114 | MISA_CSR = CSR_MISA, 115 | MEDELEG_CSR = CSR_MEDELEG, 116 | MIDELEG_CSR = CSR_MIDELEG, 117 | MIE_CSR = CSR_MIE, 118 | MTVEC_CSR = CSR_MTVEC, 119 | MCOUNTEREN_CSR = CSR_MCOUNTEREN, 120 | MENVCFG_CSR = CSR_MENVCFG, 121 | MCOUNTINHIBIT_CSR = CSR_MCOUNTINHIBIT, 122 | MSCRATCH_CSR = CSR_MSCRATCH, 123 | MEPC_CSR = CSR_MEPC, 124 | MCAUSE_CSR = CSR_MCAUSE, 125 | MTVAL_CSR = CSR_MTVAL, 126 | MIP_CSR = CSR_MIP, 127 | MTINST_CSR = CSR_MTINST, 128 | MTVAL2_CSR = CSR_MTVAL2, 129 | PMPCFG0_CSR = CSR_PMPCFG0, 130 | PMPCFG1_CSR = CSR_PMPCFG1, 131 | PMPCFG2_CSR = CSR_PMPCFG2, 132 | PMPCFG3_CSR = CSR_PMPCFG3, 133 | PMPCFG4_CSR = CSR_PMPCFG4, 134 | PMPCFG5_CSR = CSR_PMPCFG5, 135 | PMPCFG6_CSR = CSR_PMPCFG6, 136 | PMPCFG7_CSR = CSR_PMPCFG7, 137 | PMPCFG8_CSR = CSR_PMPCFG8, 138 | PMPCFG9_CSR = CSR_PMPCFG9, 139 | PMPCFG10_CSR = CSR_PMPCFG10, 140 | PMPCFG11_CSR = CSR_PMPCFG11, 141 | PMPCFG12_CSR = CSR_PMPCFG12, 142 | PMPCFG13_CSR = CSR_PMPCFG13, 143 | PMPCFG14_CSR = CSR_PMPCFG14, 144 | PMPCFG15_CSR = CSR_PMPCFG15, 145 | PMPADDR0_CSR = CSR_PMPADDR0, 146 | PMPADDR1_CSR = CSR_PMPADDR1, 147 | PMPADDR2_CSR = CSR_PMPADDR2, 148 | PMPADDR3_CSR = CSR_PMPADDR3, 149 | PMPADDR4_CSR = CSR_PMPADDR4, 150 | PMPADDR5_CSR = CSR_PMPADDR5, 151 | PMPADDR6_CSR = CSR_PMPADDR6, 152 | PMPADDR7_CSR = CSR_PMPADDR7, 153 | PMPADDR8_CSR = CSR_PMPADDR8, 154 | PMPADDR9_CSR = CSR_PMPADDR9, 155 | PMPADDR10_CSR = CSR_PMPADDR10, 156 | PMPADDR11_CSR = CSR_PMPADDR11, 157 | PMPADDR12_CSR = CSR_PMPADDR12, 158 | PMPADDR13_CSR = CSR_PMPADDR13, 159 | PMPADDR14_CSR = CSR_PMPADDR14, 160 | PMPADDR15_CSR = CSR_PMPADDR15, 161 | PMPADDR16_CSR = CSR_PMPADDR16, 162 | PMPADDR17_CSR = CSR_PMPADDR17, 163 | PMPADDR18_CSR = CSR_PMPADDR18, 164 | PMPADDR19_CSR = CSR_PMPADDR19, 165 | PMPADDR20_CSR = CSR_PMPADDR20, 166 | PMPADDR21_CSR = CSR_PMPADDR21, 167 | PMPADDR22_CSR = CSR_PMPADDR22, 168 | PMPADDR23_CSR = CSR_PMPADDR23, 169 | PMPADDR24_CSR = CSR_PMPADDR24, 170 | PMPADDR25_CSR = CSR_PMPADDR25, 171 | PMPADDR26_CSR = CSR_PMPADDR26, 172 | PMPADDR27_CSR = CSR_PMPADDR27, 173 | PMPADDR28_CSR = CSR_PMPADDR28, 174 | PMPADDR29_CSR = CSR_PMPADDR29, 175 | PMPADDR30_CSR = CSR_PMPADDR30, 176 | PMPADDR31_CSR = CSR_PMPADDR31, 177 | PMPADDR32_CSR = CSR_PMPADDR32, 178 | PMPADDR33_CSR = CSR_PMPADDR33, 179 | PMPADDR34_CSR = CSR_PMPADDR34, 180 | PMPADDR35_CSR = CSR_PMPADDR35, 181 | PMPADDR36_CSR = CSR_PMPADDR36, 182 | PMPADDR37_CSR = CSR_PMPADDR37, 183 | PMPADDR38_CSR = CSR_PMPADDR38, 184 | PMPADDR39_CSR = CSR_PMPADDR39, 185 | PMPADDR40_CSR = CSR_PMPADDR40, 186 | PMPADDR41_CSR = CSR_PMPADDR41, 187 | PMPADDR42_CSR = CSR_PMPADDR42, 188 | PMPADDR43_CSR = CSR_PMPADDR43, 189 | PMPADDR44_CSR = CSR_PMPADDR44, 190 | PMPADDR45_CSR = CSR_PMPADDR45, 191 | PMPADDR46_CSR = CSR_PMPADDR46, 192 | PMPADDR47_CSR = CSR_PMPADDR47, 193 | PMPADDR48_CSR = CSR_PMPADDR48, 194 | PMPADDR49_CSR = CSR_PMPADDR49, 195 | PMPADDR50_CSR = CSR_PMPADDR50, 196 | PMPADDR51_CSR = CSR_PMPADDR51, 197 | PMPADDR52_CSR = CSR_PMPADDR52, 198 | PMPADDR53_CSR = CSR_PMPADDR53, 199 | PMPADDR54_CSR = CSR_PMPADDR54, 200 | PMPADDR55_CSR = CSR_PMPADDR55, 201 | PMPADDR56_CSR = CSR_PMPADDR56, 202 | PMPADDR57_CSR = CSR_PMPADDR57, 203 | PMPADDR58_CSR = CSR_PMPADDR58, 204 | PMPADDR59_CSR = CSR_PMPADDR59, 205 | PMPADDR60_CSR = CSR_PMPADDR60, 206 | PMPADDR61_CSR = CSR_PMPADDR61, 207 | PMPADDR62_CSR = CSR_PMPADDR62, 208 | PMPADDR63_CSR = CSR_PMPADDR63, 209 | MSECCFG_CSR = CSR_MSECCFG, 210 | TSELECT_CSR = CSR_TSELECT, 211 | TDATA1_CSR = CSR_TDATA1, 212 | TDATA2_CSR = CSR_TDATA2, 213 | TDATA3_CSR = CSR_TDATA3, 214 | TINFO_CSR = CSR_TINFO, 215 | TCONTROL_CSR = CSR_TCONTROL, 216 | MCONTEXT_CSR = CSR_MCONTEXT, 217 | MSCONTEXT_CSR = CSR_MSCONTEXT, 218 | DCSR_CSR = CSR_DCSR, 219 | DPC_CSR = CSR_DPC, 220 | DSCRATCH0_CSR = CSR_DSCRATCH0, 221 | DSCRATCH1_CSR = CSR_DSCRATCH1, 222 | MCYCLE_CSR = CSR_MCYCLE, 223 | MINSTRET_CSR = CSR_MINSTRET, 224 | MHPMCOUNTER3_CSR = CSR_MHPMCOUNTER3, 225 | MHPMCOUNTER4_CSR = CSR_MHPMCOUNTER4, 226 | MHPMCOUNTER5_CSR = CSR_MHPMCOUNTER5, 227 | MHPMCOUNTER6_CSR = CSR_MHPMCOUNTER6, 228 | MHPMCOUNTER7_CSR = CSR_MHPMCOUNTER7, 229 | MHPMCOUNTER8_CSR = CSR_MHPMCOUNTER8, 230 | MHPMCOUNTER9_CSR = CSR_MHPMCOUNTER9, 231 | MHPMCOUNTER10_CSR = CSR_MHPMCOUNTER10, 232 | MHPMCOUNTER11_CSR = CSR_MHPMCOUNTER11, 233 | MHPMCOUNTER12_CSR = CSR_MHPMCOUNTER12, 234 | MHPMCOUNTER13_CSR = CSR_MHPMCOUNTER13, 235 | MHPMCOUNTER14_CSR = CSR_MHPMCOUNTER14, 236 | MHPMCOUNTER15_CSR = CSR_MHPMCOUNTER15, 237 | MHPMCOUNTER16_CSR = CSR_MHPMCOUNTER16, 238 | MHPMCOUNTER17_CSR = CSR_MHPMCOUNTER17, 239 | MHPMCOUNTER18_CSR = CSR_MHPMCOUNTER18, 240 | MHPMCOUNTER19_CSR = CSR_MHPMCOUNTER19, 241 | MHPMCOUNTER20_CSR = CSR_MHPMCOUNTER20, 242 | MHPMCOUNTER21_CSR = CSR_MHPMCOUNTER21, 243 | MHPMCOUNTER22_CSR = CSR_MHPMCOUNTER22, 244 | MHPMCOUNTER23_CSR = CSR_MHPMCOUNTER23, 245 | MHPMCOUNTER24_CSR = CSR_MHPMCOUNTER24, 246 | MHPMCOUNTER25_CSR = CSR_MHPMCOUNTER25, 247 | MHPMCOUNTER26_CSR = CSR_MHPMCOUNTER26, 248 | MHPMCOUNTER27_CSR = CSR_MHPMCOUNTER27, 249 | MHPMCOUNTER28_CSR = CSR_MHPMCOUNTER28, 250 | MHPMCOUNTER29_CSR = CSR_MHPMCOUNTER29, 251 | MHPMCOUNTER30_CSR = CSR_MHPMCOUNTER30, 252 | MHPMCOUNTER31_CSR = CSR_MHPMCOUNTER31, 253 | MHPMEVENT3_CSR = CSR_MHPMEVENT3, 254 | MHPMEVENT4_CSR = CSR_MHPMEVENT4, 255 | MHPMEVENT5_CSR = CSR_MHPMEVENT5, 256 | MHPMEVENT6_CSR = CSR_MHPMEVENT6, 257 | MHPMEVENT7_CSR = CSR_MHPMEVENT7, 258 | MHPMEVENT8_CSR = CSR_MHPMEVENT8, 259 | MHPMEVENT9_CSR = CSR_MHPMEVENT9, 260 | MHPMEVENT10_CSR = CSR_MHPMEVENT10, 261 | MHPMEVENT11_CSR = CSR_MHPMEVENT11, 262 | MHPMEVENT12_CSR = CSR_MHPMEVENT12, 263 | MHPMEVENT13_CSR = CSR_MHPMEVENT13, 264 | MHPMEVENT14_CSR = CSR_MHPMEVENT14, 265 | MHPMEVENT15_CSR = CSR_MHPMEVENT15, 266 | MHPMEVENT16_CSR = CSR_MHPMEVENT16, 267 | MHPMEVENT17_CSR = CSR_MHPMEVENT17, 268 | MHPMEVENT18_CSR = CSR_MHPMEVENT18, 269 | MHPMEVENT19_CSR = CSR_MHPMEVENT19, 270 | MHPMEVENT20_CSR = CSR_MHPMEVENT20, 271 | MHPMEVENT21_CSR = CSR_MHPMEVENT21, 272 | MHPMEVENT22_CSR = CSR_MHPMEVENT22, 273 | MHPMEVENT23_CSR = CSR_MHPMEVENT23, 274 | MHPMEVENT24_CSR = CSR_MHPMEVENT24, 275 | MHPMEVENT25_CSR = CSR_MHPMEVENT25, 276 | MHPMEVENT26_CSR = CSR_MHPMEVENT26, 277 | MHPMEVENT27_CSR = CSR_MHPMEVENT27, 278 | MHPMEVENT28_CSR = CSR_MHPMEVENT28, 279 | MHPMEVENT29_CSR = CSR_MHPMEVENT29, 280 | MHPMEVENT30_CSR = CSR_MHPMEVENT30, 281 | MHPMEVENT31_CSR = CSR_MHPMEVENT31, 282 | MVENDORID_CSR = CSR_MVENDORID, 283 | MARCHID_CSR = CSR_MARCHID, 284 | MIMPID_CSR = CSR_MIMPID, 285 | MHARTID_CSR = CSR_MHARTID, 286 | MCONFIGPTR_CSR = CSR_MCONFIGPTR, 287 | HTIMEDELTAH_CSR = CSR_HTIMEDELTAH, 288 | HENVCFGH_CSR = CSR_HENVCFGH, 289 | CYCLEH_CSR = CSR_CYCLEH, 290 | TIMEH_CSR = CSR_TIMEH, 291 | INSTRETH_CSR = CSR_INSTRETH, 292 | HPMCOUNTER3H_CSR = CSR_HPMCOUNTER3H, 293 | HPMCOUNTER4H_CSR = CSR_HPMCOUNTER4H, 294 | HPMCOUNTER5H_CSR = CSR_HPMCOUNTER5H, 295 | HPMCOUNTER6H_CSR = CSR_HPMCOUNTER6H, 296 | HPMCOUNTER7H_CSR = CSR_HPMCOUNTER7H, 297 | HPMCOUNTER8H_CSR = CSR_HPMCOUNTER8H, 298 | HPMCOUNTER9H_CSR = CSR_HPMCOUNTER9H, 299 | HPMCOUNTER10H_CSR = CSR_HPMCOUNTER10H, 300 | HPMCOUNTER11H_CSR = CSR_HPMCOUNTER11H, 301 | HPMCOUNTER12H_CSR = CSR_HPMCOUNTER12H, 302 | HPMCOUNTER13H_CSR = CSR_HPMCOUNTER13H, 303 | HPMCOUNTER14H_CSR = CSR_HPMCOUNTER14H, 304 | HPMCOUNTER15H_CSR = CSR_HPMCOUNTER15H, 305 | HPMCOUNTER16H_CSR = CSR_HPMCOUNTER16H, 306 | HPMCOUNTER17H_CSR = CSR_HPMCOUNTER17H, 307 | HPMCOUNTER18H_CSR = CSR_HPMCOUNTER18H, 308 | HPMCOUNTER19H_CSR = CSR_HPMCOUNTER19H, 309 | HPMCOUNTER20H_CSR = CSR_HPMCOUNTER20H, 310 | HPMCOUNTER21H_CSR = CSR_HPMCOUNTER21H, 311 | HPMCOUNTER22H_CSR = CSR_HPMCOUNTER22H, 312 | HPMCOUNTER23H_CSR = CSR_HPMCOUNTER23H, 313 | HPMCOUNTER24H_CSR = CSR_HPMCOUNTER24H, 314 | HPMCOUNTER25H_CSR = CSR_HPMCOUNTER25H, 315 | HPMCOUNTER26H_CSR = CSR_HPMCOUNTER26H, 316 | HPMCOUNTER27H_CSR = CSR_HPMCOUNTER27H, 317 | HPMCOUNTER28H_CSR = CSR_HPMCOUNTER28H, 318 | HPMCOUNTER29H_CSR = CSR_HPMCOUNTER29H, 319 | HPMCOUNTER30H_CSR = CSR_HPMCOUNTER30H, 320 | HPMCOUNTER31H_CSR = CSR_HPMCOUNTER31H, 321 | MSTATUSH_CSR = CSR_MSTATUSH, 322 | MENVCFGH_CSR = CSR_MENVCFGH, 323 | MSECCFGH_CSR = CSR_MSECCFGH, 324 | MCYCLEH_CSR = CSR_MCYCLEH, 325 | MINSTRETH_CSR = CSR_MINSTRETH, 326 | MHPMCOUNTER3H_CSR = CSR_MHPMCOUNTER3H, 327 | MHPMCOUNTER4H_CSR = CSR_MHPMCOUNTER4H, 328 | MHPMCOUNTER5H_CSR = CSR_MHPMCOUNTER5H, 329 | MHPMCOUNTER6H_CSR = CSR_MHPMCOUNTER6H, 330 | MHPMCOUNTER7H_CSR = CSR_MHPMCOUNTER7H, 331 | MHPMCOUNTER8H_CSR = CSR_MHPMCOUNTER8H, 332 | MHPMCOUNTER9H_CSR = CSR_MHPMCOUNTER9H, 333 | MHPMCOUNTER10H_CSR = CSR_MHPMCOUNTER10H, 334 | MHPMCOUNTER11H_CSR = CSR_MHPMCOUNTER11H, 335 | MHPMCOUNTER12H_CSR = CSR_MHPMCOUNTER12H, 336 | MHPMCOUNTER13H_CSR = CSR_MHPMCOUNTER13H, 337 | MHPMCOUNTER14H_CSR = CSR_MHPMCOUNTER14H, 338 | MHPMCOUNTER15H_CSR = CSR_MHPMCOUNTER15H, 339 | MHPMCOUNTER16H_CSR = CSR_MHPMCOUNTER16H, 340 | MHPMCOUNTER17H_CSR = CSR_MHPMCOUNTER17H, 341 | MHPMCOUNTER18H_CSR = CSR_MHPMCOUNTER18H, 342 | MHPMCOUNTER19H_CSR = CSR_MHPMCOUNTER19H, 343 | MHPMCOUNTER20H_CSR = CSR_MHPMCOUNTER20H, 344 | MHPMCOUNTER21H_CSR = CSR_MHPMCOUNTER21H, 345 | MHPMCOUNTER22H_CSR = CSR_MHPMCOUNTER22H, 346 | MHPMCOUNTER23H_CSR = CSR_MHPMCOUNTER23H, 347 | MHPMCOUNTER24H_CSR = CSR_MHPMCOUNTER24H, 348 | MHPMCOUNTER25H_CSR = CSR_MHPMCOUNTER25H, 349 | MHPMCOUNTER26H_CSR = CSR_MHPMCOUNTER26H, 350 | MHPMCOUNTER27H_CSR = CSR_MHPMCOUNTER27H, 351 | MHPMCOUNTER28H_CSR = CSR_MHPMCOUNTER28H, 352 | MHPMCOUNTER29H_CSR = CSR_MHPMCOUNTER29H, 353 | MHPMCOUNTER30H_CSR = CSR_MHPMCOUNTER30H, 354 | MHPMCOUNTER31H_CSR = CSR_MHPMCOUNTER31H 355 | }; 356 | -------------------------------------------------------------------------------- /hammer_pybind.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | #include 8 | #include 9 | 10 | PYBIND11_MODULE(hammer, m) { 11 | m.doc() = "Hammer Python Interface"; 12 | 13 | pybind11::class_(m, "mem_cfg_t").def(pybind11::init()); 14 | 15 | pybind11::class_(m, "mem_t").def(pybind11::init()); 16 | 17 | pybind11::class_(m, "Hammer") 18 | .def(pybind11::init, 19 | std::vector, const std::string, 20 | const std::optional>()) 21 | .def("hello_world", &Hammer::hello_world) 22 | .def("get_gpr", &Hammer::get_gpr) 23 | .def("set_gpr", &Hammer::set_gpr) 24 | .def("get_fpr", &Hammer::get_fpr) 25 | .def("get_PC", &Hammer::get_PC) 26 | .def("set_PC", &Hammer::set_PC) 27 | .def("get_csr", &Hammer::get_csr) 28 | .def("get_flen", &Hammer::get_flen) 29 | .def("get_vlen", &Hammer::get_vlen) 30 | .def("get_elen", &Hammer::get_elen) 31 | .def("get_vector_reg", &Hammer::get_vector_reg) 32 | .def("get_memory_at_VA", 33 | [](Hammer &h, uint8_t hart_id, uint64_t virtual_address, size_t num_bytes_to_read, 34 | size_t stride) -> pybind11::object { 35 | switch (stride) { 36 | case 1: 37 | return pybind11::cast( 38 | h.get_memory_at_VA(hart_id, virtual_address, num_bytes_to_read)); 39 | case 2: 40 | return pybind11::cast( 41 | h.get_memory_at_VA(hart_id, virtual_address, num_bytes_to_read)); 42 | case 4: 43 | return pybind11::cast( 44 | h.get_memory_at_VA(hart_id, virtual_address, num_bytes_to_read)); 45 | case 8: 46 | return pybind11::cast( 47 | h.get_memory_at_VA(hart_id, virtual_address, num_bytes_to_read)); 48 | default: 49 | throw std::length_error("Invalid stride"); 50 | } 51 | return pybind11::none(); 52 | }) 53 | .def("set_memory_at_VA", 54 | [](Hammer &h, uint8_t hart_id, uint64_t virtual_address, pybind11::list &data, 55 | size_t stride) { 56 | switch (stride) { 57 | case 1: 58 | return h.set_memory_at_VA(hart_id, virtual_address, 59 | data.cast>()); 60 | case 2: 61 | return h.set_memory_at_VA(hart_id, virtual_address, 62 | data.cast>()); 63 | case 4: 64 | return h.set_memory_at_VA(hart_id, virtual_address, 65 | data.cast>()); 66 | case 8: 67 | return h.set_memory_at_VA(hart_id, virtual_address, 68 | data.cast>()); 69 | default: 70 | throw std::length_error("Invalid stride"); 71 | } 72 | return -EINVAL; 73 | }) 74 | .def("single_step", &Hammer::single_step); 75 | 76 | // Reference: 77 | // https://stackoverflow.com/questions/47893832/pybind11-global-level-enum 78 | pybind11::enum_(m, "PlatformDefines") 79 | .value("DramBase", DramBase) 80 | .export_values(); 81 | 82 | pybind11::enum_(m, "CsrDefines") 83 | .value("FFLAGS_CSR", FFLAGS_CSR) 84 | .export_values() 85 | .value("FRM_CSR", FRM_CSR) 86 | .export_values() 87 | .value("FCSR_CSR", FCSR_CSR) 88 | .export_values() 89 | .value("VSTART_CSR", VSTART_CSR) 90 | .export_values() 91 | .value("VXSAT_CSR", VXSAT_CSR) 92 | .export_values() 93 | .value("VXRM_CSR", VXRM_CSR) 94 | .export_values() 95 | .value("VCSR_CSR", VCSR_CSR) 96 | .export_values() 97 | .value("SEED_CSR", SEED_CSR) 98 | .export_values() 99 | .value("CYCLE_CSR", CYCLE_CSR) 100 | .export_values() 101 | .value("TIME_CSR", TIME_CSR) 102 | .export_values() 103 | .value("INSTRET_CSR", INSTRET_CSR) 104 | .export_values() 105 | .value("HPMCOUNTER3_CSR", HPMCOUNTER3_CSR) 106 | .export_values() 107 | .value("HPMCOUNTER4_CSR", HPMCOUNTER4_CSR) 108 | .export_values() 109 | .value("HPMCOUNTER5_CSR", HPMCOUNTER5_CSR) 110 | .export_values() 111 | .value("HPMCOUNTER6_CSR", HPMCOUNTER6_CSR) 112 | .export_values() 113 | .value("HPMCOUNTER7_CSR", HPMCOUNTER7_CSR) 114 | .export_values() 115 | .value("HPMCOUNTER8_CSR", HPMCOUNTER8_CSR) 116 | .export_values() 117 | .value("HPMCOUNTER9_CSR", HPMCOUNTER9_CSR) 118 | .export_values() 119 | .value("HPMCOUNTER10_CSR", HPMCOUNTER10_CSR) 120 | .export_values() 121 | .value("HPMCOUNTER11_CSR", HPMCOUNTER11_CSR) 122 | .export_values() 123 | .value("HPMCOUNTER12_CSR", HPMCOUNTER12_CSR) 124 | .export_values() 125 | .value("HPMCOUNTER13_CSR", HPMCOUNTER13_CSR) 126 | .export_values() 127 | .value("HPMCOUNTER14_CSR", HPMCOUNTER14_CSR) 128 | .export_values() 129 | .value("HPMCOUNTER15_CSR", HPMCOUNTER15_CSR) 130 | .export_values() 131 | .value("HPMCOUNTER16_CSR", HPMCOUNTER16_CSR) 132 | .export_values() 133 | .value("HPMCOUNTER17_CSR", HPMCOUNTER17_CSR) 134 | .export_values() 135 | .value("HPMCOUNTER18_CSR", HPMCOUNTER18_CSR) 136 | .export_values() 137 | .value("HPMCOUNTER19_CSR", HPMCOUNTER19_CSR) 138 | .export_values() 139 | .value("HPMCOUNTER20_CSR", HPMCOUNTER20_CSR) 140 | .export_values() 141 | .value("HPMCOUNTER21_CSR", HPMCOUNTER21_CSR) 142 | .export_values() 143 | .value("HPMCOUNTER22_CSR", HPMCOUNTER22_CSR) 144 | .export_values() 145 | .value("HPMCOUNTER23_CSR", HPMCOUNTER23_CSR) 146 | .export_values() 147 | .value("HPMCOUNTER24_CSR", HPMCOUNTER24_CSR) 148 | .export_values() 149 | .value("HPMCOUNTER25_CSR", HPMCOUNTER25_CSR) 150 | .export_values() 151 | .value("HPMCOUNTER26_CSR", HPMCOUNTER26_CSR) 152 | .export_values() 153 | .value("HPMCOUNTER27_CSR", HPMCOUNTER27_CSR) 154 | .export_values() 155 | .value("HPMCOUNTER28_CSR", HPMCOUNTER28_CSR) 156 | .export_values() 157 | .value("HPMCOUNTER29_CSR", HPMCOUNTER29_CSR) 158 | .export_values() 159 | .value("HPMCOUNTER30_CSR", HPMCOUNTER30_CSR) 160 | .export_values() 161 | .value("HPMCOUNTER31_CSR", HPMCOUNTER31_CSR) 162 | .export_values() 163 | .value("VL_CSR", VL_CSR) 164 | .export_values() 165 | .value("VTYPE_CSR", VTYPE_CSR) 166 | .export_values() 167 | .value("VLENB_CSR", VLENB_CSR) 168 | .export_values() 169 | .value("SSTATUS_CSR", SSTATUS_CSR) 170 | .export_values() 171 | .value("SEDELEG_CSR", SEDELEG_CSR) 172 | .export_values() 173 | .value("SIDELEG_CSR", SIDELEG_CSR) 174 | .export_values() 175 | .value("SIE_CSR", SIE_CSR) 176 | .export_values() 177 | .value("STVEC_CSR", STVEC_CSR) 178 | .export_values() 179 | .value("SCOUNTEREN_CSR", SCOUNTEREN_CSR) 180 | .export_values() 181 | .value("SENVCFG_CSR", SENVCFG_CSR) 182 | .export_values() 183 | .value("SSCRATCH_CSR", SSCRATCH_CSR) 184 | .export_values() 185 | .value("SEPC_CSR", SEPC_CSR) 186 | .export_values() 187 | .value("SCAUSE_CSR", SCAUSE_CSR) 188 | .export_values() 189 | .value("STVAL_CSR", STVAL_CSR) 190 | .export_values() 191 | .value("SIP_CSR", SIP_CSR) 192 | .export_values() 193 | .value("SATP_CSR", SATP_CSR) 194 | .export_values() 195 | .value("SCONTEXT_CSR", SCONTEXT_CSR) 196 | .export_values() 197 | .value("VSSTATUS_CSR", VSSTATUS_CSR) 198 | .export_values() 199 | .value("VSIE_CSR", VSIE_CSR) 200 | .export_values() 201 | .value("VSTVEC_CSR", VSTVEC_CSR) 202 | .export_values() 203 | .value("VSSCRATCH_CSR", VSSCRATCH_CSR) 204 | .export_values() 205 | .value("VSEPC_CSR", VSEPC_CSR) 206 | .export_values() 207 | .value("VSCAUSE_CSR", VSCAUSE_CSR) 208 | .export_values() 209 | .value("VSTVAL_CSR", VSTVAL_CSR) 210 | .export_values() 211 | .value("VSIP_CSR", VSIP_CSR) 212 | .export_values() 213 | .value("VSATP_CSR", VSATP_CSR) 214 | .export_values() 215 | .value("HSTATUS_CSR", HSTATUS_CSR) 216 | .export_values() 217 | .value("HEDELEG_CSR", HEDELEG_CSR) 218 | .export_values() 219 | .value("HIDELEG_CSR", HIDELEG_CSR) 220 | .export_values() 221 | .value("HIE_CSR", HIE_CSR) 222 | .export_values() 223 | .value("HTIMEDELTA_CSR", HTIMEDELTA_CSR) 224 | .export_values() 225 | .value("HCOUNTEREN_CSR", HCOUNTEREN_CSR) 226 | .export_values() 227 | .value("HGEIE_CSR", HGEIE_CSR) 228 | .export_values() 229 | .value("HENVCFG_CSR", HENVCFG_CSR) 230 | .export_values() 231 | .value("HTVAL_CSR", HTVAL_CSR) 232 | .export_values() 233 | .value("HIP_CSR", HIP_CSR) 234 | .export_values() 235 | .value("HVIP_CSR", HVIP_CSR) 236 | .export_values() 237 | .value("HTINST_CSR", HTINST_CSR) 238 | .export_values() 239 | .value("HGATP_CSR", HGATP_CSR) 240 | .export_values() 241 | .value("HCONTEXT_CSR", HCONTEXT_CSR) 242 | .export_values() 243 | .value("HGEIP_CSR", HGEIP_CSR) 244 | .export_values() 245 | .value("UTVT_CSR", UTVT_CSR) 246 | .export_values() 247 | .value("UNXTI_CSR", UNXTI_CSR) 248 | .export_values() 249 | .value("UINTSTATUS_CSR", UINTSTATUS_CSR) 250 | .export_values() 251 | .value("USCRATCHCSW_CSR", USCRATCHCSW_CSR) 252 | .export_values() 253 | .value("USCRATCHCSWL_CSR", USCRATCHCSWL_CSR) 254 | .export_values() 255 | .value("STVT_CSR", STVT_CSR) 256 | .export_values() 257 | .value("SNXTI_CSR", SNXTI_CSR) 258 | .export_values() 259 | .value("SINTSTATUS_CSR", SINTSTATUS_CSR) 260 | .export_values() 261 | .value("SSCRATCHCSW_CSR", SSCRATCHCSW_CSR) 262 | .export_values() 263 | .value("SSCRATCHCSWL_CSR", SSCRATCHCSWL_CSR) 264 | .export_values() 265 | .value("MTVT_CSR", MTVT_CSR) 266 | .export_values() 267 | .value("MNXTI_CSR", MNXTI_CSR) 268 | .export_values() 269 | .value("MINTSTATUS_CSR", MINTSTATUS_CSR) 270 | .export_values() 271 | .value("MSCRATCHCSW_CSR", MSCRATCHCSW_CSR) 272 | .export_values() 273 | .value("MSCRATCHCSWL_CSR", MSCRATCHCSWL_CSR) 274 | .export_values() 275 | .value("MSTATUS_CSR", MSTATUS_CSR) 276 | .export_values() 277 | .value("MISA_CSR", MISA_CSR) 278 | .export_values() 279 | .value("MEDELEG_CSR", MEDELEG_CSR) 280 | .export_values() 281 | .value("MIDELEG_CSR", MIDELEG_CSR) 282 | .export_values() 283 | .value("MIE_CSR", MIE_CSR) 284 | .export_values() 285 | .value("MTVEC_CSR", MTVEC_CSR) 286 | .export_values() 287 | .value("MCOUNTEREN_CSR", MCOUNTEREN_CSR) 288 | .export_values() 289 | .value("MENVCFG_CSR", MENVCFG_CSR) 290 | .export_values() 291 | .value("MCOUNTINHIBIT_CSR", MCOUNTINHIBIT_CSR) 292 | .export_values() 293 | .value("MSCRATCH_CSR", MSCRATCH_CSR) 294 | .export_values() 295 | .value("MEPC_CSR", MEPC_CSR) 296 | .export_values() 297 | .value("MCAUSE_CSR", MCAUSE_CSR) 298 | .export_values() 299 | .value("MTVAL_CSR", MTVAL_CSR) 300 | .export_values() 301 | .value("MIP_CSR", MIP_CSR) 302 | .export_values() 303 | .value("MTINST_CSR", MTINST_CSR) 304 | .export_values() 305 | .value("MTVAL2_CSR", MTVAL2_CSR) 306 | .export_values() 307 | .value("PMPCFG0_CSR", PMPCFG0_CSR) 308 | .export_values() 309 | .value("PMPCFG1_CSR", PMPCFG1_CSR) 310 | .export_values() 311 | .value("PMPCFG2_CSR", PMPCFG2_CSR) 312 | .export_values() 313 | .value("PMPCFG3_CSR", PMPCFG3_CSR) 314 | .export_values() 315 | .value("PMPCFG4_CSR", PMPCFG4_CSR) 316 | .export_values() 317 | .value("PMPCFG5_CSR", PMPCFG5_CSR) 318 | .export_values() 319 | .value("PMPCFG6_CSR", PMPCFG6_CSR) 320 | .export_values() 321 | .value("PMPCFG7_CSR", PMPCFG7_CSR) 322 | .export_values() 323 | .value("PMPCFG8_CSR", PMPCFG8_CSR) 324 | .export_values() 325 | .value("PMPCFG9_CSR", PMPCFG9_CSR) 326 | .export_values() 327 | .value("PMPCFG10_CSR", PMPCFG10_CSR) 328 | .export_values() 329 | .value("PMPCFG11_CSR", PMPCFG11_CSR) 330 | .export_values() 331 | .value("PMPCFG12_CSR", PMPCFG12_CSR) 332 | .export_values() 333 | .value("PMPCFG13_CSR", PMPCFG13_CSR) 334 | .export_values() 335 | .value("PMPCFG14_CSR", PMPCFG14_CSR) 336 | .export_values() 337 | .value("PMPCFG15_CSR", PMPCFG15_CSR) 338 | .export_values() 339 | .value("PMPADDR0_CSR", PMPADDR0_CSR) 340 | .export_values() 341 | .value("PMPADDR1_CSR", PMPADDR1_CSR) 342 | .export_values() 343 | .value("PMPADDR2_CSR", PMPADDR2_CSR) 344 | .export_values() 345 | .value("PMPADDR3_CSR", PMPADDR3_CSR) 346 | .export_values() 347 | .value("PMPADDR4_CSR", PMPADDR4_CSR) 348 | .export_values() 349 | .value("PMPADDR5_CSR", PMPADDR5_CSR) 350 | .export_values() 351 | .value("PMPADDR6_CSR", PMPADDR6_CSR) 352 | .export_values() 353 | .value("PMPADDR7_CSR", PMPADDR7_CSR) 354 | .export_values() 355 | .value("PMPADDR8_CSR", PMPADDR8_CSR) 356 | .export_values() 357 | .value("PMPADDR9_CSR", PMPADDR9_CSR) 358 | .export_values() 359 | .value("PMPADDR10_CSR", PMPADDR10_CSR) 360 | .export_values() 361 | .value("PMPADDR11_CSR", PMPADDR11_CSR) 362 | .export_values() 363 | .value("PMPADDR12_CSR", PMPADDR12_CSR) 364 | .export_values() 365 | .value("PMPADDR13_CSR", PMPADDR13_CSR) 366 | .export_values() 367 | .value("PMPADDR14_CSR", PMPADDR14_CSR) 368 | .export_values() 369 | .value("PMPADDR15_CSR", PMPADDR15_CSR) 370 | .export_values() 371 | .value("PMPADDR16_CSR", PMPADDR16_CSR) 372 | .export_values() 373 | .value("PMPADDR17_CSR", PMPADDR17_CSR) 374 | .export_values() 375 | .value("PMPADDR18_CSR", PMPADDR18_CSR) 376 | .export_values() 377 | .value("PMPADDR19_CSR", PMPADDR19_CSR) 378 | .export_values() 379 | .value("PMPADDR20_CSR", PMPADDR20_CSR) 380 | .export_values() 381 | .value("PMPADDR21_CSR", PMPADDR21_CSR) 382 | .export_values() 383 | .value("PMPADDR22_CSR", PMPADDR22_CSR) 384 | .export_values() 385 | .value("PMPADDR23_CSR", PMPADDR23_CSR) 386 | .export_values() 387 | .value("PMPADDR24_CSR", PMPADDR24_CSR) 388 | .export_values() 389 | .value("PMPADDR25_CSR", PMPADDR25_CSR) 390 | .export_values() 391 | .value("PMPADDR26_CSR", PMPADDR26_CSR) 392 | .export_values() 393 | .value("PMPADDR27_CSR", PMPADDR27_CSR) 394 | .export_values() 395 | .value("PMPADDR28_CSR", PMPADDR28_CSR) 396 | .export_values() 397 | .value("PMPADDR29_CSR", PMPADDR29_CSR) 398 | .export_values() 399 | .value("PMPADDR30_CSR", PMPADDR30_CSR) 400 | .export_values() 401 | .value("PMPADDR31_CSR", PMPADDR31_CSR) 402 | .export_values() 403 | .value("PMPADDR32_CSR", PMPADDR32_CSR) 404 | .export_values() 405 | .value("PMPADDR33_CSR", PMPADDR33_CSR) 406 | .export_values() 407 | .value("PMPADDR34_CSR", PMPADDR34_CSR) 408 | .export_values() 409 | .value("PMPADDR35_CSR", PMPADDR35_CSR) 410 | .export_values() 411 | .value("PMPADDR36_CSR", PMPADDR36_CSR) 412 | .export_values() 413 | .value("PMPADDR37_CSR", PMPADDR37_CSR) 414 | .export_values() 415 | .value("PMPADDR38_CSR", PMPADDR38_CSR) 416 | .export_values() 417 | .value("PMPADDR39_CSR", PMPADDR39_CSR) 418 | .export_values() 419 | .value("PMPADDR40_CSR", PMPADDR40_CSR) 420 | .export_values() 421 | .value("PMPADDR41_CSR", PMPADDR41_CSR) 422 | .export_values() 423 | .value("PMPADDR42_CSR", PMPADDR42_CSR) 424 | .export_values() 425 | .value("PMPADDR43_CSR", PMPADDR43_CSR) 426 | .export_values() 427 | .value("PMPADDR44_CSR", PMPADDR44_CSR) 428 | .export_values() 429 | .value("PMPADDR45_CSR", PMPADDR45_CSR) 430 | .export_values() 431 | .value("PMPADDR46_CSR", PMPADDR46_CSR) 432 | .export_values() 433 | .value("PMPADDR47_CSR", PMPADDR47_CSR) 434 | .export_values() 435 | .value("PMPADDR48_CSR", PMPADDR48_CSR) 436 | .export_values() 437 | .value("PMPADDR49_CSR", PMPADDR49_CSR) 438 | .export_values() 439 | .value("PMPADDR50_CSR", PMPADDR50_CSR) 440 | .export_values() 441 | .value("PMPADDR51_CSR", PMPADDR51_CSR) 442 | .export_values() 443 | .value("PMPADDR52_CSR", PMPADDR52_CSR) 444 | .export_values() 445 | .value("PMPADDR53_CSR", PMPADDR53_CSR) 446 | .export_values() 447 | .value("PMPADDR54_CSR", PMPADDR54_CSR) 448 | .export_values() 449 | .value("PMPADDR55_CSR", PMPADDR55_CSR) 450 | .export_values() 451 | .value("PMPADDR56_CSR", PMPADDR56_CSR) 452 | .export_values() 453 | .value("PMPADDR57_CSR", PMPADDR57_CSR) 454 | .export_values() 455 | .value("PMPADDR58_CSR", PMPADDR58_CSR) 456 | .export_values() 457 | .value("PMPADDR59_CSR", PMPADDR59_CSR) 458 | .export_values() 459 | .value("PMPADDR60_CSR", PMPADDR60_CSR) 460 | .export_values() 461 | .value("PMPADDR61_CSR", PMPADDR61_CSR) 462 | .export_values() 463 | .value("PMPADDR62_CSR", PMPADDR62_CSR) 464 | .export_values() 465 | .value("PMPADDR63_CSR", PMPADDR63_CSR) 466 | .export_values() 467 | .value("MSECCFG_CSR", MSECCFG_CSR) 468 | .export_values() 469 | .value("TSELECT_CSR", TSELECT_CSR) 470 | .export_values() 471 | .value("TDATA1_CSR", TDATA1_CSR) 472 | .export_values() 473 | .value("TDATA2_CSR", TDATA2_CSR) 474 | .export_values() 475 | .value("TDATA3_CSR", TDATA3_CSR) 476 | .export_values() 477 | .value("TINFO_CSR", TINFO_CSR) 478 | .export_values() 479 | .value("TCONTROL_CSR", TCONTROL_CSR) 480 | .export_values() 481 | .value("MCONTEXT_CSR", MCONTEXT_CSR) 482 | .export_values() 483 | .value("MSCONTEXT_CSR", MSCONTEXT_CSR) 484 | .export_values() 485 | .value("DCSR_CSR", DCSR_CSR) 486 | .export_values() 487 | .value("DPC_CSR", DPC_CSR) 488 | .export_values() 489 | .value("DSCRATCH0_CSR", DSCRATCH0_CSR) 490 | .export_values() 491 | .value("DSCRATCH1_CSR", DSCRATCH1_CSR) 492 | .export_values() 493 | .value("MCYCLE_CSR", MCYCLE_CSR) 494 | .export_values() 495 | .value("MINSTRET_CSR", MINSTRET_CSR) 496 | .export_values() 497 | .value("MHPMCOUNTER3_CSR", MHPMCOUNTER3_CSR) 498 | .export_values() 499 | .value("MHPMCOUNTER4_CSR", MHPMCOUNTER4_CSR) 500 | .export_values() 501 | .value("MHPMCOUNTER5_CSR", MHPMCOUNTER5_CSR) 502 | .export_values() 503 | .value("MHPMCOUNTER6_CSR", MHPMCOUNTER6_CSR) 504 | .export_values() 505 | .value("MHPMCOUNTER7_CSR", MHPMCOUNTER7_CSR) 506 | .export_values() 507 | .value("MHPMCOUNTER8_CSR", MHPMCOUNTER8_CSR) 508 | .export_values() 509 | .value("MHPMCOUNTER9_CSR", MHPMCOUNTER9_CSR) 510 | .export_values() 511 | .value("MHPMCOUNTER10_CSR", MHPMCOUNTER10_CSR) 512 | .export_values() 513 | .value("MHPMCOUNTER11_CSR", MHPMCOUNTER11_CSR) 514 | .export_values() 515 | .value("MHPMCOUNTER12_CSR", MHPMCOUNTER12_CSR) 516 | .export_values() 517 | .value("MHPMCOUNTER13_CSR", MHPMCOUNTER13_CSR) 518 | .export_values() 519 | .value("MHPMCOUNTER14_CSR", MHPMCOUNTER14_CSR) 520 | .export_values() 521 | .value("MHPMCOUNTER15_CSR", MHPMCOUNTER15_CSR) 522 | .export_values() 523 | .value("MHPMCOUNTER16_CSR", MHPMCOUNTER16_CSR) 524 | .export_values() 525 | .value("MHPMCOUNTER17_CSR", MHPMCOUNTER17_CSR) 526 | .export_values() 527 | .value("MHPMCOUNTER18_CSR", MHPMCOUNTER18_CSR) 528 | .export_values() 529 | .value("MHPMCOUNTER19_CSR", MHPMCOUNTER19_CSR) 530 | .export_values() 531 | .value("MHPMCOUNTER20_CSR", MHPMCOUNTER20_CSR) 532 | .export_values() 533 | .value("MHPMCOUNTER21_CSR", MHPMCOUNTER21_CSR) 534 | .export_values() 535 | .value("MHPMCOUNTER22_CSR", MHPMCOUNTER22_CSR) 536 | .export_values() 537 | .value("MHPMCOUNTER23_CSR", MHPMCOUNTER23_CSR) 538 | .export_values() 539 | .value("MHPMCOUNTER24_CSR", MHPMCOUNTER24_CSR) 540 | .export_values() 541 | .value("MHPMCOUNTER25_CSR", MHPMCOUNTER25_CSR) 542 | .export_values() 543 | .value("MHPMCOUNTER26_CSR", MHPMCOUNTER26_CSR) 544 | .export_values() 545 | .value("MHPMCOUNTER27_CSR", MHPMCOUNTER27_CSR) 546 | .export_values() 547 | .value("MHPMCOUNTER28_CSR", MHPMCOUNTER28_CSR) 548 | .export_values() 549 | .value("MHPMCOUNTER29_CSR", MHPMCOUNTER29_CSR) 550 | .export_values() 551 | .value("MHPMCOUNTER30_CSR", MHPMCOUNTER30_CSR) 552 | .export_values() 553 | .value("MHPMCOUNTER31_CSR", MHPMCOUNTER31_CSR) 554 | .export_values() 555 | .value("MHPMEVENT3_CSR", MHPMEVENT3_CSR) 556 | .export_values() 557 | .value("MHPMEVENT4_CSR", MHPMEVENT4_CSR) 558 | .export_values() 559 | .value("MHPMEVENT5_CSR", MHPMEVENT5_CSR) 560 | .export_values() 561 | .value("MHPMEVENT6_CSR", MHPMEVENT6_CSR) 562 | .export_values() 563 | .value("MHPMEVENT7_CSR", MHPMEVENT7_CSR) 564 | .export_values() 565 | .value("MHPMEVENT8_CSR", MHPMEVENT8_CSR) 566 | .export_values() 567 | .value("MHPMEVENT9_CSR", MHPMEVENT9_CSR) 568 | .export_values() 569 | .value("MHPMEVENT10_CSR", MHPMEVENT10_CSR) 570 | .export_values() 571 | .value("MHPMEVENT11_CSR", MHPMEVENT11_CSR) 572 | .export_values() 573 | .value("MHPMEVENT12_CSR", MHPMEVENT12_CSR) 574 | .export_values() 575 | .value("MHPMEVENT13_CSR", MHPMEVENT13_CSR) 576 | .export_values() 577 | .value("MHPMEVENT14_CSR", MHPMEVENT14_CSR) 578 | .export_values() 579 | .value("MHPMEVENT15_CSR", MHPMEVENT15_CSR) 580 | .export_values() 581 | .value("MHPMEVENT16_CSR", MHPMEVENT16_CSR) 582 | .export_values() 583 | .value("MHPMEVENT17_CSR", MHPMEVENT17_CSR) 584 | .export_values() 585 | .value("MHPMEVENT18_CSR", MHPMEVENT18_CSR) 586 | .export_values() 587 | .value("MHPMEVENT19_CSR", MHPMEVENT19_CSR) 588 | .export_values() 589 | .value("MHPMEVENT20_CSR", MHPMEVENT20_CSR) 590 | .export_values() 591 | .value("MHPMEVENT21_CSR", MHPMEVENT21_CSR) 592 | .export_values() 593 | .value("MHPMEVENT22_CSR", MHPMEVENT22_CSR) 594 | .export_values() 595 | .value("MHPMEVENT23_CSR", MHPMEVENT23_CSR) 596 | .export_values() 597 | .value("MHPMEVENT24_CSR", MHPMEVENT24_CSR) 598 | .export_values() 599 | .value("MHPMEVENT25_CSR", MHPMEVENT25_CSR) 600 | .export_values() 601 | .value("MHPMEVENT26_CSR", MHPMEVENT26_CSR) 602 | .export_values() 603 | .value("MHPMEVENT27_CSR", MHPMEVENT27_CSR) 604 | .export_values() 605 | .value("MHPMEVENT28_CSR", MHPMEVENT28_CSR) 606 | .export_values() 607 | .value("MHPMEVENT29_CSR", MHPMEVENT29_CSR) 608 | .export_values() 609 | .value("MHPMEVENT30_CSR", MHPMEVENT30_CSR) 610 | .export_values() 611 | .value("MHPMEVENT31_CSR", MHPMEVENT31_CSR) 612 | .export_values() 613 | .value("MVENDORID_CSR", MVENDORID_CSR) 614 | .export_values() 615 | .value("MARCHID_CSR", MARCHID_CSR) 616 | .export_values() 617 | .value("MIMPID_CSR", MIMPID_CSR) 618 | .export_values() 619 | .value("MHARTID_CSR", MHARTID_CSR) 620 | .export_values() 621 | .value("MCONFIGPTR_CSR", MCONFIGPTR_CSR) 622 | .export_values() 623 | .value("HTIMEDELTAH_CSR", HTIMEDELTAH_CSR) 624 | .export_values() 625 | .value("HENVCFGH_CSR", HENVCFGH_CSR) 626 | .export_values() 627 | .value("CYCLEH_CSR", CYCLEH_CSR) 628 | .export_values() 629 | .value("TIMEH_CSR", TIMEH_CSR) 630 | .export_values() 631 | .value("INSTRETH_CSR", INSTRETH_CSR) 632 | .export_values() 633 | .value("HPMCOUNTER3H_CSR", HPMCOUNTER3H_CSR) 634 | .export_values() 635 | .value("HPMCOUNTER4H_CSR", HPMCOUNTER4H_CSR) 636 | .export_values() 637 | .value("HPMCOUNTER5H_CSR", HPMCOUNTER5H_CSR) 638 | .export_values() 639 | .value("HPMCOUNTER6H_CSR", HPMCOUNTER6H_CSR) 640 | .export_values() 641 | .value("HPMCOUNTER7H_CSR", HPMCOUNTER7H_CSR) 642 | .export_values() 643 | .value("HPMCOUNTER8H_CSR", HPMCOUNTER8H_CSR) 644 | .export_values() 645 | .value("HPMCOUNTER9H_CSR", HPMCOUNTER9H_CSR) 646 | .export_values() 647 | .value("HPMCOUNTER10H_CSR", HPMCOUNTER10H_CSR) 648 | .export_values() 649 | .value("HPMCOUNTER11H_CSR", HPMCOUNTER11H_CSR) 650 | .export_values() 651 | .value("HPMCOUNTER12H_CSR", HPMCOUNTER12H_CSR) 652 | .export_values() 653 | .value("HPMCOUNTER13H_CSR", HPMCOUNTER13H_CSR) 654 | .export_values() 655 | .value("HPMCOUNTER14H_CSR", HPMCOUNTER14H_CSR) 656 | .export_values() 657 | .value("HPMCOUNTER15H_CSR", HPMCOUNTER15H_CSR) 658 | .export_values() 659 | .value("HPMCOUNTER16H_CSR", HPMCOUNTER16H_CSR) 660 | .export_values() 661 | .value("HPMCOUNTER17H_CSR", HPMCOUNTER17H_CSR) 662 | .export_values() 663 | .value("HPMCOUNTER18H_CSR", HPMCOUNTER18H_CSR) 664 | .export_values() 665 | .value("HPMCOUNTER19H_CSR", HPMCOUNTER19H_CSR) 666 | .export_values() 667 | .value("HPMCOUNTER20H_CSR", HPMCOUNTER20H_CSR) 668 | .export_values() 669 | .value("HPMCOUNTER21H_CSR", HPMCOUNTER21H_CSR) 670 | .export_values() 671 | .value("HPMCOUNTER22H_CSR", HPMCOUNTER22H_CSR) 672 | .export_values() 673 | .value("HPMCOUNTER23H_CSR", HPMCOUNTER23H_CSR) 674 | .export_values() 675 | .value("HPMCOUNTER24H_CSR", HPMCOUNTER24H_CSR) 676 | .export_values() 677 | .value("HPMCOUNTER25H_CSR", HPMCOUNTER25H_CSR) 678 | .export_values() 679 | .value("HPMCOUNTER26H_CSR", HPMCOUNTER26H_CSR) 680 | .export_values() 681 | .value("HPMCOUNTER27H_CSR", HPMCOUNTER27H_CSR) 682 | .export_values() 683 | .value("HPMCOUNTER28H_CSR", HPMCOUNTER28H_CSR) 684 | .export_values() 685 | .value("HPMCOUNTER29H_CSR", HPMCOUNTER29H_CSR) 686 | .export_values() 687 | .value("HPMCOUNTER30H_CSR", HPMCOUNTER30H_CSR) 688 | .export_values() 689 | .value("HPMCOUNTER31H_CSR", HPMCOUNTER31H_CSR) 690 | .export_values() 691 | .value("MSTATUSH_CSR", MSTATUSH_CSR) 692 | .export_values() 693 | .value("MENVCFGH_CSR", MENVCFGH_CSR) 694 | .export_values() 695 | .value("MSECCFGH_CSR", MSECCFGH_CSR) 696 | .export_values() 697 | .value("MCYCLEH_CSR", MCYCLEH_CSR) 698 | .export_values() 699 | .value("MINSTRETH_CSR", MINSTRETH_CSR) 700 | .export_values() 701 | .value("MHPMCOUNTER3H_CSR", MHPMCOUNTER3H_CSR) 702 | .export_values() 703 | .value("MHPMCOUNTER4H_CSR", MHPMCOUNTER4H_CSR) 704 | .export_values() 705 | .value("MHPMCOUNTER5H_CSR", MHPMCOUNTER5H_CSR) 706 | .export_values() 707 | .value("MHPMCOUNTER6H_CSR", MHPMCOUNTER6H_CSR) 708 | .export_values() 709 | .value("MHPMCOUNTER7H_CSR", MHPMCOUNTER7H_CSR) 710 | .export_values() 711 | .value("MHPMCOUNTER8H_CSR", MHPMCOUNTER8H_CSR) 712 | .export_values() 713 | .value("MHPMCOUNTER9H_CSR", MHPMCOUNTER9H_CSR) 714 | .export_values() 715 | .value("MHPMCOUNTER10H_CSR", MHPMCOUNTER10H_CSR) 716 | .export_values() 717 | .value("MHPMCOUNTER11H_CSR", MHPMCOUNTER11H_CSR) 718 | .export_values() 719 | .value("MHPMCOUNTER12H_CSR", MHPMCOUNTER12H_CSR) 720 | .export_values() 721 | .value("MHPMCOUNTER13H_CSR", MHPMCOUNTER13H_CSR) 722 | .export_values() 723 | .value("MHPMCOUNTER14H_CSR", MHPMCOUNTER14H_CSR) 724 | .export_values() 725 | .value("MHPMCOUNTER15H_CSR", MHPMCOUNTER15H_CSR) 726 | .export_values() 727 | .value("MHPMCOUNTER16H_CSR", MHPMCOUNTER16H_CSR) 728 | .export_values() 729 | .value("MHPMCOUNTER17H_CSR", MHPMCOUNTER17H_CSR) 730 | .export_values() 731 | .value("MHPMCOUNTER18H_CSR", MHPMCOUNTER18H_CSR) 732 | .export_values() 733 | .value("MHPMCOUNTER19H_CSR", MHPMCOUNTER19H_CSR) 734 | .export_values() 735 | .value("MHPMCOUNTER20H_CSR", MHPMCOUNTER20H_CSR) 736 | .export_values() 737 | .value("MHPMCOUNTER21H_CSR", MHPMCOUNTER21H_CSR) 738 | .export_values() 739 | .value("MHPMCOUNTER22H_CSR", MHPMCOUNTER22H_CSR) 740 | .export_values() 741 | .value("MHPMCOUNTER23H_CSR", MHPMCOUNTER23H_CSR) 742 | .export_values() 743 | .value("MHPMCOUNTER24H_CSR", MHPMCOUNTER24H_CSR) 744 | .export_values() 745 | .value("MHPMCOUNTER25H_CSR", MHPMCOUNTER25H_CSR) 746 | .export_values() 747 | .value("MHPMCOUNTER26H_CSR", MHPMCOUNTER26H_CSR) 748 | .export_values() 749 | .value("MHPMCOUNTER27H_CSR", MHPMCOUNTER27H_CSR) 750 | .export_values() 751 | .value("MHPMCOUNTER28H_CSR", MHPMCOUNTER28H_CSR) 752 | .export_values() 753 | .value("MHPMCOUNTER29H_CSR", MHPMCOUNTER29H_CSR) 754 | .export_values() 755 | .value("MHPMCOUNTER30H_CSR", MHPMCOUNTER30H_CSR) 756 | .export_values() 757 | .value("MHPMCOUNTER31H_CSR", MHPMCOUNTER31H_CSR) 758 | .export_values(); 759 | } 760 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | project('hammer lib', 'cpp', 6 | default_options : [ 7 | 'cpp_std=c++20', 8 | 'warning_level=2', # https://github.com/mesonbuild/meson/issues/7748 9 | 'werror=true', 10 | 'default_library=static' 11 | ] 12 | ) 13 | 14 | spike_install_dir = get_option('spike_install_dir') 15 | 16 | if spike_install_dir == '' 17 | if build_machine.system() == 'linux' 18 | spike_release_version = 'latest' 19 | 20 | lsb_release = find_program('lsb_release') 21 | lsb_release_ret = run_command(lsb_release, ['-ds'], check: true) 22 | 23 | if lsb_release_ret.stdout().contains('Ubuntu') 24 | distro = 'ubuntu.20.04' 25 | elif lsb_release_ret.stdout().contains('CentOS') 26 | distro = 'centos.7' 27 | endif 28 | 29 | spike_install_dir = '/tools/foss/riscv-isa-sim/dv-release/latest' / distro 30 | 31 | elif build_machine.system() == 'darwin' 32 | spike_release_version = '' 33 | 34 | distro = 'darwin' 35 | 36 | spike_install_dir = '/Users/joy/workspace/dv-release/' / distro 37 | endif 38 | endif 39 | 40 | spike_lib_directory = spike_install_dir / 'lib/' 41 | 42 | spike_include_directory = spike_install_dir / 'include/' 43 | 44 | thread_libdep = dependency('threads') 45 | 46 | cpp = meson.get_compiler('cpp') 47 | riscv_libdep = cpp.find_library('riscv', dirs: spike_lib_directory, required: true) 48 | 49 | spike_incdirs = include_directories([ 50 | spike_include_directory + 'softfloat', 51 | spike_include_directory + 'fesvr', 52 | spike_include_directory, 53 | '.' 54 | ]) 55 | 56 | hammer_lib = library('hammer', 57 | 'hammer.cpp', 58 | include_directories : spike_incdirs, 59 | dependencies : [riscv_libdep], 60 | install : true 61 | ) 62 | 63 | python3_instance = import('python').find_installation('python3') 64 | pybind11_config = find_program('pybind11-config') 65 | pybind11_config_ret = run_command(pybind11_config, ['--includes'], check: true) 66 | pybind11 = declare_dependency( 67 | include_directories: [pybind11_config_ret.stdout().split('-I')[-1].strip()], 68 | ) 69 | 70 | python3 = dependency('python3', ) 71 | 72 | hammer_pylib = python3_instance.extension_module('hammer', 73 | sources: ['hammer_pybind.cpp', 'hammer.cpp',], 74 | include_directories : spike_incdirs, 75 | dependencies : [python3, pybind11, riscv_libdep], 76 | link_language : 'cpp', 77 | override_options: [ 78 | 'cpp_rtti=true', 79 | ], 80 | cpp_args: [ 81 | '-Wno-macro-redefined', # silence complaint about HAVE_DLOPEN set in both Spike and pybind11 82 | '-Wno-nonportable-include-path' # silence complaint about spike/VERSION and include in pybind11 clashing 83 | ], 84 | install : true 85 | ) 86 | 87 | install_headers('hammer.h', 'hammer_enums.h') 88 | 89 | subdir('tests') 90 | subdir('pytests') 91 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | option('spike_install_dir', 6 | type : 'string', 7 | value : '', 8 | description : 'Install directory containing the Spike headers and libraries') 9 | -------------------------------------------------------------------------------- /native-file.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # GCC has trouble with some of the compiler flags so use clang instead. 6 | 7 | [binaries] 8 | cc = 'clang' 9 | cpp = 'clang++' 10 | -------------------------------------------------------------------------------- /pytests/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | riscv_compiler = find_program('riscv64-unknown-elf-gcc', required : true) 6 | 7 | linker_script_parameter = '-T' + meson.current_source_dir() + '/testinput.link.ld' 8 | 9 | riscv_compiler_parameters = [ 10 | '-static', 11 | '-mcmodel=medany', 12 | '-fvisibility=hidden', 13 | '-nostdlib', 14 | '-nostartfiles', 15 | '-Wa,-march=rv64gcv', 16 | '-std=gnu99', 17 | '-O0', 18 | linker_script_parameter, 19 | ] 20 | 21 | hammer_tests = [ 22 | ['get GPR, FPR, CSR and VecReg values', 'pytest000'], 23 | ['set GPR values', 'pytest001'], 24 | ['get/set memory contents', 'pytest002'], 25 | ['set PC', 'pytest003'] 26 | ] 27 | 28 | foreach hammer_test : hammer_tests 29 | test_description = hammer_test[0] 30 | test_name = hammer_test[1] 31 | 32 | pytest = find_program(test_name + '.py').full_path() 33 | 34 | infile = test_name + '.input.S' 35 | outfile = test_name + '.input.elf' 36 | 37 | test_input = custom_target(test_name, 38 | output : outfile, 39 | input : infile, 40 | command : [ 41 | riscv_compiler, 42 | riscv_compiler_parameters, 43 | '@INPUT@', 44 | '-o', 45 | '@OUTPUT@' 46 | ] 47 | ) 48 | 49 | test( 50 | 'Python ' + test_description, 51 | import('python').find_installation('python3'), 52 | args : [pytest, test_input], 53 | env : dyld_lib_path 54 | ) 55 | 56 | endforeach 57 | -------------------------------------------------------------------------------- /pytests/pytest000.input.S: -------------------------------------------------------------------------------- 1 | ../tests/test000.input.S -------------------------------------------------------------------------------- /pytests/pytest000.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # SPDX-FileCopyrightText: 2022 Rivos Inc. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | import pathlib 8 | import sys 9 | 10 | sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.resolve())) 11 | 12 | # hammer needs to be built for builddir/ to exist. 13 | import builddir.hammer as pyhammer 14 | 15 | 16 | def main(): 17 | if len(sys.argv) != 2: 18 | sys.exit("Unexpected number of parameters passed to test.") 19 | 20 | elf_name = sys.argv[1] 21 | 22 | mem_size = 2048 << 20 23 | mem_layout = pyhammer.mem_cfg_t(pyhammer.DramBase, mem_size) 24 | hart_ids = [0] 25 | 26 | mems = [(pyhammer.DramBase, pyhammer.mem_t(mem_size))] 27 | 28 | hammer = pyhammer.Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, [mem_layout], elf_name, 29 | None) 30 | 31 | flen = hammer.get_flen(0) 32 | if (flen != 64): 33 | sys.exit(f"Unexpected flen: {flen}") 34 | 35 | vlen = hammer.get_vlen(0) 36 | if (vlen != 512): 37 | sys.exit(f"Unexpected vlen: {vlen}") 38 | 39 | elen = hammer.get_elen(0) 40 | if (elen != 64): 41 | sys.exit(f"Unexpected elen: {elen}") 42 | 43 | # hammer.hello_world() 44 | 45 | for _ in range(8): 46 | hammer.single_step(0) 47 | 48 | current_pc = hammer.get_PC(0) 49 | current_x1 = hammer.get_gpr(0, 1) 50 | current_x2 = hammer.get_gpr(0, 2) 51 | current_x3 = hammer.get_gpr(0, 3) 52 | 53 | if (current_pc != 0x80000008): 54 | sys.exit(f'Unexpected PC: 0x{current_pc:x}') 55 | 56 | if (current_x1 != 1): 57 | sys.exit(f'Unexpected x1: {current_x1}') 58 | 59 | if (current_x2 != 2): 60 | sys.exit(f'Unexpected x2: {current_x2}') 61 | 62 | if (current_x3 != 3): 63 | sys.exit(f'Unexpected x3: {current_x3}') 64 | 65 | for _ in range(13): 66 | hammer.single_step(0) 67 | 68 | current_mstatus = hammer.get_csr(0, pyhammer.MSTATUS_CSR) 69 | if (current_mstatus != 0x8000000a00002600): 70 | sys.exit(f"Unexpected mstatus: {current_mstatus:x}") 71 | 72 | current_x1 = hammer.get_gpr(0, 1) 73 | if (current_x1 != 4): 74 | sys.exit(f'Unexpected x1 after vsetivli {current_x1}') 75 | 76 | v1 = hammer.get_vector_reg(0, 1) 77 | if len(v1) != 8: 78 | sys.exit(f"Unexpected number of 64 bit elements in v1: {len(v1)}") 79 | 80 | if (v1[0] != 0x1000 or v1[1] != 0x0 or v1[2] != 0x0 or v1[3] != 0): 81 | sys.exit(f"Unexpected value in v1: 0x{v1[3]:x}{v1[2]:x}{v1[1]:x}{v1[0]:x}") 82 | 83 | v2 = hammer.get_vector_reg(0, 2) 84 | if len(v2) != 8: 85 | sys.exit(f"Unexpected number of 64 bit elements in v2: {len(v2)}") 86 | 87 | if (v2[0] != 0x2000 or v2[1] != 0x0 or v2[2] != 0x0 or v2[3] != 0): 88 | sys.exit(f"Unexpected value in v2: 0x{v2[3]:x}{v2[2]:x}{v2[1]:x}{v2[0]:x}") 89 | 90 | v3 = hammer.get_vector_reg(0, 3) 91 | if len(v3) != 8: 92 | sys.exit(f"Unexpected number of 64 bit elements in v3: {len(v3)}") 93 | 94 | if (v3[0] != 0x3000 or v3[1] != 0x0 or v3[2] != 0x0 or v3[3] != 0): 95 | sys.exit(f"Unexpected value in v3: 0x{v3[3]:x}{v3[2]:x}{v3[1]:x}{v3[0]:x}") 96 | 97 | for _ in range(2): 98 | hammer.single_step(0) 99 | 100 | current_f1 = hammer.get_fpr(0, 1) 101 | if (current_f1 != 0xffffffff3fc00000): 102 | sys.exit(f"Unexpected f1: {current_f1:x}") 103 | 104 | pass 105 | 106 | 107 | if __name__ == '__main__': 108 | main() 109 | -------------------------------------------------------------------------------- /pytests/pytest001.input.S: -------------------------------------------------------------------------------- 1 | ../tests/test001.input.S -------------------------------------------------------------------------------- /pytests/pytest001.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # SPDX-FileCopyrightText: 2022 Rivos Inc. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | import pathlib 8 | import sys 9 | 10 | sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.resolve())) 11 | 12 | # hammer needs to be built for builddir/ to exist. 13 | import builddir.hammer as pyhammer 14 | 15 | 16 | def main(): 17 | if len(sys.argv) != 2: 18 | sys.exit("Unexpected number of parameters passed to test.") 19 | 20 | elf_name = sys.argv[1] 21 | 22 | mem_size = 2048 << 20 23 | mem_layout = pyhammer.mem_cfg_t(pyhammer.DramBase, mem_size) 24 | hart_ids = [0] 25 | 26 | mems = [(pyhammer.DramBase, pyhammer.mem_t(mem_size))] 27 | 28 | hammer = pyhammer.Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, [mem_layout], elf_name, 29 | None) 30 | 31 | for _ in range(7): 32 | hammer.single_step(0) 33 | 34 | current_pc = hammer.get_PC(0) 35 | current_x15 = hammer.get_gpr(0, 15) 36 | current_x16 = hammer.get_gpr(0, 16) 37 | 38 | if (current_pc != 0x80000004): 39 | sys.exit(f'Unexpected PC: 0x{current_pc:x}') 40 | 41 | if (current_x15 != 15): 42 | sys.exit(f'Unexpected x15: {current_x15}') 43 | 44 | if (current_x16 != 16): 45 | sys.exit(f'Unexpected x16: {current_x16}') 46 | 47 | hammer.set_gpr(0, 15, 2015) 48 | hammer.set_gpr(0, 16, 2016) 49 | 50 | current_x15 = hammer.get_gpr(0, 15) 51 | current_x16 = hammer.get_gpr(0, 16) 52 | 53 | if (current_x15 != 2015): 54 | sys.exit(f"Unexpected x15: {current_x15}") 55 | 56 | if (current_x16 != 2016): 57 | sys.exit(f"Unexpected x16: {current_x16}") 58 | 59 | for _ in range(2): 60 | hammer.single_step(0) 61 | 62 | current_x5 = hammer.get_gpr(0, 5) 63 | current_x6 = hammer.get_gpr(0, 6) 64 | 65 | if (current_x5 != 2015): 66 | sys.exit(f"Unexpected x5: {current_x5}") 67 | 68 | if (current_x6 != 2016): 69 | sys.exit(f"Unexpected x6: {current_x6}") 70 | 71 | pass 72 | 73 | 74 | if __name__ == '__main__': 75 | main() 76 | -------------------------------------------------------------------------------- /pytests/pytest002.input.S: -------------------------------------------------------------------------------- 1 | ../tests/test002.input.S -------------------------------------------------------------------------------- /pytests/pytest002.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # SPDX-FileCopyrightText: 2022 Rivos Inc. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | import pathlib 8 | import sys 9 | 10 | sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.resolve())) 11 | 12 | # hammer needs to be built for builddir/ to exist. 13 | import builddir.hammer as pyhammer 14 | 15 | 16 | def main(): 17 | if len(sys.argv) != 2: 18 | sys.exit("Unexpected number of parameters passed to test.") 19 | 20 | elf_name = sys.argv[1] 21 | 22 | mem_size = 2048 << 20 23 | mem_layout = pyhammer.mem_cfg_t(pyhammer.DramBase, mem_size) 24 | hart_ids = [0] 25 | 26 | mems = [(pyhammer.DramBase, pyhammer.mem_t(mem_size))] 27 | 28 | hammer = pyhammer.Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, [mem_layout], elf_name, 29 | None) 30 | 31 | # Tests Hammer::set/get_memory_at_VA() 32 | # Reads memory using Hammer::get_memory_at_VA(), single steps a load that 33 | # reads the same address and compares values. 34 | virtual_address = 0x80001000 35 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 8, 1) 36 | 37 | if (memory_contents is None): 38 | sys.exit("ERROR: Unable to read memory") 39 | 40 | value_at_address = 0 41 | i = 0 42 | for byte_value in memory_contents: 43 | value_at_address |= (byte_value << (i * 8)) 44 | i = i + 1 45 | 46 | for _ in range(8): 47 | hammer.single_step(0) 48 | 49 | current_x2 = hammer.get_gpr(0, 2) 50 | 51 | if (value_at_address != current_x2): 52 | print(f"get_memory_at_VA() returned a different value {value_at_address:x} from" 53 | "the load instruction which returned {current_x2}") 54 | sys.exit(1) 55 | 56 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 8, 8) 57 | if (memory_contents[0] != current_x2): 58 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 59 | 60 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 8, 4) 61 | memory_contents[0] |= memory_contents[1] << 32 62 | if (memory_contents[0] != current_x2): 63 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 64 | 65 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 8, 2) 66 | memory_contents[0] |= memory_contents[1] << 16 67 | memory_contents[0] |= memory_contents[2] << 32 68 | memory_contents[0] |= memory_contents[3] << 48 69 | if (memory_contents[0] != current_x2): 70 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 71 | 72 | # Writes memory using Hammer::set_memory_at_VA(), single steps a load that 73 | # reads the same address and compares values. 74 | new_memory_contents = [0xab, 0xcd, 0xef, 0xde, 0x11, 0x22, 0x33, 0x44] 75 | new_value_at_address = 0 76 | i = 0 77 | for byte_value in new_memory_contents: 78 | new_value_at_address |= (byte_value << (i * 8)) 79 | i = i + 1 80 | 81 | if (hammer.set_memory_at_VA(0, virtual_address, new_memory_contents, 1)): 82 | sys.exit("ERROR: set_memory_at_VA() failed") 83 | 84 | # Step the next load that will read the same location 85 | hammer.single_step(0) 86 | 87 | current_x2 = hammer.get_gpr(0, 2) 88 | 89 | if (new_value_at_address != current_x2): 90 | print(f"set_memory_at_VA() updated memory with {new_value_at_address:x} " 91 | "the load instruction returned {current_x2:x}") 92 | sys.exit(1) 93 | 94 | # Tests the fail case. 95 | memory_contents = hammer.get_memory_at_VA(0, 0xabcdabcdabcd, 1, 1) 96 | if (memory_contents is not None): 97 | sys.exit("ERROR: Expected memory load to fail.") 98 | 99 | if (hammer.set_memory_at_VA(0, 0xabcdabcdabcd, new_memory_contents, 1) == 0): 100 | sys.exit("ERROR: Expected memory store to fail.") 101 | 102 | # Test set of various sizes (8/4/2) 103 | new_memory_contents = [0xdeadbeef01234567] 104 | if (hammer.set_memory_at_VA(0, virtual_address, new_memory_contents, 8)): 105 | sys.exit("ERROR: set_memory_at_VA() failed") 106 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 8, 8) 107 | if (memory_contents[0] != new_memory_contents[0]): 108 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 109 | 110 | new_memory_contents = [0xdeadbeef] 111 | if (hammer.set_memory_at_VA(0, virtual_address, new_memory_contents, 4)): 112 | sys.exit("ERROR: set_memory_at_VA() failed") 113 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 4, 4) 114 | if (memory_contents[0] != new_memory_contents[0]): 115 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 116 | 117 | new_memory_contents = [0xdead] 118 | if (hammer.set_memory_at_VA(0, virtual_address, new_memory_contents, 2)): 119 | sys.exit("ERROR: set_memory_at_VA() failed") 120 | memory_contents = hammer.get_memory_at_VA(0, virtual_address, 2, 2) 121 | if (memory_contents[0] != new_memory_contents[0]): 122 | sys.exit(f'unexpected data read: 0x{memory_contents[0]:x}') 123 | 124 | # Invalid stride 125 | try: 126 | hammer.set_memory_at_VA(0, virtual_address, new_memory_contents, 3) 127 | except ValueError: 128 | pass 129 | try: 130 | hammer.get_memory_at_VA(0, virtual_address, 2, 5) 131 | except ValueError: 132 | pass 133 | 134 | pass 135 | 136 | 137 | if __name__ == '__main__': 138 | main() 139 | -------------------------------------------------------------------------------- /pytests/pytest003.input.S: -------------------------------------------------------------------------------- 1 | ../tests/test003.input.S -------------------------------------------------------------------------------- /pytests/pytest003.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # SPDX-FileCopyrightText: 2022 Rivos Inc. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | import pathlib 8 | import sys 9 | 10 | sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.resolve())) 11 | 12 | # hammer needs to be built for builddir/ to exist. 13 | import builddir.hammer as pyhammer 14 | 15 | 16 | def main(): 17 | if len(sys.argv) != 2: 18 | sys.exit("Unexpected number of parameters passed to test.") 19 | 20 | elf_name = sys.argv[1] 21 | 22 | mem_size = 2048 << 20 23 | mem_layout = pyhammer.mem_cfg_t(pyhammer.DramBase, mem_size) 24 | hart_ids = [0] 25 | 26 | mems = [(pyhammer.DramBase, pyhammer.mem_t(mem_size))] 27 | 28 | hammer = pyhammer.Hammer("RV64GCV", "MSU", "vlen:512,elen:32", hart_ids, [mem_layout], elf_name, 29 | None) 30 | 31 | for _ in range(8): 32 | hammer.single_step(0) 33 | 34 | current_PC = hammer.get_PC(0) 35 | current_x1 = hammer.get_gpr(0, 1) 36 | current_x2 = hammer.get_gpr(0, 2) 37 | current_x3 = hammer.get_gpr(0, 3) 38 | 39 | if (current_PC != 0x80000008): 40 | sys.exit(f'Unexpected PC: 0x{current_PC:x}') 41 | 42 | if (current_x1 != 1): 43 | sys.exit(f'Unexpected x1: {current_x1}') 44 | 45 | if (current_x2 != 2): 46 | sys.exit(f'Unexpected x2: {current_x2}') 47 | 48 | if (current_x3 != 3): 49 | sys.exit(f'Unexpected x3: {current_x3}') 50 | 51 | # Skip over the bad instructions 52 | next_PC = current_PC + (4 * 8) 53 | hammer.set_PC(0, next_PC) 54 | hammer.single_step(0) 55 | 56 | current_PC = hammer.get_PC(0) 57 | current_x3 = hammer.get_gpr(0, 3) 58 | 59 | if (current_PC != (next_PC + 2)): 60 | sys.exit(f'Unexpected PC after skipping over the bad instruction: {current_PC:x}') 61 | 62 | if (current_x3 != 4): 63 | sys.exit(f'Unexpected x3 after skipping over the bad instruction: {current_x3}') 64 | 65 | pass 66 | 67 | 68 | if __name__ == '__main__': 69 | main() 70 | -------------------------------------------------------------------------------- /pytests/testinput.link.ld: -------------------------------------------------------------------------------- 1 | ../tests/testinput.link.ld -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | riscv_compiler = find_program('riscv64-unknown-elf-gcc', required : true) 6 | 7 | linker_script_parameter = '-T' + meson.current_source_dir() + '/testinput.link.ld' 8 | 9 | riscv_compiler_parameters = [ 10 | '-static', 11 | '-mcmodel=medany', 12 | '-fvisibility=hidden', 13 | '-nostdlib', 14 | '-nostartfiles', 15 | '-Wa,-march=rv64gcv', 16 | '-std=gnu99', 17 | '-O0', 18 | linker_script_parameter, 19 | ] 20 | 21 | if build_machine.system() == 'darwin' 22 | dyld_lib_path = ['DYLD_LIBRARY_PATH=' + meson.source_root() + '/spike/build'] 23 | else 24 | dyld_lib_path = [] 25 | endif 26 | 27 | hammer_tests = [ 28 | ['get GPR, FPR CSR and VecReg values', 'test000'], 29 | ['set GPR values', 'test001'], 30 | ['get/set memory contents', 'test002'], 31 | ['set PC', 'test003'], 32 | ] 33 | 34 | foreach hammer_test : hammer_tests 35 | test_description = hammer_test[0] 36 | test_name = hammer_test[1] 37 | 38 | infile = test_name + '.input.S' 39 | outfile = test_name + '.input.elf' 40 | 41 | test_input = custom_target(test_name, 42 | output : outfile, 43 | input : infile, 44 | command : [ 45 | riscv_compiler, 46 | riscv_compiler_parameters, 47 | '@INPUT@', 48 | '-o', 49 | '@OUTPUT@' 50 | ] 51 | ) 52 | 53 | exe = executable(test_name, 54 | test_name + '.cpp', 55 | link_with : hammer_lib, 56 | include_directories : spike_incdirs, 57 | dependencies : [riscv_libdep] 58 | ) 59 | test('C++ ' + test_description, 60 | exe, args : [test_input], env : dyld_lib_path) 61 | 62 | endforeach 63 | -------------------------------------------------------------------------------- /tests/test000.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | int main(int argc, char *argv[]) { 8 | assert(argc == 2); 9 | const std::string target_binary = argv[1]; 10 | 11 | std::vector memory_layout; 12 | // This is what Spike sets it to 13 | memory_layout.push_back(mem_cfg_t(reg_t(DRAM_BASE), reg_t(2048) << 20)); 14 | 15 | std::vector hart_ids{0}; 16 | 17 | Hammer hammer = Hammer("RV64GCV", "MSU", "vlen:512,elen:32", hart_ids, memory_layout, 18 | target_binary, std::nullopt); 19 | 20 | // hammer.hello_world(); 21 | uint32_t flen = hammer.get_flen(0); 22 | if (flen != 64) { 23 | printf("Unexpected flen: %d\n", flen); 24 | exit(1); 25 | } 26 | 27 | uint32_t vlen = hammer.get_vlen(0); 28 | if (vlen != 512) { 29 | printf("Unexpected vlen: %d\n", vlen); 30 | exit(1); 31 | } 32 | 33 | uint32_t elen = hammer.get_elen(0); 34 | if (elen != 32) { 35 | printf("Unexpected elen: %d\n", elen); 36 | exit(1); 37 | } 38 | 39 | for (uint32_t i = 0; i < 8; ++i) { 40 | hammer.single_step(0); 41 | } 42 | 43 | uint64_t current_pc = hammer.get_PC(0); 44 | uint64_t current_x1 = hammer.get_gpr(0, 1); 45 | uint64_t current_x2 = hammer.get_gpr(0, 2); 46 | uint64_t current_x3 = hammer.get_gpr(0, 3); 47 | 48 | if (current_pc != 0x80000008) { 49 | printf("Unexpected PC: 0x%" PRIx64 "\n", current_pc); 50 | exit(1); 51 | } 52 | 53 | if (current_x1 != 1) { 54 | printf("Unexpected x1: 0x%" PRIx64 "\n", current_x1); 55 | exit(1); 56 | } 57 | 58 | if (current_x2 != 2) { 59 | printf("Unexpected x2: 0x%" PRIx64 "\n", current_x2); 60 | exit(1); 61 | } 62 | 63 | if (current_x3 != 3) { 64 | printf("Unexpected x3: 0x%" PRIx64 "\n", current_x3); 65 | exit(1); 66 | } 67 | 68 | for (uint32_t i = 0; i < 13; ++i) { 69 | hammer.single_step(0); 70 | } 71 | 72 | reg_t current_mstatus = hammer.get_csr(0, MSTATUS_CSR); 73 | if (current_mstatus != 0x8000000a00002600) { 74 | printf("Unexpected mstatus: 0x%" PRIx64 "\n", current_mstatus); 75 | exit(1); 76 | } 77 | 78 | current_x1 = hammer.get_gpr(0, 1); 79 | if (current_x1 != 4) { 80 | printf("Unexpected x1: 0x%" PRIx64 " after vsetivli\n", current_x1); 81 | exit(1); 82 | } 83 | 84 | std::vector v1 = hammer.get_vector_reg(0, 1); 85 | if (v1.size() != 8) { 86 | printf("Unexpected number of 64 bit elements in v1: %lu\n", v1.size()); 87 | exit(1); 88 | } 89 | 90 | if (v1[0] != 0x1000 || v1[1] != 0x0 || v1[2] != 0x0 || v1[3] != 0) { 91 | printf("Unexpected value in v1: 0x%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "\n", v1[3], v1[2], 92 | v1[1], v1[0]); 93 | exit(1); 94 | } 95 | 96 | std::vector v2 = hammer.get_vector_reg(0, 2); 97 | if (v2.size() != 8) { 98 | printf("Unexpected number of 64 bit elements in v2: %lu\n", v2.size()); 99 | exit(1); 100 | } 101 | 102 | if (v2[0] != 0x2000 || v2[1] != 0x0 || v2[2] != 0x0 || v2[3] != 0) { 103 | printf("Unexpected value in v2: 0x%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "\n", v2[3], v2[2], 104 | v2[1], v2[0]); 105 | exit(1); 106 | } 107 | 108 | std::vector v3 = hammer.get_vector_reg(0, 3); 109 | if (v3.size() != 8) { 110 | printf("Unexpected number of 64 bit elements in v3: %lu\n", v3.size()); 111 | exit(1); 112 | } 113 | 114 | if (v3[0] != 0x3000 || v3[1] != 0x0 || v3[2] != 0x0 || v3[3] != 0) { 115 | printf("Unexpected value in v3: 0x%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "\n", v3[3], v3[2], 116 | v3[1], v3[0]); 117 | exit(1); 118 | } 119 | 120 | for (uint32_t i = 0; i < 2; ++i) { 121 | hammer.single_step(0); 122 | } 123 | 124 | uint64_t current_f1 = hammer.get_fpr(0, 1); 125 | if (current_f1 != 0xffffffff3fc00000) { 126 | printf("Unexpected f1: 0x%" PRIx64 "\n", current_f1); 127 | exit(1); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /tests/test000.input.S: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | .text 6 | 7 | .global _start 8 | _start: 9 | 10 | li x1, 1 11 | li x2, 2 12 | add x3, x2, x1; # x3 = x2 + x1 13 | 14 | li a3, 0xa00002200 15 | csrw mstatus, a3 16 | 17 | vsetivli x1, 4, e32, m1 18 | 19 | lui a3, 1 20 | vmv.s.x v1, a3 21 | 22 | lui a3, 2 23 | vmv.s.x v2, a3 24 | 25 | lui a3, 0 26 | vmv.s.x v3, a3 27 | 28 | vadd.vv v3, v2, v1 29 | 30 | li x1, 0x3fc00000 31 | fmv.w.x f1, x1 32 | 33 | # Magic instruction to terminate the run. 34 | lui x0, 0xdeadb 35 | 36 | .data 37 | 38 | tdat: 39 | .dword 0x1817161514131110 40 | .dword 0x2827262524232120 41 | .dword 0x3837363534333130 42 | .dword 0x4847464544434140 43 | -------------------------------------------------------------------------------- /tests/test001.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | int main(int argc, char *argv[]) { 8 | assert(argc == 2); 9 | const std::string target_binary = argv[1]; 10 | 11 | std::vector memory_layout; 12 | // This is what Spike sets it to 13 | memory_layout.push_back(mem_cfg_t(reg_t(DRAM_BASE), reg_t(2048) << 20)); 14 | 15 | std::vector hart_ids{0}; 16 | 17 | Hammer hammer = Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, memory_layout, 18 | target_binary, std::nullopt); 19 | 20 | for (uint32_t i = 0; i < 7; ++i) { 21 | hammer.single_step(0); 22 | } 23 | 24 | uint64_t current_pc = hammer.get_PC(0); 25 | uint64_t current_x15 = hammer.get_gpr(0, 15); 26 | uint64_t current_x16 = hammer.get_gpr(0, 16); 27 | 28 | if (current_pc != 0x80000004) { 29 | printf("Unexpected PC: 0x%" PRIx64 "\n", current_pc); 30 | exit(1); 31 | } 32 | 33 | if (current_x15 != 15) { 34 | printf("Unexpected x15: 0x%" PRIx64 "\n", current_x15); 35 | exit(1); 36 | } 37 | 38 | if (current_x16 != 16) { 39 | printf("Unexpected x16: 0x%" PRIx64 "\n", current_x16); 40 | exit(1); 41 | } 42 | 43 | // Test set_gpr() 44 | hammer.set_gpr(0, 15, 2015); 45 | hammer.set_gpr(0, 16, 2016); 46 | 47 | current_x15 = hammer.get_gpr(0, 15); 48 | current_x16 = hammer.get_gpr(0, 16); 49 | 50 | if (current_x15 != 2015) { 51 | printf("Unexpected x15: 0x%" PRIx64 "\n", current_x15); 52 | exit(1); 53 | } 54 | 55 | if (current_x16 != 2016) { 56 | printf("Unexpected x16: 0x%" PRIx64 "\n", current_x16); 57 | exit(1); 58 | } 59 | 60 | for (uint32_t i = 0; i < 2; ++i) { 61 | hammer.single_step(0); 62 | } 63 | 64 | uint64_t current_x5 = hammer.get_gpr(0, 5); 65 | uint64_t current_x6 = hammer.get_gpr(0, 6); 66 | 67 | if (current_x5 != 2015) { 68 | printf("Unexpected x5: 0x%" PRIx64 "\n", current_x5); 69 | exit(1); 70 | } 71 | 72 | if (current_x6 != 2016) { 73 | printf("Unexpected x6: 0x%" PRIx64 "\n", current_x6); 74 | exit(1); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/test001.input.S: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | .text 6 | 7 | .global _start 8 | _start: 9 | 10 | li x15, 15 11 | li x16, 16 12 | 13 | mv x5, x15 14 | mv x6, x16 15 | 16 | # Magic instruction to terminate the run. 17 | lui x0, 0xdeadb 18 | 19 | .data 20 | 21 | tdat: 22 | .dword 0x1817161514131110 23 | .dword 0x2827262524232120 24 | .dword 0x3837363534333130 25 | .dword 0x4847464544434140 26 | -------------------------------------------------------------------------------- /tests/test002.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | constexpr uint64_t data_area_start_address = 0x80001000; 8 | 9 | int main(int argc, char *argv[]) { 10 | assert(argc == 2); 11 | const std::string target_binary = argv[1]; 12 | 13 | std::vector memory_layout; 14 | // This is what Spike sets it to 15 | memory_layout.push_back(mem_cfg_t(reg_t(DRAM_BASE), reg_t(2048) << 20)); 16 | 17 | std::vector hart_ids{0}; 18 | 19 | Hammer hammer = Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, memory_layout, 20 | target_binary, std::nullopt); 21 | 22 | // Tests Hammer::set/get_memory_at_VA() 23 | // single steps a load that reads a location, reads the same location with 24 | // get_memory_at_VA() and compares values. 25 | for (uint32_t i = 0; i < 8; ++i) { 26 | hammer.single_step(0); 27 | } 28 | uint64_t current_x2 = hammer.get_gpr(0, 2); 29 | 30 | uint64_t virtual_address = data_area_start_address; 31 | for (uint32_t bytes_to_read = 8; bytes_to_read > 0; --bytes_to_read) { 32 | auto memory_contents = hammer.get_memory_at_VA(0, virtual_address, bytes_to_read); 33 | if (memory_contents.has_value() == false) { 34 | printf("ERROR: Unable to read memory\n"); 35 | exit(1); 36 | } 37 | 38 | if (memory_contents.value().size() != bytes_to_read) { 39 | printf("ERROR: Bytes read did not match requested num bytes\n"); 40 | exit(1); 41 | } 42 | 43 | uint64_t value_at_address = 0; 44 | uint8_t i = 0; 45 | for (uint64_t byte_value : memory_contents.value()) { 46 | value_at_address |= (byte_value << (i * 8)); 47 | ++i; 48 | } 49 | 50 | uint64_t expected_value_at_address = current_x2 >> ((8 - bytes_to_read) * 8); 51 | if (expected_value_at_address != value_at_address) { 52 | printf("ERROR: %d bytes read from 0x%" PRIx64 " were 0x%" PRIx64 53 | " but " 54 | "expected were 0x%" PRIx64 "\n", 55 | bytes_to_read, virtual_address, value_at_address, expected_value_at_address); 56 | exit(1); 57 | } 58 | 59 | ++virtual_address; 60 | } 61 | 62 | // Writes memory using Hammer::set_memory_at_VA(), single steps a load that 63 | // reads the same address and compares values. 64 | std::vector new_memory_contents{0xab, 0xcd, 0xef, 0xde, 0x11, 0x22, 0x33, 0x44}; 65 | uint64_t new_value_at_address = 0; 66 | uint8_t i = 0; 67 | for (uint64_t byte_value : new_memory_contents) { 68 | new_value_at_address |= (byte_value << (i * 8)); 69 | ++i; 70 | } 71 | 72 | virtual_address = data_area_start_address; 73 | if (hammer.set_memory_at_VA(0, virtual_address, new_memory_contents)) { 74 | printf("ERROR: set_memory_at_VA() failed\n"); 75 | exit(1); 76 | } 77 | 78 | // Step the next load that will read the same location 79 | hammer.single_step(0); 80 | 81 | current_x2 = hammer.get_gpr(0, 2); 82 | 83 | if (new_value_at_address != current_x2) { 84 | printf("set_memory_at_VA() updated memory with 0x%" PRIx64 85 | " but " 86 | "the load instruction returned 0x%" PRIx64 "\n", 87 | new_value_at_address, current_x2); 88 | exit(1); 89 | } 90 | 91 | // Tests the fail case. 92 | auto memory_contents = hammer.get_memory_at_VA(0, 0xabcdabcdabcd, 1); 93 | if (memory_contents.has_value()) { 94 | printf("ERROR: Expected memory load to fail.\n"); 95 | exit(1); 96 | } 97 | 98 | if (hammer.set_memory_at_VA(0, 0xabcdabcdabcd, new_memory_contents) == 0) { 99 | printf("ERROR: Expected memory store to fail.\n"); 100 | exit(1); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /tests/test002.input.S: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | .text 6 | 7 | .global _start 8 | _start: 9 | 10 | la x1, tdat 11 | ld x2, (x1) 12 | 13 | ld x2, (x1) 14 | 15 | # Magic instruction to terminate the run. 16 | lui x0, 0xdeadb 17 | 18 | .data 19 | 20 | tdat: 21 | .dword 0xcafecafecafecafe 22 | .dword 0xba11ba11ba11ba11 23 | -------------------------------------------------------------------------------- /tests/test003.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "hammer.h" 6 | 7 | int main(int argc, char *argv[]) { 8 | assert(argc == 2); 9 | const std::string target_binary = argv[1]; 10 | 11 | std::vector memory_layout; 12 | // This is what Spike sets it to 13 | memory_layout.push_back(mem_cfg_t(reg_t(DRAM_BASE), reg_t(2048) << 20)); 14 | 15 | std::vector htif_args; 16 | htif_args.push_back(target_binary); 17 | 18 | std::vector hart_ids{0}; 19 | 20 | Hammer hammer = Hammer("RV64GCV", "MSU", "vlen:512,elen:64", hart_ids, memory_layout, 21 | target_binary, std::nullopt); 22 | 23 | // hammer.hello_world(); 24 | for (uint32_t i = 0; i < 8; ++i) { 25 | hammer.single_step(0); 26 | } 27 | 28 | uint64_t current_PC = hammer.get_PC(0); 29 | uint64_t current_x1 = hammer.get_gpr(0, 1); 30 | uint64_t current_x2 = hammer.get_gpr(0, 2); 31 | uint64_t current_x3 = hammer.get_gpr(0, 3); 32 | 33 | if (current_PC != 0x80000008) { 34 | printf("Unexpected PC: 0x%" PRIx64 "\n", current_PC); 35 | exit(1); 36 | } 37 | 38 | if (current_x1 != 1) { 39 | printf("Unexpected x1: 0x%" PRIx64 "\n", current_x1); 40 | exit(1); 41 | } 42 | 43 | if (current_x2 != 2) { 44 | printf("Unexpected x2: 0x%" PRIx64 "\n", current_x2); 45 | exit(1); 46 | } 47 | 48 | if (current_x3 != 3) { 49 | printf("Unexpected x3: 0x%" PRIx64 "\n", current_x3); 50 | exit(1); 51 | } 52 | 53 | // Skip over the bad data 54 | uint64_t next_PC = current_PC + (4 * 8); 55 | hammer.set_PC(0, next_PC); 56 | hammer.single_step(0); 57 | 58 | current_PC = hammer.get_PC(0); 59 | current_x3 = hammer.get_gpr(0, 3); 60 | 61 | if (current_PC != (next_PC + 2)) { 62 | printf("Unexpected PC after skipping over the bad instruction: 0x%" PRIx64 "\n", current_PC); 63 | exit(1); 64 | } 65 | 66 | if (current_x3 != 4) { 67 | printf("Unexpected x3 after skipping over the bad instruction: 0x%" PRIx64 "\n", current_x3); 68 | exit(1); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/test003.input.S: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Rivos Inc. 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | .text 6 | 7 | .global _start 8 | _start: 9 | 10 | li x1, 1 11 | li x2, 2 12 | add x3, x2, x1; # x3 = x2 + x1 = 3 13 | 14 | .rept 8 15 | .4byte 0xbad1bad2 # bad instruction we're going to skip over 16 | .endr 17 | 18 | c.add x3, x1 # x3 = x3 + x1 = 4 19 | 20 | # Magic instruction to terminate the run. 21 | lui x0, 0xdeadb 22 | 23 | .data 24 | 25 | tdat: 26 | .dword 0x1817161514131110 27 | .dword 0x2827262524232120 28 | .dword 0x3837363534333130 29 | .dword 0x4847464544434140 30 | -------------------------------------------------------------------------------- /tests/testinput.link.ld: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 Rivos Inc. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | OUTPUT_ARCH( "riscv" ) 6 | ENTRY(_start) 7 | 8 | SECTIONS 9 | { 10 | . = 0x80000000; 11 | .text.init : { *(.text.init) } 12 | . = ALIGN(0x1000); 13 | .tohost : { *(.tohost) } 14 | . = ALIGN(0x1000); 15 | .text : { *(.text) } 16 | . = ALIGN(0x1000); 17 | .data : { *(.data) } 18 | .bss : { *(.bss) } 19 | _end = .; 20 | } 21 | --------------------------------------------------------------------------------