diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..c5f267096 --- /dev/null +++ b/.clang-format @@ -0,0 +1,74 @@ +BasedOnStyle: LLVM +Standard: c++17 +ColumnLimit: 132 +UseTab: Never +UseCRLF: false +AlignEscapedNewlines: Left +AllowShortFunctionsOnASingleLine: Inline +AllowShortCaseLabelsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +BinPackArguments: false +AllowAllArgumentsOnNextLine: true +BinPackParameters: false +AllowAllParametersOfDeclarationOnNextLine: true +BitFieldColonSpacing: Both +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false +ConstructorInitializerIndentWidth: 2 +BreakConstructorInitializers: BeforeColon +ContinuationIndentWidth: 2 +FixNamespaceComments: true +IndentWrappedFunctionNames: true +SortIncludes: true +SpaceBeforeParens: Never +SpacesInAngles: Never +SpacesInParentheses: true +SpacesInSquareBrackets: false +SpacesInConditionalStatement: true +SpacesInCStyleCastParentheses: false +SpaceInEmptyParentheses: false +SpaceAfterTemplateKeyword: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCaseColon: false +SpaceBeforeAssignmentOperators: true +SpaceAfterLogicalNot: false +SpaceAfterCStyleCast: true +SpaceAroundPointerQualifiers: Default +PointerAlignment: Left +DerivePointerAlignment: false +ReferenceAlignment: Pointer +InsertTrailingCommas: Wrapped +MaxEmptyLinesToKeep: 1 +AlignTrailingComments: true +SpacesBeforeTrailingComments: 2 +AlignArrayOfStructures: Right +AlignConsecutiveAssignments: AcrossEmptyLinesAndComments +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveMacros: AcrossEmptyLinesAndComments +AlignConsecutiveBitFields: AcrossEmptyLinesAndComments +AlignAfterOpenBracket: BlockIndent +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBinaryOperators: false +BreakBeforeTernaryOperators: false +AlignOperands: Align +ReflowComments: false +SeparateDefinitionBlocks: Always +EmptyLineBeforeAccessModifier: LogicalBlock diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 000000000..9a06ecd20 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,313 @@ +#!/bin/bash +# +# This pre-commit hook reformats text files to meet coding guidelines. +# +# Based on https://github.com/rocm/rocBLAS +# +# shellcheck enable=all +# shellcheck disable=2034,2059,2064,2250,2310,2312 + +set_shell_options() { + set -eEu -o pipefail + shopt -s nocasematch + export PATH=$PATH:/usr/bin:/bin + exec >&2 +} + +# Terminal colors +set_colors() { + if [[ -z ${NO_COLOR+x} ]] && tty -s <&2; then + RED="\033[91m" + YELLOW="\033[93m" + GREEN="\033[92m" + END="\033[0m" + else + RED= + YELLOW= + GREEN= + END= + fi +} + +usage() { + cat</dev/null; then + INSTALL="brew install $package" + fi + elif [[ $OSTYPE = linux* ]]; then + if [[ -f /etc/redhat-release ]]; then + if command -v dnf >/dev/null; then + INSTALL="sudo dnf install $package" + elif command -v yum >/dev/null; then + if [[ $package = shellcheck ]]; then + package=ShellCheck + fi + INSTALL="sudo yum install $package" + fi + elif [[ -f /etc/debian_version ]] && command -v apt-get >/dev/null; then + INSTALL="sudo apt-get install $package" + fi + fi + if [[ -n $INSTALL ]]; then + printf "${YELLOW}\nTo install $package, run:\n\n%s\n\n${END}" "$INSTALL" + else + printf "${YELLOW}\nInstall $package and make sure it is in PATH.\n\n${END}" + fi +} + +# Check for existence of clang-format or print error message on how to install +check_clang_format() { + if ! command -v clang-format >/dev/null; then + printf "${RED}\nError: clang-format not found\n${END}" + howto_install clang-format + exit 1 + fi +} + +# Test a file for changes and add them to the Git commit if changed +detect_change() { + if ! cmp -s "$1" "$2"; then + printf "${YELLOW}$3${END}\n" "$1" + cp -f "$2" "$1" + if [[ -z $EXPLICIT_FILES && -z $NOSTAGE ]]; then + git add -u "$1" + fi + fi +} + +# Generate list of modified files +# If --reformat is used, all files are reformatted +get_files() { + if [[ -n $EXPLICIT_FILES ]]; then + # cd to this script's directory before running clang-format + # so that the .clang-format from this script's repo is used + REPO=$(dirname "$0") + else + # Do everything from top level + REPO=$(git rev-parse --show-toplevel) + cd "$REPO" + if [[ -n $REFORMAT ]]; then + while IFS= read -r -d $'\0' FILE; do + FILES+=("$FILE") + done < <(git ls-files -z --exclude-standard) + else + if git rev-parse --verify HEAD >/dev/null 2>&1; then + against=HEAD + else + # Initial commit: diff against initial commit + against=$(git log --reverse --pretty=format:%H | head -1) + fi + while IFS= read -r -d $'\0' FILE; do + FILES+=("$FILE") + done < <(git diff-index -z --cached --name-only "$against") + fi + fi +} + +# Test if argument is a text file +# git grep tests whether Git considers it a text file +# If files were explicitly specified, they are assumed to be text files +is_text_file() { + [[ -n $EXPLICIT_FILES ]] || git grep -Iqe . -- "$1" +} + +# Test if argument is a C/C++ file +is_cxx_file() { + local file=$1 + trap "$(shopt -p nocasematch)" RETURN + shopt -u nocasematch + case $file in + *.c|*.h|*.cc) true ;; + *.hpp) printf "${RED}${file}: Error: C++ header files should have .h extension instead of .hpp${END}\n\n" + errors=true ;; + *.cxx) printf "${RED}${file}: Error: C++ source files should have .cc extension instead of .cxx${END}\n\n" + errors=true ;; + *.cpp) printf "${RED}${file}: Error: C++ source files should have .cc extension instead of .cpp${END}\n\n" + errors=true ;; + *.C) printf "${RED}${file}: Error: C++ source files should have .cc extension instead of .C${END}\n\n" + errors=true ;; + *) false + esac +} + + +# Check for redundant C++ directives +check_override_final() { + local file=$1 err + if err=$(grep -Hno "^[^/].*\bvirtual\b.*\boverride\b" "$file"); then + printf "${err}\n${RED}Error: virtual keyword is redundant with override directive${END}\n\n" + errors=true + elif err=$(grep -Hno "^[^/].*\bvirtual\b.*\bfinal\b" "$file"); then + printf "${err}\n${RED}Error: If final directive is used, virtual should not be specified${END}\n\n" + errors=true + elif err=$(grep -Hno "^[^/].*\boverride\b.*\bfinal\b" "$file") || err=$(grep -Hno "\bfinal\b.*\boverride\b" "$file"); then + printf "${err}\n${RED}Error: If final directive is used, override is redundant${END}\n\n" + errors=true + fi +} + +# Check for correct magic and filename extensions +# filename extension mime-type shebang +check_extension() { + local file=$1 ext=$2 mimetype=$3 shebang=$4 instead + trap "$(shopt -p nocasematch)" RETURN + shopt -u nocasematch + if [[ ! $(file -Lb --mime-type "$1") =~ ${mimetype} ]]; then + if [[ $file = *$ext ]]; then + printf "\n${RED}${file}: Error: Not recognized as ${mimetype}.\n${shebang:+Make sure that shebang ${shebang} is at the top of ${file}.\n}${END}" + errors=true + fi + elif [[ $file != *$ext ]]; then + instead=$( if [[ $file = *.* ]]; then echo "instead of .${file##*.}"; fi ) + printf "\n${RED}${file}: Error: ${mimetype} filenames should have $ext extension ${instead}${END}\n" + errors=true + fi +} + +reformat_files() { + # Temporary file for reformatting + temp=$(mktemp) + trap 'rm -f "$temp"' EXIT + + # Get the list of files into FILES + get_files + + # Fix formatting on text files + if [[ ${#FILES[@]} -eq 0 ]]; then + return 0 + fi + + errors=false + shellcheck_warning= + +# Fix formatting on text files + for file in "${FILES[@]}"; do + if [[ -f $file ]] && is_text_file "$file"; then + # Replace non-ASCII characters with ASCII equivalents + if ! iconv -s -f utf-8 -t ascii//TRANSLIT "$file" > "$temp"; then + cat < "$temp"${END} +EOF + iconv -f utf-8 -t ascii//TRANSLIT "$file" > "$temp" || true + fold -s -w79 < "$temp"; then + detect_change "$file" "$temp" "%s: Changing copyright date" + fi + + # Run clang-format on C/C++ files + if is_cxx_file "$file"; then + check_clang_format + (cd "$REPO" && clang-format) < "$file" > "$temp" + detect_change "$file" "$temp" "%s: Reformatting with clang-format according to coding guidelines" + check_override_final "$file" + fi + + # Remove trailing whitespace at end of lines + sed -e 's/[[:space:]]*$//' < "$file" > "$temp" + detect_change "$file" "$temp" "%s: Removing trailing whitespace at line endings" + + # Add missing newline at EOF + awk 1 < "$file" > "$temp" + detect_change "$file" "$temp" "%s: Adding missing newline at end of file" + + # check filename extensions and magic + if [[ $file != **/pre-commit ]]; then + check_extension "$file" ".sh" "^text/x-shellscript$" "#!/bin/bash" + check_extension "$file" ".py" "^text/x-script\.python|text/x-python$" "#!/usr/bin/env python3" + check_extension "$file" ".pl" "^text/x-perl$" "#!/usr/bin/perl" + fi + + # Python files + if [[ $file = *.py ]]; then + if command -v flake8 >/dev/null 2>&1; then + flake8 --max-line-length 131 "$file" || errors=true + else + printf "${RED}Error: flake8 utility not found. %s not checked with flake8.${END}\n" "$file" + printf "${YELLOW}\nTo Install flake8, type:\n\npip install flake8\n\n${END}" + exit 1 + fi + fi + + # Shell scripts + if [[ $file = *.sh || $file = **/pre-commit ]]; then + if command -v shellcheck >/dev/null 2>&1 && shellcheck -o all -e2148 /dev/null >/dev/null 2>&1; then + shellcheck -o all -e 1091,2059,2154,2248,2250,2312 "$file" || errors=true + else + printf "${YELLOW}Warning: %s not checked with shellcheck.${END}\n" "$file" + shellcheck_warning=1 + fi + fi + fi + done + + if [[ -n $shellcheck_warning ]]; then + printf "${YELLOW}\nWarning: shellcheck utility not found or not recent enough version.\n${END}" + howto_install shellcheck + fi + + if [[ $errors = true ]]; then + exit 1 + fi +} + +# Main Program +set_shell_options +set_colors +parse_options "$@" +reformat_files diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2fda652b1..08ad3728d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -11,7 +11,7 @@ assignees: '' A clear and concise description of what the issue is. Please note that issues labeled "broken" with little to no descriptive behavior will be immediately closed. Further, issues that do not include any information to reproduce the behavior will be immediately closed. **To Reproduce** -All issues must be accompanied by: +All issues must be accompanied by: - The version of SST utilized (`sst --version`; `sst-config --CXX`; `sst-config --ELEMENT_CXXFLAGS`) - The source code branch being used - The last commit hash @@ -24,7 +24,7 @@ All issues must be accompanied by: A clear and concise description of what you expected to happen. **Trace** -If applicable, post a trace of the execution. +If applicable, post a trace of the execution. **Additional context** Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index 33548d601..12a1c9ec8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,9 @@ *.csv .cache/clangd/index .vscode -*.dylib +*.o .#* *~ .gdb_history *.out -build/* *.asm diff --git a/CMakeLists.txt b/CMakeLists.txt index 3adf743a1..6cc00c17f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # RevCPU Top-Level CMake -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # See LICENSE in the top level directory for licensing details @@ -13,6 +13,9 @@ endif() cmake_minimum_required(VERSION 3.19) project(revcpu CXX) +# Make sure Git hooks are set properly +execute_process(COMMAND_ERROR_IS_FATAL ANY COMMAND_ECHO STDERR COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/test_git_hooks.sh) + # Options for enabling tests option(CTEST_BLAS_REQUIRED_TESTS "Enable tests which require BLAS headers" OFF) option(CTEST_MULTILIB_TESTS "Enable 32-bit tests" ON) @@ -73,14 +76,14 @@ endif() # Compiler Options if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(WERROR_FLAG "") - set(FP_MODE_FLAG "-ffp-model=strict") + set(FP_MODE_FLAG "-ffp-model=strict -frounding-math -ftrapping-math") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument") else() - set(WERROR_FLAG "-Werror") - set(FP_MODE_FLAG "-frounding-math") + set(FP_MODE_FLAG "-frounding-math -ftrapping-math") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-format-attribute -Wsuggest-final-methods -Wsuggest-final-types -Wvolatile") endif() -set(CMAKE_CXX_FLAGS "-std=c++17 ${FP_MODE_FLAG} -O2 -Wall -Wextra ${WERROR_FLAG} -Wvla -Wuninitialized -Wfloat-conversion -Wdouble-promotion -Wno-unused-parameter -Wno-deprecated-declarations ${CMAKE_CXX_FLAGS} -I./ ${LDFLAGS} ${REVCPU_COMPILER_MACROS}") +set(CMAKE_CXX_FLAGS "-std=c++17 ${FP_MODE_FLAG} -O2 -Wall -Wextra -Wsuggest-override -Wmissing-noreturn -Wvla -Wuninitialized -Wdouble-promotion -Wsign-conversion -Wconversion -Wno-unused-parameter -Wno-deprecated-declarations -Wno-macro-redefined -Werror ${CMAKE_CXX_FLAGS} -I./ ${LDFLAGS} ${REVCPU_COMPILER_MACROS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall ${REVCPU_COMPILER_MACROS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -Wall ${REVCPU_COMPILER_MACROS}") @@ -99,7 +102,7 @@ if(BUILD_DOCUMENTATION) message(FATAL_ERROR "Doxygen is required to build the documentation.") endif() - set(doxyfile ${CMAKE_CURRENT_SOURCE_DIR}/doxygen/RevCPU.conf) + set(doxyfile ${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Rev.conf) add_custom_target(doc COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} diff --git a/LICENSE b/LICENSE index ad537f1fb..21bdb26a1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2023 Tactical Computing Laboratories LLC +Copyright (C) 2023-2024 Tactical Computing Laboratories LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 54df9dc65..f22850607 100644 --- a/README.md +++ b/README.md @@ -41,13 +41,21 @@ version for this is `3.19`. Building the Rev SST component from source using CMake (>= 3.19) can be performed as follows: git clone + git config core.hooksPath .githooks cd rev/build - cmake -DRVCC=/path/to/riscv/compiler/exe .. + cmake -DRVCC=/path/to/riscv/c/compiler/exe -DRVCXX=/path/to/riscv/c++/compiler/exe .. make -j make install +RVCC and RVCXX can be set as environment variables in lieu of passing them to CMake. + +There are 3 test levels which can be chosen: +-DTEST_LEVEL=1 A very small number of tests +-DTEST_LEVEL=2 Most tests, including assembly language ISA tests +-DTEST_LEVEL=3 All tests (the default) + Additional build options include: - * -DBUILD_ASM_TESTING=ON + * -DBUILD_DOCUMENTATION=ON : enables Doxygen source code generation (use `make doc`) After a successful build you can test your install with: @@ -73,7 +81,7 @@ RISC-V compiler from source. This will permit you to tune the necessary options in order to support a multitude of different standard, optional and custom extensions. -We recommend compiling the [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain) +We recommend compiling the [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain) using the `multilib` option. This is analogous to the following: git clone https://github.com/riscv/riscv-gnu-toolchain diff --git a/README_REV.md b/README_REV.md new file mode 100644 index 000000000..f22850607 --- /dev/null +++ b/README_REV.md @@ -0,0 +1,222 @@ +# rev : RISC-V Native CPU Model for SST + +![rev](documentation/imgs/rev_logo.png) + +## Getting Started + +The Rev SST component is designed to provide cycle-based simulation +capabilities of an arbitrary RISC-V core or cores. Rev utilizes the Sandia +[Structural Simulation Toolkit](http://sst-simulator.org/) as the core parallel +discrete event simulation framework. We utilize the standard SST "core" +component libraries to build the Rev component. As a result, Rev can be +attached to any other existing SST component for full system and network +simulations. + +The Rev model is unique in the scope of other SST CPU models in that is +provides users the ability to load compiled binaries (ELF binaries). Rather +than requiring input in the form of textual assembly or hex dumps, SST contains +a RISC-V compatible loader function that generates all the necessary symbol +tables and addressing modes for the target RISC-V CPU. Further, Rev permits +users to generate simulation configurations that contain heterogeneous RISC-V +designs with support for disparate extensions. + +The Rev component infrastructure can also be extended to include custom +instruction extensions. This provides users the ability to design new +instruction templates without requiring modifications to the core crack+decode +infrastructure. For more information on creating custom templates, see the +developer documentation. + +## Prerequisites + +Given that this is an SST external component, the primary prerequisite is a +current installation of the SST Core. The Rev building infrastructure assumes +that the `sst-config` tool is installed and can be found in the current PATH +environment. + +Rev relies on CMake for building the component from source. The minimum required +version for this is `3.19`. + +## Building + +Building the Rev SST component from source using CMake (>= 3.19) can be performed as follows: + + git clone + git config core.hooksPath .githooks + cd rev/build + cmake -DRVCC=/path/to/riscv/c/compiler/exe -DRVCXX=/path/to/riscv/c++/compiler/exe .. + make -j + make install + +RVCC and RVCXX can be set as environment variables in lieu of passing them to CMake. + +There are 3 test levels which can be chosen: +-DTEST_LEVEL=1 A very small number of tests +-DTEST_LEVEL=2 Most tests, including assembly language ISA tests +-DTEST_LEVEL=3 All tests (the default) + +Additional build options include: + * -DBUILD_DOCUMENTATION=ON : enables Doxygen source code generation (use `make doc`) + +After a successful build you can test your install with: + + make test + +You can also run a single test with: + + ctest -R + +where you can substitute `test_name` with the name of the test, for example: + + ctest -R TEST_EX1 + +will run the test found in test/ex1. See the full list of tests in +`test/CMakeLists.txt`. + +## Building Compatible Compilers + +As mentioned above, the Rev SST model supports standard ELF binary payloads as +input to the model. As a result, we need a cross compilation framework to build +source code into suitable binaries. We highly recommend building a suitable +RISC-V compiler from source. This will permit you to tune the necessary options +in order to support a multitude of different standard, optional and custom +extensions. + +We recommend compiling the [riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain) +using the `multilib` option. This is analogous to the following: + + git clone https://github.com/riscv/riscv-gnu-toolchain + cd riscv-gnu-toolchain + git submodule update --init --recursive + ./configure --prefix=/opt/riscv --enable-multilib + make -j + +## Example Execution + +### Component Options + +The Rev SST component contains the following options: + +| Parameter | Required? | Type | Description | +|---------------------|-----------|--------------------|-------------| +| verbose | | unsigned integer | Values of 0-8. Increasing values increase the verbosity of output | +| numCores | X | unsigned integer | Values of 1-N. Sets the number of cores in the simulation | +| clock | X | Hertz | "xGHz", "xKHz". Sets the clock frequency of the device. | +| memSize | X | unsigned integer | Sets the size of physical memory in bytes | +| machine | X | "[Core:Arch]" | "[0:RV32I],[1:RV64G]". Sets the RISC-V architecture for the target core | +| startAddr | X | "[Core:StartAddr]" | "[0:0x00010144],[1:0x123456]". Sets the entry point for each core | +| memCost | | "[Core:Min:Max]" | "[0:1:10],[1:50:100]", Sets the minimum and maximum latency (in cycles) for each core's memory load | +| program | X | string | "example.exe". Sets the target ELF executable | +| table | | string | "/path/to/table.txt". Sets the path the instruction cost table | +| splash | | 0/1 | Default=0. Setting to 1 displays the Rev bootsplash | +| enable\_nic | | 0/1 | Default=0. Setting to 1 enables a standard NIC | +| enable\_pan | | 0/1 | Default=0. Setting to 1 enables a PAN NIC | +| enable\_test | | 0/1 | Default=0. Setting to 1 enables the internal PAN test harness | +| enable\_pan\_stats | | 0/1 | Default=0. Setting to 1 enables internal statistics for PAN commands | +| enableRDMAMbox | | 0/1 | Default=1. Setting to 1 enables the internal RDMA Mailbox for applications to initiate messages | +| msgPerCycle | | unsigned integer | Default=1. Sets the number of messages to inject per cycle | +| testIters | | unsigned integer | Default=255. Sets the number of iterations for each PAN test loop | + +### Deriving the ELF Entry Point + +The latest version of Rev no longer requires the user to manually derive the +starting address for binaries that contain a `main()` function. If the user +specifies the starting address as `0x00`, then the Rev loader will +automatically derive the `main()` symbol address and use it as the starting +address. From here, the Rev model will perform an initial setup and reset of +the target core or cores in the same manner as prescribed by the RISC-V ABI. +Most users will expect to execute their application starting at the `main()` +function. If the user requires a different starting address or the target +payload does not contain a `main()` function, then the user must manually +derive the address. Given an executable that has been compiled +(`example.exe`), we may derive the entry point address using the tool chain's +`objdump` tool. An example of doing so is as follows: + + riscv64-unknown-elf-objdump -dC example.exe | grep "
" + +This will give us output similar to the following: + + 00010144
: + +Using this, the address `0x00010144` becomes our entry point address. + +The Rev component model has the ability to start execution at valid address in +the RISC-V text space. However, keep in mind, that Rev assumes no prior state +when starting execution (start from reset). As a result, the user cannot assume +that the Rev model will prepopulate any memory or register state outside of +what is provided when executing from `main()`. + +### Multicore Execution +As mentioned above, Rev has the ability to execute multiple, heterogeneous +cores in the same simulation. However, if users seek to execute multiple, +homogeneous cores, there is an additional configuration option for doing so. +For example, if you seek to simulate 8 homogeneous cores, set `numCores` to 8 +and use the following configuration parameter for the `machine` option: + + "machine" : "[CORES:RV64G]" + +This `CORES` option sets all 8 cores to `RV64G`. Similarly, if you seek to start +all the cores at the same `startAddr`, you can use the same option as follows: + + "startAddr : "[CORES:0x00000000]" + +### Sample Execution + +Executing one of the included sample tests can be performed as follows: + + export REV_EXE=ex1.exe + sst rev-test-ex1.py + +## Adding Tests to the test suite + +To add tests to the Rev test suite, edit `test/CMakeLists.txt`. By default, the +tests look for the SST output string "Program Execution Complete" and have a +max runtime of 30 seconds. Both of these values are user defined with the +`test/CMakeLists.txt` file. + +All tests should follow the existing directory structure and be added to +`test//` + +CTest will look in your newly created folder for a shell script, this is the +script that will build the RISC-VV executable using the RISC-V compiler. See +`test/ext/run_ex1.sh` for an example. + +## Contributing + +We welcome outside contributions from corporate, academic and individual +developers. However, there are a number of fundamental ground rules that you +must adhere to in order to participate. These rules are outlined as follows: + +* By contributing to this code, one must agree to the licensing described in +the top-level [LICENSE](LICENSE) file. +* All code must adhere to the existing C++ coding style. While we are somewhat +flexible in basic style, you will adhere to what is currently in place. This +includes camel case C++ methods and inline comments. Uncommented, complicated +algorithmic constructs will be rejected. +* We support compilaton and adherence to C++ standard methods. All new methods +and variables contained within public, private and protected class methods must +be commented using the existing Doxygen-style formatting. All new classes must +also include Doxygen blocks in the new header files. Any pull requests that +lack these features will be rejected. +* All changes to functionality and the API infrastructure must be accompanied +by complementary tests All external pull requests **must** target the `devel` +branch. No external pull requests will be accepted to the master branch. +* All external pull requests must contain sufficient documentation in the pull +request comments in order to be accepted. + +## Extension Development + +See the [developer documentation](documentation/ExtensionDevelopment.md). + +## License + +See the [LICENSE](./LICENSE) file + +## Authors +* *John Leidel* - *Chief Scientist* - [Tactical Computing Labs](http://www.tactcomplabs.com) +* *David Donofrio* - *Chief Hardware Architect* - [Tactical Computing Labs](http://www.tactcomplabs.com) +* *Chris Taylor* - *Sr. Principal Research Engineer* - [Tactical Computing Labs](http://www.tactcomplabs.com) +* *Ryan Kabrick* - *Sr. Research Engineer* - [Tactical Computing Labs](http://www.tactcomplabs.com) +* *Lee Killough* - *Sr. Principal Research Engineer* - [Tactical Computing Labs](http://www.tactcomplabs.com) + +## Acknowledgements +* TBD diff --git a/common/include/RevCommon.h b/common/include/RevCommon.h index 3fd6440e5..7f98bda40 100644 --- a/common/include/RevCommon.h +++ b/common/include/RevCommon.h @@ -1,7 +1,7 @@ // // _Rev_Common_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -11,6 +11,7 @@ #ifndef __REV_COMMON__ #define __REV_COMMON__ +#include #include #include #include @@ -23,51 +24,97 @@ #endif #ifndef _REV_INVALID_HART_ID_ -#define _REV_INVALID_HART_ID_ (unsigned(~0)) +#define _REV_INVALID_HART_ID_ ( unsigned( ~0 ) ) #endif -#define _INVALID_ADDR_ (~uint64_t{0}) +#define _INVALID_ADDR_ ( ~uint64_t{ 0 } ) -#define _INVALID_TID_ (uint32_t{0}) +#define _INVALID_TID_ ( uint32_t{ 0 } ) -#define _MAX_HARTS_ 4096 +#define _MAX_HARTS_ 4096 -namespace SST::RevCPU{ +namespace SST::RevCPU { + +// using float16 = _Float16; + +/// Safe non-narrowing cast of enum to integer type +/// C++17 allows non-narrowing cast of integer to scoped enum, but not the reverse +template>() } )> +constexpr std::enable_if_t && std::is_enum_v, INT> safe_static_cast( ENUM e ) { + return static_cast( e ); +} + +/// Allow non-narrowing integer->integer cast with safe_static_cast +template() } )> +constexpr std::enable_if_t && std::is_integral_v, INT> safe_static_cast( ENUM e ) { + return static_cast( e ); +} + +/// Make an expression dependent on arbitrary template type parameters. +/// This has the effect of lazy evaluation of an expression until a template containing it is instantiated. +/// It can be used to wrap an incomplete class type which will be completed by template instantiation time. +template +constexpr T&& make_dependent( T&& x ) { + return std::forward( x ); +} /// Zero-extend value of bits size template -constexpr auto ZeroExt(T val, size_t bits){ - return static_cast>(val) & ~(~std::make_unsigned_t{0} << bits); +constexpr auto ZeroExt( T val, int bits ) { + using UT = std::make_unsigned_t; + return UT( UT( val ) & UT( ~( UT( ~UT{} ) << bits ) ) ); } /// Sign-extend value of bits size template -constexpr auto SignExt(T val, size_t bits){ - auto signbit = std::make_unsigned_t{1} << (bits-1); - return static_cast>((ZeroExt(val, bits) ^ signbit) - signbit); +constexpr auto SignExt( T val, int bits ) { + auto signbit = std::make_unsigned_t{ 1 } << ( bits - 1 ); + return std::make_signed_t( ( ZeroExt( val, bits ) ^ signbit ) - signbit ); } /// Base-2 logarithm of integers template -constexpr int lg(T x){ - static_assert(std::is_integral_v); - +constexpr int lg( T x ) { + static_assert( std::is_integral_v ); // We select the __builtin_clz which takes integers no smaller than x - if constexpr(sizeof(x) <= sizeof(int)){ - return x ? 8*sizeof(int)-1 - __builtin_clz(x) : -1; - }else if constexpr(sizeof(x) <= sizeof(long)){ - return x ? 8*sizeof(long)-1 - __builtin_clzl(x) : -1; - }else{ - return x ? 8*sizeof(long long)-1 - __builtin_clzll(x) : -1; + if constexpr( sizeof( x ) <= sizeof( int ) ) { + return x ? int{ 8 * sizeof( int ) - 1 } - __builtin_clz( x ) : INT_MIN; + } else if constexpr( sizeof( x ) <= sizeof( long ) ) { + return x ? int{ 8 * sizeof( long ) - 1 } - __builtin_clzl( x ) : INT_MIN; + } else { + return x ? int{ 8 * sizeof( long long ) - 1 } - __builtin_clzll( x ) : INT_MIN; } } -enum class RevRegClass : uint8_t { ///< Rev CPU Register Classes - RegUNKNOWN = 0, ///< RevRegClass: Unknown register file - RegIMM = 1, ///< RevRegClass: Treat the reg class like an immediate: S-Format - RegGPR = 2, ///< RevRegClass: GPR reg file - RegCSR = 3, ///< RevRegClass: CSR reg file - RegFLOAT = 4, ///< RevRegClass: Float register file +/// Bit extraction of (pos+width-1 : pos) into a signed or unsigned type +template +constexpr auto BitExtract( T x ) { + if constexpr( std::is_signed_v ) + return SignExt( x >> pos, width ); + else + return ZeroExt( x >> pos, width ); +} + +/// Bit deposit of a value into (pos+width-1 : pos) +template +constexpr T& BitDeposit( T& x, U val ) { + auto mask = ~std::make_unsigned_t( ( std::make_unsigned_t( ~std::make_unsigned_t{} ) << width ) << pos ); + return x = ( x & ~mask ) | ( std::make_unsigned_t( val ) << pos & mask ); +} + +/// Bit shift of a value by a positive (left) or negative (right) shift amount +template +constexpr auto BitShift( T x, int shift ) { + return shift <= 0 ? T( x >> -shift ) : T( std::make_unsigned_t( x ) << shift ); +} + +enum class RevRegClass : uint8_t { ///< Rev CPU Register Classes + RegUNKNOWN = 0, ///< RevRegClass: Unknown register file + RegIMM = 1, ///< RevRegClass: Treat the reg class like an immediate: S-Format + RegGPR = 2, ///< RevRegClass: GPR reg file + RegCSR = 3, ///< RevRegClass: CSR reg file + RegFLOAT = 4, ///< RevRegClass: Float register file + RegVEC = 5, ///< RevRegClass: Vector register file }; enum class MemOp : uint8_t { @@ -83,59 +130,50 @@ enum class MemOp : uint8_t { MemOpAMO = 9, }; -std::ostream& operator<<(std::ostream& os, MemOp op); +std::ostream& operator<<( std::ostream& os, MemOp op ); template -constexpr uint64_t LSQHash(T DestReg, RevRegClass RegType, unsigned Hart){ - return static_cast(RegType) << (16 + 8) | static_cast(DestReg) << 16 | Hart; +constexpr uint64_t LSQHash( T DestReg, RevRegClass RegType, unsigned Hart ) { + return static_cast( RegType ) << ( 16 + 8 ) | static_cast( DestReg ) << 16 | Hart; } -struct MemReq{ - MemReq() = default; - MemReq(const MemReq&) = default; - MemReq(MemReq&&) = default; - MemReq& operator=(const MemReq&) = default; - MemReq& operator=(MemReq&&) = default; - ~MemReq() = default; +struct MemReq { + MemReq() = default; + MemReq( const MemReq& ) = default; + MemReq( MemReq&& ) = default; + MemReq& operator=( const MemReq& ) = default; + MemReq& operator=( MemReq&& ) = default; + ~MemReq() = default; template - MemReq(uint64_t Addr, - T DestReg, - RevRegClass RegType, - unsigned Hart, - MemOp ReqType, - bool isOutstanding, - std::function MarkLoadCompleteFunc) : - Addr(Addr), - DestReg(uint16_t(DestReg)), - RegType(RegType), - Hart(Hart), - ReqType(ReqType), - isOutstanding(isOutstanding), - MarkLoadCompleteFunc(std::move(MarkLoadCompleteFunc)){} - - void MarkLoadComplete() const { - MarkLoadCompleteFunc(*this); - } + MemReq( + uint64_t Addr, + T DestReg, + RevRegClass RegType, + unsigned Hart, + MemOp ReqType, + bool isOutstanding, + std::function MarkLoadCompleteFunc + ) + : Addr( Addr ), DestReg( uint16_t( DestReg ) ), RegType( RegType ), Hart( Hart ), ReqType( ReqType ), + isOutstanding( isOutstanding ), MarkLoadCompleteFunc( std::move( MarkLoadCompleteFunc ) ) {} - auto LSQHash() const { - return SST::RevCPU::LSQHash(DestReg, RegType, Hart); - } + void MarkLoadComplete() const { MarkLoadCompleteFunc( *this ); } - auto LSQHashPair() const { - return std::make_pair( LSQHash(), *this ); - } + auto LSQHash() const { return SST::RevCPU::LSQHash( DestReg, RegType, Hart ); } - uint64_t Addr = _INVALID_ADDR_; - uint16_t DestReg = 0; - RevRegClass RegType = RevRegClass::RegUNKNOWN; - unsigned Hart = _REV_INVALID_HART_ID_; - MemOp ReqType = MemOp::MemOpCUSTOM; - bool isOutstanding = false; + auto LSQHashPair() const { return std::make_pair( LSQHash(), *this ); } - std::function MarkLoadCompleteFunc = nullptr; + uint64_t Addr = _INVALID_ADDR_; + uint16_t DestReg = 0; + RevRegClass RegType = RevRegClass::RegUNKNOWN; + unsigned Hart = _REV_INVALID_HART_ID_; + MemOp ReqType = MemOp::MemOpCUSTOM; + bool isOutstanding = false; -};//struct MemReq + std::function MarkLoadCompleteFunc = nullptr; + +}; //struct MemReq // Enum for tracking the state of a RevThread. // Ex. Possible flow of thread state: @@ -162,7 +200,6 @@ enum class ThreadState { DONE, // Thread has finished; deallocate resources. }; - -}//namespace SST::RevCPU +} //namespace SST::RevCPU #endif diff --git a/common/include/revalloc.h b/common/include/revalloc.h new file mode 100644 index 000000000..d61046cc1 --- /dev/null +++ b/common/include/revalloc.h @@ -0,0 +1,135 @@ +#ifndef __REV_REVALLOC__ +#define __REV_REVALLOC__ + +#include "syscalls.h" +#include "unistd.h" +#include +#include +#include +#include +#include + +template +struct StandardAllocPolicy { + // typedefs + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // convert an StandardAllocPolicy to StandardAllocPolicy + template + struct rebind { + typedef StandardAllocPolicy other; + }; + + explicit StandardAllocPolicy() = default; + ~StandardAllocPolicy() = default; + StandardAllocPolicy( StandardAllocPolicy const& ) = default; + + template + explicit StandardAllocPolicy( StandardAllocPolicy const& ) {} + + // memory allocation + pointer allocate( size_type cnt, typename std::allocator::const_pointer = 0 ) { + return reinterpret_cast( rev_mmap( + 0, // Let rev choose the address + cnt * sizeof( T ), + PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions + MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous + -1, // No file descriptor because it's an anonymous mapping + 0 // No offset, irrelevant for anonymous mappings + ) ); + } + + void deallocate( pointer p, size_type n ) { + std::size_t addr = reinterpret_cast( p ); + rev_munmap( addr, n ); + } + + // size + size_type max_size() const { return std::numeric_limits::max(); } + + // construction/destruction + template + void construct( U* p, Args&&... args ) { + new( p ) U( std::forward( args )... ); + }; + + void destroy( pointer p ) { p->~T(); } +}; // end of class StandardAllocPolicy + +// determines if memory from another +// allocator can be deallocated from this one +template +bool operator==( StandardAllocPolicy const&, StandardAllocPolicy const& ) { + return true; +} + +template +bool operator==( StandardAllocPolicy const&, OtherAllocator const& ) { + return false; +} + +template> +class Allocator : public Policy { + typedef Policy AllocationPolicy; + +public: + typedef typename AllocationPolicy::size_type size_type; + typedef typename AllocationPolicy::difference_type difference_type; + typedef typename AllocationPolicy::pointer pointer; + typedef typename AllocationPolicy::const_pointer const_pointer; + typedef typename AllocationPolicy::reference reference; + typedef typename AllocationPolicy::const_reference const_reference; + typedef typename AllocationPolicy::value_type value_type; + + template + struct rebind { + typedef Allocator::other> other; + }; + + explicit Allocator() = default; + ~Allocator() = default; + Allocator( Allocator const& ) = default; + + template + Allocator( Allocator const& rhs ) : Policy( rhs ) {} +}; // end of class Allocator + +// determines if memory from another +// allocator can be deallocated from this one +template +bool operator==( Allocator const& lhs, Allocator const& rhs ) { + return operator==( static_cast( lhs ), static_cast( rhs ) ); +} + +template +bool operator==( Allocator const& lhs, Allocator const& rhs ) { + return operator==( static_cast( lhs ), static_cast( rhs ) ); +} + +template +bool operator==( Allocator const& lhs, OtherAllocator const& rhs ) { + return operator==( static_cast( lhs ), rhs ); +} + +template +bool operator!=( Allocator const& lhs, Allocator const& rhs ) { + return !operator==( lhs, rhs ); +} + +template +bool operator!=( Allocator const& lhs, Allocator const& rhs ) { + return !operator==( lhs, rhs ); +} + +template +bool operator!=( Allocator const& lhs, OtherAllocator const& rhs ) { + return !operator==( lhs, rhs ); +} + +#endif diff --git a/common/syscalls/syscalls.h b/common/syscalls/syscalls.h index d2b77c9da..f15abab3c 100644 --- a/common/syscalls/syscalls.h +++ b/common/syscalls/syscalls.h @@ -11,15 +11,17 @@ #ifndef _SYSCALLS_H_ #define _SYSCALLS_H_ - -#include +#include +#include #include #include #include -#include -#include #include +#ifdef __cplusplus +extern "C" { +#endif + // The following is required to build on MacOS // because sigval & siginfo_t are already defined // in the two headers that get pulled in when building @@ -28,28 +30,29 @@ // try adding another type from this file to the // ifdef #ifdef __APPLE__ - #include - #include +#include +#include #else - union sigval { - int sival_int; - void *sival_ptr; - }; +union sigval { + int sival_int; + void* sival_ptr; +}; - typedef struct{ - int si_signo; - int si_code; - union sigval si_value; - int si_errno; - pid_t si_pid; - uid_t si_uid; - void *si_addr; - int si_status; - int si_band; - }siginfo_t; +typedef struct { + int si_signo; + int si_code; + union sigval si_value; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void* si_addr; + int si_status; + int si_band; +} siginfo_t; #endif // Clone Flags +// clang-format off #define CSIGNAL 0x000000ff /* Signal mask to be sent at exit */ #define CLONE_VM 0x00000100 /* Set if VM shared between processes */ #define CLONE_FS 0x00000200 /* Set if fs info shared between processes */ @@ -186,7 +189,7 @@ #define STDOUT_FILENO 1 /* standard output file descriptor */ #define STDERR_FILENO 2 /* standard error file descriptor */ - +// clang-format on struct __aio_sigset; struct epoll_event; @@ -250,18 +253,23 @@ struct clone_args; struct open_how; struct mount_attr; struct landlock_ruleset_attr; +struct old_timespec32; +struct __kernel_itimerspec; +struct sigevent; +struct sigaction; +struct siginfo; - -typedef uint32_t rwf_t; +typedef uint32_t rwf_t; typedef unsigned long aio_context_t; -typedef uint16_t aio_key; -typedef uint16_t aio_rw_flags; -typedef int32_t key_serial_t; /* key handle serial number */ -typedef uint32_t key_perm_t; /* key handle permissions mask */ +typedef uint16_t aio_key; +typedef uint16_t aio_rw_flags; +typedef int32_t key_serial_t; /* key handle serial number */ +typedef uint32_t key_perm_t; /* key handle permissions mask */ + typedef struct __user_cap_header_struct { uint32_t version; - int pid; -} *cap_user_header_t; + int pid; +}* cap_user_header_t; #define __kernel_timespec timespec @@ -269,3546 +277,432 @@ typedef struct __user_cap_data_struct { uint32_t effective; uint32_t permitted; uint32_t inheritable; -} *cap_user_data_t; +}* cap_user_data_t; /* To optimize the implementation one can use the following struct. */ -struct aioinit - { - int aio_threads; /* Maximum number of threads. */ - int aio_num; /* Number of expected simultaneous requests. */ - int aio_locks; /* Not used. */ - int aio_usedba; /* Not used. */ - int aio_debug; /* Not used. */ - int aio_numusers; /* Not used. */ - int aio_idle_time; /* Number of seconds before idle thread terminates. */ - int aio_reserved; - }; +struct aioinit { + int aio_threads; /* Maximum number of threads. */ + int aio_num; /* Number of expected simultaneous requests. */ + int aio_locks; /* Not used. */ + int aio_usedba; /* Not used. */ + int aio_debug; /* Not used. */ + int aio_numusers; /* Not used. */ + int aio_idle_time; /* Number of seconds before idle thread terminates. */ + int aio_reserved; +}; typedef unsigned short umode_t; typedef unsigned short qid_t; -typedef off_t loff_t; +typedef off_t loff_t; + struct clone_args { - int flags; /* Flags bit mask */ - int pidfd; /* Where to store PID file descriptor (int *) */ - int child_tid; /* Where to store child TID, in child's memory (pid_t *) */ - int parent_tid; /* Where to store child TID, in parent's memory (pid_t *) */ - int exit_signal; /* Signal to deliver to parent on child termination */ - int stack; /* Pointer to lowest byte of stack */ - int stack_size; /* Size of stack */ - int tls; /* Location of new TLS */ - int set_tid; /* Pointer to a pid_t array (since Linux 5.5) */ - int set_tid_size; /* Number of elements in set_tid (since Linux 5.5) */ - int cgroup; /* File descriptor for target cgroup of child (since Linux 5.7) */ + int flags; /* Flags bit mask */ + int pidfd; /* Where to store PID file descriptor (int *) */ + int child_tid; /* Where to store child TID, in child's memory (pid_t *) */ + int parent_tid; /* Where to store child TID, in parent's memory (pid_t *) */ + int exit_signal; /* Signal to deliver to parent on child termination */ + int stack; /* Pointer to lowest byte of stack */ + int stack_size; /* Size of stack */ + int tls; /* Location of new TLS */ + int set_tid; /* Pointer to a pid_t array (since Linux 5.5) */ + int set_tid_size; /* Number of elements in set_tid (since Linux 5.5) */ + int cgroup; /* File descriptor for target cgroup of child (since Linux 5.7) */ }; /* read() from /dev/aio returns these structures. */ struct io_event { - uint64_t data; /* the data field from the iocb */ - uint64_t obj; /* what iocb this event came from */ - int64_t res; /* result code for this event */ - int64_t res2; /* secondary result */ + uint64_t data; /* the data field from the iocb */ + uint64_t obj; /* what iocb this event came from */ + int64_t res; /* result code for this event */ + int64_t res2; /* secondary result */ }; - struct iocb { - uint64_t aio_data; - uint16_t aio_key; - uint16_t aio_rw_flags; - uint16_t aio_lio_opcode; - int16_t aio_reqprio; - uint32_t aio_fildes; - uint64_t aio_buf; - uint64_t aio_nbytes; - int64_t aio_offset; - uint64_t aio_reserved2; - uint32_t aio_flags; - uint32_t aio_resfd; + uint64_t aio_data; + uint16_t aio_key; + uint16_t aio_rw_flags; + uint16_t aio_lio_opcode; + int16_t aio_reqprio; + uint32_t aio_fildes; + uint64_t aio_buf; + uint64_t aio_nbytes; + int64_t aio_offset; + uint64_t aio_reserved2; + uint32_t aio_flags; + uint32_t aio_resfd; }; struct rev_cpuinfo { - uint32_t cores; - uint32_t harts_per_core; + uint32_t cores; + uint32_t harts_per_core; }; struct rev_stats { - uint64_t cycles; - uint64_t instructions; + uint64_t cycles; + uint64_t instructions; }; #ifndef SYSCALL_TYPES_ONLY -// Actual System Calls -// int rev_io_setup(unsigned nr_reqs, aio_context_t *ctx); -// int rev_io_destroy(aio_context_t ctx); -// int rev_io_submit(aio_context_t, long, struct iocb * *); -// int rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result); -// int rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout); -// int rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags); -// int rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags); -// int rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); -// int rev_getxattr(const char *path, const char *name, void *value, size_t size); -// int rev_lgetxattr(const char *path, const char *name, void *value, size_t size); -// int rev_fgetxattr(int fd, const char *name, void *value, size_t size); -// int rev_listxattr(const char *path, char *list, size_t size); -// int rev_llistxattr(const char *path, char *list, size_t size); -// int rev_flistxattr(int fd, char *list, size_t size); -// int rev_removexattr(const char *path, const char *name); -// int rev_lremovexattr(const char *path, const char *name); -// int rev_fremovexattr(int fd, const char *name); -// int rev_getcwd(char *buf, unsigned long size); -// int rev_lookup_dcookie(uint64_t cookie64, char *buf, size_t len); -// int rev_eventfd2(unsigned int count, int flags); -// int rev_epoll_create1(int flags); -// int rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -// int rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize); -// int rev_dup(unsigned int fildes); -// int rev_dup3(unsigned int oldfd, unsigned int newfd, int flags); -// int rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg); -// int rev_inotify_init1(int flags); -// int rev_inotify_add_watch(int fd, const char *path, uint32_t mask); -// int rev_inotify_rm_watch(int fd, int32_t wd); -// int rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); -// int rev_ioprio_set(int which, int who, int ioprio); -// int rev_ioprio_get(int which, int who); -// int rev_flock(unsigned int fd, unsigned int cmd); -// int rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev); -// int rev_mkdirat(int dfd, const char * pathname, umode_t mode); -// int rev_unlinkat(int dfd, const char * pathname, int flag); -// int rev_symlinkat(const char * oldname, int newdfd, const char * newname); -// int rev_unlinkat(int dfd, const char * pathname, int flag); -// int rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname); -// int rev_umount(char *name, int flags); -// int rev_umount(char *name, int flags); -// int rev_pivot_root(const char *new_root, const char *put_old); -// int rev_ni_syscall(void); -// int rev_statfs64(const char *path, size_t sz, struct statfs64 *buf); -// int rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf); -// int rev_truncate64(const char *path, loff_t length); -// int rev_ftruncate64(unsigned int fd, loff_t length); -// int rev_fallocate(int fd, int mode, loff_t offset, loff_t len); -// int rev_faccessat(int dfd, const char *filename, int mode); -// int rev_chdir(const char *filename); -// int rev_fchdir(unsigned int fd); -// int rev_chroot(const char *filename); -// int rev_fchmod(unsigned int fd, umode_t mode); -// int rev_fchmodat(int dfd, const char * filename, umode_t mode); -// int rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag); -// int rev_fchown(unsigned int fd, uid_t user, gid_t group); -// int rev_openat(int dfd, const char *filename, int flags, umode_t mode); -// int rev_close(unsigned int fd); -// int rev_vhangup(void); -// int rev_pipe2(int *fildes, int flags); -// int rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr); -// int rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count); -// int rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence); -// int rev_read(unsigned int fd, char *buf, size_t count); -// int rev_write(unsigned int fd, const char *buf, size_t count); -// int rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen); -// int rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen); -// int rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos); -// int rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos); -// int rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h); -// int rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h); -// int rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count); -// int rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *); -// int rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t); -// int rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags); -// int rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags); -// int rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags); -// int rev_tee(int fdin, int fdout, size_t len, unsigned int flags); -// int rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz); -// int rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag); -// int rev_newfstat(unsigned int fd, struct stat *statbuf); -// int rev_sync(void); -// int rev_fsync(unsigned int fd); -// int rev_fdatasync(unsigned int fd); -// int rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes); -// int rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags); -// int rev_timerfd_create(int clockid, int flags); -// int rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr); -// int rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr); -// int rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags); -// int rev_acct(const char *name); -// int rev_capget(cap_user_header_t header, cap_user_data_t dataptr); -// int rev_capset(cap_user_header_t header, const cap_user_data_t data); -// int rev_personality(unsigned int personality); -// int rev_exit(int error_code); -// int rev_exit_group(int error_code); -// int rev_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *ru); -// int rev_set_tid_address(int *tidptr); -// int rev_unshare(unsigned long unshare_flags); -// int rev_futex(uint32_t *uaddr, int op, uint32_t val, struct __kernel_timespec *utime, uint32_t *uaddr2, uint32_t val3); -// int rev_set_robust_list(struct robust_list_head *head, size_t len); -// int rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr); -// int rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp); -// int rev_getitimer(int which, struct __kernel_old_itimerval *value); -// int rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue); -// int rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags); -// int rev_init_module(void *umod, unsigned long len, const char *uargs); -// int rev_delete_module(const char *name_user, unsigned int flags); -// int rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id); -// int rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting); -// int rev_timer_getoverrun(timer_t timer_id); -// int rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting); -// int rev_timer_delete(timer_t timer_id); -// // int rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp); -// int rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp); -// int rev_syslog(int type, char *buf, int len); -// int rev_ptrace(long request, long pid, unsigned long addr, unsigned long data); -// int rev_sched_setparam(pid_t pid, struct sched_param *param); -// int rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param); -// int rev_sched_getscheduler(pid_t pid); -// int rev_sched_getparam(pid_t pid, struct sched_param *param); -// int rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); -// int rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); -// int rev_sched_yield(void); -// int rev_sched_get_priority_max(int policy); -// int rev_sched_get_priority_min(int policy); -// int rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval); -// int rev_restart_syscall(void); -// int rev_kill(pid_t pid, int sig); -// int rev_tkill(pid_t pid, int sig); -// int rev_tgkill(pid_t tgid, pid_t pid, int sig); -// int rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss); -// int rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize); -// int rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t); -// int rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); -// int rev_rt_sigpending(sigset_t *set, size_t sigsetsize); -// int rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize); -// int rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo); -// int rev_setpriority(int which, int who, int niceval); -// int rev_getpriority(int which, int who); -// int rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg); -// int rev_setregid(gid_t rgid, gid_t egid); -// int rev_setgid(gid_t gid); -// int rev_setreuid(uid_t ruid, uid_t euid); -// int rev_setuid(uid_t uid); -// int rev_setresuid(uid_t ruid, uid_t euid, uid_t suid); -// int rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); -// int rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid); -// int rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); -// int rev_setfsuid(uid_t uid); -// int rev_setfsgid(gid_t gid); -// int rev_times(struct tms *tbuf); -// int rev_setpgid(pid_t pid, pid_t pgid); -// int rev_getpgid(pid_t pid); -// int rev_getsid(pid_t pid); -// int rev_setsid(void); -// int rev_getgroups(int gidsetsize, gid_t *grouplist); -// int rev_setgroups(int gidsetsize, gid_t *grouplist); -// int rev_newuname(struct new_utsname *name); -// int rev_sethostname(char *name, int len); -// int rev_setdomainname(char *name, int len); -// int rev_getrlimit(unsigned int resource, struct rlimit *rlim); -// int rev_setrlimit(unsigned int resource, struct rlimit *rlim); -// int rev_getrusage(int who, struct rusage *ru); -// int rev_umask(int mask); -// int rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); -// int rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache); -// int rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); -// int rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); -// int rev_adjtimex(struct __kernel_timex *txc_p); -// int rev_getpid(void); -// int rev_getppid(void); -// int rev_getuid(void); -// int rev_geteuid(void); -// int rev_getgid(void); -// int rev_getegid(void); -// int rev_gettid(void); -// int rev_sysinfo(struct sysinfo *info); -// int rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr); -// int rev_mq_unlink(const char *name); -// int rev_mq_timedsend(uint64_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout); -// int rev_mq_timedreceive(uint64_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout); -// int rev_mq_notify(uint64_t mqdes, const struct sigevent *notification); -// int rev_mq_getsetattr(uint64_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat); -// int rev_msgget(key_t key, int msgflg); -// int rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf); -// int rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg); -// int rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); -// int rev_semget(key_t key, int nsems, int semflg); -// int rev_semctl(int semid, int semnum, int cmd, unsigned long arg); -// int rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout); -// int rev_semop(int semid, struct sembuf *sops, unsigned nsops); -// int rev_shmget(key_t key, size_t size, int flag); -// int rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf); -// int rev_shmat(int shmid, char *shmaddr, int shmflg); -// int rev_shmdt(char *shmaddr); -// int rev_socket(int, int, int); -// int rev_socketpair(int, int, int, int *); -// int rev_bind(int, struct sockaddr *, int); -// int rev_listen(int, int); -// int rev_accept(int, struct sockaddr *, int *); -// int rev_connect(int, struct sockaddr *, int); -// int rev_getsockname(int, struct sockaddr *, int *); -// int rev_getpeername(int, struct sockaddr *, int *); -// int rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int); -// int rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *); -// int rev_setsockopt(int fd, int level, int optname, char *optval, int optlen); -// int rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen); -// int rev_shutdown(int, int); -// int rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags); -// int rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags); -// int rev_readahead(int fd, loff_t offset, size_t count); -// int rev_brk(unsigned long brk); -// int rev_munmap(unsigned long addr, size_t len); -// int rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr); -// int rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid); -// int rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid); -// int rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); -// int rev_fork(); // Actually uses clone under the hood -// int rev_clone(unsigned long, unsigned long, int *, unsigned long, int *); -// int rev_execve(const char *filename, const char *const *argv, const char *const *envp); -// int rev_old_mmap(struct mmap_arg_struct *arg); -// int rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); -// int rev_swapon(const char *specialfile, int swap_flags); -// int rev_swapoff(const char *specialfile); -// int rev_mprotect(unsigned long start, size_t len, unsigned long prot); -// int rev_msync(unsigned long start, size_t len, int flags); -// int rev_mlock(unsigned long start, size_t len); -// int rev_munlock(unsigned long start, size_t len); -// int rev_mlockall(int flags); -// int rev_munlockall(void); -// int rev_mincore(unsigned long start, size_t len, unsigned char * vec); -// int rev_madvise(unsigned long start, size_t len, int behavior); -// int rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags); -// int rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags); -// int rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags); -// int rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode); -// int rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to); -// int rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags); -// int rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo); -// int rev_perf_event_open(); -// int rev_accept4(int, struct sockaddr *, int *, int); -// int rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout); -// int rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru); -// int rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim); -// int rev_fanotify_init(unsigned int flags, unsigned int event_f_flags); -// int rev_fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask, int fd, const char *pathname); -// int rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag); -// int rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags); -// int rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx); -// int rev_syncfs(int fd); -// int rev_setns(int fd, int nstype); -// int rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags); -// int rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags); -// int rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags); -// int rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2); -// int rev_finit_module(int fd, const char *uargs, int flags); -// int rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags); -// int rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags); -// int rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags); -// int rev_seccomp(unsigned int op, unsigned int flags, void *uargs); -// int rev_getrandom(char *buf, size_t count, unsigned int flags); -// int rev_memfd_create(const char *uname_ptr, unsigned int flags); -// int rev_bpf(int cmd, union bpf_attr *attr, unsigned int size); -// int rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags); -// int rev_userfaultfd(int flags); -// int rev_membarrier(int cmd, unsigned int flags, int cpu_id); -// int rev_mlock2(unsigned long start, size_t len, int flags); -// int rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags); -// int rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags); -// int rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags); -// int rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey); -// int rev_pkey_alloc(unsigned long flags, unsigned long init_val); -// int rev_pkey_free(int pkey); -// int rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer); -// // int rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig); -// int rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig); -// int rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags); -// int rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp); -// int rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp); -// int rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx); -// int rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp); -// // int rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp); -// // int rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting); -// // int rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting); -// // int rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr); -// // int rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr); -// // int rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags); -// int rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig); -// // int rev_mq_timedsend(uint64_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout); -// // int rev_mq_timedreceive(uint64_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout); -// int rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags); -// int rev_io_uring_setup(uint32_t entries, struct io_uring_params *p); -// int rev_io_uring_enter(unsigned int fd, uint32_t to_submit, uint32_t min_complete, uint32_t flags, const sigset_t *sig, size_t sigsz); -// int rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args); -// int rev_open_tree(int dfd, const char *path, unsigned flags); -// int rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags); -// int rev_fsopen(const char *fs_name, unsigned int flags); -// int rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux); -// int rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); -// int rev_fspick(int dfd, const char *path, unsigned int flags); -// int rev_pidfd_open(pid_t pid, unsigned int flags); -// int rev_clone3(struct clone_args *uargs, size_t size); -// int rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags); -// int rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size); -// int rev_pidfd_getfd(int pidfd, int fd, unsigned int flags); -// int rev_faccessat2(int dfd, const char *filename, int mode, int flags); -// int rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags); - -static int rev_io_setup(unsigned nr_reqs, aio_context_t *ctx){ - int rc; - asm volatile ( - "li a7, 0 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_destroy(aio_context_t ctx){ - int rc; - asm volatile ( - "li a7, 1 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_submit(aio_context_t, long, struct iocb * *){ - int rc; - asm volatile ( - "li a7, 2 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result){ - int rc; - asm volatile ( - "li a7, 3 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout){ - int rc; - asm volatile ( - "li a7, 4 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags){ - int rc; - asm volatile ( - "li a7, 5 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags){ - int rc; - asm volatile ( - "li a7, 6 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags){ - int rc; - asm volatile ( - "li a7, 7 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getxattr(const char *path, const char *name, void *value, size_t size){ - int rc; - asm volatile ( - "li a7, 8 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_lgetxattr(const char *path, const char *name, void *value, size_t size){ - int rc; - asm volatile ( - "li a7, 9 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fgetxattr(int fd, const char *name, void *value, size_t size){ - int rc; - asm volatile ( - "li a7, 10 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_listxattr(const char *path, char *list, size_t size){ - int rc; - asm volatile ( - "li a7, 11 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_llistxattr(const char *path, char *list, size_t size){ - int rc; - asm volatile ( - "li a7, 12 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_flistxattr(int fd, char *list, size_t size){ - int rc; - asm volatile ( - "li a7, 13 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_removexattr(const char *path, const char *name){ - int rc; - asm volatile ( - "li a7, 14 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_lremovexattr(const char *path, const char *name){ - int rc; - asm volatile ( - "li a7, 15 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fremovexattr(int fd, const char *name){ - int rc; - asm volatile ( - "li a7, 16 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getcwd(char *buf, unsigned long size){ - int rc; - asm volatile ( - "li a7, 17 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_lookup_dcookie(uint64_t cookie64, char *buf, size_t len){ - int rc; - asm volatile ( - "li a7, 18 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_eventfd2(unsigned int count, int flags){ - int rc; - asm volatile ( - "li a7, 19 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_epoll_create1(int flags){ - int rc; - asm volatile ( - "li a7, 20 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event){ - int rc; - asm volatile ( - "li a7, 21 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize){ - int rc; - asm volatile ( - "li a7, 22 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_dup(unsigned int fildes){ - int rc; - asm volatile ( - "li a7, 23 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_dup3(unsigned int oldfd, unsigned int newfd, int flags){ - int rc; - asm volatile ( - "li a7, 24 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg){ - int rc; - asm volatile ( - "li a7, 25 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_inotify_init1(int flags){ - int rc; - asm volatile ( - "li a7, 26 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_inotify_add_watch(int fd, const char *path, uint32_t mask){ - int rc; - asm volatile ( - "li a7, 27 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_inotify_rm_watch(int fd, int32_t wd){ - int rc; - asm volatile ( - "li a7, 28 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ - int rc; - asm volatile ( - "li a7, 29 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ioprio_set(int which, int who, int ioprio){ - int rc; - asm volatile ( - "li a7, 30 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ioprio_get(int which, int who){ - int rc; - asm volatile ( - "li a7, 31 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_flock(unsigned int fd, unsigned int cmd){ - int rc; - asm volatile ( - "li a7, 32 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev){ - int rc; - asm volatile ( - "li a7, 33 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mkdirat(int dfd, const char * pathname, umode_t mode){ - int rc; - asm volatile ( - "li a7, 34 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_unlinkat(int dfd, const char * pathname, int flag){ - int rc; - asm volatile ( - "li a7, 35 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_symlinkat(const char * oldname, int newdfd, const char * newname){ - int rc; - asm volatile ( - "li a7, 36 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_unlinkat(int dfd, const char * pathname, int flag){ -// int rc; -// asm volatile ( -// "li a7, 37 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname){ - int rc; - asm volatile ( - "li a7, 38 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_umount(char *name, int flags){ - int rc; - asm volatile ( - "li a7, 39 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_umount(char *name, int flags){ -// int rc; -// asm volatile ( -// "li a7, 40 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_pivot_root(const char *new_root, const char *put_old){ - int rc; - asm volatile ( - "li a7, 41 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ni_syscall(void){ - int rc; - asm volatile ( - "li a7, 42 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_statfs64(const char *path, size_t sz, struct statfs64 *buf){ - int rc; - asm volatile ( - "li a7, 43 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf){ - int rc; - asm volatile ( - "li a7, 44 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_truncate64(const char *path, loff_t length){ - int rc; - asm volatile ( - "li a7, 45 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ftruncate64(unsigned int fd, loff_t length){ - int rc; - asm volatile ( - "li a7, 46 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fallocate(int fd, int mode, loff_t offset, loff_t len){ - int rc; - asm volatile ( - "li a7, 47 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_faccessat(int dfd, const char *filename, int mode){ - int rc; - asm volatile ( - "li a7, 48 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_chdir(const char *filename){ - int rc; - asm volatile ( - "li a7, 49 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fchdir(unsigned int fd){ - int rc; - asm volatile ( - "li a7, 50 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_chroot(const char *filename){ - int rc; - asm volatile ( - "li a7, 51 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fchmod(unsigned int fd, umode_t mode){ - int rc; - asm volatile ( - "li a7, 52 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fchmodat(int dfd, const char * filename, umode_t mode){ - int rc; - asm volatile ( - "li a7, 53 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag){ - int rc; - asm volatile ( - "li a7, 54 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fchown(unsigned int fd, uid_t user, gid_t group){ - int rc; - asm volatile ( - "li a7, 55 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_openat(int dfd, const char *filename, int flags, umode_t mode){ - int rc; - asm volatile ( - "li a7, 56 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_close(unsigned int fd){ - int rc; - asm volatile ( - "li a7, 57 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_vhangup(void){ - int rc; - asm volatile ( - "li a7, 58 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pipe2(int *fildes, int flags){ - int rc; - asm volatile ( - "li a7, 59 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr){ - int rc; - asm volatile ( - "li a7, 60 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count){ - int rc; - asm volatile ( - "li a7, 61 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence){ - int rc; - asm volatile ( - "li a7, 62 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_read(unsigned int fd, char *buf, size_t count){ - int rc; - asm volatile ( - "li a7, 63 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_write(unsigned int fd, const char *buf, size_t count){ - int rc; - asm volatile ( - "li a7, 64 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen){ - int rc; - asm volatile ( - "li a7, 65 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen){ - int rc; - asm volatile ( - "li a7, 66 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos){ - int rc; - asm volatile ( - "li a7, 67 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos){ - int rc; - asm volatile ( - "li a7, 68 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h){ - int rc; - asm volatile ( - "li a7, 69 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h){ - int rc; - asm volatile ( - "li a7, 70 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count){ - int rc; - asm volatile ( - "li a7, 71 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *){ - int rc; - asm volatile ( - "li a7, 72 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t){ - int rc; - asm volatile ( - "li a7, 73 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags){ - int rc; - asm volatile ( - "li a7, 74 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 75 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags){ -// int rc; -// asm volatile ( -// "li a7, 76 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_tee(int fdin, int fdout, size_t len, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 77 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz){ - int rc; - asm volatile ( - "li a7, 78 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag){ - int rc; - asm volatile ( - "li a7, 79 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_newfstat(unsigned int fd, struct stat *statbuf){ - int rc; - asm volatile ( - "li a7, 80 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sync(void){ - int rc; - asm volatile ( - "li a7, 81 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fsync(unsigned int fd){ - int rc; - asm volatile ( - "li a7, 82 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fdatasync(unsigned int fd){ - int rc; - asm volatile ( - "li a7, 83 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes){ - int rc; - asm volatile ( - "li a7, 84 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 84 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timerfd_create(int clockid, int flags){ - int rc; - asm volatile ( - "li a7, 85 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr){ - int rc; - asm volatile ( - "li a7, 86 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr){ - int rc; - asm volatile ( - "li a7, 87 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags){ - int rc; - asm volatile ( - "li a7, 88 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} -static int rev_acct(const char *name){ - int rc; - asm volatile ( - "li a7, 89 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_capget(cap_user_header_t header, cap_user_data_t dataptr){ - int rc; - asm volatile ( - "li a7, 90 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_capset(cap_user_header_t header, const cap_user_data_t data){ - int rc; - asm volatile ( - "li a7, 91 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_personality(unsigned int personality){ - int rc; - asm volatile ( - "li a7, 92 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_exit(int error_code){ - int rc; - asm volatile ( - "li a7, 93 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_exit_group(int error_code){ - int rc; - asm volatile ( - "li a7, 94 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru){ - int rc; - asm volatile ( - "li a7, 95 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_set_tid_address(int *tidptr){ - int rc; - asm volatile ( - "li a7, 96 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_unshare(unsigned long unshare_flags){ - int rc; - asm volatile ( - "li a7, 97 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_futex(uint32_t *uaddr, int op, uint32_t val, struct __kernel_timespec *utime, uint32_t *uaddr2, uint32_t val3){ -// int rc; -// asm volatile ( -// "li a7, 98 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_set_robust_list(struct robust_list_head *head, size_t len){ - int rc; - asm volatile ( - "li a7, 99 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr){ - int rc; - asm volatile ( - "li a7, 100 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp){ - int rc; - asm volatile ( - "li a7, 101 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getitimer(int which, struct __kernel_old_itimerval *value){ - int rc; - asm volatile ( - "li a7, 102 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue){ - int rc; - asm volatile ( - "li a7, 103 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 104 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_init_module(void *umod, unsigned long len, const char *uargs){ - int rc; - asm volatile ( - "li a7, 105 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_delete_module(const char *name_user, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 106 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id){ - int rc; - asm volatile ( - "li a7, 107 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting){ - int rc; - asm volatile ( - "li a7, 108 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timer_getoverrun(timer_t timer_id){ - int rc; - asm volatile ( - "li a7, 109 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting){ - int rc; - asm volatile ( - "li a7, 110 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_timer_delete(timer_t timer_id){ - int rc; - asm volatile ( - "li a7, 111 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp){ - int rc; - asm volatile ( - "li a7, 112 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +//----------------------------------------------------------------------------- +// Create a Rev wrapper to a System Call +// __attribute__((naked)) prevents GCC/Clang from modifying any registers in +// the prologue or epilogue, and prevents optimizing away the ECALL at -O3 +//----------------------------------------------------------------------------- +// clang-format off +#define REV_SYSCALL(NUM, PROTO) __attribute__((naked)) \ + static PROTO{ asm(" li a7," #NUM "; ecall; ret"); } + +REV_SYSCALL( 0, int rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) ); +REV_SYSCALL( 1, int rev_io_destroy(aio_context_t ctx) ); +REV_SYSCALL( 2, int rev_io_submit(aio_context_t ctx_id, long nr, struct iocb **iocbpp) ); +REV_SYSCALL( 3, int rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) ); +REV_SYSCALL( 4, int rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) ); +REV_SYSCALL( 5, int rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) ); +REV_SYSCALL( 6, int rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) ); +REV_SYSCALL( 7, int rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) ); +REV_SYSCALL( 8, ssize_t rev_getxattr(const char *path, const char *name, void *value, size_t size) ); +REV_SYSCALL( 9, ssize_t rev_lgetxattr(const char *path, const char *name, void *value, size_t size) ); +REV_SYSCALL( 10, ssize_t rev_fgetxattr(int fd, const char *name, void *value, size_t size) ); +REV_SYSCALL( 11, ssize_t rev_listxattr(const char *path, char *list, size_t size) ); +REV_SYSCALL( 12, ssize_t rev_llistxattr(const char *path, char *list, size_t size) ); +REV_SYSCALL( 13, ssize_t rev_flistxattr(int fd, char *list, size_t size) ); +REV_SYSCALL( 14, int rev_removexattr(const char *path, const char *name) ); +REV_SYSCALL( 15, int rev_lremovexattr(const char *path, const char *name) ); +REV_SYSCALL( 16, int rev_fremovexattr(int fd, const char *name) ); +REV_SYSCALL( 17, int rev_getcwd(char *buf, unsigned long size) ); +REV_SYSCALL( 18, int rev_lookup_dcookie(uint64_t cookie64, char *buf, size_t len) ); +REV_SYSCALL( 19, int rev_eventfd2(unsigned int count, int flags) ); +REV_SYSCALL( 20, int rev_epoll_create1(int flags) ); +REV_SYSCALL( 21, int rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) ); +REV_SYSCALL( 22, int rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) ); +REV_SYSCALL( 23, int rev_dup(unsigned int fildes) ); +REV_SYSCALL( 24, int rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) ); +REV_SYSCALL( 25, int rev_fcntl64(int fd, unsigned int cmd, unsigned long arg) ); +REV_SYSCALL( 26, int rev_inotify_init1(int flags) ); +REV_SYSCALL( 27, int rev_inotify_add_watch(int fd, const char *path, uint32_t mask) ); +REV_SYSCALL( 28, int rev_inotify_rm_watch(int fd, int32_t wd) ); +REV_SYSCALL( 29, int rev_ioctl(int fd, unsigned int cmd, unsigned long arg) ); +REV_SYSCALL( 30, int rev_ioprio_set(int which, int who, int ioprio) ); +REV_SYSCALL( 31, int rev_ioprio_get(int which, int who) ); +REV_SYSCALL( 32, int rev_flock(int fd, unsigned int cmd) ); +REV_SYSCALL( 33, int rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) ); +REV_SYSCALL( 34, int rev_mkdirat(int dfd, const char * pathname, umode_t mode) ); +REV_SYSCALL( 35, int rev_unlinkat(int dfd, const char * pathname, int flag) ); +REV_SYSCALL( 36, int rev_symlinkat(const char * oldname, int newdfd, const char * newname) ); +REV_SYSCALL( 37, int rev_linkat(int dfd, const char * pathname, int flag) ); +REV_SYSCALL( 38, int rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) ); +REV_SYSCALL( 39, int rev_umount(char *name, int flags) ); +REV_SYSCALL( 40, int rev_mount(char *name, int flags) ); +REV_SYSCALL( 41, int rev_pivot_root(const char *new_root, const char *put_old) ); +REV_SYSCALL( 42, int rev_ni_syscall(void) ); +REV_SYSCALL( 43, int rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) ); +REV_SYSCALL( 44, int rev_fstatfs64(int fd, size_t sz, struct statfs64 *buf) ); +REV_SYSCALL( 45, int rev_truncate64(const char *path, loff_t length) ); +REV_SYSCALL( 46, int rev_ftruncate64(int fd, loff_t length) ); +REV_SYSCALL( 47, int rev_fallocate(int fd, int mode, loff_t offset, loff_t len) ); +REV_SYSCALL( 48, int rev_faccessat(int dfd, const char *filename, int mode) ); +REV_SYSCALL( 49, int rev_chdir(const char *filename) ); +REV_SYSCALL( 50, int rev_fchdir(int fd) ); +REV_SYSCALL( 51, int rev_chroot(const char *filename) ); +REV_SYSCALL( 52, int rev_fchmod(int fd, umode_t mode) ); +REV_SYSCALL( 53, int rev_fchmodat(int dfd, const char * filename, umode_t mode) ); +REV_SYSCALL( 54, int rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) ); +REV_SYSCALL( 55, int rev_fchown(int fd, uid_t user, gid_t group) ); +REV_SYSCALL( 56, int rev_openat(int dfd, const char *filename, int flags, umode_t mode) ); +REV_SYSCALL( 57, int rev_close(int fd) ); +REV_SYSCALL( 58, int rev_vhangup(void) ); +REV_SYSCALL( 59, int rev_pipe2(int *fildes, int flags) ); +REV_SYSCALL( 60, int rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) ); +REV_SYSCALL( 61, ssize_t rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) ); +REV_SYSCALL( 62, int rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) ); +REV_SYSCALL( 63, ssize_t rev_read(unsigned int fd, char *buf, size_t count) ); +REV_SYSCALL( 64, ssize_t rev_write(unsigned int fd, const char *buf, size_t count) ); +REV_SYSCALL( 65, ssize_t rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) ); +REV_SYSCALL( 66, ssize_t rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) ); +REV_SYSCALL( 67, ssize_t rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) ); +REV_SYSCALL( 68, ssize_t rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) ); +REV_SYSCALL( 69, ssize_t rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) ); +REV_SYSCALL( 70, ssize_t rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) ); +REV_SYSCALL( 71, ssize_t rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) ); +REV_SYSCALL( 72, int rev_pselect6_time32(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct old_timespec32 *tsp, void *sig) ); +REV_SYSCALL( 73, int rev_ppoll_time32(struct pollfd *ufds, unsigned int nfds, struct old_timespec32 *tsp, const sigset_t *sigmask, size_t sigsetsize) ); +REV_SYSCALL( 74, int rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) ); +REV_SYSCALL( 75, ssize_t rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) ); +REV_SYSCALL( 76, ssize_t rev_splice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) ); +REV_SYSCALL( 77, ssize_t rev_tee(int fdin, int fdout, size_t len, unsigned int flags) ); +REV_SYSCALL( 78, ssize_t rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) ); +REV_SYSCALL( 79, int rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) ); +REV_SYSCALL( 80, int rev_newfstat(int fd, struct stat *statbuf) ); +REV_SYSCALL( 81, int rev_sync(void) ); +REV_SYSCALL( 82, int rev_fsync(int fd) ); +REV_SYSCALL( 83, int rev_fdatasync(int fd) ); +REV_SYSCALL( 84, int rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) ); +REV_SYSCALL( 84, int rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) ); +REV_SYSCALL( 85, int rev_timerfd_create(int clockid, int flags) ); +REV_SYSCALL( 86, int rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) ); +REV_SYSCALL( 87, int rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) ); +REV_SYSCALL( 88, int rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) ); +REV_SYSCALL( 89, int rev_acct(const char *name) ); +REV_SYSCALL( 90, int rev_capget(cap_user_header_t header, cap_user_data_t dataptr) ); +REV_SYSCALL( 91, int rev_capset(cap_user_header_t header, const cap_user_data_t data) ); +REV_SYSCALL( 92, int rev_personality(unsigned int personality) ); +REV_SYSCALL( 93, int rev_exit(int error_code) ); +REV_SYSCALL( 94, int rev_exit_group(int error_code) ); +REV_SYSCALL( 95, int rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) ); +REV_SYSCALL( 96, pid_t rev_set_tid_address(int *tidptr) ); +REV_SYSCALL( 97, int rev_unshare(int unshare_flags) ); +REV_SYSCALL( 98, int rev_futex(uint32_t *uaddr, int op, uint32_t val, struct __kernel_timespec *utime, uint32_t *uaddr2, uint32_t val3) ); +REV_SYSCALL( 99, int rev_set_robust_list(struct robust_list_head *head, size_t len) ); +REV_SYSCALL( 100, int rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) ); +REV_SYSCALL( 101, int rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) ); +REV_SYSCALL( 102, int rev_getitimer(int which, struct __kernel_old_itimerval *value) ); +REV_SYSCALL( 103, int rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) ); +REV_SYSCALL( 104, int rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) ); +REV_SYSCALL( 105, int rev_init_module(void *umod, unsigned long len, const char *uargs) ); +REV_SYSCALL( 106, int rev_delete_module(const char *name_user, unsigned int flags) ); +REV_SYSCALL( 107, int rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) ); +REV_SYSCALL( 108, int rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) ); +REV_SYSCALL( 109, int rev_timer_getoverrun(timer_t timer_id) ); +REV_SYSCALL( 110, int rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) ); +REV_SYSCALL( 111, int rev_timer_delete(timer_t timer_id) ); +REV_SYSCALL( 112, int rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) ); +REV_SYSCALL( 113, int rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) ); +REV_SYSCALL( 114, int rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) ); +REV_SYSCALL( 115, int rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) ); +REV_SYSCALL( 116, int rev_syslog(int type, char *buf, int len) ); +REV_SYSCALL( 117, int rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) ); +REV_SYSCALL( 118, int rev_sched_setparam(pid_t pid, struct sched_param *param) ); +REV_SYSCALL( 119, int rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) ); +REV_SYSCALL( 120, int rev_sched_getscheduler(pid_t pid) ); +REV_SYSCALL( 121, int rev_sched_getparam(pid_t pid, struct sched_param *param) ); +REV_SYSCALL( 122, int rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) ); +REV_SYSCALL( 123, int rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) ); +REV_SYSCALL( 124, int rev_sched_yield(void) ); +REV_SYSCALL( 125, int rev_sched_get_priority_max(int policy) ); +REV_SYSCALL( 126, int rev_sched_get_priority_min(int policy) ); +REV_SYSCALL( 127, int rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) ); +REV_SYSCALL( 128, long rev_restart_syscall(void) ); +REV_SYSCALL( 129, int rev_kill(pid_t pid, int sig) ); +REV_SYSCALL( 130, int rev_tkill(pid_t pid, int sig) ); +REV_SYSCALL( 131, int rev_tgkill(pid_t tgid, pid_t pid, int sig) ); +REV_SYSCALL( 132, int rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) ); +REV_SYSCALL( 133, int rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) ); +REV_SYSCALL( 134, int rev_rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact, size_t sigsetsize) ); +REV_SYSCALL( 135, int rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) ); +REV_SYSCALL( 136, int rev_rt_sigpending(sigset_t *set, size_t sigsetsize) ); +REV_SYSCALL( 137, int rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) ); +REV_SYSCALL( 138, int rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) ); +REV_SYSCALL( 140, int rev_setpriority(int which, int who, int niceval) ); +REV_SYSCALL( 141, int rev_getpriority(int which, int who) ); +REV_SYSCALL( 142, int rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) ); +REV_SYSCALL( 143, int rev_setregid(gid_t rgid, gid_t egid) ); +REV_SYSCALL( 144, int rev_setgid(gid_t gid) ); +REV_SYSCALL( 145, int rev_setreuid(uid_t ruid, uid_t euid) ); +REV_SYSCALL( 146, int rev_setuid(uid_t uid) ); +REV_SYSCALL( 147, int rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) ); +REV_SYSCALL( 148, int rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) ); +REV_SYSCALL( 149, int rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) ); +REV_SYSCALL( 150, int rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) ); +REV_SYSCALL( 151, int rev_setfsuid(uid_t uid) ); +REV_SYSCALL( 152, int rev_setfsgid(gid_t gid) ); +REV_SYSCALL( 153, clock_t rev_times(struct tms *tbuf) ); +REV_SYSCALL( 154, int rev_setpgid(pid_t pid, pid_t pgid) ); +REV_SYSCALL( 155, int rev_getpgid(pid_t pid) ); +REV_SYSCALL( 156, int rev_getsid(pid_t pid) ); +REV_SYSCALL( 157, int rev_setsid(void) ); +REV_SYSCALL( 158, int rev_getgroups(int gidsetsize, gid_t *grouplist) ); +REV_SYSCALL( 159, int rev_setgroups(int gidsetsize, gid_t *grouplist) ); +REV_SYSCALL( 160, int rev_newuname(struct new_utsname *name) ); +REV_SYSCALL( 161, int rev_sethostname(char *name, int len) ); +REV_SYSCALL( 162, int rev_setdomainname(char *name, int len) ); +REV_SYSCALL( 163, int rev_getrlimit(unsigned int resource, struct rlimit *rlim) ); +REV_SYSCALL( 164, int rev_setrlimit(unsigned int resource, struct rlimit *rlim) ); +REV_SYSCALL( 165, int rev_getrusage(int who, struct rusage *ru) ); +REV_SYSCALL( 166, int rev_umask(int mask) ); +REV_SYSCALL( 167, int rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) ); +REV_SYSCALL( 168, int rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) ); +REV_SYSCALL( 169, int rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) ); +REV_SYSCALL( 170, int rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) ); +REV_SYSCALL( 171, int rev_adjtimex(struct __kernel_timex *txc_p) ); +REV_SYSCALL( 172, int rev_getpid(void) ); +REV_SYSCALL( 173, int rev_getppid(void) ); +REV_SYSCALL( 174, int rev_getuid(void) ); +REV_SYSCALL( 175, int rev_geteuid(void) ); +REV_SYSCALL( 176, int rev_getgid(void) ); +REV_SYSCALL( 177, int rev_getegid(void) ); +REV_SYSCALL( 178, int rev_gettid(void) ); +REV_SYSCALL( 179, int rev_sysinfo(struct sysinfo *info) ); +REV_SYSCALL( 180, int rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) ); +REV_SYSCALL( 181, int rev_mq_unlink(const char *name) ); +#if 0 // whenever mqd_t is defined -- it lives in +REV_SYSCALL( 182, int rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) ); +REV_SYSCALL( 183, int rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) ); +REV_SYSCALL( 184, int rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) ); +REV_SYSCALL( 185, int rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) ); +#endif +REV_SYSCALL( 186, int rev_msgget(key_t key, int msgflg) ); +REV_SYSCALL( 187, int rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) ); +REV_SYSCALL( 188, ssize_t rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) ); +REV_SYSCALL( 189, int rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) ); +REV_SYSCALL( 190, int rev_semget(key_t key, int nsems, int semflg) ); +REV_SYSCALL( 191, int rev_semctl(int semid, int semnum, int cmd, unsigned long arg) ); +REV_SYSCALL( 192, int rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) ); +REV_SYSCALL( 193, int rev_semop(int semid, struct sembuf *sops, unsigned nsops) ); +REV_SYSCALL( 194, int rev_shmget(key_t key, size_t size, int flag) ); +REV_SYSCALL( 195, int rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) ); +REV_SYSCALL( 196, int rev_shmat(int shmid, char *shmaddr, int shmflg) ); +REV_SYSCALL( 197, int rev_shmdt(char *shmaddr) ); +REV_SYSCALL( 198, int rev_socket(int domain, int type, int proocol) ); +REV_SYSCALL( 199, int rev_socketpair(int domain, int type, int protocol, int *sv) ); +REV_SYSCALL( 200, int rev_bind(int sockfd, struct sockaddr *addr, int addrlen) ); +REV_SYSCALL( 201, int rev_listen(int sockfd, int backlog) ); +REV_SYSCALL( 202, int rev_accept(int sockfd, struct sockaddr *addr, int *addrlen) ); +REV_SYSCALL( 203, int rev_connect(int sockfd, struct sockaddr *addr, int addrlen) ); +REV_SYSCALL( 204, int rev_getsockname(int sockfd, struct sockaddr *addr, int *addrlen) ); +REV_SYSCALL( 205, int rev_getpeername(int sockfd, struct sockaddr *addr, int *addrlen) ); +REV_SYSCALL( 206, ssize_t rev_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, int addrlen) ); +REV_SYSCALL( 207, ssize_t rev_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, int *addrlen) ); +REV_SYSCALL( 208, int rev_setsockopt(int sockfd, int level, int optname, char *optval, int optlen) ); +REV_SYSCALL( 209, int rev_getsockopt(int sockfd, int level, int optname, char *optval, int *optlen) ); +REV_SYSCALL( 210, int rev_shutdown(int sockfd, int how) ); +REV_SYSCALL( 211, ssize_t rev_sendmsg(int sockfd, struct user_msghdr *msg, unsigned flags) ); +REV_SYSCALL( 212, ssize_t rev_recvmsg(int sockfd, struct user_msghdr *msg, unsigned flags) ); +REV_SYSCALL( 213, ssize_t rev_readahead(int sockfd, loff_t offset, size_t count) ); +REV_SYSCALL( 214, int rev_brk(unsigned long brk) ); +REV_SYSCALL( 215, int rev_munmap(unsigned long addr, size_t len) ); +REV_SYSCALL( 216, int rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) ); +REV_SYSCALL( 217, int rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) ); +REV_SYSCALL( 218, int rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) ); +REV_SYSCALL( 219, int rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) ); +REV_SYSCALL( 220, int rev_fork(void) ); +REV_SYSCALL( 220, int rev_clone(unsigned long flags, void *stack, int *parent_tid, void *tls, int *child_tid) ); +REV_SYSCALL( 221, int rev_execve(const char *filename, const char *const *argv, const char *const *envp) ); +REV_SYSCALL( 222, uint64_t rev_mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset) ); +REV_SYSCALL( 223, int rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) ); +REV_SYSCALL( 224, int rev_swapon(const char *specialfile, int swap_flags) ); +REV_SYSCALL( 225, int rev_swapoff(const char *specialfile) ); +REV_SYSCALL( 226, int rev_mprotect(unsigned long start, size_t len, unsigned long prot) ); +REV_SYSCALL( 227, int rev_msync(unsigned long start, size_t len, int flags) ); +REV_SYSCALL( 228, int rev_mlock(unsigned long start, size_t len) ); +REV_SYSCALL( 229, int rev_munlock(unsigned long start, size_t len) ); +REV_SYSCALL( 230, int rev_mlockall(int flags) ); +REV_SYSCALL( 231, int rev_munlockall(void) ); +REV_SYSCALL( 232, int rev_mincore(unsigned long start, size_t len, unsigned char * vec) ); +REV_SYSCALL( 233, int rev_madvise(unsigned long start, size_t len, int behavior) ); +REV_SYSCALL( 234, long rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) ); +REV_SYSCALL( 235, long rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) ); +REV_SYSCALL( 236, int rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) ); +REV_SYSCALL( 237, int rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) ); +REV_SYSCALL( 238, int rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) ); +REV_SYSCALL( 239, int rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) ); +REV_SYSCALL( 240, int rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) ); +REV_SYSCALL( 241, int rev_perf_event_open(void) ); +REV_SYSCALL( 242, int rev_accept4(int sockfd, struct sockaddr *addr, int *addrlen, int flags) ); +REV_SYSCALL( 243, int rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32* timeout) ); +REV_SYSCALL( 260, int rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) ); +REV_SYSCALL( 261, int rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) ); +REV_SYSCALL( 262, int rev_fanotify_init(unsigned int flags, unsigned int event_int) ); +REV_SYSCALL( 263, int rev_fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask, int fd, const char *p) ); +REV_SYSCALL( 264, int rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) ); +REV_SYSCALL( 265, int rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) ); +REV_SYSCALL( 266, int rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) ); +REV_SYSCALL( 267, int rev_syncfs(int fd) ); +REV_SYSCALL( 268, int rev_setns(int fd, int nstype ) ); +REV_SYSCALL( 269, int rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) ); +REV_SYSCALL( 270, int rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) ); +REV_SYSCALL( 271, int rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) ); +REV_SYSCALL( 272, int rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) ); +REV_SYSCALL( 273, int rev_finit_module(int fd, const char *uargs, int flags) ); +REV_SYSCALL( 274, int rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) ); +REV_SYSCALL( 275, int rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) ); +REV_SYSCALL( 276, int rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) ); +REV_SYSCALL( 277, int rev_seccomp(unsigned int op, unsigned int flags, void *uargs) ); +REV_SYSCALL( 278, int rev_getrandom(char *buf, size_t count, unsigned int flags) ); +REV_SYSCALL( 279, int rev_memfd_create(const char *uname_ptr, unsigned int flags) ); +REV_SYSCALL( 280, int rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) ); +REV_SYSCALL( 281, int rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) ); +REV_SYSCALL( 282, int rev_userfaultfd(int flags) ); +REV_SYSCALL( 283, int rev_membarrier(int cmd, unsigned int flags, int cpu_id) ); +REV_SYSCALL( 284, int rev_mlock2(unsigned long start, size_t len, int flags) ); +REV_SYSCALL( 285, int rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) ); +REV_SYSCALL( 286, int rev_preadv2(int fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) ); +REV_SYSCALL( 287, int rev_pwritev2(int fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) ); +REV_SYSCALL( 288, int rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot) ); +REV_SYSCALL( 289, int rev_pkey_alloc(unsigned long flags, unsigned long init_val) ); +REV_SYSCALL( 290, int rev_pkey_free(int pkey) ); +REV_SYSCALL( 291, int rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) ); +REV_SYSCALL( 292, int rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) ); +REV_SYSCALL( 293, int rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) ); +REV_SYSCALL( 294, int rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) ); + +REV_SYSCALL( 424, int rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) ); +REV_SYSCALL( 425, int rev_io_uring_setup(uint32_t entries, struct io_uring_params *p) ); +REV_SYSCALL( 426, int rev_io_uring_enter(int fd, uint32_t to_submit, uint32_t min_complete, uint32_t flags, const sigset_t *sig, size_t sigsz) ); +REV_SYSCALL( 427, int rev_io_uring_register(int fd, unsigned int op, void *arg, unsigned int nr_args) ); +REV_SYSCALL( 428, int rev_open_tree(int dfd, const char *path, unsigned flags) ); +REV_SYSCALL( 429, int rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) ); +REV_SYSCALL( 430, int rev_fsopen(const char *fs_name, unsigned int flags) ); +REV_SYSCALL( 431, int rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) ); +REV_SYSCALL( 432, int rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) ); +REV_SYSCALL( 433, int rev_fspick(int dfd, const char *path, unsigned int flags) ); +REV_SYSCALL( 434, int rev_pidfd_open(pid_t pid, unsigned int flags) ); +REV_SYSCALL( 435, int rev_clone3(struct clone_args *uargs, size_t size) ); +REV_SYSCALL( 436, int rev_close_range(int fd, unsigned int max_fd, unsigned int flags) ); +REV_SYSCALL( 437, int rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) ); +REV_SYSCALL( 438, int rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) ); +REV_SYSCALL( 439, int rev_faccessat2(int dfd, const char *filename, int mode, int flags) ); +REV_SYSCALL( 440, int rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) ); + +REV_SYSCALL( 500, int rev_cpuinfo(struct rev_cpuinfo *info) ); +REV_SYSCALL( 501, int rev_perf_stats(struct rev_stats *stats) ); -static int rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp){ - int rc; - asm volatile ( - "li a7, 113 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +// ==================== REV PTHREADS +typedef unsigned long int rev_pthread_t; +// pthread_t *restrict thread +// const pthread_attr_t *restrict attr - NOT USED RIGHT NOW +// void *(*start_routine)(void *) +// void *restrict arg); +REV_SYSCALL( 1000, int rev_pthread_create( rev_pthread_t* thread, void* attr, void* fn, void* arg ) ); +REV_SYSCALL( 1001, int rev_pthread_join( rev_pthread_t thread ) ); -static int rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp){ - int rc; - asm volatile ( - "li a7, 114 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +// ==================== REV MEMDUMP +REV_SYSCALL( 9000, void dump_mem_range( uint64_t addr, uint64_t size ) ); +REV_SYSCALL( 9001, void dump_mem_range_to_file( const char* outputFile, uint64_t addr, uint64_t size ) ); +REV_SYSCALL( 9002, void dump_stack( ) ); +REV_SYSCALL( 9003, void dump_stack_to_file( const char* outputFile ) ); +REV_SYSCALL( 9004, void dump_valid_mem( ) ); +REV_SYSCALL( 9005, void dump_valid_mem_to_file( const char* outputFile ) ); +REV_SYSCALL( 9006, void dump_thread_mem( ) ); +REV_SYSCALL( 9007, void dump_thread_mem_to_file( const char* outputFile ) ); -static int rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp){ - int rc; - asm volatile ( - "li a7, 115 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +// clang-format on -static int rev_syslog(int type, char *buf, int len){ - int rc; - asm volatile ( - "li a7, 116 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +// ==================== REV PRINT UTILITIES -static int rev_ptrace(long request, long pid, unsigned long addr, unsigned long data){ - int rc; - asm volatile ( - "li a7, 117 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +#ifdef __cplusplus -static int rev_sched_setparam(pid_t pid, struct sched_param *param){ - int rc; - asm volatile ( - "li a7, 118 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +} // extern "C" -static int rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param){ - int rc; - asm volatile ( - "li a7, 119 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; +template +__attribute__( ( naked ) ) static int rev_fast_printf( const char* format, Ts... args ) { + asm( " li a7, 9110; ecall; ret" ); } -static int rev_sched_getscheduler(pid_t pid){ - int rc; - asm volatile ( - "li a7, 120 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +#else // __cplusplus -static int rev_sched_getparam(pid_t pid, struct sched_param *param){ - int rc; - asm volatile ( - "li a7, 121 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; +__attribute__( ( naked ) ) static int rev_fast_printf() { + asm( " li a7, 9110; ecall; ret" ); } -static int rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr){ - int rc; - asm volatile ( - "li a7, 122 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +#endif // __cplusplus -static int rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr){ - int rc; - asm volatile ( - "li a7, 123 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +#else //SYSCALL_TYPES_ONLY -static int rev_sched_yield(void){ - int rc; - asm volatile ( - "li a7, 124 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} +#ifdef __cplusplus +} // extern "C" +#endif -static int rev_sched_get_priority_max(int policy){ - int rc; - asm volatile ( - "li a7, 125 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sched_get_priority_min(int policy){ - int rc; - asm volatile ( - "li a7, 126 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval){ - int rc; - asm volatile ( - "li a7, 127 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_restart_syscall(void){ - int rc; - asm volatile ( - "li a7, 128 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_kill(pid_t pid, int sig){ - int rc; - asm volatile ( - "li a7, 129 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_tkill(pid_t pid, int sig){ - int rc; - asm volatile ( - "li a7, 130 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_tgkill(pid_t tgid, pid_t pid, int sig){ - int rc; - asm volatile ( - "li a7, 131 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss){ - int rc; - asm volatile ( - "li a7, 132 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize){ - int rc; - asm volatile ( - "li a7, 133 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t){ - int rc; - asm volatile ( - "li a7, 134 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize){ - int rc; - asm volatile ( - "li a7, 135 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigpending(sigset_t *set, size_t sigsetsize){ - int rc; - asm volatile ( - "li a7, 136 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize){ - int rc; - asm volatile ( - "li a7, 137 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo){ - int rc; - asm volatile ( - "li a7, 138 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setpriority(int which, int who, int niceval){ - int rc; - asm volatile ( - "li a7, 140 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getpriority(int which, int who){ - int rc; - asm volatile ( - "li a7, 141 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg){ - int rc; - asm volatile ( - "li a7, 142 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setregid(gid_t rgid, gid_t egid){ - int rc; - asm volatile ( - "li a7, 143 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setgid(gid_t gid){ - int rc; - asm volatile ( - "li a7, 144 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setreuid(uid_t ruid, uid_t euid){ - int rc; - asm volatile ( - "li a7, 145 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setuid(uid_t uid){ - int rc; - asm volatile ( - "li a7, 146 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setresuid(uid_t ruid, uid_t euid, uid_t suid){ - int rc; - asm volatile ( - "li a7, 147 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid){ - int rc; - asm volatile ( - "li a7, 148 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid){ - int rc; - asm volatile ( - "li a7, 149 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid){ - int rc; - asm volatile ( - "li a7, 150 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setfsuid(uid_t uid){ - int rc; - asm volatile ( - "li a7, 151 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setfsgid(gid_t gid){ - int rc; - asm volatile ( - "li a7, 152 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_times(struct tms *tbuf){ - int rc; - asm volatile ( - "li a7, 153 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setpgid(pid_t pid, pid_t pgid){ - int rc; - asm volatile ( - "li a7, 154 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getpgid(pid_t pid){ - int rc; - asm volatile ( - "li a7, 155 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getsid(pid_t pid){ - int rc; - asm volatile ( - "li a7, 156 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setsid(void){ - int rc; - asm volatile ( - "li a7, 157 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getgroups(int gidsetsize, gid_t *grouplist){ - int rc; - asm volatile ( - "li a7, 158 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setgroups(int gidsetsize, gid_t *grouplist){ - int rc; - asm volatile ( - "li a7, 159 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_newuname(struct new_utsname *name){ - int rc; - asm volatile ( - "li a7, 160 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sethostname(char *name, int len){ - int rc; - asm volatile ( - "li a7, 161 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setdomainname(char *name, int len){ - int rc; - asm volatile ( - "li a7, 162 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getrlimit(unsigned int resource, struct rlimit *rlim){ - int rc; - asm volatile ( - "li a7, 163 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setrlimit(unsigned int resource, struct rlimit *rlim){ - int rc; - asm volatile ( - "li a7, 164 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getrusage(int who, struct rusage *ru){ - int rc; - asm volatile ( - "li a7, 165 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_umask(int mask){ - int rc; - asm volatile ( - "li a7, 166 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5){ - int rc; - asm volatile ( - "li a7, 167 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache){ - int rc; - asm volatile ( - "li a7, 168 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz){ - int rc; - asm volatile ( - "li a7, 169 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz){ - int rc; - asm volatile ( - "li a7, 170 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_adjtimex(struct __kernel_timex *txc_p){ - int rc; - asm volatile ( - "li a7, 171 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getpid(void){ - int rc; - asm volatile ( - "li a7, 172 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getppid(void){ - int rc; - asm volatile ( - "li a7, 173 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getuid(void){ - int rc; - asm volatile ( - "li a7, 174 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_geteuid(void){ - int rc; - asm volatile ( - "li a7, 175 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getgid(void){ - int rc; - asm volatile ( - "li a7, 176 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getegid(void){ - int rc; - asm volatile ( - "li a7, 177 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_gettid(void){ - int rc; - asm volatile ( - "li a7, 178 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sysinfo(struct sysinfo *info){ - int rc; - asm volatile ( - "li a7, 179 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr){ - int rc; - asm volatile ( - "li a7, 180 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mq_unlink(const char *name){ - int rc; - asm volatile ( - "li a7, 181 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout){ -// int rc; -// asm volatile ( -// "li a7, 182 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout){ -// int rc; -// asm volatile ( -// "li a7, 183 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_mq_notify(mqd_t mqdes, const struct sigevent *notification){ -// int rc; -// asm volatile ( -// "li a7, 184 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat){ -// int rc; -// asm volatile ( -// "li a7, 185 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_msgget(key_t key, int msgflg){ - int rc; - asm volatile ( - "li a7, 186 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf){ - int rc; - asm volatile ( - "li a7, 187 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg){ - int rc; - asm volatile ( - "li a7, 188 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg){ - int rc; - asm volatile ( - "li a7, 189 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_semget(key_t key, int nsems, int semflg){ - int rc; - asm volatile ( - "li a7, 190 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_semctl(int semid, int semnum, int cmd, unsigned long arg){ - int rc; - asm volatile ( - "li a7, 191 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout){ - int rc; - asm volatile ( - "li a7, 192 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_semop(int semid, struct sembuf *sops, unsigned nsops){ - int rc; - asm volatile ( - "li a7, 193 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_shmget(key_t key, size_t size, int flag){ - int rc; - asm volatile ( - "li a7, 194 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf){ - int rc; - asm volatile ( - "li a7, 195 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_shmat(int shmid, char *shmaddr, int shmflg){ - int rc; - asm volatile ( - "li a7, 196 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_shmdt(char *shmaddr){ - int rc; - asm volatile ( - "li a7, 197 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_socket(int, int, int){ - int rc; - asm volatile ( - "li a7, 198 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_socketpair(int, int, int, int *){ - int rc; - asm volatile ( - "li a7, 199 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_bind(int, struct sockaddr *, int){ - int rc; - asm volatile ( - "li a7, 200 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_listen(int, int){ - int rc; - asm volatile ( - "li a7, 201 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_accept(int, struct sockaddr *, int *){ - int rc; - asm volatile ( - "li a7, 202 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_connect(int, struct sockaddr *, int){ - int rc; - asm volatile ( - "li a7, 203 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getsockname(int, struct sockaddr *, int *){ - int rc; - asm volatile ( - "li a7, 204 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getpeername(int, struct sockaddr *, int *){ - int rc; - asm volatile ( - "li a7, 205 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int){ - int rc; - asm volatile ( - "li a7, 206 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *){ - int rc; - asm volatile ( - "li a7, 207 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setsockopt(int fd, int level, int optname, char *optval, int optlen){ - int rc; - asm volatile ( - "li a7, 208 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen){ - int rc; - asm volatile ( - "li a7, 209 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_shutdown(int, int){ - int rc; - asm volatile ( - "li a7, 210 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags){ - int rc; - asm volatile ( - "li a7, 211 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags){ - int rc; - asm volatile ( - "li a7, 212 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_readahead(int fd, loff_t offset, size_t count){ - int rc; - asm volatile ( - "li a7, 213 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_brk(unsigned long brk){ - int rc; - asm volatile ( - "li a7, 214 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_munmap(unsigned long addr, size_t len){ - int rc; - asm volatile ( - "li a7, 215 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr){ - int rc; - asm volatile ( - "li a7, 216 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid){ - int rc; - asm volatile ( - "li a7, 217 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid){ - int rc; - asm volatile ( - "li a7, 218 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5){ - int rc; - asm volatile ( - "li a7, 219 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fork(){ - int rc; - asm volatile ( - "li a7, 220 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_clone(unsigned long, unsigned long, int *, unsigned long, int *){ - int rc; - asm volatile ( - "li a7, 220 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_execve(const char *filename, const char *const *argv, const char *const *envp){ - int rc; - asm volatile ( - "li a7, 221 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -__attribute__((naked)) -static void* rev_mmap(uint64_t addr, size_t length, int prot, int flags, int fd, off_t offset){ - asm volatile ( - "li a7, 222 \n\t" - "ecall \n\t" - "ret" - ); -} - -static int rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice){ - int rc; - asm volatile ( - "li a7, 223 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_swapon(const char *specialfile, int swap_flags){ - int rc; - asm volatile ( - "li a7, 224 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_swapoff(const char *specialfile){ - int rc; - asm volatile ( - "li a7, 225 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mprotect(unsigned long start, size_t len, unsigned long prot){ - int rc; - asm volatile ( - "li a7, 226 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_msync(unsigned long start, size_t len, int flags){ - int rc; - asm volatile ( - "li a7, 227 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mlock(unsigned long start, size_t len){ - int rc; - asm volatile ( - "li a7, 228 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_munlock(unsigned long start, size_t len){ - int rc; - asm volatile ( - "li a7, 229 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mlockall(int flags){ - int rc; - asm volatile ( - "li a7, 230 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_munlockall(void){ - int rc; - asm volatile ( - "li a7, 231 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mincore(unsigned long start, size_t len, unsigned char * vec){ - int rc; - asm volatile ( - "li a7, 232 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_madvise(unsigned long start, size_t len, int behavior){ - int rc; - asm volatile ( - "li a7, 233 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 234 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags){ - int rc; - asm volatile ( - "li a7, 235 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 236 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode){ - int rc; - asm volatile ( - "li a7, 237 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to){ - int rc; - asm volatile ( - "li a7, 238 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags){ - int rc; - asm volatile ( - "li a7, 239 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo){ - int rc; - asm volatile ( - "li a7, 240 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_perf_event_open(){ - int rc; - asm volatile ( - "li a7, 241 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_accept4(int, struct sockaddr *, int *, int){ - int rc; - asm volatile ( - "li a7, 242 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32* timeout){ - int rc; - asm volatile ( - "li a7, 243 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru){ - int rc; - asm volatile ( - "li a7, 260 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim){; - int rc; - asm volatile ( - "li a7, 261 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fanotify_init(unsigned int flags, unsigned int event_int){ - int rc; - asm volatile ( - "li a7, 262 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask, int fd, const char *p){ - int rc; - asm volatile ( - "li a7, 263 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag){ - int rc; - asm volatile ( - "li a7, 264 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags){ - int rc; - asm volatile ( - "li a7, 265 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx){ - int rc; - asm volatile ( - "li a7, 266 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_syncfs(int fd){ - int rc; - asm volatile ( - "li a7, 267 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_setns(int fd, int nstype ){ - int rc; - asm volatile ( - "li a7, 268 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); -return rc; -} - -static int rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags){ - int rc; - asm volatile ( - "li a7, 269 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 270 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 271 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2){ - int rc; - asm volatile ( - "li a7, 272 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_finit_module(int fd, const char *uargs, int flags){ - int rc; - asm volatile ( - "li a7, 273 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); -return rc; -} - -static int rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 274 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 275 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 276 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_seccomp(unsigned int op, unsigned int flags, void *uargs){ - int rc; - asm volatile ( - "li a7, 277 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_getrandom(char *buf, size_t count, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 278 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_memfd_create(const char *uname_ptr, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 279 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_bpf(int cmd, union bpf_attr *attr, unsigned int size){ - int rc; - asm volatile ( - "li a7, 280 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags){ - int rc; - asm volatile ( - "li a7, 281 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_userfaultfd(int flags){ - int rc; - asm volatile ( - "li a7, 282 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_membarrier(int cmd, unsigned int flags, int cpu_id){ - int rc; - asm volatile ( - "li a7, 283 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_mlock2(unsigned long start, size_t len, int flags){ - int rc; - asm volatile ( - "li a7, 284 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 285 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags){ - int rc; - asm volatile ( - "li a7, 286 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags){ - int rc; - asm volatile ( - "li a7, 287 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot){ - int rc; - asm volatile ( - "li a7, 288 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_pkey_alloc(unsigned long flags, unsigned long init_val){ - int rc; - asm volatile ( - "li a7, 289 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pkey_free(int pkey){ - int rc; - asm volatile ( - "li a7, 290 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer){ - int rc; - asm volatile ( - "li a7, 291 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig){ - int rc; - asm volatile ( - "li a7, 292 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig){ - int rc; - asm volatile ( - "li a7, 293 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags){ - int rc; - asm volatile ( - "li a7, 294 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -// int rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp){ -// int rc; -// asm volatile ( -// "li a7, 403 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp){ -// int rc; -// asm volatile ( -// "li a7, 404 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_clock_adjtime(clockid_t which_clock, struct __kernel_timint rc; -// asm volatile ( -// "li a7, 405 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_clock_getres(clockid_t which_clock, struct __kernel_timespint rc; -// asm volatile ( -// "li a7, 406 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespecint rc; -// asm volatile ( -// "li a7, 407 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *tp){ -// int rc; -// asm volatile ( -// "li a7, 408 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting){ -// int rc; -// asm volatile ( -// "li a7, 409 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_timerfd_gettime(int ufd, struct __kernel_itimerspecint rc; -// asm volatile ( -// "li a7, 410 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspecint rc; -// asm volatile ( -// "li a7, 411 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags){ -// asm volatile ( -// "li a7, 412 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigsint rc; -// asm volatile ( -// "li a7, 416 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_ -// asm volatile ( -// "li a7, 418 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_int rc; -// asm volatile ( -// "li a7, 419 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *int rc; -// asm volatile ( -// "li a7, 420 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_futex(uint32_t *uaddr, int op, uint32_t val, struct __kernel_timespec *utime, uint32_t *uaddr2, uint rc; -// asm volatile ( -// "li a7, 422 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -// int rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *iint rc; -// asm volatile ( -// "li a7, 423 \n\t" -// "ecall \n\t" -// "mv %0, a0" : "=r" (rc) -// ); -// return rc; -// } - -static int rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 424 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_io_uring_setup(uint32_t entries, struct io_uring_params *p){ - int rc; - asm volatile ( - "li a7, 425 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_uring_enter(unsigned int fd, uint32_t to_submit, uint32_t min_complete, uint32_t flags, const sigset_t *sig, size_t sigsz){ - int rc; - asm volatile ( - "li a7, 426 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args){ - int rc; - asm volatile ( - "li a7, 427 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_open_tree(int dfd, const char *path, unsigned flags){ - int rc; - asm volatile ( - "li a7, 428 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags){ - int rc; - asm volatile ( - "li a7, 429 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fsopen(const char *fs_name, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 430 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux){ - int rc; - asm volatile ( - "li a7, 431 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags){ - int rc; - asm volatile ( - "li a7, 432 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) -); -return rc; -} - -static int rev_fspick(int dfd, const char *path, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 433 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pidfd_open(pid_t pid, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 434 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_clone3(struct clone_args *uargs, size_t size){ - int rc; - asm volatile ( - "li a7, 435 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 436 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size){ - int rc; - asm volatile ( - "li a7, 437 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pidfd_getfd(int pidfd, int fd, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 438 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_faccessat2(int dfd, const char *filename, int mode, int flags){ - int rc; - asm volatile ( - "li a7, 439 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags){ - int rc; - asm volatile ( - "li a7, 440 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_cpuinfo(struct rev_cpuinfo *info) { - int rc; - asm volatile ( - "li a7, 500 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_perf_stats(struct rev_stats *stats) { - int rc; - asm volatile ( - "li a7, 501 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -typedef unsigned long int rev_pthread_t; - -// pthread_t *restrict thread -// const pthread_attr_t *restrict attr - NOT USED RIGHT NOW -// void *(*start_routine)(void *) -// void *restrict arg); -// ==================== REV PTHREADS -static int rev_pthread_create( rev_pthread_t* thread, void* attr, void* fn, void* arg ){ - int rc; - asm volatile ( - "li a7, 1000 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} - -static int rev_pthread_join( rev_pthread_t thread ){ - int rc; - asm volatile ( - "li a7, 1001 \n\t" - "ecall \n\t" - "mv %0, a0" : "=r" (rc) - ); - return rc; -} -#endif //SYSCALL_TYPES_ONLY +#endif //SYSCALL_TYPES_ONLY #endif diff --git a/documentation/ExtensionDevelopment.md b/documentation/ExtensionDevelopment.md index 026f2a54f..7ee770ff7 100644 --- a/documentation/ExtensionDevelopment.md +++ b/documentation/ExtensionDevelopment.md @@ -1,12 +1,12 @@ # Extension Development ## Overview -The Rev SST component permits users to create unique extensions that are not defined as a standard extension by the RISC-V standards body. This allows users to experiment with features that may be advanced or override default extension behavior. Further, this also allows users to experiment with accelerators that may be orthogonal to the base RISC-V ISA. Each RISC-V extension is implemented in Rev using a single header file. The header file contains the instruction encoding table and an implementation function for each individual instruction contained within the extension. +The Rev SST component permits users to create unique extensions that are not defined as a standard extension by the RISC-V standards body. This allows users to experiment with features that may be advanced or override default extension behavior. Further, this also allows users to experiment with accelerators that may be orthogonal to the base RISC-V ISA. Each RISC-V extension is implemented in Rev using a single header file. The header file contains the instruction encoding table and an implementation function for each individual instruction contained within the extension. There are also several limitations of the current extension functionality. These limitations can be overcome, but will require additional source code modifications. These limitations are noted as follows: 1. The Rev crack/decode functions currently only support the standard set of RISC-V instruction formats. Additional formats can be supported, but will require additional source code modifications to the crack/decode engine. -2. The Rev model supports the ability for users to override default extensions (for example, the D-extension) with new functionality. However, you cannot load two extensions with conflicting encodings. This will break the Rev crack/decode engine. +2. The Rev model supports the ability for users to override default extensions (for example, the D-extension) with new functionality. However, you cannot load two extensions with conflicting encodings. This will break the Rev crack/decode engine. 3. The naming convention for the new extension cannot conflict with the standard set of the extensions if they are utilized in the same core. Eg, an RV64IMAFD device cannot have a second "F" extension. You must utilize a different naming convention. 4. The Rev model utilizes a standard ELF loader. If the extension breaks the base RISC-V (RV32, RV64) relocation, then the device may not function as expected. 5. The Rev model supports the standard set of RV32/RV64-G registers for integer and floating point. Any extension-specific register state will require additional source code modifications. @@ -21,7 +21,7 @@ From the base Rev directory, all the source code resides in `src`. The instruct | `src/RevInstTable.h` | Contains the base strucutures utilized to create each extension as well as functions to assist in instruction implementation. | | `src/RevFeature.h` | Contains the feature to extension mappings. | | `src/RevMem.h` | Contains all the interfaces for reading/writing memory. | -| `src/RevProc.cc` | Contains the main simulation driver and instruction table loader. | +| `src/RevCore.cc` | Contains the main simulation driver and instruction table loader. | ## Documentation @@ -31,7 +31,7 @@ The Rev source tree utilizes Doxygen style comments for documentaton. This incl ### Choose an Extension Mnemonic -Each extension requires a notional mnemonic that can be parsed by the Rev infrastructure and recognized as a supported extension. It is generally good practice to choose an unused or unsupport letter for your extension. In this case, we choose the letter `Z` to represent our sample extension. +Each extension requires a notional mnemonic that can be parsed by the Rev infrastructure and recognized as a supported extension. It is generally good practice to choose an unused or unsupport letter for your extension. In this case, we choose the letter `Z` to represent our sample extension. ### Add the Mnemonic to the RevFeature Handlers @@ -70,7 +70,7 @@ Now we need to add support in the extension parser. This resides in the `ParseM This function a loop over the device string and adds the necessary support for the specific extension(s). Adding support for new features is as simple as adding a new entry into the machine model table as folows. -Notice how we utilize the `SetMachineEntry` function with the appropriate enumerated type defined above. +Notice how we utilize the `SetMachineEntry` function with the appropriate enumerated type defined above. ```c++ ///< List of architecture extensions. These must listed in canonical order @@ -128,8 +128,8 @@ Notice how we utilize the `SetMachineEntry` function with the appropriate enumer ``` ### Add the Extension Header to the RevInstTables Header -Now that you've defined your new extension mnemonic, you need to add an entry in the `RevInstTables.h` header -file such that the remainder of the Rev infrastructure can find the new implementation details. The header +Now that you've defined your new extension mnemonic, you need to add an entry in the `RevInstTables.h` header +file such that the remainder of the Rev infrastructure can find the new implementation details. The header name that you choose here must also be utilized in the next step. As an example, we create the `Z` extension and add the `RV32Z.h` header file. @@ -176,10 +176,10 @@ As an example, we create the `Z` extension and add the `RV32Z.h` header file. ### Add the Instruction Table Loader In this section, we need to add support for loading the new extension's instructions into the internal Rev instruction table. Rev utilizes an internal instruction table with compressed encodings in order to permit rapid crack/decode. Each table entry contains a pointer to the respective implementation function for the target instruction. In this case, we need to add the necessary logic to 1) detect that our new extension is enabled and 2) add the associated instructions to the internal instruction table. -For this, we need to modify the `RevProc.cc` implementation file. Specifically, we will be modifying the contents of the `SeedInstTable` function. Each new instruction implementation object is statically cast to the base `RevExt` type and passed to the `EnableExt` function. An example of adding the `Z` extension is as follows. Also note that the newly created `RV32Z` object is given the feature object, a pointer to the register file, the memory object and the SST output object. +For this, we need to modify the `RevCore.cc` implementation file. Specifically, we will be modifying the contents of the `SeedInstTable` function. Each new instruction implementation object is statically cast to the base `RevExt` type and passed to the `EnableExt` function. An example of adding the `Z` extension is as follows. Also note that the newly created `RV32Z` object is given the feature object, a pointer to the register file, the memory object and the SST output object. ```c++ -bool RevProc::SeedInstTable(){ +bool RevCore::SeedInstTable(){ // Z-Extension if( feature->IsModeEnabled(RV_Z) ){ EnableExt(static_cast(new RV32Z(feature, &RegFile, mem, output))); @@ -196,9 +196,9 @@ bool RevProc::SeedInstTable(){ ``` ### Create the Extension Header -The final series of steps to create a new extension is where the bulk of the code will reside. As we stated above, each implementation includes a unique header file that provides the instruction implementations and encoding tables for the target extension. In this section, we will create the header file and add several basic instructions. This will elicit how we 1) construct the instruction tables, 2) create instruction implementations and 3) utilize the provided functions to perform basic memory and arithmetic operations. +The final series of steps to create a new extension is where the bulk of the code will reside. As we stated above, each implementation includes a unique header file that provides the instruction implementations and encoding tables for the target extension. In this section, we will create the header file and add several basic instructions. This will elicit how we 1) construct the instruction tables, 2) create instruction implementations and 3) utilize the provided functions to perform basic memory and arithmetic operations. -The first thing we need to do is create the basic header file at `src/insns/RV32Z.h`. The basic skeleton of this header will resemble the following: +The first thing we need to do is create the basic header file at `src/insns/RV32Z.h`. The basic skeleton of this header will resemble the following: ```c++ // @@ -217,92 +217,86 @@ The first thing we need to do is create the basic header file at `src/insns/RV32 using namespace SST::RevCPU; -namespace SST{ - namespace RevCPU{ - struct RV32Z : RevExt { +namespace SST::RevCPU{ + class RV32Z : public RevExt { - // RV32Z Implementation Functions + // RV32Z Implementation Functions - // RV32Z Instruction Table + // RV32Z Instruction Table - /// RV32Z: standard constructor - RV32Z( RevFeature *Feature, - RevRegFile *RegFile, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32Z", Feature, RegFile, RevMem, Output ) { - SetTable(RV32ZTable); - } - - /// RV32Z: standard destructor - ~RV32Z() = default; +public: + /// RV32Z: standard constructor + RV32Z( RevFeature *Feature, + RevRegFile *RegFile, + RevMem *RevMem, + SST::Output *Output ) + : RevExt( "RV32Z", Feature, RegFile, RevMem, Output ) { + SetTable(std::move(RV32ZTable)); + } - }; // end class RV32I - } // namespace RevCPU -} // namespace SST + }; // end class RV32Z +} // namespace SST::RevCPU ``` -There are a few important things we need to point out before we move on. First, -notice how the new implementation class resides inside the `SST::RevCPU` +There are a few important things we need to point out before we move on. +First, notice how the new implementation class resides inside the `SST::RevCPU` namespace and inherits functions from the base `RevExt` class. This is very important in order to correctly load your new instructions into the simulator. Second, notice how we instantiate the constructor for the new extension. The -constructor **MUST** contain a call to `SetTable(RV32ZTable)`. Given that this -is a header-only implementation, the order of which the class constructors and -associated data members must be preserved. This method forces the child -constructor to create its private data members before registering them with the -base class. +constructor **MUST** contain a call to `SetTable(std::move(RV32ZTable))`. The +`std::move()` is required because `SetTable()` requires an rvalue argument. +This design avoids deep copies of the tables, and limits the number of moves +to one. The child constructor constructs its private data members before +registering them with the base class. Now that we have our basic skeleton in place, we can start creating our instruction table. The table is actually a C++ vector of struct entries where each entry corresponds to a single instruction entry. This needs to be done in the private section of the class (see the comment above for RV32Z Instruction -Table). The stuct for each entry is created by an in-line creation of a -`RevInstEntryBuilder< >` object. This object will utilize the class declared in -the template parameter for the default values. The base default values can be -found in the `RevInstDefaults` class and can be overriden through inheritence -(shown in the example below). The individual elements of the `RevInstEntry` -struct are initialized using named arguments so they can be initialized in any -order. It is important to end the argument initialization chain with -`.InstEntry` as this is the actual struct that will be added to the -`std::vector`.First, lets create a few basic entries in our table, then we'll -explain what each entry is used for. +Table). The struct for each entry is created by an in-line creation of a +`RevInstDefaults` object, or a class derived from `RevInstDefaults`. This +will create the class for the default values. The base default values can be +found in the `RevInstDefaults` class and can be overriden by calling `Set*` +functions in the derived class constructor (shown in the example below). The +individual elements of the `RevInstEntry` struct are initialized by calling +chains of `Set*` functions with named arguments as suffixes, so they can be +initialized in any order. First, lets create a few basic entries in our table, +then we'll explain what each entry is used for. ```c++ struct Rev32ZInstDefaults : RevInstDefaults { - RevRegF format = RVTypeR; -} + Rev32ZInstDefaults(){ + SetFormat(RVTypeR); + } +}; + std::vector RV32ZTable = { -{RevInstEntryBuilder().SetMnemonic("zadd %rd, %rs1, %rs2").SetCost(1).SetOpcode(0b0110011).SetFunct3(0b000).SetFunct7(0b0000000). - SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR)Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetImplFunc(&zadd).InstEntry }, -{RevInstEntryBuilder().SetMnemonic("zsub %rd, %rs1, %rs2").SetCost(1).SetOpcode(0b0110011).SetFunct3(0b000).SetFunct7(0b0100000). - SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetImplFunc(&zsub).InstEntry }, -{RevInstEntryBuilder().SetMnemonic("zlb %rd, $imm(%rs1)").SetCost(1).SetOpcode(0b0000011).SetFunct3(0b000).SetFunct7(0b0). - SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&zlb).InstEntry }, -{RevInstEntryBuilder().SetMnemonic("zsb %rs2, $imm(%rs1)").SetCost(1).SetOpcode(0b0100011).SetFunct3(0b000).SetFunct7(0b0). - SetrdClass(RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeS).SetImplFunc(&zsub).InstEntry }, +{ Rev32ZInstDefaults().SetMnemonic("zadd %rd, %rs1, %rs2").SetCost(1).SetFunct3(0b000).SetFunct2or7(0b0000000).SetImplFunc(zadd).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).SetOpcode(0b0110011).Setimm12(0b0).Setimm(FUnk) }, +{ Rev32ZInstDefaults().SetMnemonic("zsub %rd, %rs1, %rs2").SetCost(1).SetFunct3(0b000).SetFunct2or7(0b0100000).SetImplFunc(zsub).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).SetOpcode(0b0110011).Setimm12(0b0).Setimm(FUnk) }, +{ Rev32ZInstDefaults().SetMnemonic("zlb %rd, $imm(%rs1)").SetCost(1).SetFunct3(0b000).SetFunct2or7(0b0).SetImplFunc(zlb).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeI).SetOpcode(0b0000011).Setimm12(0b0).Setimm(FImm) }, +{ Rev32ZInstDefaults().SetMnemonic("zsb %rs2, $imm(%rs1)").SetCost(1).SetFunct3(0b000).SetFunct2or7(0b0).SetImplFunc(zsub).SetrdClass(RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeS).SetOpcode(0b0100011).Setimm12(0b0).Setimm(FUnk) }, }; ``` -For this, we've created four instructions: `zadd`, `zsub`, `zlb` and `zsb` to represent two arithmetic instructions a load instruction and a store instruction. Each field in the entry have specific values associated with them. The field entries are outlined (in order) as follows. Please be careful with entering data into the tables as the data contained therein drives the crack/decode and execution of the core simulation. +For this, we've created four instructions: `zadd`, `zsub`, `zlb` and `zsb` to represent two arithmetic instructions a load instruction and a store instruction. Each field in the entry have specific values associated with them. The field entries are outlined (in order) as follows. Please be careful with entering data into the tables as the data contained therein drives the crack/decode and execution of the core simulation. | Field Num | Field | Description | | ----------- | ----------- | ----------- | | 1 | mnemonic | This describes how to *type* the instruction. This is a specical syntax that can utilized during debugging or disassembly. Register fields are noted using percent signs and their field name and immediate fields are noted using the dollar sign and their field name. Ex: `add %rd, %rs1, %rs2` or `lb %rd, $imm(%rs1)` | | 2 | cost | This is a nonzero value that represents the cost (in clock cycles) of the default instruction implementation. This will determine how many cycles this instruction will execute prior to being retired. This value can be overridden by the user at runtime. | -| 3 | opcode | This is the seven bit opcode of the instruction. | | 4 | funct3 | This is the funct3 encoding field. If the respective instruction does not utilize the field, set this value to `0b000` | -| 5 | funct7 | This is the funct7 encoding field. If the respective instruction does not utilize the field, set this value to `0b0000000` | -| 6 | rdClass | If the instruction has an `rd` register slot, this denotes the register class utilized. Values for this can be one of `RevRegClass::RegGPR` for the general purpose register file, `RegCSR` for the CSR register file, `RegFloat` for the floating point register file, `RegIMM` (treat the reg class like an immediate, only utilized in the S-format) or `RevRegClass::RegUNKNOWN` if the field is not utilized. | -| 7 | rs1Class | Defines the register class for the `rs1` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | -| 8 | rs2Class | Defines the register class for the `rs2` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | -| 9 | rs3Class | Defines the register class for the `rs3` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | -| 10 | imm12 | Defines the value of the `imm12` slot if the immediate is hardwired to a single value. | -| 11 | imm | Defines the functionality of th `imm12` field. If the field is not used, set this to `Funk`. `FImm` indicates that the field is present and utilized, `FEnc` indicates that this field is an encoding value and `FVal` is an incoming register value. When using `FEnc`, the `imm12` entry (10) must also be set. | -| 12 | format | Defines the instruction format. This is one of: `RVTypeUNKNOWN`, `RVTypeR`, `RVTypeI`, `RVTypeS`, `RVTypeU`, `RVTypeB`, `RVTypeJ` or `RVTypeR4` | -| 13 | func | This contains a function pointer to the implementation function of the target instruction | - -Now that we have our instruction encoding tables, we can begin implementing each of our instruction functions in the private section of the header file. Note that this must be done **above** the instruction table as the symbol names must be defined prior to their use in the instruction table. First, we'll show an example implementation of our four instructions before outlining all the requirements and features. +| 5 | funct2or7 | This is the funct2or7 encoding field. If the respective instruction does not utilize the field, set this value to `0b0000000` | +| 6 | func | This contains a function pointer to the implementation function of the target instruction | +| 7 | rdClass | If the instruction has an `rd` register slot, this denotes the register class utilized. Values for this can be one of `RevRegClass::RegGPR` for the general purpose register file, `RegCSR` for the CSR register file, `RegFloat` for the floating point register file, `RegIMM` (treat the reg class like an immediate, only utilized in the S-format) or `RevRegClass::RegUNKNOWN` if the field is not utilized. | +| 8 | rs1Class | Defines the register class for the `rs1` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | +| 9 | rs2Class | Defines the register class for the `rs2` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | +| 10 | rs3Class | Defines the register class for the `rs3` slot. Use `RevRegClass::RegUNKNOWN` if this slot is not utilized | +| 11 | format | Defines the instruction format. This is one of: `RVTypeUNKNOWN`, `RVTypeR`, `RVTypeI`, `RVTypeS`, `RVTypeU`, `RVTypeB`, `RVTypeJ` or `RVTypeR4` | +| 12 | opcode | This is the seven bit opcode of the instruction. | +| 13 | imm12 | Defines the value of the `imm12` slot if the immediate is hardwired to a single value. | +| 14 | imm | Defines the functionality of th `imm12` field. If the field is not used, set this to `Funk`. `FImm` indicates that the field is present and utilized, `FEnc` indicates that this field is an encoding value and `FVal` is an incoming register value. When using `FEnc`, the `imm12` entry (10) must also be set. | + +Now that we have our instruction encoding tables, we can begin implementing each of our instruction functions in the private section of the header file. First, we'll show an example implementation of our four instructions before outlining all the requirements and features. ### Helper Functions There are several helper functions to make generating instruction implementations easier. @@ -543,34 +537,36 @@ Or, with the helper functions: As we can see from the source code above, each function must be formatted as: `static bool FUNC(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst)`. All instructions carry the same arguments. The first thing to note is the ability to use the `RevFeature` object to query the device architecture. The Rev model stores register state in different logical storage for RV32 and RV64. As a result, if your extension supports both variations of *XLEN*, then its often useful to query the loaded features to see which register file to manipulate, but the `R->GetX(reg)` and `R->SetX(reg, value) functions can automate this. -The second and third arguments represent the register file object and the memory object, respectively. These objects permit the user to access internal register state and read/write memory. Finally, the `RevInst` structure contains all the decoded state from the instruction. This includes all the opcode and function codes as well as each of the encoded register values. This structure also contains the floating point rounding mode information. For more information on the exacting contents and their respective data types, see the `RevInstTable.h` header file. +The second and third arguments represent the register file object and the memory object, respectively. These objects permit the user to access internal register state and read/write memory. Finally, the `RevInst` structure contains all the decoded state from the instruction. This includes all the opcode and function codes as well as each of the encoded register values. This structure also contains the floating point rounding mode information. For more information on the exacting contents and their respective data types, see the `RevInstTable.h` header file. + +Now that we've decoded the necessary state and the simulation execution engine launches the function, we can start executing the target arithmetic. For example, in the `zadd` function, we seek to add two unsigned integers of *XLEN* size. We use `R->GetX(Inst.rs1)` and `R->GetX(Inst.rs2)` to read registers as `uint32_t` values, add two values, and then use `R->SetX(Inst.rd, val)` to write the result into the destination register. -Now that we've decoded the necessary state and the simulation execution engine launches the function, we can start executing the target arithmetic. For example, in the `zadd` function, we seek to add two unsigned integers of *XLEN* size. Normally, this could be achieved using a simple `Rd = Rs1 + Rs2`. However, recall from the RISC-V specification that arithmetic is performed in two's complement form. As a result, we must utilize some utility functions to convert to/from two's complement form. The `td_u32` and `td_u64` functions convert a value *from* two's complement *to* decimal form. The `dt_u32` and `dt_u64` convert values from decimal form to two's complement. As you can see in the `zadd` and `zsub` functions, we utilize the `Inst` payload to decode the register indices, the `RevRegFile` structure to retrieve the necesary register value and the `td_u32/64` functions to convert to decimal form. We then perform the arithmetic, convert the value back to two's complement form and write it back to the register file. The final step in the basic arithmetic functions is incrementing the PC. The PC can be manually manipulated (eg, for branch operations), but this is normally done by incrementing the PC by the size of the instruction payload (in bytes). +The final step in the basic arithmetic functions is incrementing the PC. The PC can be manually manipulated (eg, for branch operations) with `R->SetPC(PC)`, but this is normally done by incrementing the PC by the size of the instruction payload (in bytes) with `R->AdvancePC(Inst)`. -In the next functions, `zlb` and `zsb` we seek to load and store data to memory. Just as we did above, we need to convert the input values to decimal form in order to perform the necessary address arithmetic. We then utilize the `RevMem` object to write the desired number of bytes or read the desired number of bytes via the `ReadU8` and `WriteU8` routines. The `RevMem` object provides a number of standard interfaces for writing common data types, arbitrary data and performing load reserve/store conditional operations. Also note the use of the `SEXT` macro. This performs sign extension on the incoming load value. The infrastructure also provides a `ZEXT` macro for zero extension. +In the next functions, `zlb` and `zsb` we seek to load and store data to memory. We utilize the `RevMem` object to write the desired number of bytes or read the desired number of bytes via the `Read` and `Write` methods. The `RevMem` object provides a number of standard interfaces for writing common data types, arbitrary data and performing load reserve/store conditional operations. Also note the use of the `SignExt()` function. This performs sign extension on the incoming load value. The infrastructure also provides a `ZeroExt()` function for zero extension. -Finally, it is important to note the use of the `M->RandCost()` function. Typically, RISC-V processor implementations do not hazard on memory store operations given the inherent weak memory ordering (or TSO). However, for load operations, the processor is required to flag a hazard in order to ensure that the data returns before it is utilized in subsquent operations. The `RandCost()` function provides the simulator the ability to add an arbitrary cost to load operations that is randomly generated in the range of `F->GetMinCost()` and `F->GetMaxCost()`. These values are set at runtime by the user in the SST Python script. In this manner, each load operation will generate a random *cost* and set its respective cost (in cycles). +Finally, it is important to note the use of the `M->RandCost()` function. Typically, RISC-V processor implementations do not hazard on memory store operations given the inherent weak memory ordering (or TSO). However, for load operations, the processor is required to flag a hazard in order to ensure that the data returns before it is utilized in subsquent operations. The `RandCost()` function provides the simulator the ability to add an arbitrary cost to load operations that is randomly generated in the range of `F->GetMinCost()` and `F->GetMaxCost()`. These values are set at runtime by the user in the SST Python script. In this manner, each load operation will generate a random *cost* and set its respective cost (in cycles). ## Contributions -We welcome outside contributions from corporate, acaddemic and individual developers. However, -there are a number of fundamental ground rules that you must adhere to in order to participate. These +We welcome outside contributions from corporate, acaddemic and individual developers. However, +there are a number of fundamental ground rules that you must adhere to in order to participate. These rules are outlined as follows: -* All code must adhere to the existing C++ coding style. While we are somewhat flexible in basic style, you will -adhere to what is currently in place. This includes camel case C++ methods and inline comments. Uncommented, +* All code must adhere to the existing C++ coding style. While we are somewhat flexible in basic style, you will +adhere to what is currently in place. This includes camel case C++ methods and inline comments. Uncommented, complicated algorithmic constructs will be rejected. * We support compilaton and adherence to C++17 methods. -* All new methods and variables contained within public, private and protected class methods must be commented -using the existing Doxygen-style formatting. All new classes must also include Doxygen blocks in the new header +* All new methods and variables contained within public, private and protected class methods must be commented +using the existing Doxygen-style formatting. All new classes must also include Doxygen blocks in the new header files. Any pull requests that lack these features will be rejected. * All changes to functionality and/or the API infrastructure must be accompanied by complementary tests -* All external pull requests **must** target the *devel* branch. No external pull requests will be accepted +* All external pull requests **must** target the *devel* branch. No external pull requests will be accepted to the master or main branches. -* All external pull requests must contain sufficient documentation in the pull request comments in order to +* All external pull requests must contain sufficient documentation in the pull request comments in order to be accepted. * All pull requests will be reviewed by the core development staff. Any necessary changes will be marked -in the respective pull request comments. All pull requests will be tested against in the Tactical -Computing Laboratories development infrastructure. This includes tests against all supported platforms. +in the respective pull request comments. All pull requests will be tested against in the Tactical +Computing Laboratories development infrastructure. This includes tests against all supported platforms. Any failures in the test infrastructure will be noted in the pull request comments. ## Authors diff --git a/documentation/Tracer.md b/documentation/Tracer.md index 436a6f721..a4321e9c0 100644 --- a/documentation/Tracer.md +++ b/documentation/Tracer.md @@ -12,7 +12,7 @@ The execution tracer is configured using the following cmake compile options: - REV_TRACER=OFF : do not compile in tracing support - REV_USE_SPIKE=ON : Use spike libdiasm.a for disassembly - REV_USE_SPIKE=OFF : Use internal REV instruction format (default) - + When setting REV_USE_SPIKE to ON, GCC tools and links to libdisasm.a must be available. These are part of rev_isa_sim (Spike). If this library is not found the tracer should revert to the an internal REV format. Previous instruction execution trace output is replaced by the compact tracer format. Compiling with REV_TRACER=0 will revert the output to to the old format and elliminate any possible performance impacts. @@ -30,11 +30,11 @@ sst-info revcpu will now includes the following additional options: To achieve compact traces, the tracer is initially off. The user must enable it using one of two methods: a. Programatic Controls: These are 'nop' instructions embedded in the target code that will activate or deactive tracing. This allows for tracing only specific code of interest and avoiding extreme file sizes. The 'trcOp' option provides the base opcode and must be the following subset of custom hints defined in the RISCV specification: - + slti, sltiu, slli, srli, srai b. Cycle Based control: This simply allows the user to specify a starting cycle to start tracing for a CPU. This will affect all cores and will defeat all programatic controls. However, setting 'trcCycle' to 0 will have no effect. - + Important: trcStartCycle and trcLimit are specified in terms of REV cycles, not time. ## Test Sample @@ -53,31 +53,31 @@ traces at the end of this document. Programatic controls are realized through macros provided in 'rev-macros.h'. The default values are: - #define TRACE_OFF asm volatile("slli x0,x0,0"); - #define TRACE_ON asm volatile("slli x0,x0,1"); - #define TRACE_PUSH_OFF asm volatile("slli x0,x0,2"); - #define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); + #define TRACE_OFF asm volatile("slli x0,x0,0"); + #define TRACE_ON asm volatile("slli x0,x0,1"); + #define TRACE_PUSH_OFF asm volatile("slli x0,x0,2"); + #define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); #define TRACE_POP asm volatile("slli x0,x0,4"); If there is a conflict with the 'slli' instruction, it can instruction can be changed using the 'trcOp' option. The header file must be changedto match or tracing will not be enabled. See 2.2 for the list of supported instructions. When one of these instruction is encountered the trace will indicate and on or off event using '+' or '-' before the instruction mnemonic. -Example: +Example: The prefix fields showing cycle, cpu, thread, and hart information are omitted. // Tracing starts 0x10330:00301013 + slli zero, zero, 3 0x0<-zero zero<-0x0 pc<-0x10334 - 0x10334:fec42703 lw a4, -20(s0) 0x3ffffba0<-s0 0x000003de<-[0x3ffffb8c,4] a4<-0x3de - 0x10338:3de00793 li a5, 990 0x0<-zero a5<-0x3de + 0x10334:fec42703 lw a4, -20(s0) 0x3ffffba0<-s0 0x000003de<-[0x3ffffb8c,4] a4<-0x3de + 0x10338:3de00793 li a5, 990 0x0<-zero a5<-0x3de 0x1033c:00f70463 beq a4, a5, pc + 8 0x3de<-a4 0x3de<-a5 pc<-0x10344 0x10344:00201013 - slli zero, zero, 2 0x0<-zero zero<-0x0 // Tracing ends and then resumes at a later cycle - 0x10358:00301013 + slli zero, zero, 3 0x0<-zero zero<-0x0 pc<-0x1035c - 0x1035c:fec42783 lw a5, -20(s0) 0x3ffffba0<-s0 0x00000000<-[0x3ffffb8c,4] a5<-0x0 - 0x10360:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x10368 - 0x10368:00201013 - slli zero, zero, 2 0x0<-zero zero<-0x0 + 0x10358:00301013 + slli zero, zero, 3 0x0<-zero zero<-0x0 pc<-0x1035c + 0x1035c:fec42783 lw a5, -20(s0) 0x3ffffba0<-s0 0x00000000<-[0x3ffffb8c,4] a5<-0x0 + 0x10360:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x10368 + 0x10368:00201013 - slli zero, zero, 2 0x0<-zero zero<-0x0 // tracing ends # Tracer Output @@ -88,7 +88,7 @@ The prefix fields showing cycle, cpu, thread, and hart information are omitted. an additional text to support extraction from the log file. |-- Standard logging prefix --| key | - RevCPU[cpu0:InstTrace:18156000]: Core 0; Hart 0; Thread 1]; *I + RevCPU[cpu0:InstTrace:18156000]: Core 0; Hart 0; Thread 1]; *I ## Instruction Disassembly @@ -105,9 +105,9 @@ The prefix fields showing cycle, cpu, thread, and hart information are omitted. ## Register to Register Format | PC : INSN | Disassembly | Effects | - 0x10474:00c50533 add a0, a0, a2 0x14<-a0 0x50<-a2 a0<-0x64 + 0x10474:00c50533 add a0, a0, a2 0x14<-a0 0x50<-a2 a0<-0x64 - Notice that the effects include the same register naming conventions as the disassembled instruction. + Notice that the effects include the same register naming conventions as the disassembled instruction. Effects interpretation: - data<-reg : Source register read @@ -133,8 +133,8 @@ The prefix fields showing cycle, cpu, thread, and hart information are omitted. 0x102d4:fec42783 lw a5, -20(s0) | Effects | - 0x3fefff90<-s0 0x0<-a5 0xacee1190<-[0x3fefff7c,4] a5<-0xacee1190 - + 0x3fefff90<-s0 0x0<-a5 0xacee1190<-[0x3fefff7c,4] a5<-0xacee1190 + Effects interpretation: - data<-reg : Source register read @@ -144,22 +144,22 @@ The prefix fields showing cycle, cpu, thread, and hart information are omitted. ## Memory to Register (Load) - Memory Hierarchy When "enable_memh" is 1 and the RevMemCtrl subcomponent is used, the issuing of the load and the load effects are separated. This is shown in the following trace. The prefix showing Core, Hart, and Thread information has been omitted. - + (1) *I 0x1511c:0007ae83 lw t4, 0(a5) 0x3ffffbc8<-a5 t4<-[0x3ffffbc8,4] (2) *I 0x15120:fffe0e13 addi t3, t3, -1 0x1<-t3 t3<-0x0 (3) *A 0x1ace4ff0<-[0x3ffffbc8,4] t4<-0x1ace4ff0 (4) *I 0x15124:001e8e93 addi t4, t4, 1 0x1ace4ff0<-t4 t4<-0x1ace4ff1 - Instruction execution is preceded by '*I' and asynchronous events, such as the returning load data, is preceded by '*A'. + Instruction execution is preceded by '*I' and asynchronous events, such as the returning load data, is preceded by '*A'. Effects interpretation: - - Cycle 1: t4<-[0x3ffffbc8,4] : + - Cycle 1: t4<-[0x3ffffbc8,4] : The load request is send to the memory component. In this case, 4 bytes are read from 0x3ffffbc8 and the results will eventually be written into register t4. The t4 register is marked as 'busy' so that any instruction that depends on register t4 will stall until the load completes. - - Cycle 2: addi t3, t3, -1 0x1<-t3 t3<-0x0 + - Cycle 2: addi t3, t3, -1 0x1<-t3 t3<-0x0 This is an independent instruction that does not depend on t4. It is free to execute without stalling. - - Cycle 3: *A 0x1ace4ff0<-[0x3ffffbc8,4] t4<-0x1ace4ff0 + - Cycle 3: *A 0x1ace4ff0<-[0x3ffffbc8,4] t4<-0x1ace4ff0 This is the asynchronous load completion showing the memory location and number of bytes read, the returning load data, and the write to register t4. - - Cycle 4: addi t4, t4, 1 0x1ace4ff0<-t4 + - Cycle 4: addi t4, t4, 1 0x1ace4ff0<-t4 An instruction that depends on register t4 that must be stalled until the t4 register scoreboard bit is cleared by the preceding load completion. ## Program Counter Writes (Branches/Jumps) @@ -172,7 +172,7 @@ The prefix fields showing cycle, cpu, thread, and hart information are omitted. - reg<-data : Destination link register write - pc<-address: Resolved branch target - <_Z5checki> : Matching ELF symbol associated with new PC - + # Sample Traces The source code for these samples is found in /test/tracer. @@ -184,16 +184,16 @@ illustrative trace test cases. ## Traced assertion macro This example demonstrates the usage of the following macros defined - in rev-macros.h - - #define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); + in rev-macros.h + + #define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); #define TRACE_POP asm volatile("slli x0,x0,4"); #define TRACE_ASSERT(x) { TRACE_PUSH_ON; \ if (!(x)) { asm volatile(".word 0x0"); }; \ TRACE_PUSH_OFF } - For this line of C code: - + For this line of C code: + TRACE_ASSERT(res*2==1980); We have the following disassembly. @@ -208,82 +208,82 @@ illustrative trace test cases. And the following trace: - 1 0x147e4:00301013 + slli zero, zero, 3 0x0<-zero zero<-0x0 pc<-0x147e8 - 2 0x147e8:fec42703 lw a4, -20(s0) 0x3ffffba0<-s0 0x000003de<-[0x3ffffb8c,4] a4<-0x3de - 3 0x147ec:3de00793 li a5, 990 0x0<-zero a5<-0x3de - 4 0x147f0:00f70463 beq a4, a5, pc+8 0x3de<-a4 0x3de<-a5 pc<-0x147f8 - 5 0x147f8:00201013 - slli zero, zero, 2 0x0<-zero zero<-0x0 + 1 0x147e4:00301013 + slli zero, zero, 3 0x0<-zero zero<-0x0 pc<-0x147e8 + 2 0x147e8:fec42703 lw a4, -20(s0) 0x3ffffba0<-s0 0x000003de<-[0x3ffffb8c,4] a4<-0x3de + 3 0x147ec:3de00793 li a5, 990 0x0<-zero a5<-0x3de + 4 0x147f0:00f70463 beq a4, a5, pc+8 0x3de<-a4 0x3de<-a5 pc<-0x147f8 + 5 0x147f8:00201013 - slli zero, zero, 2 0x0<-zero zero<-0x0 Line by line interpretation: - - Cycle 1: + + Cycle 1: - The '+' indicates the first line of a trace sequence. This TRACE_PUSH_ON macro will push the current state of the tracer onto a stack and enable tracing. - 0x0<-zero : indicates the x0 register has been read - pc<-0x147e8: The tracer prints the program counter at the start of new traces or for any branch occurance. -Cycle 2: +Cycle 2: - 0x3ffffba0<-s0 : s0 read for part of the memory address calculation. - 0x000003de<-[0x3ffffb8c,4]: - 4 bytes are read from memory location 0x3ffffb8c. The data is 0x3de. - a4<-0x3de : Register a4 is written with the return load data. -Cycle 3: +Cycle 3: - 0x0<-zero: 'li' is implementation an 'addi' using the x0 register. - a5<-0x3de: a5 is written with the immediate field -Cycle 4: +Cycle 4: - 0x3de<-a4 0x3de<-a5: Read of the 2 sources being compared. - pc<-0x147f8: target instruction address for the taken branch. - + Cycle 5: - The '-' indicates that tracing is being disabled. ## 32-bit vs 64-bit instructions Here is a sequence of memory accesses using byte, half-word, and word data. The data is -1 in order to observe the effects of sign extensions. - + This sequence is run on using REV configured for RV32I instructions. li t3, -1 0x0<-zero t3<-0xffffffff - sb t3, 0(a5) 0x3ffffb78<-a5 0xff<-t3 [0x3ffffb78,1]<-0xff - lb t4, 0(a5) 0x3ffffb78<-a5 0xff<-[0x3ffffb78,1] t4<-0xffffffff - sh t3, 0(a5) 0x3ffffb78<-a5 0xffff<-t3 [0x3ffffb78,2]<-0xffff + sb t3, 0(a5) 0x3ffffb78<-a5 0xff<-t3 [0x3ffffb78,1]<-0xff + lb t4, 0(a5) 0x3ffffb78<-a5 0xff<-[0x3ffffb78,1] t4<-0xffffffff + sh t3, 0(a5) 0x3ffffb78<-a5 0xffff<-t3 [0x3ffffb78,2]<-0xffff lh t4, 0(a5) 0x3ffffb78<-a5 0xffff<-[0x3ffffb78,2] t4<-0xffffffff - sw t3, 0(a5) 0x3ffffb78<-a5 0xffffffff<-t3 [0x3ffffb78,4]<-0xffffffff + sw t3, 0(a5) 0x3ffffb78<-a5 0xffffffff<-t3 [0x3ffffb78,4]<-0xffffffff lw t4, 0(a5) 0x3ffffb78<-a5 0xffffffff<-[0x3ffffb78,4] t4<-0xffffffff This next sequence also includes 64-bit operations and is run using RV64G instructions. - - li t3, -1 0x0<-zero t3<-0xffffffffffffffff - sb t3, 0(a5) 0x3ffffb28<-a5 0xff<-t3 [0x3ffffb28,1]<-0xff - lb t4, 0(a5) 0x3ffffb28<-a5 0xff<-[0x3ffffb28,1] t4<-0xffffffffffffffff - sh t3, 0(a5) 0x3ffffb28<-a5 0xffff<-t3 [0x3ffffb28,2]<-0xffff - lh t4, 0(a5) 0x3ffffb28<-a5 0xffff<-[0x3ffffb28,2] t4<-0xffffffffffffffff - sw t3, 0(a5) 0x3ffffb28<-a5 0xffffffff<-t3 [0x3ffffb28,4]<-0xffffffff - lw t4, 0(a5) 0x3ffffb28<-a5 0xffffffff<-[0x3ffffb28,4] t4<-0xffffffffffffffff - addi a5, s0, -48 0x3ffffb58<-s0 a5<-0x3ffffb28 - sd t3, 0(a5) 0x3ffffb28<-a5 0xffffffffffffffff<-t3 [0x3ffffb28,8]<-0xffffffffffffffff - lwu t4, 0(a5) 0x3ffffb28<-a5 0xffffffff<-[0x3ffffb28,4] t4<-0xffffffff - ld t4, 0(a5) 0x3ffffb28<-a5 0xffffffffffffffff<-[0x3ffffb28,8] t4<-0xffffffffffffffff + + li t3, -1 0x0<-zero t3<-0xffffffffffffffff + sb t3, 0(a5) 0x3ffffb28<-a5 0xff<-t3 [0x3ffffb28,1]<-0xff + lb t4, 0(a5) 0x3ffffb28<-a5 0xff<-[0x3ffffb28,1] t4<-0xffffffffffffffff + sh t3, 0(a5) 0x3ffffb28<-a5 0xffff<-t3 [0x3ffffb28,2]<-0xffff + lh t4, 0(a5) 0x3ffffb28<-a5 0xffff<-[0x3ffffb28,2] t4<-0xffffffffffffffff + sw t3, 0(a5) 0x3ffffb28<-a5 0xffffffff<-t3 [0x3ffffb28,4]<-0xffffffff + lw t4, 0(a5) 0x3ffffb28<-a5 0xffffffff<-[0x3ffffb28,4] t4<-0xffffffffffffffff + addi a5, s0, -48 0x3ffffb58<-s0 a5<-0x3ffffb28 + sd t3, 0(a5) 0x3ffffb28<-a5 0xffffffffffffffff<-t3 [0x3ffffb28,8]<-0xffffffffffffffff + lwu t4, 0(a5) 0x3ffffb28<-a5 0xffffffff<-[0x3ffffb28,4] t4<-0xffffffff + ld t4, 0(a5) 0x3ffffb28<-a5 0xffffffffffffffff<-[0x3ffffb28,8] t4<-0xffffffffffffffff Observe that the data for each memory read matches the data size. - - sb: [0x3ffffb28,1]<-0xff + + sb: [0x3ffffb28,1]<-0xff lb: 0xff<-[0x3ffffb28,1] - sh: [0x3ffffb28,2]<-0xffff + sh: [0x3ffffb28,2]<-0xffff lh: 0xffff<-[0x3ffffb28,2] - sw: [0x3ffffb28,4]<-0xffffffff + sw: [0x3ffffb28,4]<-0xffffffff lw: 0xffffffff<-[0x3ffffb28,4] sd: [0x3ffffb28,8]<-0xffffffffffffffff - lwu: 0xffffffff<-[0x3ffffb28,4] + lwu: 0xffffffff<-[0x3ffffb28,4] ld: 0xffffffffffffffff<-[0x3ffffb28,8] The final register writes for loads are sign-extended except when using lwu. The register write size depends on whether using 32-bit or 64-bit designs. - lb (32-bit): t4<-0xffffffff - lb (64-bit): t4<-0xffffffffffffffff - lwu(64-bit): t4<-0xffffffff - ld (64-bit): t4<-0xffffffffffffffff + lb (32-bit): t4<-0xffffffff + lb (64-bit): t4<-0xffffffffffffffff + lwu(64-bit): t4<-0xffffffff + ld (64-bit): t4<-0xffffffffffffffff # Issues/Enhancements @@ -292,7 +292,7 @@ Cycle 5: instruction types (floating point, coprocessor, vector,... ) are not. - Effects of atomic memory operations are not yet traced. - + - ECalls are also not yet traced - Tracing information may be sent to different output streams in more @@ -302,4 +302,4 @@ Cycle 5: is printed. It should be possible to support a full disassembler within REV.In general, threading with tracing has not been tested. - - Loads that target the zero register (x0) are not shown. \ No newline at end of file + - Loads that target the zero register (x0) are not shown. diff --git a/include/AllRevInstTables.h b/include/AllRevInstTables.h index 16727ea09..bf90e5630 100644 --- a/include/AllRevInstTables.h +++ b/include/AllRevInstTables.h @@ -19,17 +19,23 @@ // and implementation for each block of RISC-V isntructions // +#include "insns/RV32D.h" +#include "insns/RV32F.h" #include "insns/RV32I.h" -#include "insns/RV64I.h" #include "insns/RV32M.h" -#include "insns/RV64M.h" -#include "insns/RV32A.h" -#include "insns/RV64A.h" -#include "insns/RV32F.h" -#include "insns/RV64F.h" -#include "insns/RV32D.h" #include "insns/RV64D.h" +#include "insns/RV64F.h" +#include "insns/RV64I.h" +#include "insns/RV64M.h" #include "insns/RV64P.h" +#ifdef REVVEC +#include "insns/RVVec.h" +#endif +#include "insns/Zaamo.h" +#include "insns/Zalrsc.h" +#include "insns/Zfa.h" #include "insns/Zicbom.h" +#include "insns/Zicsr.h" +#include "insns/Zifencei.h" #endif diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index c582d898d..f2e4bca4e 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,6 +1,6 @@ # include/CoreGen/StoneCutter/Intrinsics CMakeLists.txt # -# Copyright (C) 2017-2022 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/include/RevCPU.h b/include/RevCPU.h index 6289ef4ec..9dba4b105 100644 --- a/include/RevCPU.h +++ b/include/RevCPU.h @@ -1,7 +1,7 @@ // // _RevCPU_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -12,53 +12,56 @@ #define _SST_REVCPU_H_ // -- Standard Headers +#include +#include #include -#include #include -#include -#include +#include #include #include +#include #include -#include +#include #include -#include #include -#include // -- SST Headers #include "SST.h" // -- Rev Headers -#include "RevOpts.h" +#include "RevCoProc.h" +#include "RevCore.h" +#include "RevLoader.h" #include "RevMem.h" #include "RevMemCtrl.h" -#include "RevLoader.h" -#include "RevProc.h" -#include "RevThread.h" #include "RevNIC.h" -#include "RevCoProc.h" +#include "RevOpts.h" #include "RevRand.h" +#include "RevThread.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RevCPU : public SST::Component{ +class RevCPU : public SST::Component { public: /// RevCPU: top-level SST component constructor RevCPU( SST::ComponentId_t id, const SST::Params& params ); /// RevCPU: top-level SST component destructor - ~RevCPU(); + ~RevCPU() = default; + + /// RevCPU: disallow copying and assignment + RevCPU( const RevCPU& ) = delete; + RevCPU& operator=( const RevCPU& ) = delete; /// RevCPU: standard SST component 'setup' function - void setup(); + void setup() final; /// RevCPU: standard SST component 'finish' function - void finish(); + void finish() final; /// RevCPU: standard SST component 'init' function - void init( unsigned int phase ); + void init( uint32_t phase ) final; /// RevCPU: standard SST component clock function bool clockTick( SST::Cycle_t currentCycle ); @@ -68,50 +71,51 @@ class RevCPU : public SST::Component{ // ------------------------------------------------------- /// RevCPU: Register the component with the SST core SST_ELI_REGISTER_COMPONENT( - RevCPU, // component class - "revcpu", // component library - "RevCPU", // component name + RevCPU, // component class + "revcpu", // component library + "RevCPU", // component name SST_ELI_ELEMENT_VERSION( 1, 0, 0 ), "RISC-V SST CPU", COMPONENT_CATEGORY_PROCESSOR - ) + ) // ------------------------------------------------------- // RevCPU Component Parameter Data // ------------------------------------------------------- + // clang-format off SST_ELI_DOCUMENT_PARAMS( - {"verbose", "Sets the verbosity level of output", "0" }, - {"clock", "Clock for the CPU", "1GHz" }, - {"program", "Sets the binary executable", "a.out" }, - {"args", "Sets the argument list", ""}, - {"numCores", "Number of RISC-V cores to instantiate", "1" }, - {"numHarts", "Number of harts (per core) to instantiate", "1" }, - {"memSize", "Main memory size in bytes", "1073741824"}, - {"startAddr", "Starting PC of the target core", "core:0x80000000"}, - {"startSymbol", "Starting symbol name of the target core", "core:symbol"}, - {"machine", "RISC-V machine model of the target core", "core:G"}, - {"memCost", "Memory latency range in cycles min:max", "core:0:10"}, - {"prefetchDepth", "Instruction prefetch depth per core", "core:1"}, - {"table", "Instruction cost table", "core:/path/to/table"}, - {"enable_nic", "Enable the internal RevNIC", "0"}, - {"enable_pan", "Enable PAN network endpoint", "0"}, - {"enable_test", "Enable PAN network endpoint test", "0"}, - {"enable_pan_stats", "Enable PAN network statistics", "1"}, - {"enable_memH", "Enable memHierarchy", "0"}, - {"enableRDMAMbox", "Enable the RDMA mailbox", "1"}, - {"enableCoProc", "Enable an attached coProcessor for all cores", "0"}, - {"enable_faults", "Enable the fault injection logic", "0"}, - {"faults", "Enable specific faults", "decode,mem,reg,alu"}, - {"fault_width", "Specify the bit width of potential faults", "single,word,N"}, - {"fault_range", "Specify the range of faults in cycles", "65536"}, - {"msgPerCycle", "Number of messages per cycle to inject", "1"}, - {"RDMAPerCycle", "Number of RDMA messages per cycle to inject", "1"}, - {"testIters", "Number of PAN test messages to send", "255"}, - {"trcOp", "Tracer instruction trigger", "slli"}, - {"trcLimit", "Max trace lines per core (0 no limit)", "0"}, - {"trcStartCycle", "Starting tracer cycle (disables trcOp)", "0"}, - {"splash", "Display the splash logo", "0"}, - {"independentCoprocClock", "Enables each coprocessor to register its own clock handler", "0"}, + { "verbose", "Sets the verbosity level of output", "0" }, + { "clock", "Clock for the CPU", "1GHz" }, + { "program", "Sets the binary executable", "a.out" }, + { "args", "Sets the argument list", "" }, + { "numCores", "Number of RISC-V cores to instantiate", "1" }, + { "numHarts", "Number of harts (per core) to instantiate", "1" }, + { "memSize", "Main memory size in bytes", "1073741824" }, + { "startAddr", "Starting PC of the target core", "core:0x80000000" }, + { "startSymbol", "Starting symbol name of the target core", "core:symbol" }, + { "machine", "RISC-V machine model of the target core", "core:G" }, + { "memCost", "Memory latency range in cycles min:max", "core:0:10" }, + { "prefetchDepth", "Instruction prefetch depth per core", "core:1" }, + { "table", "Instruction cost table", "core:/path/to/table" }, + { "enable_nic", "Enable the internal RevNIC", "0" }, + { "enable_pan", "Enable PAN network endpoint", "0" }, + { "enable_test", "Enable PAN network endpoint test", "0" }, + { "enable_pan_stats", "Enable PAN network statistics", "1" }, + { "enableMemH", "Enable memHierarchy", "0" }, + { "enableRDMAMbox", "Enable the RDMA mailbox", "1" }, + { "enableCoProc", "Enable an attached coProcessor for all cores", "0" }, + { "enable_faults", "Enable the fault injection logic", "0" }, + { "faults", "Enable specific faults", "decode,mem,reg,alu" }, + { "fault_width", "Specify the bit width of potential faults", "single,word,N" }, + { "fault_range", "Specify the range of faults in cycles", "65536" }, + { "msgPerCycle", "Number of messages per cycle to inject", "1" }, + { "RDMAPerCycle", "Number of RDMA messages per cycle to inject", "1" }, + { "testIters", "Number of PAN test messages to send", "255" }, + { "trcOp", "Tracer instruction trigger", "slli" }, + { "trcLimit", "Max trace lines per core (0 no limit)", "0" }, + { "trcStartCycle", "Starting tracer cycle to use with verbose=5", "0" }, + { "splash", "Display the splash logo", "0" }, + { "independentCoprocClock", "Enables each coprocessor to register its own clock handler", "0" }, ) // ------------------------------------------------------- @@ -124,115 +128,112 @@ class RevCPU : public SST::Component{ // RevCPU SubComponent Parameter Data // ------------------------------------------------------- SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( - {"nic", "Network interface", "SST::RevCPU::RevNIC"}, - {"pan_nic", "PAN Network interface", "SST::RevCPU::PanNet"}, - {"memory", "Memory interface to utilize for cache/memory hierachy", "SST::RevCPU::RevMemCtrl"}, - {"co_proc", "Co-processor attached to RevProc", "SST::RevCPU::RevSimpleCoProc"}, + { "nic", "Network interface", "SST::RevCPU::RevNIC" }, + { "pan_nic", "PAN Network interface", "SST::RevCPU::PanNet" }, + { "memory", "Memory interface to utilize for cache/memory hierachy", "SST::RevCPU::RevMemCtrl" }, + { "co_proc", "Co-processor attached to RevCore", "SST::RevCPU::RevSimpleCoProc" }, ) // ------------------------------------------------------- // RevCPU Component Statistics Data // ------------------------------------------------------- SST_ELI_DOCUMENT_STATISTICS( - {"SyncGetSend", "Operation count for outgoing SyncGet Commands", "count", 1}, - {"SyncPutSend", "Operation count for outgoing SyncPut Commands", "count", 1}, - {"AsyncGetSend", "Operation count for outgoing AsyncGet Commands", "count", 1}, - {"AsyncPutSend", "Operation count for outgoing AsyncPut Commands", "count", 1}, - {"SyncStreamGetSend", "Operation count for outgoing SyncStreamGet Commands", "count", 1}, - {"SyncStreamPutSend", "Operation count for outgoing SyncStreamPut Commands", "count", 1}, - {"AsyncStreamGetSend", "Operation count for outgoing AsyncStreamGet Commands", "count", 1}, - {"AsyncStreamPutSend", "Operation count for outgoing AsyncStreamPut Commands", "count", 1}, - {"ExecSend", "Operation count for outgoing Exec Commands", "count", 1}, - {"StatusSend", "Operation count for outgoing Status Commands", "count", 1}, - {"CancelSend", "Operation count for outgoing Cancel Commands", "count", 1}, - {"ReserveSend", "Operation count for outgoing Reserve Commands", "count", 1}, - {"RevokeSend", "Operation count for outgoing Revoke Commands", "count", 1}, - {"HaltSend", "Operation count for outgoing Halt Commands", "count", 1}, - {"ResumeSend", "Operation count for outgoing Resume Commands", "count", 1}, - {"ReadRegSend", "Operation count for outgoing ReadReg Commands", "count", 1}, - {"WriteRegSend", "Operation count for outgoing WriteReg Commands", "count", 1}, - {"SingleStepSend", "Operation count for outgoing SingleStep Commands", "count", 1}, - {"SetFutureSend", "Operation count for outgoing SetFuture Commands", "count", 1}, - {"RevokeFutureSend", "Operation count for outgoing RevokeFuture Commands", "count", 1}, - {"StatusFutureSend", "Operation count for outgoing StatusFuture Commands", "count", 1}, - {"SuccessSend", "Operation count for outgoing Success Commands", "count", 1}, - {"FailedSend", "Operation count for outgoing Failed Commands", "count", 1}, - {"BOTWSend", "Operation count for outgoing BOTW Commands", "count", 1}, - {"SyncGetRecv", "Operation count for incoming SyncGet Commands", "count", 1}, - {"SyncPutRecv", "Operation count for incoming SyncPut Commands", "count", 1}, - {"AsyncGetRecv", "Operation count for incoming AsyncGet Commands", "count", 1}, - {"AsyncPutRecv", "Operation count for incoming AsyncPut Commands", "count", 1}, - {"SyncStreamGetRecv", "Operation count for incoming SyncStreamGet Commands", "count", 1}, - {"SyncStreamPutRecv", "Operation count for incoming SyncStreamPut Commands", "count", 1}, - {"AsyncStreamGetRecv", "Operation count for incoming AsyncStreamGet Commands", "count", 1}, - {"AsyncStreamPutRecv", "Operation count for incoming AsyncStreamPut Commands", "count", 1}, - {"ExecRecv", "Operation count for incoming Exec Commands", "count", 1}, - {"StatusRecv", "Operation count for incoming Status Commands", "count", 1}, - {"CancelRecv", "Operation count for incoming Cancel Commands", "count", 1}, - {"ReserveRecv", "Operation count for incoming Reserve Commands", "count", 1}, - {"RevokeRecv", "Operation count for incoming Revoke Commands", "count", 1}, - {"HaltRecv", "Operation count for incoming Halt Commands", "count", 1}, - {"ResumeRecv", "Operation count for incoming Resume Commands", "count", 1}, - {"ReadRegRecv", "Operation count for incoming ReadReg Commands", "count", 1}, - {"WriteRegRecv", "Operation count for incoming WriteReg Commands", "count", 1}, - {"SingleStepRecv", "Operation count for incoming SingleStep Commands", "count", 1}, - {"SetFutureRecv", "Operation count for incoming SetFuture Commands", "count", 1}, - {"RevokeFutureRecv", "Operation count for incoming RevokeFuture Commands", "count", 1}, - {"StatusFutureRecv", "Operation count for incoming StatusFuture Commands", "count", 1}, - {"SuccessRecv", "Operation count for incoming Success Commands", "count", 1}, - {"FailedRecv", "Operation count for incoming Failed Commands", "count", 1}, - {"BOTWRecv", "Operation count for incoming BOTW Commands", "count", 1}, - - {"CyclesWithIssue", "Cycles with succesful instruction issue", "count", 1}, - {"TotalCycles", "Total clock cycles", "count", 1}, - {"FloatsRead", "Total SP floating point values read", "count", 1}, - {"FloatsWritten", "Total SP floating point values written", "count", 1}, - {"DoublesRead", "Total DP floating point values read", "count", 1}, - {"DoublesWritten", "Total DP floating point values written", "count", 1}, - {"BytesRead", "Total bytes read", "count", 1}, - {"BytesWritten", "Total bytes written", "count", 1}, - {"FloatsExec", "Total SP or DP float instructions executed", "count", 1}, - {"TLBHitsPerCore", "TLB hits per core", "count", 1}, - {"TLBMissesPerCore", "TLB misses per core", "count", 1}, - - {"TLBHits", "TLB hits", "count", 1}, - {"TLBMisses", "TLB misses", "count", 1}, + { "SyncGetSend", "Operation count for outgoing SyncGet Commands", "count", 1 }, + { "SyncPutSend", "Operation count for outgoing SyncPut Commands", "count", 1 }, + { "AsyncGetSend", "Operation count for outgoing AsyncGet Commands", "count", 1 }, + { "AsyncPutSend", "Operation count for outgoing AsyncPut Commands", "count", 1 }, + { "SyncStreamGetSend", "Operation count for outgoing SyncStreamGet Commands", "count", 1 }, + { "SyncStreamPutSend", "Operation count for outgoing SyncStreamPut Commands", "count", 1 }, + { "AsyncStreamGetSend", "Operation count for outgoing AsyncStreamGet Commands", "count", 1 }, + { "AsyncStreamPutSend", "Operation count for outgoing AsyncStreamPut Commands", "count", 1 }, + { "ExecSend", "Operation count for outgoing Exec Commands", "count", 1 }, + { "StatusSend", "Operation count for outgoing Status Commands", "count", 1 }, + { "CancelSend", "Operation count for outgoing Cancel Commands", "count", 1 }, + { "ReserveSend", "Operation count for outgoing Reserve Commands", "count", 1 }, + { "RevokeSend", "Operation count for outgoing Revoke Commands", "count", 1 }, + { "HaltSend", "Operation count for outgoing Halt Commands", "count", 1 }, + { "ResumeSend", "Operation count for outgoing Resume Commands", "count", 1 }, + { "ReadRegSend", "Operation count for outgoing ReadReg Commands", "count", 1 }, + { "WriteRegSend", "Operation count for outgoing WriteReg Commands", "count", 1 }, + { "SingleStepSend", "Operation count for outgoing SingleStep Commands", "count", 1 }, + { "SetFutureSend", "Operation count for outgoing SetFuture Commands", "count", 1 }, + { "RevokeFutureSend", "Operation count for outgoing RevokeFuture Commands", "count", 1 }, + { "StatusFutureSend", "Operation count for outgoing StatusFuture Commands", "count", 1 }, + { "SuccessSend", "Operation count for outgoing Success Commands", "count", 1 }, + { "FailedSend", "Operation count for outgoing Failed Commands", "count", 1 }, + { "BOTWSend", "Operation count for outgoing BOTW Commands", "count", 1 }, + { "SyncGetRecv", "Operation count for incoming SyncGet Commands", "count", 1 }, + { "SyncPutRecv", "Operation count for incoming SyncPut Commands", "count", 1 }, + { "AsyncGetRecv", "Operation count for incoming AsyncGet Commands", "count", 1 }, + { "AsyncPutRecv", "Operation count for incoming AsyncPut Commands", "count", 1 }, + { "SyncStreamGetRecv", "Operation count for incoming SyncStreamGet Commands", "count", 1 }, + { "SyncStreamPutRecv", "Operation count for incoming SyncStreamPut Commands", "count", 1 }, + { "AsyncStreamGetRecv", "Operation count for incoming AsyncStreamGet Commands", "count", 1 }, + { "AsyncStreamPutRecv", "Operation count for incoming AsyncStreamPut Commands", "count", 1 }, + { "ExecRecv", "Operation count for incoming Exec Commands", "count", 1 }, + { "StatusRecv", "Operation count for incoming Status Commands", "count", 1 }, + { "CancelRecv", "Operation count for incoming Cancel Commands", "count", 1 }, + { "ReserveRecv", "Operation count for incoming Reserve Commands", "count", 1 }, + { "RevokeRecv", "Operation count for incoming Revoke Commands", "count", 1 }, + { "HaltRecv", "Operation count for incoming Halt Commands", "count", 1 }, + { "ResumeRecv", "Operation count for incoming Resume Commands", "count", 1 }, + { "ReadRegRecv", "Operation count for incoming ReadReg Commands", "count", 1 }, + { "WriteRegRecv", "Operation count for incoming WriteReg Commands", "count", 1 }, + { "SingleStepRecv", "Operation count for incoming SingleStep Commands", "count", 1 }, + { "SetFutureRecv", "Operation count for incoming SetFuture Commands", "count", 1 }, + { "RevokeFutureRecv", "Operation count for incoming RevokeFuture Commands", "count", 1 }, + { "StatusFutureRecv", "Operation count for incoming StatusFuture Commands", "count", 1 }, + { "SuccessRecv", "Operation count for incoming Success Commands", "count", 1 }, + { "FailedRecv", "Operation count for incoming Failed Commands", "count", 1 }, + { "BOTWRecv", "Operation count for incoming BOTW Commands", "count", 1 }, + + { "CyclesWithIssue", "Cycles with succesful instruction issue", "count", 1 }, + { "TotalCycles", "Total clock cycles", "count", 1 }, + { "FloatsRead", "Total SP floating point values read", "count", 1 }, + { "FloatsWritten", "Total SP floating point values written", "count", 1 }, + { "DoublesRead", "Total DP floating point values read", "count", 1 }, + { "DoublesWritten", "Total DP floating point values written", "count", 1 }, + { "BytesRead", "Total bytes read", "count", 1 }, + { "BytesWritten", "Total bytes written", "count", 1 }, + { "FloatsExec", "Total SP or DP float instructions executed", "count", 1 }, + { "TLBHitsPerCore", "TLB hits per core", "count", 1 }, + { "TLBMissesPerCore", "TLB misses per core", "count", 1 }, + + { "TLBHits", "TLB hits", "count", 1 }, + { "TLBMisses", "TLB misses", "count", 1 }, ) - // Passed as a function pointer to each RevProc for when they encounter a function that + // clang-format on + + // Passed as a function pointer to each RevCore for when they encounter a function that // results in a new RevThread being spawned std::function GetNewTID() { - return std::function([this]() { return GetNewThreadID(); }); + return std::function( [this]() { return GetNewThreadID(); } ); } private: - unsigned numCores; ///< RevCPU: number of RISC-V cores - unsigned numHarts; ///< RevCPU: number of RISC-V cores - unsigned msgPerCycle; ///< RevCPU: number of messages to send per cycle - unsigned RDMAPerCycle; ///< RevCPU: number of RDMA messages per cycle to inject into PAN network - unsigned testStage; ///< RevCPU: controls the PAN Test harness staging - unsigned testIters; ///< RevCPU: the number of message iters for each PAN Test - std::string Exe; ///< RevCPU: binary executable - std::string Args; ///< RevCPU: argument list - RevOpts *Opts; ///< RevCPU: Simulation options object - RevMem *Mem; ///< RevCPU: RISC-V main memory object - RevLoader *Loader; ///< RevCPU: RISC-V loader - std::vector Procs; ///< RevCPU: RISC-V processor objects - bool *Enabled; ///< RevCPU: Completion structure + uint32_t numCores{}; ///< RevCPU: number of RISC-V cores + uint32_t numHarts{}; ///< RevCPU: number of RISC-V cores + uint32_t msgPerCycle{}; ///< RevCPU: number of messages to send per cycle + // uint32_t RDMAPerCycle{}; ///< RevCPU: number of RDMA messages per cycle to inject into PAN network + // uint32_t testStage{}; ///< RevCPU: controls the PAN Test harness staging + // uint32_t testIters{}; ///< RevCPU: the number of message iters for each PAN Test + std::unique_ptr Opts; ///< RevCPU: Simulation options object + std::unique_ptr Mem; ///< RevCPU: RISC-V main memory object + std::unique_ptr Loader; ///< RevCPU: RISC-V loader + std::vector> Procs; ///< RevCPU: RISC-V processor objects + std::vector Enabled; ///< RevCPU: Completion structure // Initializes a RevThread object. // - Adds it's ThreadID to the ThreadQueue to be scheduled - void InitThread(std::unique_ptr&& ThreadToInit); + void InitThread( std::unique_ptr&& ThreadToInit ); // Initializes the main thread - void InitMainThread(uint32_t MainThreadID, uint64_t StartAddr); + void InitMainThread( uint32_t MainThreadID, uint64_t StartAddr ); // Adds Thread with ThreadID to AssignedThreads vector for ProcID // - Handles updating LSQueue & MarkLoadComplete function pointers - void AssignThread(std::unique_ptr&& ThreadToAssign, unsigned ProcID); - - // Sets up arguments for a thread with a given ID and feature set. - void SetupArgs(const std::unique_ptr& RegFile); + void AssignThread( std::unique_ptr&& ThreadToAssign, uint32_t ProcID ); // Checks the status of ALL threads that are currently blocked. void CheckBlockedThreads(); @@ -240,153 +241,148 @@ class RevCPU : public SST::Component{ // Checks core w/ ProcID to see if it has any available harts to assign work to // if it does and there is work to assign (ie. ThreadQueue is not empty) // assign it and enable the processor if not already enabled. - void UpdateThreadAssignments(uint32_t ProcID); + void UpdateThreadAssignments( uint32_t ProcID ); // Checks for state changes in the threads of a given processor index 'ProcID' // and handle appropriately - void HandleThreadStateChangesForProc(uint32_t ProcID); + void HandleThreadStateChangesForProc( uint32_t ProcID ); // Checks if a thread with a given Thread ID can proceed (used for pthread_join). // it does this by seeing if a given thread's WaitingOnTID has completed - bool ThreadCanProceed(const std::unique_ptr& Thread); + bool ThreadCanProceed( const std::unique_ptr& Thread ); // vector of Threads which are ready to be scheduled - std::vector> ReadyThreads = {}; + std::vector> ReadyThreads{}; // List of Threads that are currently blocked (waiting for their WaitingOnTID to be a key in CompletedThreads). - std::list> BlockedThreads = {}; + std::list> BlockedThreads{}; // Set of Thread IDs and their corresponding RevThread that have completed their execution on this RevCPU - std::unordered_map> CompletedThreads = {}; + std::unordered_map> CompletedThreads{}; // Generates a new Thread ID using the RNG. - uint32_t GetNewThreadID() { return RevRand(0, UINT32_MAX); } + uint32_t GetNewThreadID() { return RevRand( 0, UINT32_MAX ); } - uint8_t PrivTag; ///< RevCPU: private tag locator - uint32_t LToken; ///< RevCPU: token identifier for PAN Test + uint8_t PrivTag{}; ///< RevCPU: private tag locator + // uint32_t LToken{}; ///< RevCPU: token identifier for PAN Test - int address; ///< RevCPU: local network address + int64_t address{ -1 }; ///< RevCPU: local network address - unsigned fault_width; ///< RevCPU: the width (in bits) for target faults - int64_t fault_range; ///< RevCPU: the range of cycles to inject the fault - int64_t FaultCntr; ///< RevCPU: the fault counter + uint32_t fault_width{}; ///< RevCPU: the width (in bits) for target faults + // int64_t fault_range{}; ///< RevCPU: the range of cycles to inject the fault + int64_t FaultCntr{}; ///< RevCPU: the fault counter - uint64_t PrevAddr; ///< RevCPU: previous address for handling PAN messages + // uint64_t PrevAddr{}; ///< RevCPU: previous address for handling PAN messages - bool EnableNIC; ///< RevCPU: Flag for enabling the NIC - bool EnableMemH; ///< RevCPU: Enable memHierarchy - bool EnableCoProc; ///< RevCPU: Enable a co-processor attached to all cores + bool EnableNIC{}; ///< RevCPU: Flag for enabling the NIC + bool EnableMemH{}; ///< RevCPU: Enable memHierarchy + bool EnableCoProc{}; ///< RevCPU: Enable a co-processor attached to all cores - bool EnableFaults; ///< RevCPU: Enable fault injection logic - bool EnableCrackFaults; ///< RevCPU: Enable Crack+Decode Faults - bool EnableMemFaults; ///< RevCPU: Enable memory faults (bit flips) - bool EnableRegFaults; ///< RevCPU: Enable register faults - bool EnableALUFaults; ///< RevCPU: Enable ALU faults + bool EnableFaults{}; ///< RevCPU: Enable fault injection logic + bool EnableCrackFaults{}; ///< RevCPU: Enable Crack+Decode Faults + bool EnableMemFaults{}; ///< RevCPU: Enable memory faults (bit flips) + bool EnableRegFaults{}; ///< RevCPU: Enable register faults + bool EnableALUFaults{}; ///< RevCPU: Enable ALU faults - bool DisableCoprocClock; ///< RevCPU: Disables manual coproc clocking + bool DisableCoprocClock{}; ///< RevCPU: Disables manual coproc clocking - TimeConverter* timeConverter; ///< RevCPU: SST time conversion handler - SST::Output output; ///< RevCPU: SST output handler + TimeConverter* timeConverter{}; ///< RevCPU: SST time conversion handler + SST::Output output{}; ///< RevCPU: SST output handler - nicAPI *Nic; ///< RevCPU: Network interface controller - RevMemCtrl *Ctrl; ///< RevCPU: Rev memory controller + nicAPI* Nic{}; ///< RevCPU: Network interface controller + std::unique_ptr Ctrl; ///< RevCPU: Rev memory controller - std::vector CoProcs; ///< RevCPU: CoProcessor attached to Rev + std::vector> CoProcs; ///< RevCPU: CoProcessor attached to Rev - SST::Clock::Handler* ClockHandler; ///< RevCPU: Clock Handler + SST::Clock::Handler* ClockHandler{}; ///< RevCPU: Clock Handler - std::queue> ZeroRqst; ///< RevCPU: tracks incoming zero address put requests; pair - std::list> TrackTags; ///< RevCPU: tracks the outgoing messages; pair - std::vector> TrackGets; ///< RevCPU: tracks the outstanding get messages; tuple - std::vector> ReadQueue; ///< RevCPU: outgoing memory read queue + std::queue> ZeroRqst{}; ///< RevCPU: tracks incoming zero address put requests; pair + std::list> TrackTags{}; ///< RevCPU: tracks the outgoing messages; pair + std::vector> + TrackGets{}; ///< RevCPU: tracks the outstanding get messages; tuple ///< - Tag ///< - Size ///< - Cost ///< - Src ///< - Addr + std::vector> ReadQueue{}; ///< RevCPU: outgoing memory read queue //------------------------------------------------------- // -- STATISTICS //------------------------------------------------------- - Statistic* SyncGetSend; - Statistic* SyncPutSend; - Statistic* AsyncGetSend; - Statistic* AsyncPutSend; - Statistic* SyncStreamGetSend; - Statistic* SyncStreamPutSend; - Statistic* AsyncStreamGetSend; - Statistic* AsyncStreamPutSend; - Statistic* ExecSend; - Statistic* StatusSend; - Statistic* CancelSend; - Statistic* ReserveSend; - Statistic* RevokeSend; - Statistic* HaltSend; - Statistic* ResumeSend; - Statistic* ReadRegSend; - Statistic* WriteRegSend; - Statistic* SingleStepSend; - Statistic* SetFutureSend; - Statistic* RevokeFutureSend; - Statistic* StatusFutureSend; - Statistic* SuccessSend; - Statistic* FailedSend; - Statistic* BOTWSend; - Statistic* SyncGetRecv; - Statistic* SyncPutRecv; - Statistic* AsyncGetRecv; - Statistic* AsyncPutRecv; - Statistic* SyncStreamGetRecv; - Statistic* SyncStreamPutRecv; - Statistic* AsyncStreamGetRecv; - Statistic* AsyncStreamPutRecv; - Statistic* ExecRecv; - Statistic* StatusRecv; - Statistic* CancelRecv; - Statistic* ReserveRecv; - Statistic* RevokeRecv; - Statistic* HaltRecv; - Statistic* ResumeRecv; - Statistic* ReadRegRecv; - Statistic* WriteRegRecv; - Statistic* SingleStepRecv; - Statistic* SetFutureRecv; - Statistic* RevokeFutureRecv; - Statistic* StatusFutureRecv; - Statistic* SuccessRecv; - Statistic* FailedRecv; - Statistic* BOTWRecv; + Statistic* SyncGetSend{}; + Statistic* SyncPutSend{}; + Statistic* AsyncGetSend{}; + Statistic* AsyncPutSend{}; + Statistic* SyncStreamGetSend{}; + Statistic* SyncStreamPutSend{}; + Statistic* AsyncStreamGetSend{}; + Statistic* AsyncStreamPutSend{}; + Statistic* ExecSend{}; + Statistic* StatusSend{}; + Statistic* CancelSend{}; + Statistic* ReserveSend{}; + Statistic* RevokeSend{}; + Statistic* HaltSend{}; + Statistic* ResumeSend{}; + Statistic* ReadRegSend{}; + Statistic* WriteRegSend{}; + Statistic* SingleStepSend{}; + Statistic* SetFutureSend{}; + Statistic* RevokeFutureSend{}; + Statistic* StatusFutureSend{}; + Statistic* SuccessSend{}; + Statistic* FailedSend{}; + Statistic* BOTWSend{}; + Statistic* SyncGetRecv{}; + Statistic* SyncPutRecv{}; + Statistic* AsyncGetRecv{}; + Statistic* AsyncPutRecv{}; + Statistic* SyncStreamGetRecv{}; + Statistic* SyncStreamPutRecv{}; + Statistic* AsyncStreamGetRecv{}; + Statistic* AsyncStreamPutRecv{}; + Statistic* ExecRecv{}; + Statistic* StatusRecv{}; + Statistic* CancelRecv{}; + Statistic* ReserveRecv{}; + Statistic* RevokeRecv{}; + Statistic* HaltRecv{}; + Statistic* ResumeRecv{}; + Statistic* ReadRegRecv{}; + Statistic* WriteRegRecv{}; + Statistic* SingleStepRecv{}; + Statistic* SetFutureRecv{}; + Statistic* RevokeFutureRecv{}; + Statistic* StatusFutureRecv{}; + Statistic* SuccessRecv{}; + Statistic* FailedRecv{}; + Statistic* BOTWRecv{}; // ----- Per Core Statistics - std::vector*> TotalCycles; - std::vector*> CyclesWithIssue; - std::vector*> FloatsRead; - std::vector*> FloatsWritten; - std::vector*> DoublesRead; - std::vector*> DoublesWritten; - std::vector*> BytesRead; - std::vector*> BytesWritten; - std::vector*> FloatsExec; - std::vector*> TLBMissesPerCore; - std::vector*> TLBHitsPerCore; + std::vector*> TotalCycles{}; + std::vector*> CyclesWithIssue{}; + std::vector*> FloatsRead{}; + std::vector*> FloatsWritten{}; + std::vector*> DoublesRead{}; + std::vector*> DoublesWritten{}; + std::vector*> BytesRead{}; + std::vector*> BytesWritten{}; + std::vector*> FloatsExec{}; + std::vector*> TLBMissesPerCore{}; + std::vector*> TLBHitsPerCore{}; //------------------------------------------------------- // -- FUNCTIONS //------------------------------------------------------- /// RevCPU: decode the fault codes - void DecodeFaultCodes(const std::vector& faults); + void DecodeFaultCodes( const std::vector& faults ); /// RevCPU:: decode the fault width - void DecodeFaultWidth(const std::string& width); + void DecodeFaultWidth( const std::string& width ); /// RevCPU: RevNIC message handler - void handleMessage(SST::Event *ev); + void handleMessage( SST::Event* ev ); /// RevCPU: Creates a unique tag for this message uint8_t createTag(); @@ -395,26 +391,26 @@ class RevCPU : public SST::Component{ void registerStatistics(); /// RevCPU: handle fault injection - void HandleFaultInjection(SST::Cycle_t currentCycle); + void HandleFaultInjection( SST::Cycle_t currentCycle ); /// RevCPU: handle crack+decode fault injection - void HandleCrackFault(SST::Cycle_t currentCycle); + void HandleCrackFault( SST::Cycle_t currentCycle ); /// RevCPU: handle memory fault - void HandleMemFault(SST::Cycle_t currentCycle); + void HandleMemFault( SST::Cycle_t currentCycle ); /// RevCPU: handle register fault - void HandleRegFault(SST::Cycle_t currentCycle); + void HandleRegFault( SST::Cycle_t currentCycle ); /// RevCPU: handle ALU fault - void HandleALUFault(SST::Cycle_t currentCycle); + void HandleALUFault( SST::Cycle_t currentCycle ); /// RevCPU: updates sst statistics on a per core basis - void UpdateCoreStatistics(unsigned coreNum); + void UpdateCoreStatistics( uint32_t coreNum ); -}; // class RevCPU +}; // class RevCPU -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevCSR.h b/include/RevCSR.h new file mode 100644 index 000000000..ae7722714 --- /dev/null +++ b/include/RevCSR.h @@ -0,0 +1,570 @@ +// +// _RevCSR_h_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// +#ifndef _SST_REVCSR_H_ +#define _SST_REVCSR_H_ + +#include "RevCommon.h" +#include "RevFCSR.h" +#include "RevFeature.h" +#include "RevZicntr.h" +#include "SST.h" +#include +#include +#include +#include +#include +#include +#include + +namespace SST::RevCPU { + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// A note about the separation of scopes in include/insns/Zicsr.h and include/RevCSR.h: +// +// RevCSR.h: GetCSR() and SetCSR() are used to get and set specific CSR registers in the register file, regardless of how we arrive +// here. If a particular CSR register is disabled because of CPU extensions present, or if a particular CSR register does not apply +// to it (such as RDTIMEH on RV64), then raise an invalid instruction or other exception here. +// +// Zicsr.h: Decode and execute one of only 6 CSR instructions (csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci). Do not enable or +// disable certain CSR registers, or implement the semantics of particular CSR registers here. All CSR instructions with a valid +// encoding are valid as far as Zicsr.h is concerned. The particular CSR register accessed in a CSR instruction is secondary to the +// scope of Zicsr.h. Certain pseudoinstructions like RDTIME or FRFLAGS are listed separately in Zicsr.h only for user-friendly +// disassembly, not for enabling, disabling or implementing them. +// +// To ease maintainability and prevent large code size, it is recommended that functions related to specific CSR registers be made +// base classes of RevCSR in separate header files (e.g. RevZicntr). RevCSR can then dispatch the GetCSR()/SetCSR() functions of +// these CSR registers to the base class. +// +// To access a RevCSR or RevRegFile member function in one of its base classes, it is recommended that the function be made a pure +// virtual function in the base class so that RevCSR or RevRegFile must override it, similar to how GetCore() is a pure virtual +// function in RevZicntr which RevRegFile overrides. RevZicntr needs GetCore(), but rather than have to store a pointer in +// RevZicntr's constructor, it is much simpler to simply declare GetCore() as a pure virtual function in RevZicntr which must be +// overriden, which makes RevZicntr and RevCSR abstract classes which cannot be instantiated except as a base class of RevRegFile, +// which defines GetCore(). +// +// To register a handler to Get or Set a CSR register, call SetCSRGetter() and SetCSRSetter(), supplying it a function. For CSR +// registers which are not Hart-local but are Core-local, call SetCSRGetter() and SetCSRSetter() in RevCore. +// +// The GetCSR() and SetCSR() functions in this class are called at the Hart execution level, and the CSR registers in this class +// are hart-specific, but the GetCSR() and SetCSR() functions can be overriden to read/write CSR resources outside of this class. +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class RevCore; + +struct RevCSR : RevZicntr { + static constexpr size_t CSR_LIMIT = 0x1000; + + RevCSR() = default; + RevCSR( const RevCSR& ) = delete; + RevCSR( RevCSR&& ) = default; + RevCSR& operator=( const RevCSR& ) = delete; + RevCSR& operator=( RevCSR&& ) = delete; + virtual ~RevCSR() = default; + + // CSR Registers + enum : uint16_t { + // Unprivileged and User-level CSRs + fflags = 0x001, + frm = 0x002, + fcsr = 0x003, + + // Vector CSR Group 1 + vstart = 0x008, + vxsat = 0x009, + vxrm = 0x00a, + vcsr = 0x00f, + + // Performance counters + cycle = 0xc00, + time = 0xc01, + instret = 0xc02, + hpmcounter3 = 0xc03, + hpmcounter4 = 0xc04, + hpmcounter5 = 0xc05, + hpmcounter6 = 0xc06, + hpmcounter7 = 0xc07, + hpmcounter8 = 0xc08, + hpmcounter9 = 0xc09, + hpmcounter10 = 0xc0a, + hpmcounter11 = 0xc0b, + hpmcounter12 = 0xc0c, + hpmcounter13 = 0xc0d, + hpmcounter14 = 0xc0e, + hpmcounter15 = 0xc0f, + hpmcounter16 = 0xc10, + hpmcounter17 = 0xc11, + hpmcounter18 = 0xc12, + hpmcounter19 = 0xc13, + hpmcounter20 = 0xc14, + hpmcounter21 = 0xc15, + hpmcounter22 = 0xc16, + hpmcounter23 = 0xc17, + hpmcounter24 = 0xc18, + hpmcounter25 = 0xc19, + hpmcounter26 = 0xc1a, + hpmcounter27 = 0xc1b, + hpmcounter28 = 0xc1c, + hpmcounter29 = 0xc1d, + hpmcounter30 = 0xc1e, + hpmcounter31 = 0xc1f, + + // Vector CSR Group 2 + vl = 0xc20, + vtype = 0xc21, + vlenb = 0xc22, + + // Performance counters high 32 bits + cycleh = 0xc80, + timeh = 0xc81, + instreth = 0xc82, + hpmcounter3h = 0xc83, + hpmcounter4h = 0xc84, + hpmcounter5h = 0xc85, + hpmcounter6h = 0xc86, + hpmcounter7h = 0xc87, + hpmcounter8h = 0xc88, + hpmcounter9h = 0xc89, + hpmcounter10h = 0xc8a, + hpmcounter11h = 0xc8b, + hpmcounter12h = 0xc8c, + hpmcounter13h = 0xc8d, + hpmcounter14h = 0xc8e, + hpmcounter15h = 0xc8f, + hpmcounter16h = 0xc90, + hpmcounter17h = 0xc91, + hpmcounter18h = 0xc92, + hpmcounter19h = 0xc93, + hpmcounter20h = 0xc94, + hpmcounter21h = 0xc95, + hpmcounter22h = 0xc96, + hpmcounter23h = 0xc97, + hpmcounter24h = 0xc98, + hpmcounter25h = 0xc99, + hpmcounter26h = 0xc9a, + hpmcounter27h = 0xc9b, + hpmcounter28h = 0xc9c, + hpmcounter29h = 0xc9d, + hpmcounter30h = 0xc9e, + hpmcounter31h = 0xc9f, + + // Supervisor-Level CSRs + sstatus = 0x100, + sie = 0x104, + stvec = 0x105, + scounteren = 0x106, + senvcfg = 0x10a, + scountinhibit = 0x120, + sscratch = 0x140, + sepc = 0x141, + scause = 0x142, + stval = 0x143, + sip = 0x144, + scountovf = 0xda0, + satp = 0x180, + scontext = 0x5a8, + sstateen0 = 0x10c, + sstateen1 = 0x10d, + sstateen2 = 0x10e, + sstateen3 = 0x10f, + + // Hypervisor and VS CSRs + hstatus = 0x600, + hedeleg = 0x602, + hideleg = 0x603, + hie = 0x604, + hcounteren = 0x606, + hgeie = 0x607, + hedelegh = 0x612, + htval = 0x643, + hip = 0x644, + hvip = 0x645, + htinst = 0x64a, + hgeip = 0xe12, + henvcfg = 0x60a, + henvcfgh = 0x61a, + hgatp = 0x680, + hcontext = 0x6a8, + htimedelta = 0x605, + htimedeltah = 0x615, + hstateen0 = 0x60c, + hstateen1 = 0x60d, + hstateen2 = 0x60e, + hstateen3 = 0x60f, + hstateen0h = 0x61c, + hstateen1h = 0x61d, + hstateen2h = 0x61e, + hstateen3h = 0x61f, + vsstatus = 0x200, + vsie = 0x204, + vstvec = 0x205, + vsscratch = 0x240, + vsepc = 0x241, + vscause = 0x242, + vstval = 0x243, + vsip = 0x244, + vsatp = 0x280, + + // Machine-Level CSRs + mvendorid = 0xf11, + marchid = 0xf12, + mimpid = 0xf13, + mhartid = 0xf14, + mconfigptr = 0xf15, + mstatus = 0x300, + misa = 0x301, + medeleg = 0x302, + mideleg = 0x303, + mie = 0x304, + mtvec = 0x305, + mcounteren = 0x306, + mstatush = 0x310, + medelegh = 0x312, + mscratch = 0x340, + mepc = 0x341, + mcause = 0x342, + mtval = 0x343, + mip = 0x344, + mtinst = 0x34a, + mtval2 = 0x34b, + menvcfg = 0x30a, + menvcfgh = 0x31a, + mseccfg = 0x747, + mseccfgh = 0x757, + pmpcfg0 = 0x3a0, + pmpcfg1 = 0x3a1, + pmpcfg2 = 0x3a2, + pmpcfg3 = 0x3a3, + pmpcfg4 = 0x3a4, + pmpcfg5 = 0x3a5, + pmpcfg6 = 0x3a6, + pmpcfg7 = 0x3a7, + pmpcfg8 = 0x3a8, + pmpcfg9 = 0x3a9, + pmpcfg10 = 0x3aa, + pmpcfg11 = 0x3ab, + pmpcfg12 = 0x3ac, + pmpcfg13 = 0x3ad, + pmpcfg14 = 0x3ae, + pmpcfg15 = 0x3af, + pmpaddr0 = 0x3b0, + pmpaddr1 = 0x3b1, + pmpaddr2 = 0x3b2, + pmpaddr3 = 0x3b3, + pmpaddr4 = 0x3b4, + pmpaddr5 = 0x3b5, + pmpaddr6 = 0x3b6, + pmpaddr7 = 0x3b7, + pmpaddr8 = 0x3b8, + pmpaddr9 = 0x3b9, + pmpaddr10 = 0x3ba, + pmpaddr11 = 0x3bb, + pmpaddr12 = 0x3bc, + pmpaddr13 = 0x3bd, + pmpaddr14 = 0x3be, + pmpaddr15 = 0x3bf, + pmpaddr16 = 0x3c0, + pmpaddr17 = 0x3c1, + pmpaddr18 = 0x3c2, + pmpaddr19 = 0x3c3, + pmpaddr20 = 0x3c4, + pmpaddr21 = 0x3c5, + pmpaddr22 = 0x3c6, + pmpaddr23 = 0x3c7, + pmpaddr24 = 0x3c8, + pmpaddr25 = 0x3c9, + pmpaddr26 = 0x3ca, + pmpaddr27 = 0x3cb, + pmpaddr28 = 0x3cc, + pmpaddr29 = 0x3cd, + pmpaddr30 = 0x3ce, + pmpaddr31 = 0x3cf, + pmpaddr32 = 0x3d0, + pmpaddr33 = 0x3d1, + pmpaddr34 = 0x3d2, + pmpaddr35 = 0x3d3, + pmpaddr36 = 0x3d4, + pmpaddr37 = 0x3d5, + pmpaddr38 = 0x3d6, + pmpaddr39 = 0x3d7, + pmpaddr40 = 0x3d8, + pmpaddr41 = 0x3d9, + pmpaddr42 = 0x3da, + pmpaddr43 = 0x3db, + pmpaddr44 = 0x3dc, + pmpaddr45 = 0x3dd, + pmpaddr46 = 0x3de, + pmpaddr47 = 0x3df, + pmpaddr48 = 0x3e0, + pmpaddr49 = 0x3e1, + pmpaddr50 = 0x3e2, + pmpaddr51 = 0x3e3, + pmpaddr52 = 0x3e4, + pmpaddr53 = 0x3e5, + pmpaddr54 = 0x3e6, + pmpaddr55 = 0x3e7, + pmpaddr56 = 0x3e8, + pmpaddr57 = 0x3e9, + pmpaddr58 = 0x3ea, + pmpaddr59 = 0x3eb, + pmpaddr60 = 0x3ec, + pmpaddr61 = 0x3ed, + pmpaddr62 = 0x3ee, + pmpaddr63 = 0x3ef, + mstateen0 = 0x30c, + mstateen1 = 0x30d, + mstateen2 = 0x30e, + mstateen3 = 0x30f, + mstateen0h = 0x31c, + mstateen1h = 0x31d, + mstateen2h = 0x31e, + mstateen3h = 0x31f, + mnscratch = 0x740, + mnepc = 0x741, + mncause = 0x742, + mnstatus = 0x744, + mcycle = 0xb00, + minstret = 0xb02, + mhpmcounter3 = 0xb03, + mhpmcounter4 = 0xb04, + mhpmcounter5 = 0xb05, + mhpmcounter6 = 0xb06, + mhpmcounter7 = 0xb07, + mhpmcounter8 = 0xb08, + mhpmcounter9 = 0xb09, + mhpmcounter10 = 0xb0a, + mhpmcounter11 = 0xb0b, + mhpmcounter12 = 0xb0c, + mhpmcounter13 = 0xb0d, + mhpmcounter14 = 0xb0e, + mhpmcounter15 = 0xb0f, + mhpmcounter16 = 0xb10, + mhpmcounter17 = 0xb11, + mhpmcounter18 = 0xb12, + mhpmcounter19 = 0xb13, + mhpmcounter20 = 0xb14, + mhpmcounter21 = 0xb15, + mhpmcounter22 = 0xb16, + mhpmcounter23 = 0xb17, + mhpmcounter24 = 0xb18, + mhpmcounter25 = 0xb19, + mhpmcounter26 = 0xb1a, + mhpmcounter27 = 0xb1b, + mhpmcounter28 = 0xb1c, + mhpmcounter29 = 0xb1d, + mhpmcounter30 = 0xb1e, + mhpmcounter31 = 0xb1f, + mcycleh = 0xb80, + minstreth = 0xb82, + mhpmcounter3h = 0xb83, + mhpmcounter4h = 0xb84, + mhpmcounter5h = 0xb85, + mhpmcounter6h = 0xb86, + mhpmcounter7h = 0xb87, + mhpmcounter8h = 0xb88, + mhpmcounter9h = 0xb89, + mhpmcounter10h = 0xb8a, + mhpmcounter11h = 0xb8b, + mhpmcounter12h = 0xb8c, + mhpmcounter13h = 0xb8d, + mhpmcounter14h = 0xb8e, + mhpmcounter15h = 0xb8f, + mhpmcounter16h = 0xb90, + mhpmcounter17h = 0xb91, + mhpmcounter18h = 0xb92, + mhpmcounter19h = 0xb93, + mhpmcounter20h = 0xb94, + mhpmcounter21h = 0xb95, + mhpmcounter22h = 0xb96, + mhpmcounter23h = 0xb97, + mhpmcounter24h = 0xb98, + mhpmcounter25h = 0xb99, + mhpmcounter26h = 0xb9a, + mhpmcounter27h = 0xb9b, + mhpmcounter28h = 0xb9c, + mhpmcounter29h = 0xb9d, + mhpmcounter30h = 0xb9e, + mhpmcounter31h = 0xb9f, + mcountinhibit = 0x320, + mhpmevent3 = 0x323, + mhpmevent4 = 0x324, + mhpmevent5 = 0x325, + mhpmevent6 = 0x326, + mhpmevent7 = 0x327, + mhpmevent8 = 0x328, + mhpmevent9 = 0x329, + mhpmevent10 = 0x32a, + mhpmevent11 = 0x32b, + mhpmevent12 = 0x32c, + mhpmevent13 = 0x32d, + mhpmevent14 = 0x32e, + mhpmevent15 = 0x32f, + mhpmevent16 = 0x330, + mhpmevent17 = 0x331, + mhpmevent18 = 0x332, + mhpmevent19 = 0x333, + mhpmevent20 = 0x334, + mhpmevent21 = 0x335, + mhpmevent22 = 0x336, + mhpmevent23 = 0x337, + mhpmevent24 = 0x338, + mhpmevent25 = 0x339, + mhpmevent26 = 0x33a, + mhpmevent27 = 0x33b, + mhpmevent28 = 0x33c, + mhpmevent29 = 0x33d, + mhpmevent30 = 0x33e, + mhpmevent31 = 0x33f, + mhpmevent3h = 0x723, + mhpmevent4h = 0x724, + mhpmevent5h = 0x725, + mhpmevent6h = 0x726, + mhpmevent7h = 0x727, + mhpmevent8h = 0x728, + mhpmevent9h = 0x729, + mhpmevent10h = 0x72a, + mhpmevent11h = 0x72b, + mhpmevent12h = 0x72c, + mhpmevent13h = 0x72d, + mhpmevent14h = 0x72e, + mhpmevent15h = 0x72f, + mhpmevent16h = 0x730, + mhpmevent17h = 0x731, + mhpmevent18h = 0x732, + mhpmevent19h = 0x733, + mhpmevent20h = 0x734, + mhpmevent21h = 0x735, + mhpmevent22h = 0x736, + mhpmevent23h = 0x737, + mhpmevent24h = 0x738, + mhpmevent25h = 0x739, + mhpmevent26h = 0x73a, + mhpmevent27h = 0x73b, + mhpmevent28h = 0x73c, + mhpmevent29h = 0x73d, + mhpmevent30h = 0x73e, + mhpmevent31h = 0x73f, + tselect = 0x7a0, + tdata1 = 0x7a1, + tdata2 = 0x7a2, + tdata3 = 0x7a3, + mcontext = 0x7a8, + dcsr = 0x7b0, + dpc = 0x7b1, + dscratch0 = 0x7b2, + dscratch1 = 0x7b3, + }; + + ///< RevCSR: Register a custom getter for a particular CSR register + void SetCSRGetter( uint32_t csr, std::function handler ) { + handler ? (void) Getter.insert_or_assign( csr, std::move( handler ) ) : (void) Getter.erase( csr ); + } + + ///< RevCSR: Register a custom setter for a particular CSR register + void SetCSRSetter( uint32_t csr, std::function handler ) { + handler ? (void) Setter.insert_or_assign( csr, std::move( handler ) ) : (void) Setter.erase( csr ); + } + + ///< RevCSR: Get the custom getter for a particular CSR register + // If no custom getter exists for this RevCSR, look for one in the owning RevCore + template + auto GetCSRGetter( uint32_t csr ) const { + auto it = Getter.find( csr ); + return it != Getter.end() && it->second ? it->second : make_dependent( GetCore() )->GetCSRGetter( csr ); + } + + ///< RevCSR: Get the custom setter for a particular CSR register + // If no custom setter exists for this RevCSR, look for one in the owning RevCore + template + auto GetCSRSetter( uint32_t csr ) { + auto it = Setter.find( csr ); + return it != Setter.end() && it->second ? it->second : make_dependent( GetCore() )->GetCSRSetter( csr ); + } + + /// Get the Floating-Point Rounding Mode + FRMode GetFRM() const { return static_cast( BitExtract<5, 3>( CSR[fcsr] ) ); } + + /// Set Floating-Point flags + void SetFFlags( FCSR flags ) { CSR[fcsr] |= static_cast( flags ) & 0b11111; } + + /// Get a CSR register + template + XLEN GetCSR( uint32_t csr ) const { + // Check for valid CSR register + if( csr >= 0x1000 ) + fatal( "Invalid CSR register at PC = 0x%" PRIx64 "\n" ); + + // If a custom Getter exists, use it + auto getter = GetCSRGetter( make_dependent( csr ) ); + if( getter ) + return static_cast( getter( csr ) ); + + // clang-format off + switch( csr ) { + // Floating Point flags + case fflags: return BitExtract<0, 5>( XLEN( CSR[fcsr] ) ); + case frm: return BitExtract<5, 3>( XLEN( CSR[fcsr] ) ); + case fcsr: return BitExtract<0, 8>( XLEN( CSR[fcsr] ) ); + + // Performance Counters + case cycle: return GetPerfCounter(); + case cycleh: return GetPerfCounter(); + case time: return GetPerfCounter(); + case timeh: return GetPerfCounter(); + case instret: return GetPerfCounter(); + case instreth: return GetPerfCounter(); + + // Default behavior is to read it as an ordinary register with no side effects + default: return static_cast( CSR.at( csr ) ); + } + // clang-format on + } + + /// Set a CSR register + template + bool SetCSR( uint32_t csr, XLEN val ) { + // Check for valid CSR register + if( csr >= 0x1000 ) + fatal( "Invalid CSR register at PC = 0x%" PRIx64 "\n" ); + + // Read-only CSRs cannot be written to + if( csr >= 0xc00 && csr < 0xe00 ) + return false; + + // If a custom setter exists, use it + auto setter = GetCSRSetter( make_dependent( csr ) ); + if( setter ) + return setter( csr, val ); + + // clang-format off + switch( csr ) { + // Floating Point flags + case fflags: BitDeposit<0, 5>(CSR[fcsr], val); break; + case frm: BitDeposit<5, 3>(CSR[fcsr], val); break; + case fcsr: BitDeposit<0, 8>(CSR[fcsr], val); break; + + // Default behavior is to write to it as an ordinary register + default: CSR.at( csr ) = val; + } + // clang-format on + return true; + } + +private: + std::array CSR{}; ///< RegCSR: CSR registers + std::unordered_map> Getter{}; ///< RevCSR: CSR Getters + std::unordered_map> Setter{}; ///< RevCSR: CSR Setters + +}; // class RevCSR + +} // namespace SST::RevCPU + +#endif diff --git a/include/RevCoProc.h b/include/RevCoProc.h index 009cac965..92382a6cd 100644 --- a/include/RevCoProc.h +++ b/include/RevCoProc.h @@ -12,61 +12,62 @@ #define _SST_REVCPU_REVCOPROC_H_ // -- C++ Headers +#include #include -#include #include -#include +#include +#include #include #include #include -#include -#include #include +#include // -- SST Headers #include "SST.h" // -- RevCPU Headers -#include "RevOpts.h" +#include "RevCore.h" +#include "RevCorePasskey.h" #include "RevFeature.h" -#include "RevMem.h" #include "RevInstTable.h" -#include "RevProcPasskey.h" -#include "RevProc.h" +#include "RevMem.h" +#include "RevOpts.h" + +namespace SST::RevCPU { +class RevCore; -namespace SST::RevCPU{ -class RevProc; // ---------------------------------------- // RevCoProc // ---------------------------------------- class RevCoProc : public SST::SubComponent { public: - SST_ELI_REGISTER_SUBCOMPONENT_API(SST::RevCPU::RevCoProc, RevProc*); - SST_ELI_DOCUMENT_PARAMS({ "verbose", "Set the verbosity of output for the attached co-processor", "0" }); + SST_ELI_REGISTER_SUBCOMPONENT_API( SST::RevCPU::RevCoProc, RevCore* ); + SST_ELI_DOCUMENT_PARAMS( { "verbose", "Set the verbosity of output for the attached co-processor", "0" } ); // -------------------- // Virtual methods // -------------------- /// RevCoProc: Constructor - RevCoProc( ComponentId_t id, Params& params, RevProc* parent); + RevCoProc( ComponentId_t id, Params& params, RevCore* parent ); /// RevCoProc: default destructor virtual ~RevCoProc(); + /// RevCoProc: disallow copying and assignment + RevCoProc( const RevCoProc& ) = delete; + RevCoProc& operator=( const RevCoProc& ) = delete; + /// RevCoProc: send raw data to the coprocessor - virtual bool sendRawData(std::vector Data){ - return true; - } + virtual bool sendRawData( std::vector Data ) { return true; } /// RevCoProc: retrieve raw data from the coprocessor - virtual const std::vector getRawData(){ - output->fatal(CALL_INFO, -1, - "Error : no override method defined for getRawData()\n"); + virtual std::vector getRawData() { + output->fatal( CALL_INFO, -1, "Error : no override method defined for getRawData()\n" ); // inserting code to quiesce warnings - std::vector D; - return D; + return {}; } // -------------------- @@ -74,46 +75,48 @@ class RevCoProc : public SST::SubComponent { // -------------------- /// RevCoProc: Instruction interface to RevCore - virtual bool IssueInst(RevFeature *F, RevRegFile *R, RevMem *M, uint32_t Inst) = 0; + virtual bool IssueInst( const RevFeature* F, RevRegFile* R, RevMem* M, uint32_t Inst ) = 0; /// ReCoProc: Reset - called on startup - virtual bool Reset() = 0; + virtual bool Reset() = 0; - /// RevCoProc: Teardown - called when associated RevProc completes - virtual bool Teardown() = 0; + /// RevCoProc: Teardown - called when associated RevCore completes + virtual bool Teardown() = 0; /// RevCoProc: Clock - can be called by SST or by overriding RevCPU - virtual bool ClockTick(SST::Cycle_t cycle) = 0; + virtual bool ClockTick( SST::Cycle_t cycle ) = 0; /// RevCoProc: Returns true when co-processor has completed execution - /// - used for proper exiting of associated RevProc - virtual bool IsDone() = 0; - + /// - used for proper exiting of associated RevCore + virtual bool IsDone() = 0; protected: - SST::Output* output; ///< RevCoProc: sst output object - RevProc* const parent; ///< RevCoProc: Pointer to RevProc this CoProc is attached to + SST::Output* output{}; ///< RevCoProc: sst output object + RevCore* const parent; ///< RevCoProc: Pointer to RevCore this CoProc is attached to - ///< RevCoProc: Create the passkey object - this allows access to otherwise private members within RevProc - RevProcPasskey CreatePasskey(){return RevProcPasskey();} -}; // class RevCoProc + ///< RevCoProc: Create the passkey object - this allows access to otherwise private members within RevCore + RevCorePasskey CreatePasskey() { return RevCorePasskey(); } +}; // class RevCoProc // ---------------------------------------- // RevSimpleCoProc // ---------------------------------------- -class RevSimpleCoProc : public RevCoProc{ +class RevSimpleCoProc final : public RevCoProc { public: - SST_ELI_REGISTER_SUBCOMPONENT(RevSimpleCoProc, "revcpu", - "RevSimpleCoProc", - SST_ELI_ELEMENT_VERSION(1, 0, 0), - "RISC-V Rev Simple Co-Processor", - SST::RevCPU::RevCoProc - ); + SST_ELI_REGISTER_SUBCOMPONENT( + RevSimpleCoProc, + "revcpu", + "RevSimpleCoProc", + SST_ELI_ELEMENT_VERSION( 1, 0, 0 ), + "RISC-V Rev Simple Co-Processor", + SST::RevCPU::RevCoProc + ); // Set up parameters accesible from the python configuration - SST_ELI_DOCUMENT_PARAMS({ "verbose", "Set the verbosity of output for the co-processor", "0" }, - { "clock", "Sets the clock frequency of the co-processor", "1Ghz" }, - ); + SST_ELI_DOCUMENT_PARAMS( + { "verbose", "Set the verbosity of output for the co-processor", "0" }, + { "clock", "Sets the clock frequency of the co-processor", "1Ghz" }, + ); // Register any subcomponents used by this element SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS(); @@ -122,63 +125,64 @@ class RevSimpleCoProc : public RevCoProc{ SST_ELI_DOCUMENT_PORTS(); // Add statistics - SST_ELI_DOCUMENT_STATISTICS( - {"InstRetired", "Counts the total number of instructions retired by this coprocessor", "count", 1} - ); + SST_ELI_DOCUMENT_STATISTICS( { "InstRetired", "Counts the total number of instructions retired by this coprocessor", "count", 1 } + ); // Enum for referencing statistics - enum CoProcStats{ + enum class CoProcStats { InstRetired = 0, }; /// RevSimpleCoProc: constructor - RevSimpleCoProc(ComponentId_t id, Params& params, RevProc* parent); + RevSimpleCoProc( ComponentId_t id, Params& params, RevCore* parent ); /// RevSimpleCoProc: destructor - virtual ~RevSimpleCoProc(); + ~RevSimpleCoProc() final = default; - /// RevSimpleCoProc: clock tick function - currently not registeres with SST, called by RevCPU - virtual bool ClockTick(SST::Cycle_t cycle); + /// RevSimpleCoProc: disallow copying and assignment + RevSimpleCoProc( const RevSimpleCoProc& ) = delete; + RevSimpleCoProc& operator=( const RevSimpleCoProc& ) = delete; + + /// RevSimpleCoProc: clock tick function - currently not registered with SST, called by RevCPU + bool ClockTick( SST::Cycle_t cycle ) final; void registerStats(); /// RevSimpleCoProc: Enqueue Inst into the InstQ and return - virtual bool IssueInst(RevFeature *F, RevRegFile *R, RevMem *M, uint32_t Inst); + bool IssueInst( const RevFeature* F, RevRegFile* R, RevMem* M, uint32_t Inst ) final; /// RevSimpleCoProc: Reset the co-processor by emmptying the InstQ - virtual bool Reset(); + bool Reset() final; - /// RevSimpleCoProv: Called when the attached RevProc completes simulation. Could be used to + /// RevSimpleCoProc: Called when the attached RevCore completes simulation. Could be used to /// also signal to SST that the co-processor is done if ClockTick is registered /// to SSTCore vs. being driven by RevCPU - virtual bool Teardown() { return Reset(); }; + bool Teardown() final { return Reset(); }; /// RevSimpleCoProc: Returns true if instruction queue is empty - virtual bool IsDone(){ return InstQ.empty();} + bool IsDone() final { return InstQ.empty(); } private: struct RevCoProcInst { - RevCoProcInst() = default; - RevCoProcInst(uint32_t inst, RevFeature* F, RevRegFile* R, RevMem* M) : - Inst(inst), Feature(F), RegFile(R), Mem(M) {} - RevCoProcInst(const RevCoProcInst& rhs) = default; - - uint32_t Inst = 0; - RevFeature* Feature = nullptr; - RevRegFile* RegFile = nullptr; - RevMem* Mem = nullptr; + RevCoProcInst( uint32_t inst, const RevFeature* F, RevRegFile* R, RevMem* M ) + : Inst( inst ), Feature( F ), RegFile( R ), Mem( M ) {} + + uint32_t const Inst; + const RevFeature* const Feature; + RevRegFile* const RegFile; + RevMem* const Mem; }; /// RevSimpleCoProc: Total number of instructions retired - Statistic* num_instRetired; + Statistic* num_instRetired{}; - /// Queue of instructions sent from attached RevProc - std::queue InstQ; + /// Queue of instructions sent from attached RevCore + std::queue InstQ{}; - SST::Cycle_t cycleCount; + SST::Cycle_t cycleCount{}; -}; //class RevSimpleCoProc +}; //class RevSimpleCoProc -} //namespace SST::RevCPU +} //namespace SST::RevCPU #endif diff --git a/include/RevCore.h b/include/RevCore.h new file mode 100644 index 000000000..5f394a07c --- /dev/null +++ b/include/RevCore.h @@ -0,0 +1,905 @@ +// +// _RevCore_h_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVCPU_REVPROC_H_ +#define _SST_REVCPU_REVPROC_H_ + +// -- SST Headers +#include "SST.h" + +// -- Standard Headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -- RevCPU Headers +#include "RevCoProc.h" +#include "RevCorePasskey.h" +#include "RevFeature.h" +#include "RevHart.h" +#include "RevInstTable.h" +#include "RevLoader.h" +#include "RevMem.h" +#include "RevOpts.h" +#include "RevPrefetcher.h" +#include "RevRand.h" +#include "RevThread.h" +#include "RevTracer.h" +#define SYSCALL_TYPES_ONLY +#include "../common/syscalls/syscalls.h" +#include "RevCommon.h" + +#include "AllRevInstTables.h" + +namespace SST::RevCPU { +class RevCoProc; + +class RevCore { +public: + /// RevCore: standard constructor + RevCore( + uint32_t id, + RevOpts* opts, + uint32_t numHarts, + RevMem* mem, + RevLoader* loader, + std::function GetNewThreadID, + SST::Output* output + ); + + /// RevCore: standard destructor + ~RevCore() = default; + + /// RevCore: disallow copying and assignment + RevCore( const RevCore& ) = delete; + RevCore& operator=( const RevCore& ) = delete; + + /// RevCore: per-processor clock function + bool ClockTick( SST::Cycle_t currentCycle ); + + /// RevCore: Called by RevCPU when there is no more work to do (ie. All RevThreads are ThreadState::DONE ) + void PrintStatSummary(); + + /// RevCore: halt the CPU + bool Halt(); + + /// RevCore: resume the CPU + bool Resume(); + + /// RevCore: execute a single step + bool SingleStepHart(); + + /// RevCore: retrieve the local PC for the correct feature set + uint64_t GetPC() const { return RegFile->GetPC(); } + + /// RevCore: set time converter for RTC + void SetTimeConverter( TimeConverter* tc ) { timeConverter = tc; } + + /// RevCore: Debug mode read a register + bool DebugReadReg( uint32_t Idx, uint64_t* Value ) const; + + /// RevCore: Debug mode write a register + bool DebugWriteReg( uint32_t Idx, uint64_t Value ) const; + + /// RevCore: Set an optional tracer + void SetTracer( RevTracer* T ) { Tracer = T; } + + /// RevCore: Retrieve a random memory cost value + uint32_t RandCost() { return mem->RandCost( feature->GetMinCost(), feature->GetMaxCost() ); } + + /// RevCore: Handle register faults + void HandleRegFault( uint32_t width ); + + /// RevCore: Handle crack+decode faults + void HandleCrackFault( uint32_t width ); + + /// RevCore: Handle ALU faults + void HandleALUFault( uint32_t width ); + + /// RevCore: Handle ALU faults + void InjectALUFault( std::pair EToE, RevInst& Inst ); + + struct RevCoreStats { + uint64_t totalCycles; + uint64_t cyclesBusy; + uint64_t cyclesIdle_Total; + uint64_t cyclesStalled; + uint64_t floatsExec; + uint64_t cyclesIdle_Pipeline; + uint64_t cyclesIdle_MemoryFetch; + uint64_t retired; + }; + + auto GetAndClearStats() { + // Add each field from Stats into StatsTotal + for( auto stat : + { &RevCoreStats::totalCycles, + &RevCoreStats::cyclesBusy, + &RevCoreStats::cyclesIdle_Total, + &RevCoreStats::cyclesStalled, + &RevCoreStats::floatsExec, + &RevCoreStats::cyclesIdle_Pipeline, + &RevCoreStats::retired } ) { + StatsTotal.*stat += Stats.*stat; + } + + auto memStats = mem->GetAndClearStats(); + auto ret = std::make_pair( Stats, memStats ); + Stats = {}; // Zero out Stats + return ret; + } + + RevMem& GetMem() const { return *mem; } + + uint64_t GetCurrentSimCycle() const { return currentSimCycle; } + + ///< RevCore: Called by RevCPU to handle the state changes threads may have happened during this Core's ClockTick + auto TransferThreadsThatChangedState() { return std::move( ThreadsThatChangedState ); } + + ///< RevCore: Add + void AddThreadsThatChangedState( std::unique_ptr&& thread ) { + ThreadsThatChangedState.push_back( std::move( thread ) ); + } + + ///< RevCore: SpawnThread creates a new thread and returns its ThreadID + void CreateThread( uint32_t NewTid, uint64_t fn, void* arg ); + + ///< RevCore: Returns the current HartToExecID active pid + uint32_t GetActiveThreadID() { return Harts.at( HartToDecodeID )->GetAssignedThreadID(); } + + ///< RevCore: Get this Core's feature + const RevFeature* GetRevFeature() const { return feature; } + + ///< RevCore: Mark a current request as complete + void MarkLoadComplete( const MemReq& req ); + + ///< RevCore: Get pointer to Load / Store queue used to track memory operations + std::shared_ptr> GetLSQueue() const { return LSQueue; } + + ///< RevCore: Add a co-processor to the RevCore + void SetCoProc( RevCoProc* coproc ); + + /// GetHartToExecID: Retrieve the current executing Hart + uint32_t GetHartToExecID() const { return HartToExecID; } + + /// SetHartToExecID: Set the current executing Hart + void SetHartToExecID( uint32_t hart ) { HartToExecID = hart; } + + //--------------- External Interface for use with Co-Processor ------------------------- + ///< RevCore: Allow a co-processor to query the bits in scoreboard. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this function may not be called from even within + /// RevCore + [[deprecated( "RevRegClass regClass is used instead of bool isFloat" )]] bool + ExternalDepCheck( RevCorePasskey, uint16_t HartID, uint16_t reg, bool IsFloat ) { + RevRegClass regClass = IsFloat ? RevRegClass::RegFLOAT : RevRegClass::RegGPR; + const RevRegFile* regFile = GetRegFile( HartID ); + return LSQCheck( HartID, regFile, reg, regClass ) || ScoreboardCheck( regFile, reg, regClass ); + } + + ///< RevCore: Allow a co-processor to manipulate the scoreboard by setting a bit. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + [[deprecated( "RevRegClass regClass is used instead of bool isFloat" )]] void + ExternalDepSet( RevCorePasskey, uint16_t HartID, uint16_t RegNum, bool isFloat, bool value = true ) { + RevRegClass regClass = isFloat ? RevRegClass::RegFLOAT : RevRegClass::RegGPR; + DependencySet( HartID, RegNum, regClass, value ); + } + + ///< RevCore: Allow a co-processor to manipulate the scoreboard by clearing a bit. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + [[deprecated( "RevRegClass regClass is used instead of bool isFloat" )]] void + ExternalDepClear( RevCorePasskey, uint16_t HartID, uint16_t RegNum, bool isFloat ) { + RevRegClass regClass = isFloat ? RevRegClass::RegFLOAT : RevRegClass::RegGPR; + DependencyClear( HartID, RegNum, regClass ); + } + + //--------------- External Interface for use with Co-Processor ------------------------- + ///< RevCore: Allow a co-processor to query the bits in scoreboard. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this function may not be called from even within + /// RevCore + bool ExternalDepCheck( RevCorePasskey, uint16_t HartID, uint16_t reg, RevRegClass regClass ) { + const RevRegFile* regFile = GetRegFile( HartID ); + return LSQCheck( HartID, regFile, reg, regClass ) || ScoreboardCheck( regFile, reg, regClass ); + } + + ///< RevCore: Allow a co-processor to manipulate the scoreboard by setting a bit. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + void ExternalDepSet( RevCorePasskey, uint16_t HartID, uint16_t RegNum, RevRegClass regClass, bool value = true ) { + DependencySet( HartID, RegNum, regClass, value ); + } + + ///< RevCore: Allow a co-processor to manipulate the scoreboard by clearing a bit. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + void ExternalDepClear( RevCorePasskey, uint16_t HartID, uint16_t RegNum, RevRegClass regClass ) { + DependencyClear( HartID, RegNum, regClass ); + } + + ///< RevCore: Allow a co-processor to stall the pipeline of this proc and hold it in a stall condition + /// unitl ExternalReleaseHart() is called. Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + void ExternalStallHart( RevCorePasskey, uint16_t HartID ); + + ///< RevCore: Allow a co-processor to release the pipeline of this proc and allow a hart to continue + /// execution (this un-does the ExternalStallHart() function ). Note the RevCorePassKey may only + /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within + /// RevCore + void ExternalReleaseHart( RevCorePasskey, uint16_t HartID ); + //------------- END External Interface ------------------------------- + + ///< RevCore: Used for loading a software thread into a RevHart + void AssignThread( std::unique_ptr ThreadToAssign ); + + ///< RevCore: + void UpdateStatusOfHarts(); + + ///< RevCore: Returns the id of an idle hart (or _INVALID_HART_ID_ if none are idle) + uint32_t FindIdleHartID() const; + + ///< RevCore: Returns true if all harts are available (ie. There is nothing executing on this Core) + bool HasNoBusyHarts() const { return IdleHarts == ValidHarts; } + + ///< RevCore: Used by RevCPU to determine if it can disable this proc + /// based on the criteria there are no threads assigned to it and the + /// CoProc is done + bool HasNoWork() const; + + ///< RevCore: Returns true if there are any IdleHarts + bool HasIdleHart() const { return IdleHarts.any(); } + + ///< RevCore: Returns the number of cycles executed so far + uint64_t GetCycles() const { return cycles; } + + ///< RevCore: Register a custom getter for a particular CSR register + void SetCSRGetter( uint32_t csr, std::function handler ) { + handler ? (void) Getter.insert_or_assign( csr, std::move( handler ) ) : (void) Getter.erase( csr ); + } + + ///< RevCore: Register a custom setter for a particular CSR register + void SetCSRSetter( uint32_t csr, std::function handler ) { + handler ? (void) Setter.insert_or_assign( csr, std::move( handler ) ) : (void) Setter.erase( csr ); + } + + ///< RevCore: Get the custom getter for a particular CSR register + auto GetCSRGetter( uint32_t csr ) const { + auto it = Getter.find( csr ); + return it != Getter.end() ? it->second : std::function{}; + } + + ///< RevCore: Get the custom setter for a particular CSR register + auto GetCSRSetter( uint32_t csr ) const { + auto it = Setter.find( csr ); + return it != Setter.end() ? it->second : std::function{}; + } + +private: + std::unordered_map> Getter{}; + std::unordered_map> Setter{}; + + bool Halted = false; ///< RevCore: determines if the core is halted + bool Stalled = false; ///< RevCore: determines if the core is stalled on instruction fetch + bool SingleStep = false; ///< RevCore: determines if we are in a single step + bool CrackFault = false; ///< RevCore: determines if we need to handle a crack fault + bool ALUFault = false; ///< RevCore: determines if we need to handle an ALU fault + uint32_t fault_width = 0; ///< RevCore: the width of the target fault + uint32_t const id; ///< RevCore: processor id + uint64_t ExecPC = 0; ///< RevCore: executing PC + uint32_t HartToDecodeID = 0; ///< RevCore: Current executing ThreadID + uint32_t HartToExecID = 0; ///< RevCore: Thread to dispatch instruction + uint64_t currentSimCycle = 0; ///< RevCore: Current simulation cycle + + std::vector> Harts{}; ///< RevCore: vector of Harts without a thread assigned to them + std::bitset<_MAX_HARTS_> IdleHarts{}; ///< RevCore: bitset of Harts with no thread assigned + std::bitset<_MAX_HARTS_> ValidHarts{}; ///< RevCore: Bits 0 -> numHarts are 1 + std::bitset<_MAX_HARTS_> HartsClearToDecode{}; ///< RevCore: Thread is clear to start (proceed with decode) + std::bitset<_MAX_HARTS_> HartsClearToExecute{}; ///< RevCore: Thread is clear to execute (no register dependencides) + + uint32_t numHarts{}; ///< RevCore: Number of Harts for this core + RevOpts* opts{}; ///< RevCore: options object + RevMem* mem{}; ///< RevCore: memory object + RevCoProc* coProc{}; ///< RevCore: attached co-processor + RevLoader* loader{}; ///< RevCore: loader object + + // Function pointer to the GetNewThreadID function in RevCPU (monotonically increasing thread ID counter) + std::function const GetNewThreadID; + + // If a given assigned thread experiences a change of state, it sets the corresponding bit + std::vector> + ThreadsThatChangedState{}; ///< RevCore: used to signal to RevCPU that the thread assigned to HART has changed state + +public: + SST::Output* const output; ///< RevCore: output handler + +private: + std::unique_ptr CreateFeature(); ///< RevCore: Create a RevFeature object + std::unique_ptr const featureUP = CreateFeature(); ///< RevCore: feature handler + RevFeature* const feature = featureUP.get(); ///< RevCore: raw feature pointer + RevCoreStats Stats{}; ///< RevCore: collection of performance stats + RevCoreStats StatsTotal{}; ///< RevCore: collection of total performance stats + std::unique_ptr sfetch{}; ///< RevCore: stream instruction prefetcher + + std::shared_ptr> + LSQueue{}; ///< RevCore: Load / Store queue used to track memory operations. Currently only tracks outstanding loads. + TimeConverter* timeConverter{}; ///< RevCore: Time converter for RTC + + RevRegFile* RegFile = nullptr; ///< RevCore: Initial pointer to HartToDecodeID RegFile + uint32_t ActiveThreadID = _INVALID_TID_; ///< Software ThreadID (Not the Hart) that belongs to the Hart currently decoding + RevTracer* Tracer = nullptr; ///< RevCore: Tracer object + + std::bitset<_MAX_HARTS_> CoProcStallReq{}; + + uint64_t cycles{}; ///< RevCore: The number of cycles executed + + ///< RevCore: Utility function for system calls that involve reading a string from memory + EcallStatus EcallLoadAndParseString( uint64_t straddr, std::function ); + + // - Many of these are not implemented + // - Their existence in the ECalls table is solely to not throw errors + // - This _should_ be a comprehensive list of system calls supported on RISC-V + // - Beside each function declaration is the system call code followed by its corresponding declaration + // that you can find in `common/syscalls.h` (the file to be included to use system calls inside of rev) + // + // clang-format off + EcallStatus ECALL_io_setup(); // 0, rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) + EcallStatus ECALL_io_destroy(); // 1, rev_io_destroy(aio_context_t ctx) + EcallStatus ECALL_io_submit(); // 2, rev_io_submit(aio_context_t, long, struct iocb * *) + EcallStatus ECALL_io_cancel(); // 3, rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) + EcallStatus ECALL_io_getevents(); // 4, rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) + EcallStatus ECALL_setxattr(); // 5, rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) + EcallStatus ECALL_lsetxattr(); // 6, rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) + EcallStatus ECALL_fsetxattr(); // 7, rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) + EcallStatus ECALL_getxattr(); // 8, rev_getxattr(const char *path, const char *name, void *value, size_t size) + EcallStatus ECALL_lgetxattr(); // 9, rev_lgetxattr(const char *path, const char *name, void *value, size_t size) + EcallStatus ECALL_fgetxattr(); // 10, rev_fgetxattr(int fd, const char *name, void *value, size_t size) + EcallStatus ECALL_listxattr(); // 11, rev_listxattr(const char *path, char *list, size_t size) + EcallStatus ECALL_llistxattr(); // 12, rev_llistxattr(const char *path, char *list, size_t size) + EcallStatus ECALL_flistxattr(); // 13, rev_flistxattr(int fd, char *list, size_t size) + EcallStatus ECALL_removexattr(); // 14, rev_removexattr(const char *path, const char *name) + EcallStatus ECALL_lremovexattr(); // 15, rev_lremovexattr(const char *path, const char *name) + EcallStatus ECALL_fremovexattr(); // 16, rev_fremovexattr(int fd, const char *name) + EcallStatus ECALL_getcwd(); // 17, rev_getcwd(char *buf, unsigned long size) + EcallStatus ECALL_lookup_dcookie(); // 18, rev_lookup_dcookie(u64 cookie64, char *buf, size_t len) + EcallStatus ECALL_eventfd2(); // 19, rev_eventfd2(unsigned int count, int flags) + EcallStatus ECALL_epoll_create1(); // 20, rev_epoll_create1(int flags) + EcallStatus ECALL_epoll_ctl(); // 21, rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) + EcallStatus ECALL_epoll_pwait(); // 22, rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) + EcallStatus ECALL_dup(); // 23, rev_dup(unsigned int fildes) + EcallStatus ECALL_dup3(); // 24, rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) + EcallStatus ECALL_fcntl64(); // 25, rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) + EcallStatus ECALL_inotify_init1(); // 26, rev_inotify_init1(int flags) + EcallStatus ECALL_inotify_add_watch(); // 27, rev_inotify_add_watch(int fd, const char *path, u32 mask) + EcallStatus ECALL_inotify_rm_watch(); // 28, rev_inotify_rm_watch(int fd, __s32 wd) + EcallStatus ECALL_ioctl(); // 29, rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + EcallStatus ECALL_ioprio_set(); // 30, rev_ioprio_set(int which, int who, int ioprio) + EcallStatus ECALL_ioprio_get(); // 31, rev_ioprio_get(int which, int who) + EcallStatus ECALL_flock(); // 32, rev_flock(unsigned int fd, unsigned int cmd) + EcallStatus ECALL_mknodat(); // 33, rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) + EcallStatus ECALL_mkdirat(); // 34, rev_mkdirat(int dfd, const char * pathname, umode_t mode) + EcallStatus ECALL_unlinkat(); // 35, rev_unlinkat(int dfd, const char * pathname, int flag) + EcallStatus ECALL_symlinkat(); // 36, rev_symlinkat(const char * oldname, int newdfd, const char * newname) + EcallStatus ECALL_linkat(); // 37, rev_linkat(int dfd, const char * pathname, int flag) + EcallStatus ECALL_renameat(); // 38, rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) + EcallStatus ECALL_umount(); // 39, rev_umount(char *name, int flags) + EcallStatus ECALL_mount(); // 40, rev_mount(char *name, int flags) + EcallStatus ECALL_pivot_root(); // 41, rev_pivot_root(const char *new_root, const char *put_old) + EcallStatus ECALL_ni_syscall(); // 42, rev_ni_syscall(void) + EcallStatus ECALL_statfs64(); // 43, rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) + EcallStatus ECALL_fstatfs64(); // 44, rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf) + EcallStatus ECALL_truncate64(); // 45, rev_truncate64(const char *path, loff_t length) + EcallStatus ECALL_ftruncate64(); // 46, rev_ftruncate64(unsigned int fd, loff_t length) + EcallStatus ECALL_fallocate(); // 47, rev_fallocate(int fd, int mode, loff_t offset, loff_t len) + EcallStatus ECALL_faccessat(); // 48, rev_faccessat(int dfd, const char *filename, int mode) + EcallStatus ECALL_chdir(); // 49, rev_chdir(const char *filename) + EcallStatus ECALL_fchdir(); // 50, rev_fchdir(unsigned int fd) + EcallStatus ECALL_chroot(); // 51, rev_chroot(const char *filename) + EcallStatus ECALL_fchmod(); // 52, rev_fchmod(unsigned int fd, umode_t mode) + EcallStatus ECALL_fchmodat(); // 53, rev_fchmodat(int dfd, const char * filename, umode_t mode) + EcallStatus ECALL_fchownat(); // 54, rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) + EcallStatus ECALL_fchown(); // 55, rev_fchown(unsigned int fd, uid_t user, gid_t group) + EcallStatus ECALL_openat(); // 56, rev_openat(int dfd, const char *filename, int flags, umode_t mode) + EcallStatus ECALL_close(); // 57, rev_close(unsigned int fd) + EcallStatus ECALL_vhangup(); // 58, rev_vhangup(void) + EcallStatus ECALL_pipe2(); // 59, rev_pipe2(int *fildes, int flags) + EcallStatus ECALL_quotactl(); // 60, rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) + EcallStatus ECALL_getdents64(); // 61, rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) + EcallStatus ECALL_lseek(); // 62, rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) + EcallStatus ECALL_read(); // 63, rev_read(unsigned int fd, char *buf, size_t count) + EcallStatus ECALL_write(); // 64, rev_write(unsigned int fd, const char *buf, size_t count) + EcallStatus ECALL_readv(); // 65, rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) + EcallStatus ECALL_writev(); // 66, rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) + EcallStatus ECALL_pread64(); // 67, rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) + EcallStatus ECALL_pwrite64(); // 68, rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) + EcallStatus ECALL_preadv(); // 69, rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) + EcallStatus ECALL_pwritev(); // 70, rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) + EcallStatus ECALL_sendfile64(); // 71, rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) + EcallStatus ECALL_pselect6_time32(); // 72, rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *) + EcallStatus ECALL_ppoll_time32(); // 73, rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t) + EcallStatus ECALL_signalfd4(); // 74, rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) + EcallStatus ECALL_vmsplice(); // 75, rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) + EcallStatus ECALL_splice(); // 76, rev_splice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) + EcallStatus ECALL_tee(); // 77, rev_tee(int fdin, int fdout, size_t len, unsigned int flags) + EcallStatus ECALL_readlinkat(); // 78, rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) + EcallStatus ECALL_newfstatat(); // 79, rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) + EcallStatus ECALL_newfstat(); // 80, rev_newfstat(unsigned int fd, struct stat *statbuf) + EcallStatus ECALL_sync(); // 81, rev_sync(void) + EcallStatus ECALL_fsync(); // 82, rev_fsync(unsigned int fd) + EcallStatus ECALL_fdatasync(); // 83, rev_fdatasync(unsigned int fd) + EcallStatus ECALL_sync_file_range2(); // 84, rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) + EcallStatus ECALL_sync_file_range(); // 84, rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) + EcallStatus ECALL_timerfd_create(); // 85, rev_timerfd_create(int clockid, int flags) + EcallStatus ECALL_timerfd_settime(); // 86, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) + EcallStatus ECALL_timerfd_gettime(); // 87, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) + EcallStatus ECALL_utimensat(); // 88, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) + EcallStatus ECALL_acct(); // 89, rev_acct(const char *name) + EcallStatus ECALL_capget(); // 90, rev_capget(cap_user_header_t header, cap_user_data_t dataptr) + EcallStatus ECALL_capset(); // 91, rev_capset(cap_user_header_t header, const cap_user_data_t data) + EcallStatus ECALL_personality(); // 92, rev_personality(unsigned int personality) + [[noreturn]] EcallStatus ECALL_exit(); // 93, rev_exit(int error_code) + EcallStatus ECALL_exit_group(); // 94, rev_exit_group(int error_code) + EcallStatus ECALL_waitid(); // 95, rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) + EcallStatus ECALL_set_tid_address(); // 96, rev_set_tid_address(int *tidptr) + EcallStatus ECALL_unshare(); // 97, rev_unshare(unsigned long unshare_flags) + EcallStatus ECALL_futex(); // 98, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) + EcallStatus ECALL_set_robust_list(); // 99, rev_set_robust_list(struct robust_list_head *head, size_t len) + EcallStatus ECALL_get_robust_list(); // 100, rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) + EcallStatus ECALL_nanosleep(); // 101, rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + EcallStatus ECALL_getitimer(); // 102, rev_getitimer(int which, struct __kernel_old_itimerval *value) + EcallStatus ECALL_setitimer(); // 103, rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) + EcallStatus ECALL_kexec_load(); // 104, rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) + EcallStatus ECALL_init_module(); // 105, rev_init_module(void *umod, unsigned long len, const char *uargs) + EcallStatus ECALL_delete_module(); // 106, rev_delete_module(const char *name_user, unsigned int flags) + EcallStatus ECALL_timer_create(); // 107, rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) + EcallStatus ECALL_timer_gettime(); // 108, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) + EcallStatus ECALL_timer_getoverrun(); // 109, rev_timer_getoverrun(timer_t timer_id) + EcallStatus ECALL_timer_settime(); // 110, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) + EcallStatus ECALL_timer_delete(); // 111, rev_timer_delete(timer_t timer_id) + EcallStatus ECALL_clock_settime(); // 112, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) + EcallStatus ECALL_clock_gettime(); // 113, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) + EcallStatus ECALL_clock_getres(); // 114, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) + EcallStatus ECALL_clock_nanosleep(); // 115, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + EcallStatus ECALL_syslog(); // 116, rev_syslog(int type, char *buf, int len) + EcallStatus ECALL_ptrace(); // 117, rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) + EcallStatus ECALL_sched_setparam(); // 118, rev_sched_setparam(pid_t pid, struct sched_param *param) + EcallStatus ECALL_sched_setscheduler(); // 119, rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) + EcallStatus ECALL_sched_getscheduler(); // 120, rev_sched_getscheduler(pid_t pid) + EcallStatus ECALL_sched_getparam(); // 121, rev_sched_getparam(pid_t pid, struct sched_param *param) + EcallStatus ECALL_sched_setaffinity(); // 122, rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) + EcallStatus ECALL_sched_getaffinity(); // 123, rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) + EcallStatus ECALL_sched_yield(); // 124, rev_sched_yield(void) + EcallStatus ECALL_sched_get_priority_max(); // 125, rev_sched_get_priority_max(int policy) + EcallStatus ECALL_sched_get_priority_min(); // 126, rev_sched_get_priority_min(int policy) + EcallStatus ECALL_sched_rr_get_interval(); // 127, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) + EcallStatus ECALL_restart_syscall(); // 128, rev_restart_syscall(void) + EcallStatus ECALL_kill(); // 129, rev_kill(pid_t pid, int sig) + EcallStatus ECALL_tkill(); // 130, rev_tkill(pid_t pid, int sig) + EcallStatus ECALL_tgkill(); // 131, rev_tgkill(pid_t tgid, pid_t pid, int sig) + EcallStatus ECALL_sigaltstack(); // 132, rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) + EcallStatus ECALL_rt_sigsuspend(); // 133, rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) + EcallStatus ECALL_rt_sigaction(); // 134, rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) + EcallStatus ECALL_rt_sigprocmask(); // 135, rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) + EcallStatus ECALL_rt_sigpending(); // 136, rev_rt_sigpending(sigset_t *set, size_t sigsetsize) + EcallStatus ECALL_rt_sigtimedwait_time32(); // 137, rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) + EcallStatus ECALL_rt_sigqueueinfo(); // 138, rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) + EcallStatus ECALL_setpriority(); // 140, rev_setpriority(int which, int who, int niceval) + EcallStatus ECALL_getpriority(); // 141, rev_getpriority(int which, int who) + EcallStatus ECALL_reboot(); // 142, rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) + EcallStatus ECALL_setregid(); // 143, rev_setregid(gid_t rgid, gid_t egid) + EcallStatus ECALL_setgid(); // 144, rev_setgid(gid_t gid) + EcallStatus ECALL_setreuid(); // 145, rev_setreuid(uid_t ruid, uid_t euid) + EcallStatus ECALL_setuid(); // 146, rev_setuid(uid_t uid) + EcallStatus ECALL_setresuid(); // 147, rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) + EcallStatus ECALL_getresuid(); // 148, rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) + EcallStatus ECALL_setresgid(); // 149, rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) + EcallStatus ECALL_getresgid(); // 150, rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) + EcallStatus ECALL_setfsuid(); // 151, rev_setfsuid(uid_t uid) + EcallStatus ECALL_setfsgid(); // 152, rev_setfsgid(gid_t gid) + EcallStatus ECALL_times(); // 153, rev_times(struct tms *tbuf) + EcallStatus ECALL_setpgid(); // 154, rev_setpgid(pid_t pid, pid_t pgid) + EcallStatus ECALL_getpgid(); // 155, rev_getpgid(pid_t pid) + EcallStatus ECALL_getsid(); // 156, rev_getsid(pid_t pid) + EcallStatus ECALL_setsid(); // 157, rev_setsid(void) + EcallStatus ECALL_getgroups(); // 158, rev_getgroups(int gidsetsize, gid_t *grouplist) + EcallStatus ECALL_setgroups(); // 159, rev_setgroups(int gidsetsize, gid_t *grouplist) + EcallStatus ECALL_newuname(); // 160, rev_newuname(struct new_utsname *name) + EcallStatus ECALL_sethostname(); // 161, rev_sethostname(char *name, int len) + EcallStatus ECALL_setdomainname(); // 162, rev_setdomainname(char *name, int len) + EcallStatus ECALL_getrlimit(); // 163, rev_getrlimit(unsigned int resource, struct rlimit *rlim) + EcallStatus ECALL_setrlimit(); // 164, rev_setrlimit(unsigned int resource, struct rlimit *rlim) + EcallStatus ECALL_getrusage(); // 165, rev_getrusage(int who, struct rusage *ru) + EcallStatus ECALL_umask(); // 166, rev_umask(int mask) + EcallStatus ECALL_prctl(); // 167, rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) + EcallStatus ECALL_getcpu(); // 168, rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) + EcallStatus ECALL_gettimeofday(); // 169, rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) + EcallStatus ECALL_settimeofday(); // 170, rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) + EcallStatus ECALL_adjtimex(); // 171, rev_adjtimex(struct __kernel_timex *txc_p) + EcallStatus ECALL_getpid(); // 172, rev_getpid(void) + EcallStatus ECALL_getppid(); // 173, rev_getppid(void) + EcallStatus ECALL_getuid(); // 174, rev_getuid(void) + EcallStatus ECALL_geteuid(); // 175, rev_geteuid(void) + EcallStatus ECALL_getgid(); // 176, rev_getgid(void) + EcallStatus ECALL_getegid(); // 177, rev_getegid(void) + EcallStatus ECALL_gettid(); // 178, rev_gettid(void) + EcallStatus ECALL_sysinfo(); // 179, rev_sysinfo(struct sysinfo *info) + EcallStatus ECALL_mq_open(); // 180, rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) + EcallStatus ECALL_mq_unlink(); // 181, rev_mq_unlink(const char *name) + EcallStatus ECALL_mq_timedsend(); // 182, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) + EcallStatus ECALL_mq_timedreceive(); // 183, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) + EcallStatus ECALL_mq_notify(); // 184, rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) + EcallStatus ECALL_mq_getsetattr(); // 185, rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) + EcallStatus ECALL_msgget(); // 186, rev_msgget(key_t key, int msgflg) + EcallStatus ECALL_msgctl(); // 187, rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) + EcallStatus ECALL_msgrcv(); // 188, rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) + EcallStatus ECALL_msgsnd(); // 189, rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) + EcallStatus ECALL_semget(); // 190, rev_semget(key_t key, int nsems, int semflg) + EcallStatus ECALL_semctl(); // 191, rev_semctl(int semid, int semnum, int cmd, unsigned long arg) + EcallStatus ECALL_semtimedop(); // 192, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) + EcallStatus ECALL_semop(); // 193, rev_semop(int semid, struct sembuf *sops, unsigned nsops) + EcallStatus ECALL_shmget(); // 194, rev_shmget(key_t key, size_t size, int flag) + EcallStatus ECALL_shmctl(); // 195, rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) + EcallStatus ECALL_shmat(); // 196, rev_shmat(int shmid, char *shmaddr, int shmflg) + EcallStatus ECALL_shmdt(); // 197, rev_shmdt(char *shmaddr) + EcallStatus ECALL_socket(); // 198, rev_socket(int, int, int) + EcallStatus ECALL_socketpair(); // 199, rev_socketpair(int, int, int, int *) + EcallStatus ECALL_bind(); // 200, rev_bind(int, struct sockaddr *, int) + EcallStatus ECALL_listen(); // 201, rev_listen(int, int) + EcallStatus ECALL_accept(); // 202, rev_accept(int, struct sockaddr *, int *) + EcallStatus ECALL_connect(); // 203, rev_connect(int, struct sockaddr *, int) + EcallStatus ECALL_getsockname(); // 204, rev_getsockname(int, struct sockaddr *, int *) + EcallStatus ECALL_getpeername(); // 205, rev_getpeername(int, struct sockaddr *, int *) + EcallStatus ECALL_sendto(); // 206, rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int) + EcallStatus ECALL_recvfrom(); // 207, rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *) + EcallStatus ECALL_setsockopt(); // 208, rev_setsockopt(int fd, int level, int optname, char *optval, int optlen) + EcallStatus ECALL_getsockopt(); // 209, rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen) + EcallStatus ECALL_shutdown(); // 210, rev_shutdown(int, int) + EcallStatus ECALL_sendmsg(); // 211, rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags) + EcallStatus ECALL_recvmsg(); // 212, rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags) + EcallStatus ECALL_readahead(); // 213, rev_readahead(int fd, loff_t offset, size_t count) + EcallStatus ECALL_brk(); // 214, rev_brk(unsigned long brk) + EcallStatus ECALL_munmap(); // 215, rev_munmap(unsigned long addr, size_t len) + EcallStatus ECALL_mremap(); // 216, rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) + EcallStatus ECALL_add_key(); // 217, rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) + EcallStatus ECALL_request_key(); // 218, rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) + EcallStatus ECALL_keyctl(); // 219, rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) + EcallStatus ECALL_clone(); // 220, rev_clone(unsigned long, unsigned long, int *, unsigned long, int *) + EcallStatus ECALL_execve(); // 221, rev_execve(const char *filename, const char *const *argv, const char *const *envp) + EcallStatus ECALL_mmap(); // 222, rev_old_mmap(struct mmap_arg_struct *arg) + EcallStatus ECALL_fadvise64_64(); // 223, rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) + EcallStatus ECALL_swapon(); // 224, rev_swapon(const char *specialfile, int swap_flags) + EcallStatus ECALL_swapoff(); // 225, rev_swapoff(const char *specialfile) + EcallStatus ECALL_mprotect(); // 226, rev_mprotect(unsigned long start, size_t len, unsigned long prot) + EcallStatus ECALL_msync(); // 227, rev_msync(unsigned long start, size_t len, int flags) + EcallStatus ECALL_mlock(); // 228, rev_mlock(unsigned long start, size_t len) + EcallStatus ECALL_munlock(); // 229, rev_munlock(unsigned long start, size_t len) + EcallStatus ECALL_mlockall(); // 230, rev_mlockall(int flags) + EcallStatus ECALL_munlockall(); // 231, rev_munlockall(void) + EcallStatus ECALL_mincore(); // 232, rev_mincore(unsigned long start, size_t len, unsigned char * vec) + EcallStatus ECALL_madvise(); // 233, rev_madvise(unsigned long start, size_t len, int behavior) + EcallStatus ECALL_remap_file_pages(); // 234, rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) + EcallStatus ECALL_mbind(); // 235, rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) + EcallStatus ECALL_get_mempolicy(); // 236, rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) + EcallStatus ECALL_set_mempolicy(); // 237, rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) + EcallStatus ECALL_migrate_pages(); // 238, rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) + EcallStatus ECALL_move_pages(); // 239, rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) + EcallStatus ECALL_rt_tgsigqueueinfo(); // 240, rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) + EcallStatus ECALL_perf_event_open(); // 241, rev_perf_event_open(") + EcallStatus ECALL_accept4(); // 242, rev_accept4(int, struct sockaddr *, int *, int) + EcallStatus ECALL_recvmmsg_time32(); // 243, rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout) + EcallStatus ECALL_wait4(); // 260, rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) + EcallStatus ECALL_prlimit64(); // 261, rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) + EcallStatus ECALL_fanotify_init(); // 262, rev_fanotify_init(unsigned int flags, unsigned int event_f_flags) + EcallStatus ECALL_fanotify_mark(); // 263, rev_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char *pathname) + EcallStatus ECALL_name_to_handle_at(); // 264, rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) + EcallStatus ECALL_open_by_handle_at(); // 265, rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) + EcallStatus ECALL_clock_adjtime(); // 266, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) + EcallStatus ECALL_syncfs(); // 267, rev_syncfs(int fd) + EcallStatus ECALL_setns(); // 268, rev_setns(int fd, int nstype) + EcallStatus ECALL_sendmmsg(); // 269, rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) + EcallStatus ECALL_process_vm_readv(); // 270, rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) + EcallStatus ECALL_process_vm_writev(); // 271, rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) + EcallStatus ECALL_kcmp(); // 272, rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) + EcallStatus ECALL_finit_module(); // 273, rev_finit_module(int fd, const char *uargs, int flags) + EcallStatus ECALL_sched_setattr(); // 274, rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) + EcallStatus ECALL_sched_getattr(); // 275, rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) + EcallStatus ECALL_renameat2(); // 276, rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) + EcallStatus ECALL_seccomp(); // 277, rev_seccomp(unsigned int op, unsigned int flags, void *uargs) + EcallStatus ECALL_getrandom(); // 278, rev_getrandom(char *buf, size_t count, unsigned int flags) + EcallStatus ECALL_memfd_create(); // 279, rev_memfd_create(const char *uname_ptr, unsigned int flags) + EcallStatus ECALL_bpf(); // 280, rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) + EcallStatus ECALL_execveat(); // 281, rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) + EcallStatus ECALL_userfaultfd(); // 282, rev_userfaultfd(int flags) + EcallStatus ECALL_membarrier(); // 283, rev_membarrier(int cmd, unsigned int flags, int cpu_id) + EcallStatus ECALL_mlock2(); // 284, rev_mlock2(unsigned long start, size_t len, int flags) + EcallStatus ECALL_copy_file_range(); // 285, rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) + EcallStatus ECALL_preadv2(); // 286, rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) + EcallStatus ECALL_pwritev2(); // 287, rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) + EcallStatus ECALL_pkey_mprotect(); // 288, rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey) + EcallStatus ECALL_pkey_alloc(); // 289, rev_pkey_alloc(unsigned long flags, unsigned long init_val) + EcallStatus ECALL_pkey_free(); // 290, rev_pkey_free(int pkey) + EcallStatus ECALL_statx(); // 291, rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) + EcallStatus ECALL_io_pgetevents(); // 292, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) + EcallStatus ECALL_rseq(); // 293, rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) + EcallStatus ECALL_kexec_file_load(); // 294, rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) + // EcallStatus ECALL_clock_gettime(); // 403, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) + // EcallStatus ECALL_clock_settime(); // 404, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) + // EcallStatus ECALL_clock_adjtime(); // 405, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) + // EcallStatus ECALL_clock_getres(); // 406, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) + // EcallStatus ECALL_clock_nanosleep(); // 407, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + // EcallStatus ECALL_timer_gettime(); // 408, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) + // EcallStatus ECALL_timer_settime(); // 409, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) + // EcallStatus ECALL_timerfd_gettime(); // 410, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) + // EcallStatus ECALL_timerfd_settime(); // 411, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) + // EcallStatus ECALL_utimensat(); // 412, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) + // EcallStatus ECALL_io_pgetevents(); // 416, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) + // EcallStatus ECALL_mq_timedsend(); // 418, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) + // EcallStatus ECALL_mq_timedreceive(); // 419, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) + // EcallStatus ECALL_semtimedop(); // 420, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) + // EcallStatus ECALL_futex(); // 422, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) + // EcallStatus ECALL_sched_rr_get_interval(); // 423, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) + EcallStatus ECALL_pidfd_send_signal(); // 424, rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) + EcallStatus ECALL_io_uring_setup(); // 425, rev_io_uring_setup(u32 entries, struct io_uring_params *p) + EcallStatus ECALL_io_uring_enter(); // 426, rev_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const sigset_t *sig, size_t sigsz) + EcallStatus ECALL_io_uring_register(); // 427, rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args) + EcallStatus ECALL_open_tree(); // 428, rev_open_tree(int dfd, const char *path, unsigned flags) + EcallStatus ECALL_move_mount(); // 429, rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) + EcallStatus ECALL_fsopen(); // 430, rev_fsopen(const char *fs_name, unsigned int flags) + EcallStatus ECALL_fsconfig(); // 431, rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) + EcallStatus ECALL_fsmount(); // 432, rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) + EcallStatus ECALL_fspick(); // 433, rev_fspick(int dfd, const char *path, unsigned int flags) + EcallStatus ECALL_pidfd_open(); // 434, rev_pidfd_open(pid_t pid, unsigned int flags) + EcallStatus ECALL_clone3(); // 435, rev_clone3(struct clone_args *uargs, size_t size) + EcallStatus ECALL_close_range(); // 436, rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags) + EcallStatus ECALL_openat2(); // 437, rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) + EcallStatus ECALL_pidfd_getfd(); // 438, rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) + EcallStatus ECALL_faccessat2(); // 439, rev_faccessat2(int dfd, const char *filename, int mode, int flags) + EcallStatus ECALL_process_madvise(); // 440, rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) + + // =============== REV specific functions + EcallStatus ECALL_cpuinfo(); // 500, rev_cpuinfo(struct rev_cpuinfo *info); + EcallStatus ECALL_perf_stats(); // 501, rev_perf_stats(struct rev_stats *stats); + + // =============== REV pthread functions + EcallStatus ECALL_pthread_create(); // 1000, rev_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) + EcallStatus ECALL_pthread_join(); // 1001, rev_pthread_join(pthread_t thread, void **retval); + EcallStatus ECALL_pthread_exit(); // 1002, rev_pthread_exit(void* retval); + + EcallStatus ECALL_dump_mem_range(); // 9000, dump_mem_range(uint64_t addr, uint64_t size) + EcallStatus ECALL_dump_mem_range_to_file(); // 9001, dump_mem_range_to_file(const unsigned char* outputFile, uint64_t addr, uint64_t size) + EcallStatus ECALL_dump_stack(); // 9002, dump_stack() + EcallStatus ECALL_dump_stack_to_file(); // 9003, dump_stack(const unsigned char* outputFile) + + EcallStatus ECALL_dump_valid_mem(); // 9004, dump_valid_mem() + EcallStatus ECALL_dump_valid_mem_to_file(); // 9005, dump_valid_mem_to_file(const unsigned char* outputFile) + + EcallStatus ECALL_dump_thread_mem(); // 9006, dump_thread_mem() + EcallStatus ECALL_dump_thread_mem_to_file(); // 9007, dump_thread_mem_to_file(const unsigned char* outputFile) + + // =============== REV print utilities + EcallStatus ECALL_fast_printf(); // 9010, rev_fast_printf(const char *, ...) + + // clang-format on + + /// RevCore: Table of ecall codes w/ corresponding function pointer implementations + static const std::unordered_map Ecalls; + + /// RevCore: Execute the Ecall based on the code loaded in RegFile->GetSCAUSE() + bool ExecEcall(); + + /// RevCore: Get a pointer to the register file loaded into Hart w/ HartID + RevRegFile* GetRegFile( uint32_t HartID ) const; + + std::vector InstTable{}; ///< RevCore: target instruction table + std::vector> Extensions{}; ///< RevCore: vector of enabled extensions + //std::vector> Pipeline; ///< RevCore: pipeline of instructions + std::deque> Pipeline{}; ///< RevCore: pipeline of instructions + std::unordered_map NameToEntry{}; ///< RevCore: instruction mnemonic to table entry mapping + std::unordered_multimap EncToEntry{}; ///< RevCore: instruction encoding to table entry mapping + std::unordered_multimap CEncToEntry{}; ///< RevCore: compressed instruction encoding to table entry mapping + std::unordered_map> EntryToExt{}; ///< RevCore: instruction entry to extension mapping + /// first = Master table entry number + /// second = pair + + /// RevCore: finds an entry which matches an encoding whose predicate is true + auto matchInst( + const std::unordered_multimap& map, + uint64_t encoding, + const std::vector& InstTable, + uint32_t Inst + ) const; + + /// RevCore: parses the feature string for the target core + bool ParseFeatureStr( std::string Feature ); + + /// RevCore: loads the instruction table using the target features + bool LoadInstructionTable(); + + /// RevCore: see the instruction table the target features + bool SeedInstTable(); + + /// RevCore: enable the target extension by merging its instruction table with the master + bool EnableExt( RevExt* Ext ); + + /// RevCore: initializes the internal mapping tables + bool InitTableMapping(); + + /// RevCore: read in the user defined cost tables + bool ReadOverrideTables(); + + /// RevCore: compresses the encoding structure to a single value + uint64_t CompressEncoding( const RevInstEntry& Entry ); + + /// RevCore: compressed the compressed encoding structure to a single value + uint32_t CompressCEncoding( const RevInstEntry& Entry ); + + /// RevCore: extracts the instruction mnemonic from the table entry + std::string ExtractMnemonic( const RevInstEntry& Entry ); + + /// RevCore: reset the core and its associated features + bool Reset(); + + /// RevCore: set the PC + void SetPC( uint64_t PC ) { RegFile->SetPC( PC ); } + + /// RevCore: prefetch the next instruction + bool PrefetchInst(); + + /// RevCore: decode the instruction at the current PC + RevInst FetchAndDecodeInst(); + + /// RevCore: decode a particular instruction opcode + RevInst DecodeInst( uint32_t Inst ) const; + + /// RevCore: decode a compressed instruction + RevInst DecodeCompressed( uint32_t Inst ) const; + + /// RevCore: decode an R-type instruction + RevInst DecodeRInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode an I-type instruction + RevInst DecodeIInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode an S-type instruction + RevInst DecodeSInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a U-type instruction + RevInst DecodeUInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a B-type instruction + RevInst DecodeBInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a J-type instruction + RevInst DecodeJInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode an R4-type instruction + RevInst DecodeR4Inst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CR-type isntruction + RevInst DecodeCRInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CI-type isntruction + RevInst DecodeCIInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CSS-type isntruction + RevInst DecodeCSSInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CIW-type isntruction + RevInst DecodeCIWInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CL-type isntruction + RevInst DecodeCLInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CS-type isntruction + RevInst DecodeCSInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CA-type isntruction + RevInst DecodeCAInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CB-type isntruction + RevInst DecodeCBInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: decode a compressed CJ-type isntruction + RevInst DecodeCJInst( uint32_t Inst, uint32_t Entry ) const; + + /// RevCore: Determine next thread to execute + uint32_t GetNextHartToDecodeID() const; + + /// RevCore: Whether any scoreboard bits are set + bool AnyDependency( uint32_t HartID, RevRegClass regClass = RevRegClass::RegUNKNOWN ) const { + const RevRegFile* regFile = GetRegFile( HartID ); + switch( regClass ) { + case RevRegClass::RegGPR: return regFile->RV_Scoreboard.any(); + case RevRegClass::RegFLOAT: return regFile->FP_Scoreboard.any(); + case RevRegClass::RegUNKNOWN: return regFile->RV_Scoreboard.any() || regFile->FP_Scoreboard.any(); + default: return false; + } + } + + /// RevCore: Check LS queue for outstanding load - ignore x0 + static bool LSQCheck( uint32_t HartID, const RevRegFile* regFile, uint32_t reg, RevRegClass regClass ) { + if( reg == 0 && regClass == RevRegClass::RegGPR ) { + return false; // GPR x0 is not considered + } else { + return regFile->GetLSQueue()->count( LSQHash( reg, regClass, HartID ) ) > 0; + } + } + + /// RevCore: Check scoreboard for a source register dependency + static bool ScoreboardCheck( const RevRegFile* regFile, uint32_t reg, RevRegClass regClass ) { + switch( regClass ) { + case RevRegClass::RegGPR: return reg != 0 && regFile->RV_Scoreboard[reg]; + case RevRegClass::RegFLOAT: return regFile->FP_Scoreboard[reg]; + default: return false; + } + } + + bool HartHasNoDependencies( uint32_t HartID ) const { return !AnyDependency( HartID ); } + + ///< Removes thread from Hart and returns it + std::unique_ptr PopThreadFromHart( uint32_t HartID ); + + /// RevCore: Check scoreboard for pipeline hazards + bool DependencyCheck( uint32_t HartID, const RevInst* Inst ) const; + + /// RevCore: Set or clear scoreboard based on instruction destination + void DependencySet( uint32_t HartID, const RevInst* Inst, bool value = true ) { + DependencySet( HartID, Inst->rd, InstTable[Inst->entry].rdClass, value ); + } + + /// RevCore: Clear scoreboard on instruction retirement + void DependencyClear( uint32_t HartID, const RevInst* Inst ) { DependencySet( HartID, Inst, false ); } + + /// RevCore: Set or clear scoreboard based on register number and floating point. + template + void DependencySet( uint32_t HartID, T RegNum, RevRegClass regClass, bool value = true ) { + if( size_t( RegNum ) < _REV_NUM_REGS_ ) { + RevRegFile* regFile = GetRegFile( HartID ); + switch( regClass ) { + case RevRegClass::RegGPR: + if( size_t( RegNum ) != 0 ) + regFile->RV_Scoreboard[size_t( RegNum )] = value; + break; + case RevRegClass::RegFLOAT: regFile->FP_Scoreboard[size_t( RegNum )] = value; break; + default: break; + } + } + } + + /// RevCore: Clear scoreboard on instruction retirement + template + void DependencyClear( uint32_t HartID, T RegNum, RevRegClass regClass ) { + DependencySet( HartID, RegNum, regClass, false ); + } + +}; // class RevCore + +} // namespace SST::RevCPU + +#endif + +// EOF diff --git a/include/RevProcPasskey.h b/include/RevCorePasskey.h similarity index 54% rename from include/RevProcPasskey.h rename to include/RevCorePasskey.h index 0884b5009..8ccd7a8d5 100644 --- a/include/RevProcPasskey.h +++ b/include/RevCorePasskey.h @@ -1,5 +1,5 @@ // -// _RevProcPasskey_h_ +// _RevCorePasskey_h_ // // Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC // All Rights Reserved @@ -8,18 +8,18 @@ // See LICENSE in the top level directory for licensing details // - #ifndef __REV_PROC_PASSKEY__ #define __REV_PROC_PASSKEY__ -namespace SST::RevCPU{ - + +namespace SST::RevCPU { + template -class RevProcPasskey{ - private: +class RevCorePasskey { +private: friend T; - RevProcPasskey() {}; - RevProcPasskey(const RevProcPasskey&) {}; - RevProcPasskey& operator=(const RevProcPasskey&) = delete; + RevCorePasskey(){}; + RevCorePasskey( const RevCorePasskey& ){}; + RevCorePasskey& operator=( const RevCorePasskey& ) = delete; }; -} -#endif \ No newline at end of file +} // namespace SST::RevCPU +#endif diff --git a/include/RevExt.h b/include/RevExt.h index 067dbeb47..33e3aaebe 100644 --- a/include/RevExt.h +++ b/include/RevExt.h @@ -1,7 +1,7 @@ // // _RevExt_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -15,73 +15,64 @@ #include "SST.h" // -- Standard Headers -#include #include +#include +#include #include #include // -- RevCPU Headers -#include "RevInstTable.h" -#include "RevMem.h" #include "RevFeature.h" #include "RevFenv.h" +#include "RevInstTable.h" +#include "RevMem.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -struct RevExt{ +struct RevExt { /// RevExt: standard constructor - RevExt( std::string_view name, - RevFeature* feature, - RevMem *mem, - SST::Output *output ) - : name(name), feature(feature), mem(mem), output(output){ - } + RevExt( std::string_view name, const RevFeature* feature, RevMem* mem, SST::Output* output ) + : name( name ), feature( feature ), mem( mem ), output( output ) {} /// RevExt: standard destructor. virtual so that Extensions[i] can be deleted - virtual ~RevExt() = default; + virtual ~RevExt() = default; + + // We do not allow copying, moving or assigning + RevExt( const RevExt& ) = delete; + RevExt( RevExt&& ) = delete; + RevExt& operator=( const RevExt& ) = delete; + RevExt& operator=( RevExt&& ) = delete; /// RevExt: sets the internal instruction table - void SetTable(std::vector InstVect){ - table = std::move(InstVect); - } + // Note: && means the argument should be an rvalue or std::move(lvalue) + // This avoids deep std::vector copies and uses only one std::vector move. + void SetTable( std::vector&& InstVect ) { table = std::move( InstVect ); } /// RevExt: sets the internal compressed instruction table - void SetCTable(std::vector InstVect){ - ctable = std::move(InstVect); - } - - /// RevExt: sets the optional table (used for variant-specific compressed encodings) - void SetOTable(std::vector InstVect){ - otable = std::move(InstVect); - } + void SetCTable( std::vector&& InstVect ) { ctable = std::move( InstVect ); } /// RevExt: retrieve the extension name std::string_view GetName() const { return name; } /// RevExt: baseline execution function - bool Execute(unsigned Inst, const RevInst& Payload, uint16_t HartID, RevRegFile* regFile); + bool Execute( uint32_t Inst, const RevInst& Payload, uint32_t HartID, RevRegFile* regFile ) const; /// RevExt: retrieves the extension's instruction table - const std::vector& GetInstTable(){ return table; } + const std::vector& GetTable() const { return table; } /// RevExt: retrieves the extension's compressed instruction table - const std::vector& GetCInstTable(){ return ctable; } - - /// RevExt: retrieves the extension's optional instruction table - const std::vector& GetOInstTable(){ return otable; } + const std::vector& GetCTable() const { return ctable; } private: - std::string_view const name; ///< RevExt: extension name - RevFeature *const feature; ///< RevExt: feature object - RevMem *const mem; ///< RevExt: memory object - SST::Output *const output; ///< RevExt: output handler - - std::vector table; ///< RevExt: instruction table - std::vector ctable; ///< RevExt: compressed instruction table - std::vector otable; ///< RevExt: optional compressed instruction table - - auto SetFPEnv(unsigned Inst, const RevInst& Payload, uint16_t threadID, RevRegFile* regFile); -}; // class RevExt -} // namespace SST::RevCPU + std::string_view const name; ///< RevExt: extension name + const RevFeature* const feature; ///< RevExt: feature object + RevMem* const mem; ///< RevExt: memory object + SST::Output* const output; ///< RevExt: output handler + std::vector table{}; ///< RevExt: instruction table + std::vector ctable{}; ///< RevExt: compressed instruction table + +}; // class RevExt + +} // namespace SST::RevCPU #endif diff --git a/include/RevFCSR.h b/include/RevFCSR.h new file mode 100644 index 000000000..7fd528b8e --- /dev/null +++ b/include/RevFCSR.h @@ -0,0 +1,40 @@ +// +// _RevFCSR_h_ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVFCSR_H_ +#define _SST_REVFCSR_H_ + +#include + +namespace SST::RevCPU { + +/// Floating-Point Rounding Mode +enum class FRMode : uint32_t { + None = 0xff, + RNE = 0, // Round to Nearest, ties to Even + RTZ = 1, // Round towards Zero + RDN = 2, // Round Down (towards -Inf) + RUP = 3, // Round Up (towards +Inf) + RMM = 4, // Round to Nearest, ties to Max Magnitude + DYN = 7, // In instruction's rm field, selects dynamic rounding mode; invalid in FCSR +}; + +/// Floating-point control register +enum class FCSR : uint32_t { + NX = 1, + UF = 2, + OF = 4, + DZ = 8, + NV = 16, +}; + +} // namespace SST::RevCPU + +#endif diff --git a/include/RevFeature.h b/include/RevFeature.h index c86188a61..3077e7c77 100644 --- a/include/RevFeature.h +++ b/include/RevFeature.h @@ -1,7 +1,7 @@ // // _RevFeature_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -11,65 +11,61 @@ #ifndef _SST_REVCPU_REVFEATURE_H_ #define _SST_REVCPU_REVFEATURE_H_ -#include #include +#include // -- SST Headers #include "SST.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { /// Table of RISC-V extension flags. They must be powers of two which can be /// ORed to indicate multiple extensions being present. enum RevFeatureType : uint32_t { - RV_UNKNOWN = 0, ///< RevFeatureType: unknown feature - RV_E = 1<<0, ///< RevFeatureType: E-extension - RV_I = 1<<1, ///< RevFeatureType: I-extension - RV_M = 1<<2, ///< RevFeatureType: M-extension - RV_A = 1<<3, ///< RevFeatureType: A-extension - RV_F = 1<<4, ///< RevFeatureType: F-extension - RV_D = 1<<5, ///< RevFeatureType: D-extension - RV_Q = 1<<6, ///< RevFeatureType: Q-extension - RV_L = 1<<7, ///< RevFeatureType: L-extension - RV_C = 1<<8, ///< RevFeatureType: C-extension - RV_B = 1<<9, ///< RevFeatureType: B-extension - RV_J = 1<<10, ///< RevFeatureType: J-extension - RV_T = 1<<11, ///< RevFeatureType: T-extension - RV_P = 1<<12, ///< RevFeatureType: P-Extension - RV_V = 1<<13, ///< RevFeatureType: V-extension - RV_N = 1<<14, ///< RevFeatureType: N-extension - RV_ZICSR = 1<<15, ///< RevFEatureType: Zicsr-extension - RV_ZIFENCEI = 1<<16, ///< RevFeatureType: Zifencei-extension - RV_ZAM = 1<<17, ///< RevFeatureType: Zam-extension - RV_ZTSO = 1<<18, ///< RevFeatureType: Ztso-extension - RV_ZFA = 1<<19, ///< RevFeatureType: Zfa-extension - RV_ZICBOM = 1<<20, ///< RevFeatureType: Zicbom-extension + RV_UNKNOWN = 0, ///< RevFeatureType: unknown feature + RV_I = 1 << 0, ///< RevFeatureType: I-extension + RV_E = 1 << 1, ///< RevFeatureType: E-extension + RV_M = 1 << 2, ///< RevFeatureType: M-extension + RV_F = 1 << 3, ///< RevFeatureType: F-extension + RV_D = 1 << 4, ///< RevFeatureType: D-extension + RV_Q = 1 << 5, ///< RevFeatureType: Q-extension + RV_C = 1 << 6, ///< RevFeatureType: C-extension + RV_B = 1 << 7, ///< RevFeatureType: C-extension + RV_P = 1 << 8, ///< RevFeatureType: P-Extension + RV_V = 1 << 9, ///< RevFeatureType: V-extension + RV_H = 1 << 10, ///< RevFeatureType: H-extension + RV_ZICBOM = 1 << 11, ///< RevFeatureType: Zicbom-extension + RV_ZICNTR = 1 << 12, ///< RevFeatureType: Zicntr-extension + RV_ZICSR = 1 << 13, ///< RevFEatureType: Zicsr-extension + RV_ZIFENCEI = 1 << 14, ///< RevFeatureType: Zifencei-extension + RV_ZMMUL = 1 << 15, ///< RevFeatureType: Zmmul-extension + RV_ZAAMO = 1 << 16, ///< RevFeatureType: Zaamo-extension + RV_ZALRSC = 1 << 17, ///< RevFeatureType: Zalrsc-extension + RV_ZFA = 1 << 18, ///< RevFeatureType: Zfa-extension + RV_ZFH = 1 << 19, ///< RevFeatureType: H-extension + RV_ZFHMIN = 1 << 20, ///< RevFeatureRtpe: Zfhmin extension + RV_ZTSO = 1 << 21, ///< RevFeatureType: Ztso-extension }; -class RevFeature{ +class RevFeature { public: /// RevFeature: standard constructor - RevFeature( std::string Machine, SST::Output *Output, - unsigned Min, unsigned Max, unsigned Id ); + RevFeature( std::string Machine, SST::Output* Output, uint32_t Min, uint32_t Max, uint32_t Id ); /// RevFeature: standard destructor - ~RevFeature() = default; + ~RevFeature() = default; /// RevFeature: deleted copy constructor - RevFeature( const RevFeature& ) = delete; + RevFeature( const RevFeature& ) = delete; /// RevFeature: deleted copy assignment operator RevFeature& operator=( const RevFeature& ) = delete; /// IsModeEnabled: determines if the target mode is enabled - bool IsModeEnabled( RevFeatureType Type ) const { - return (features & Type) == Type; - } + bool IsModeEnabled( RevFeatureType Type ) const { return ( features & Type ) == Type; } /// SetMachineEntry: set the machine model item - void SetMachineEntry( RevFeatureType Type ) { - features = RevFeatureType{features | Type}; - } + void SetMachineEntry( RevFeatureType Type ) { features = RevFeatureType{ features | Type }; } /// GetMachineModel: retrieve the feature string auto GetMachineModel() const { return machine; } @@ -83,45 +79,42 @@ class RevFeature{ /// GetMaxCost: get the maximum cost auto GetMaxCost() const { return MaxCost; } - /// IsRV32: Is the device an RV32 - bool IsRV32() const { return xlen == 32; } - /// IsRV64: Is the device an RV64 - bool IsRV64() const { return xlen == 64; } + bool IsRV64() const { return xlen >= 64; } /// HasF: Does the device support F? - bool HasF() const { return IsModeEnabled(RV_F); } + bool HasF() const { return IsModeEnabled( RV_F ); } /// HasD: Does the device support D? - bool HasD() const { return IsModeEnabled(RV_D); } + bool HasD() const { return IsModeEnabled( RV_D ); } /// HasCompressed: Returns whether RV32 or RV64 "C" is enabled - bool HasCompressed() const { return IsModeEnabled(RV_C); } + bool HasCompressed() const { return IsModeEnabled( RV_C ); } /// GetProcID: Retrieve the ProcID of the target object auto GetProcID() const { return ProcID; } /// GetHartToExecID: Retrieve the current executing Hart - uint16_t GetHartToExecID() const { return HartToExecID; } + auto GetHartToExecID() const { return HartToExecID; } /// SetHartToExecID: Set the current executing Hart - void SetHartToExecID(unsigned hart) { HartToExecID = hart; } + void SetHartToExecID( uint32_t hart ) { HartToExecID = hart; } private: - std::string machine; ///< RevFeature: feature string - SST::Output *output; ///< RevFeature: output handler - unsigned MinCost; ///< RevFeature: min memory cost - unsigned MaxCost; ///< RevFeature: max memory cost - unsigned ProcID; ///< RevFeature: RISC-V Proc ID - unsigned HartToExecID; ///< RevFeature: The current executing Hart on RevProc - RevFeatureType features; ///< RevFeature: feature elements - unsigned xlen; ///< RevFeature: RISC-V Xlen + const std::string machine; ///< RevFeature: feature string + SST::Output* const output; ///< RevFeature: output handler + const uint32_t MinCost; ///< RevFeature: min memory cost + const uint32_t MaxCost; ///< RevFeature: max memory cost + const uint32_t ProcID; ///< RevFeature: RISC-V Proc ID + uint32_t HartToExecID{}; ///< RevFeature: The current executing Hart on RevCore + RevFeatureType features{ RV_UNKNOWN }; ///< RevFeature: feature elements + uint32_t xlen{}; ///< RevFeature: RISC-V Xlen /// ParseMachineModel: parse the machine model string bool ParseMachineModel(); -}; // class RevFeature +}; // class RevFeature -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevFenv.h b/include/RevFenv.h index d6df01c1c..19e9a7c80 100644 --- a/include/RevFenv.h +++ b/include/RevFenv.h @@ -11,73 +11,105 @@ #ifndef _REV_FENV_H_ #define _REV_FENV_H_ +#include "RevFCSR.h" +#include "RevRegFile.h" #include -#include +#include +#include // GCC and Clang do not fully support FENV_ACCESS now. See: // +// https://bugs.llvm.org/show_bug.cgi?id=8100 // https://gcc.gnu.org/legacy-ml/gcc-patches/2003-09/msg00104.html // https://gcc.gcc.gnu.narkive.com/hDi1eOot/setting-frounding-math-by-default -// https://bugs.llvm.org/show_bug.cgi?id=8100 -// https://github.com/llvm/llvm-project/issues/8472 // https://discourse.llvm.org/t/why-is-pragma-stdc-fenv-access-not-supported/46128/25 // // Currently FP_MODE_FLAG in CMakeLists.txt is used as a workaround //#pragma STDC FENV_ACCESS ON -namespace SST::RevCPU{ +namespace SST::RevCPU { -// TODO: Right now we only need to save/restore rounding mode. -// Later, we may need to save and restore the entire fenv_t state -class RevFenv{ - int saved_round; ///< Saved Floating-Point Rounding Mode - - // We use Meyers singleton to avoid initialization order fiasco - static int& round(){ - thread_local int round = fegetround(); - return round; - } +class RevFenv { + RevRegFile* const R; + std::fenv_t saved_env{}; // The saved FP environment which is restored public: + /// Constructor saves Fenv state to be restored at destruction + RevFenv( RevRegFile* R, FRMode rm, SST::Output* output ) : R( R ) { - /// Constructor saves Fenv state - RevFenv() : saved_round(round()) { - if(saved_round < 0){ - throw std::runtime_error("Getting floating-point rounding mode with fegetround() is not working."); + // Save host's FP environment and set flags to default, non-trapping + if( std::feholdexcept( &saved_env ) ) { + throw std::runtime_error( "Getting floating-point environment with feholdexcept() is not working." ); } - } - /// Destructor restores Fenv state - ~RevFenv() { SetRound(saved_round); } + // If the encoded rounding mode is dynamic, load the frm register + if( rm == FRMode::DYN ) { + rm = R->GetFRM(); + } - // We allow moving, but not copying RevFenv - // This is to ensure that there is only a single copy - // of the saved state at a time, similar to std::unique_ptr - RevFenv(RevFenv&&) = default; - RevFenv(const RevFenv&) = delete; + // Set the Floating-Point Rounding Mode on the host + int ret = 0; + switch( rm ) { + case FRMode::RNE: // Round to Nearest, ties to Even + ret = std::fesetround( FE_TONEAREST ); + break; - // We disallow assigning - RevFenv& operator=(const RevFenv&) = delete; - RevFenv& operator=(RevFenv&&) = delete; + case FRMode::RTZ: // Round towards Zero + ret = std::fesetround( FE_TOWARDZERO ); + break; - // Get the current FP rounding state - static int GetRound(){ - return round(); - } + case FRMode::RDN: // Round Down (towards -Inf) + ret = std::fesetround( FE_DOWNWARD ); + break; - // Set the FP rounding state if it differs from current - static int SetRound(int mode){ - int rc = 0; - if(mode != round()){ - rc = fesetround(mode); - if(rc == 0){ - round() = mode; - } + case FRMode::RUP: // Round Up (towards +Inf) + ret = std::fesetround( FE_UPWARD ); + break; + + case FRMode::RMM: // Round to Nearest, ties to Max Magnitude +#ifdef FE_TONEARESTFROMZERO + ret = std::fesetround( FE_TONEARESTFROMZERO ); +#else + output->fatal( CALL_INFO, -1, "Error: Round to nearest Max Magnitude not implemented at PC = 0x%" PRIx64 "\n", R->GetPC() ); +#endif + break; + + case FRMode::DYN: output->fatal( CALL_INFO, -1, "Illegal FRM Rounding Mode of DYN at PC = 0x%" PRIx64 "\n", R->GetPC() ); break; + + default: output->fatal( CALL_INFO, -1, "Unknown Rounding Mode at PC = 0x%" PRIx64 "\n", R->GetPC() ); break; + } + + if( ret != 0 ) { + output->fatal( CALL_INFO, -1, "Could not set FP rounding mode at PC = 0x%" PRIx64 "\n", R->GetPC() ); } - return rc; } -}; // RevFenv -} // namespace SST::RevCPU + /// Destructor sets FP exception flags and restores host FP Environment + ~RevFenv() { + // RISC-V does not support FP traps + // Set the accumulated fflags based on exceptions + int except = std::fetestexcept( FE_ALL_EXCEPT ); + if( except & FE_DIVBYZERO ) + R->SetFFlags( FCSR::DZ ); + if( except & FE_INEXACT ) + R->SetFFlags( FCSR::NX ); + if( except & FE_INVALID ) + R->SetFFlags( FCSR::NV ); + if( except & FE_OVERFLOW ) + R->SetFFlags( FCSR::OF ); + if( except & FE_UNDERFLOW ) + R->SetFFlags( FCSR::UF ); + + // Restore the host's saved FP Environment + std::fesetenv( &saved_env ); + } + + // We allow moving, but not copying or assigning RevFenv. + RevFenv( RevFenv&& ) = default; + RevFenv( const RevFenv& ) = delete; + RevFenv& operator=( const RevFenv& ) = delete; +}; // RevFenv + +} // namespace SST::RevCPU #endif diff --git a/include/RevHart.h b/include/RevHart.h index 99d37d1c5..f04f92398 100644 --- a/include/RevHart.h +++ b/include/RevHart.h @@ -1,7 +1,7 @@ // // _RevHart_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -16,11 +16,11 @@ #include "RevThread.h" #include "SST.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RevHart{ +class RevHart { ///< RevHart: Id for the Hart (0,1,2,3,etc) - unsigned ID; + uint32_t ID{}; ///< RevHart: State management object when a Hart is executing a system call EcallState Ecall{}; @@ -29,56 +29,60 @@ class RevHart{ const std::shared_ptr>& LSQueue; ///< RevHart: Pointer to the Proc's MarkLoadCompleteFunc - std::function MarkLoadCompleteFunc; + std::function MarkLoadCompleteFunc{}; ///< RevHart: Thread currently executing on this Hart - std::unique_ptr Thread = nullptr; + std::unique_ptr Thread = nullptr; std::unique_ptr RegFile = nullptr; - ///< RevHart: Make RevProc a friend of this - friend class RevProc; + ///< RevHart: Make RevCore a friend of this + friend class RevCore; public: ///< RevHart: Constructor - RevHart(unsigned ID, const std::shared_ptr>& LSQueue, - std::function MarkLoadCompleteFunc) - : ID(ID), LSQueue(LSQueue), MarkLoadCompleteFunc(std::move(MarkLoadCompleteFunc)) {} + RevHart( + uint32_t ID, + const std::shared_ptr>& LSQueue, + std::function MarkLoadCompleteFunc + ) + : ID( ID ), LSQueue( LSQueue ), MarkLoadCompleteFunc( std::move( MarkLoadCompleteFunc ) ) {} ///< RevHart: Destructor ~RevHart() = default; ///< RevHart: Get the EcallState EcallState& GetEcallState() { return Ecall; } + const EcallState& GetEcallState() const { return Ecall; } ///< RevHart: Get Hart's ID - uint16_t GetID() const { return ID; } + uint32_t GetID() const { return ID; } ///< RevHart: Returns the ID of the assigned thread - uint32_t GetAssignedThreadID() const { return (Thread != nullptr) ? Thread->GetID() : _INVALID_TID_; } + uint32_t GetAssignedThreadID() const { return Thread ? Thread->GetID() : _INVALID_TID_; } ///< RevHart: Load the register file from the RevThread - void LoadRegFile(std::unique_ptr regFile){ - RegFile = std::move(regFile); - RegFile->SetMarkLoadComplete(MarkLoadCompleteFunc); - RegFile->SetLSQueue(LSQueue); + void LoadRegFile( std::unique_ptr regFile ) { + RegFile = std::move( regFile ); + RegFile->SetMarkLoadComplete( MarkLoadCompleteFunc ); + RegFile->SetLSQueue( LSQueue ); } ///< RevHart: Assigns a RevThread to this Hart - void AssignThread(std::unique_ptr ThreadToAssign){ - Thread = std::move(ThreadToAssign); - Thread->SetState(ThreadState::RUNNING); - LoadRegFile(Thread->TransferVirtRegState()); + void AssignThread( std::unique_ptr ThreadToAssign ) { + Thread = std::move( ThreadToAssign ); + Thread->SetState( ThreadState::RUNNING ); + LoadRegFile( Thread->TransferVirtRegState() ); } ///< RevHart: Removed a RevThread from this Hart - std::unique_ptr PopThread(){ + std::unique_ptr PopThread() { // return the register file to the thread - Thread->UpdateVirtRegState(std::move(RegFile)); + Thread->UpdateVirtRegState( std::move( RegFile ) ); // return the thread - return std::move(Thread); + return std::move( Thread ); } -}; // class RevHart +}; // class RevHart -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevInstHelpers.h b/include/RevInstHelpers.h index 35d8de33f..0fe7584af 100644 --- a/include/RevInstHelpers.h +++ b/include/RevInstHelpers.h @@ -1,7 +1,7 @@ // // _RevInstHelpers_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -19,193 +19,272 @@ #include #include +#include "RevFenv.h" #include "RevInstTable.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { + +// Limits when converting from floating-point to integer +template +inline constexpr FP fpmax = 0; +template +inline constexpr FP fpmin = 0; +template<> +inline constexpr float fpmax = 0x1.fffffep+30f; +template<> +inline constexpr float fpmin = -0x1p+31f; +template<> +inline constexpr float fpmax = 0x1.fffffep+31f; +template<> +inline constexpr float fpmin = 0x0p+0f; +template<> +inline constexpr float fpmax = 0x1.fffffep+62f; +template<> +inline constexpr float fpmin = -0x1p+63f; +template<> +inline constexpr float fpmax = 0x1.fffffep+63f; +template<> +inline constexpr float fpmin = 0x0p+0f; +template<> +inline constexpr double fpmax = 0x1.fffffffcp+30; +template<> +inline constexpr double fpmin = -0x1p+31; +template<> +inline constexpr double fpmax = 0x1.fffffffep+31; +template<> +inline constexpr double fpmin = 0x0p+0; +template<> +inline constexpr double fpmax = 0x1.fffffffffffffp+62; +template<> +inline constexpr double fpmin = -0x1p+63; +template<> +inline constexpr double fpmax = 0x1.fffffffffffffp+63; +template<> +inline constexpr double fpmin = 0x0p+0; /// General template for converting between Floating Point and Integer. /// FP values outside the range of the target integer type are clipped -/// at the integer type's numerical limits, whether signed or unsigned. -template -bool CvtFpToInt(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - FP fp = R->GetFP(Inst.rs1); // Read the FP register - constexpr INT max = std::numeric_limits::max(); - constexpr INT min = std::numeric_limits::min(); - INT res = std::isnan(fp) || fp > FP(max) ? max : fp < FP(min) ? min : static_cast(fp); +/// at the integer type's numerical limits, whether signed or uint32_t. +template +bool fcvtif( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + // Read the FP register. Round to integer according to current rounding mode. + FP fp = std::rint( R->GetFP( Inst.rs1 ) ); + + // Convert to integer type + INT res; + if( std::isnan( fp ) || fp > fpmax ) { + std::feraiseexcept( FE_INVALID ); + res = std::numeric_limits::max(); + } else if( fp < fpmin ) { + std::feraiseexcept( FE_INVALID ); + res = std::numeric_limits::min(); + } else { + res = static_cast( fp ); + } // Make final result signed so sign extension occurs when sizeof(INT) < XLEN - R->SetX(Inst.rd, static_cast>(res)); + R->SetX( Inst.rd, std::make_signed_t( res ) ); - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } +enum RevFClass : uint32_t { + InfNeg = 1u << 0, + NormalNeg = 1u << 1, + SubNormalNeg = 1u << 2, + ZeroNeg = 1u << 3, + ZeroPos = 1u << 4, + SubNormalPos = 1u << 5, + NormalPos = 1u << 6, + InfPos = 1u << 7, + SignalingNaN = 1u << 8, + QuietNaN = 1u << 9, +}; + /// fclass: Return FP classification like the RISC-V fclass instruction -// See: https://github.com/riscv/riscv-isa-sim/blob/master/softfloat/f32_classify.c -// Because quiet and signaling NaNs are not distinguished by the C++ standard, -// an additional argument has been added to disambiguate between quiet and -// signaling NaNs. template -unsigned fclass(T val, bool quietNaN = true) { - switch(std::fpclassify(val)){ - case FP_INFINITE: - return std::signbit(val) ? 1 : 1 << 7; +uint32_t fclass( T val ) { + switch( std::fpclassify( val ) ) { + case FP_INFINITE: return std::signbit( val ) ? InfNeg : InfPos; + case FP_NORMAL: return std::signbit( val ) ? NormalNeg : NormalPos; + case FP_SUBNORMAL: return std::signbit( val ) ? SubNormalNeg : SubNormalPos; + case FP_ZERO: return std::signbit( val ) ? ZeroNeg : ZeroPos; case FP_NAN: - return quietNaN ? 1 << 9 : 1 << 8; - case FP_NORMAL: - return std::signbit(val) ? 1 << 1 : 1 << 6; - case FP_SUBNORMAL: - return std::signbit(val) ? 1 << 2 : 1 << 5; - case FP_ZERO: - return std::signbit(val) ? 1 << 3 : 1 << 4; - default: - return 0; + if constexpr( std::is_same_v ) { + uint32_t i32; + memcpy( &i32, &val, sizeof( i32 ) ); + return ( i32 & uint32_t{ 1 } << 22 ) != 0 ? QuietNaN : SignalingNaN; +#if 0 + } else if constexpr( std::is_same_v ) { + uint16_t i16; + memcpy( &i16, &val, sizeof( i16 ) ); + return ( i16 & uint16_t{ 1 } << 9 ) != 0 ? QuietNaN : SignalingNaN; +#endif + } else { + uint64_t i64; + memcpy( &i64, &val, sizeof( i64 ) ); + return ( i64 & uint64_t{ 1 } << 51 ) != 0 ? QuietNaN : SignalingNaN; + } + default: return 0u; } } /// Load template template -bool load(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( sizeof(T) < sizeof(int64_t) && R->IsRV32 ){ - static constexpr RevFlag flags = sizeof(T) < sizeof(int32_t) ? - std::is_signed_v ? RevFlag::F_SEXT32 : RevFlag::F_ZEXT32 : RevFlag::F_NONE; - uint64_t rs1 = R->GetX(Inst.rs1); // read once for tracer - MemReq req(rs1 + Inst.ImmSignExt(12), - Inst.rd, RevRegClass::RegGPR, - F->GetHartToExecID(), - MemOp::MemOpREAD, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert(req.LSQHashPair()); - M->ReadVal(F->GetHartToExecID(), - rs1 + Inst.ImmSignExt(12), - reinterpret_cast*>(&R->RV32[Inst.rd]), - std::move(req), - flags); - R->SetX(Inst.rd, static_cast(R->RV32[Inst.rd])); - - }else{ - static constexpr RevFlag flags = sizeof(T) < sizeof(int64_t) ? - std::is_signed_v ? RevFlag::F_SEXT64 : RevFlag::F_ZEXT64 : RevFlag::F_NONE; - uint64_t rs1 = R->GetX(Inst.rs1); - MemReq req(rs1 + Inst.ImmSignExt(12), - Inst.rd, RevRegClass::RegGPR, - F->GetHartToExecID(), - MemOp::MemOpREAD, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert(req.LSQHashPair()); - M->ReadVal(F->GetHartToExecID(), - rs1 + Inst.ImmSignExt(12), - reinterpret_cast*>(&R->RV64[Inst.rd]), - std::move(req), - flags); - R->SetX(Inst.rd, static_cast(R->RV64[Inst.rd])); +bool load( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + if( sizeof( T ) < sizeof( int64_t ) && !F->IsRV64() ) { + static constexpr RevFlag flags = + sizeof( T ) < sizeof( int32_t ) ? std::is_signed_v ? RevFlag::F_SEXT32 : RevFlag::F_ZEXT32 : RevFlag::F_NONE; + auto rs1 = R->GetX( Inst.rs1 ); // read once for tracer + MemReq req{ + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + Inst.rd, + RevRegClass::RegGPR, + F->GetHartToExecID(), + MemOp::MemOpREAD, + true, + R->GetMarkLoadComplete() }; + R->LSQueue->insert( req.LSQHashPair() ); + M->ReadVal( + F->GetHartToExecID(), + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + reinterpret_cast( &R->RV32[Inst.rd] ), + std::move( req ), + flags + ); + } else { + static constexpr RevFlag flags = + sizeof( T ) < sizeof( int64_t ) ? std::is_signed_v ? RevFlag::F_SEXT64 : RevFlag::F_ZEXT64 : RevFlag::F_NONE; + auto rs1 = R->GetX( Inst.rs1 ); + MemReq req{ + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + Inst.rd, + RevRegClass::RegGPR, + F->GetHartToExecID(), + MemOp::MemOpREAD, + true, + R->GetMarkLoadComplete() }; + R->LSQueue->insert( req.LSQHashPair() ); + M->ReadVal( + F->GetHartToExecID(), + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + reinterpret_cast( &R->RV64[Inst.rd] ), + std::move( req ), + flags + ); } // update the cost - R->cost += M->RandCost(F->GetMinCost(), F->GetMaxCost()); - R->AdvancePC(Inst); + R->cost += M->RandCost( F->GetMinCost(), F->GetMaxCost() ); + R->AdvancePC( Inst ); return true; } /// Store template template -bool store(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - M->Write(F->GetHartToExecID(), - R->GetX(Inst.rs1) + Inst.ImmSignExt(12), - R->GetX(Inst.rs2)); - R->AdvancePC(Inst); +bool store( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + M->Write( F->GetHartToExecID(), R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ), R->GetX( Inst.rs2 ) ); + R->AdvancePC( Inst ); return true; } /// Floating-point load template template -bool fload(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if(std::is_same_v || F->HasD()){ - static constexpr RevFlag flags = sizeof(T) < sizeof(double) ? - RevFlag::F_BOXNAN : RevFlag::F_NONE; - - uint64_t rs1 = R->GetX(Inst.rs1); - MemReq req(rs1 + Inst.ImmSignExt(12), - Inst.rd, - RevRegClass::RegFLOAT, - F->GetHartToExecID(), - MemOp::MemOpREAD, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert(req.LSQHashPair()); - M->ReadVal(F->GetHartToExecID(), - rs1 + Inst.ImmSignExt(12), - reinterpret_cast(&R->DPF[Inst.rd]), - std::move(req), - flags); - - // Box float value into 64-bit FP register - if(std::is_same_v){ - double fp = R->GetFP(Inst.rd); - BoxNaN(&fp, &fp); - R->SetFP(Inst.rd, fp); - } - }else{ - uint64_t rs1 = R->GetX(Inst.rs1); - MemReq req(rs1 + Inst.ImmSignExt(12), - Inst.rd, - RevRegClass::RegFLOAT, - F->GetHartToExecID(), - MemOp::MemOpREAD, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert(req.LSQHashPair()); - M->ReadVal(F->GetHartToExecID(), - rs1 + Inst.ImmSignExt(12), - &R->SPF[Inst.rd], - std::move(req), - RevFlag::F_NONE); +bool fload( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + if( std::is_same_v || F->HasD() ) { + static constexpr RevFlag flags = sizeof( T ) < sizeof( double ) ? RevFlag::F_BOXNAN : RevFlag::F_NONE; + uint64_t rs1 = R->GetX( Inst.rs1 ); + MemReq req{ + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + Inst.rd, + RevRegClass::RegFLOAT, + F->GetHartToExecID(), + MemOp::MemOpREAD, + true, + R->GetMarkLoadComplete() }; + R->LSQueue->insert( req.LSQHashPair() ); + M->ReadVal( + F->GetHartToExecID(), + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + reinterpret_cast( &R->DPF[Inst.rd] ), + std::move( req ), + flags + ); + } else { + uint64_t rs1 = R->GetX( Inst.rs1 ); + MemReq req{ + rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), + Inst.rd, + RevRegClass::RegFLOAT, + F->GetHartToExecID(), + MemOp::MemOpREAD, + true, + R->GetMarkLoadComplete() }; + R->LSQueue->insert( req.LSQHashPair() ); + M->ReadVal( + F->GetHartToExecID(), rs1 + uint64_t( Inst.ImmSignExt( 12 ) ), &R->SPF[Inst.rd], std::move( req ), RevFlag::F_NONE + ); } // update the cost - R->cost += M->RandCost(F->GetMinCost(), F->GetMaxCost()); - R->AdvancePC(Inst); + R->cost += M->RandCost( F->GetMinCost(), F->GetMaxCost() ); + R->AdvancePC( Inst ); return true; } /// Floating-point store template template -bool fstore(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - T val = R->GetFP(Inst.rs2); - M->Write(F->GetHartToExecID(), R->GetX(Inst.rs1) + Inst.ImmSignExt(12), val); - R->AdvancePC(Inst); +bool fstore( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + T val = R->GetFP( Inst.rs2 ); + M->Write( F->GetHartToExecID(), R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ), val ); + R->AdvancePC( Inst ); return true; } /// Floating-point operation template template class OP> -bool foper(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, OP()(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2))); - R->AdvancePC(Inst); +bool foper( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, OP()( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ) ) ); + R->AdvancePC( Inst ); return true; } /// Floating-point minimum functor +/// If one argument is NaN, the result is the other argument template -struct FMin{ +struct FMin { template - auto operator()(T x, T y) const { return std::fmin(x, y); } + auto operator()( T x, T y ) const { + auto xclass = fclass( x ); + auto yclass = fclass( y ); + if( xclass == SignalingNaN || yclass == SignalingNaN ) { + feraiseexcept( FE_INVALID ); + } + return ( xclass == ZeroPos && yclass == ZeroNeg ) || ( xclass == ZeroNeg && yclass == ZeroPos ) ? -T{ 0 } : std::fmin( x, y ); + } }; /// Floating-point maximum functor +/// If one argument is NaN, the result is the other argument template -struct FMax{ +struct FMax { template - auto operator()(T x, T y) const { return std::fmax(x, y); } + auto operator()( T x, T y ) const { + auto xclass = fclass( x ); + auto yclass = fclass( y ); + if( xclass == SignalingNaN || yclass == SignalingNaN ) { + feraiseexcept( FE_INVALID ); + } + return ( xclass == ZeroPos && yclass == ZeroNeg ) || ( xclass == ZeroNeg && yclass == ZeroPos ) ? T{ 0 } : std::fmax( x, y ); + } }; /// Floating-point conditional operation template template class OP> -bool fcondop(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - bool res = OP()(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2)); - R->SetX(Inst.rd, res); - R->AdvancePC(Inst); +bool fcondop( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + bool res = OP()( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ) ); + R->SetX( Inst.rd, res ); + R->AdvancePC( Inst ); return true; } @@ -217,64 +296,67 @@ enum class OpKind { Imm, Reg }; // The second parameter is the operand kind (OpKind::Imm or OpKind::Reg) // The third parameter is std::make_unsigned_t or std::make_signed_t (default) // The optional fourth parameter indicates W mode (32-bit on XLEN == 64) -template class OP, OpKind KIND, - template class SIGN = std::make_signed_t, bool W_MODE = false> - bool oper(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( !W_MODE && R->IsRV32 ){ +template class OP, OpKind KIND, template class SIGN = std::make_signed_t, bool W_MODE = false> +bool oper( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + if( !W_MODE && !F->IsRV64() ) { using T = SIGN; - T rs1 = R->GetX(Inst.rs1); - T rs2 = KIND == OpKind::Imm ? T(Inst.ImmSignExt(12)) : R->GetX(Inst.rs2); - T res = OP()(rs1, rs2); - R->SetX(Inst.rd, res); - }else{ + T rs1 = R->GetX( Inst.rs1 ); + T rs2 = KIND == OpKind::Imm ? T( Inst.ImmSignExt( 12 ) ) : R->GetX( Inst.rs2 ); + T res = OP()( rs1, rs2 ); + R->SetX( Inst.rd, res ); + } else { using T = SIGN>; - T rs1 = R->GetX(Inst.rs1); - T rs2 = KIND == OpKind::Imm ? T(Inst.ImmSignExt(12)) : R->GetX(Inst.rs2); - T res = OP()(rs1, rs2); + T rs1 = R->GetX( Inst.rs1 ); + T rs2 = KIND == OpKind::Imm ? T( Inst.ImmSignExt( 12 ) ) : R->GetX( Inst.rs2 ); + T res = OP()( rs1, rs2 ); // In W_MODE, cast the result to int32_t so that it's sign-extended - R->SetX(Inst.rd, std::conditional_t(res)); + R->SetX( Inst.rd, std::conditional_t( res ) ); } - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } /// Left shift functor - template - struct ShiftLeft{ - template - constexpr T operator()(T val, unsigned shift) const { - return val << (sizeof(T) == 4 ? shift & 0x1f : shift & 0x3f); - } - }; +template +struct ShiftLeft { + template + constexpr T operator()( T val, U shift ) const { + return val << ( sizeof( T ) == 4 ? shift & 0x1f : shift & 0x3f ); + } +}; /// Right shift functor template - struct ShiftRight{ - template - constexpr T operator()(T val, unsigned shift) const { - return val >> (sizeof(T) == 4 ? shift & 0x1f : shift & 0x3f); - } - }; +struct ShiftRight { + template + constexpr T operator()( T val, U shift ) const { + return val >> ( sizeof( T ) == 4 ? shift & 0x1f : shift & 0x3f ); + } +}; // Computes the UPPER half of multiplication, based on signedness template -bool uppermul(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( R->IsRV32 ){ - uint32_t rs1 = R->GetX(Inst.rs1); - uint32_t rs2 = R->GetX(Inst.rs2); - uint32_t mul = static_cast(rs1 * int64_t(rs2) >> 32); - if (rs1_is_signed && (rs1 & (uint32_t{1}<<31)) != 0) mul -= rs2; - if (rs2_is_signed && (rs2 & (uint32_t{1}<<31)) != 0) mul -= rs1; - R->SetX(Inst.rd, mul); - }else{ - uint64_t rs1 = R->GetX(Inst.rs1); - uint64_t rs2 = R->GetX(Inst.rs2); - uint64_t mul = static_cast(rs1 * __int128(rs2) >> 64); - if (rs1_is_signed && (rs1 & (uint64_t{1}<<63)) != 0) mul -= rs2; - if (rs2_is_signed && (rs2 & (uint64_t{1}<<63)) != 0) mul -= rs1; - R->SetX(Inst.rd, mul); +bool uppermul( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + if( F->IsRV64() ) { + uint64_t rs1 = R->GetX( Inst.rs1 ); + uint64_t rs2 = R->GetX( Inst.rs2 ); + uint64_t mul = static_cast( rs1 * __int128( rs2 ) >> 64 ); + if( rs1_is_signed && ( rs1 & ( uint64_t{ 1 } << 63 ) ) != 0 ) + mul -= rs2; + if( rs2_is_signed && ( rs2 & ( uint64_t{ 1 } << 63 ) ) != 0 ) + mul -= rs1; + R->SetX( Inst.rd, mul ); + } else { + uint32_t rs1 = R->GetX( Inst.rs1 ); + uint32_t rs2 = R->GetX( Inst.rs2 ); + uint32_t mul = static_cast( rs1 * int64_t( rs2 ) >> 32 ); + if( rs1_is_signed && ( rs1 & ( uint32_t{ 1 } << 31 ) ) != 0 ) + mul -= rs2; + if( rs2_is_signed && ( rs2 & ( uint32_t{ 1 } << 31 ) ) != 0 ) + mul -= rs1; + R->SetX( Inst.rd, mul ); } - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } @@ -285,36 +367,32 @@ enum class DivRem { Div, Rem }; // The second parameter is std::make_signed_t or std::make_unsigned_t // The optional third parameter indicates W mode (32-bit on XLEN == 64) template class SIGN, bool W_MODE = false> - bool divrem(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( !W_MODE && R->IsRV32 ){ +bool divrem( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + if( !W_MODE && !F->IsRV64() ) { using T = SIGN; - T rs1 = R->GetX(Inst.rs1); - T rs2 = R->GetX(Inst.rs2); + T rs1 = R->GetX( Inst.rs1 ); + T rs2 = R->GetX( Inst.rs2 ); T res; - if constexpr(DIVREM == DivRem::Div){ - res = std::is_signed_v && rs1 == std::numeric_limits::min() && - rs2 == -T{1} ? rs1 : rs2 ? rs1 / rs2 : -T{1}; - }else{ - res = std::is_signed_v && rs1 == std::numeric_limits::min() && - rs2 == -T{1} ? 0 : rs2 ? rs1 % rs2 : rs1; + if constexpr( DIVREM == DivRem::Div ) { + res = std::is_signed_v && rs1 == std::numeric_limits::min() && rs2 == -T{ 1 } ? rs1 : rs2 ? rs1 / rs2 : -T{ 1 }; + } else { + res = std::is_signed_v && rs1 == std::numeric_limits::min() && rs2 == -T{ 1 } ? 0 : rs2 ? rs1 % rs2 : rs1; } - R->SetX(Inst.rd, res); + R->SetX( Inst.rd, res ); } else { using T = SIGN>; - T rs1 = R->GetX(Inst.rs1); - T rs2 = R->GetX(Inst.rs2); + T rs1 = R->GetX( Inst.rs1 ); + T rs2 = R->GetX( Inst.rs2 ); T res; - if constexpr(DIVREM == DivRem::Div){ - res = std::is_signed_v && rs1 == std::numeric_limits::min() && - rs2 == -T{1} ? rs1 : rs2 ? rs1 / rs2 : -T{1}; - }else{ - res = std::is_signed_v && rs1 == std::numeric_limits::min() && - rs2 == -T{1} ? 0 : rs2 ? rs1 % rs2 : rs1; + if constexpr( DIVREM == DivRem::Div ) { + res = std::is_signed_v && rs1 == std::numeric_limits::min() && rs2 == -T{ 1 } ? rs1 : rs2 ? rs1 / rs2 : -T{ 1 }; + } else { + res = std::is_signed_v && rs1 == std::numeric_limits::min() && rs2 == -T{ 1 } ? 0 : rs2 ? rs1 % rs2 : rs1; } // In W_MODE, cast the result to int32_t so that it's sign-extended - R->SetX(Inst.rd, std::conditional_t(res)); + R->SetX( Inst.rd, std::conditional_t( res ) ); } - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } @@ -322,54 +400,150 @@ template class SIGN, bool W_MODE = false> // The first template parameter is the comparison functor // The second template parameter is std::make_signed_t or std::make_unsigned_t template class OP, template class SIGN = std::make_unsigned_t> -bool bcond(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { +bool bcond( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { bool cond; - if( R->IsRV32 ){ - cond = OP()(R->GetX>(Inst.rs1), R->GetX>(Inst.rs2)); - }else{ - cond = OP()(R->GetX>(Inst.rs1), R->GetX>(Inst.rs2)); + if( F->IsRV64() ) { + cond = OP()( R->GetX>( Inst.rs1 ), R->GetX>( Inst.rs2 ) ); + } else { + cond = OP()( R->GetX>( Inst.rs1 ), R->GetX>( Inst.rs2 ) ); } - if(cond){ - R->SetPC(R->GetPC() + Inst.ImmSignExt(13)); - }else{ - R->AdvancePC(Inst); + if( cond ) { + R->SetPC( R->GetPC() + uint64_t( Inst.ImmSignExt( 13 ) ) ); + } else { + R->AdvancePC( Inst ); } return true; } -/// Fused Multiply-Add +/// Negation function which flips sign bit, even of NaN +template +inline auto negate( T x ) { + return std::copysign( x, std::signbit( x ) ? T{ 1 } : T{ -1 } ); +} + +/// Rev FMA template which handles 0.0 * NAN and NAN * 0.0 correctly +// RISC-V requires INVALID exception when x * y is INVALID even when z = qNaN +template +inline auto revFMA( T x, T y, T z ) { + if( ( y == 0 && std::isinf( x ) ) || ( x == 0 && std::isinf( y ) ) ) { + feraiseexcept( FE_INVALID ); + } + return std::fma( x, y, z ); +} + +/// Fused Multiply+Add template -bool fmadd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::fma(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2), R->GetFP(Inst.rs3))); - R->AdvancePC(Inst); +bool fmadd( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, revFMA( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ), R->GetFP( Inst.rs3 ) ) ); + R->AdvancePC( Inst ); return true; } /// Fused Multiply-Subtract template -bool fmsub(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::fma(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2), -R->GetFP(Inst.rs3))); - R->AdvancePC(Inst); +bool fmsub( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, revFMA( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ), negate( R->GetFP( Inst.rs3 ) ) ) ); + R->AdvancePC( Inst ); return true; } /// Fused Negated (Multiply-Subtract) template -bool fnmsub(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) -{ - R->SetFP(Inst.rd, std::fma(-R->GetFP(Inst.rs1), R->GetFP(Inst.rs2), R->GetFP(Inst.rs3))); - R->AdvancePC(Inst); +bool fnmsub( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, revFMA( negate( R->GetFP( Inst.rs1 ) ), R->GetFP( Inst.rs2 ), R->GetFP( Inst.rs3 ) ) ); + R->AdvancePC( Inst ); return true; } -/// Fused Negated (Multiply-Add) +/// Fused Negated (Multiply+Add) template -bool fnmadd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, -std::fma(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2), R->GetFP(Inst.rs3))); - R->AdvancePC(Inst); +bool fnmadd( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, negate( revFMA( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ), R->GetFP( Inst.rs3 ) ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Square root +template +static bool fsqrt( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, std::sqrt( R->GetFP( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Transfer sign bit +template +static bool fsgnj( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, std::copysign( R->GetFP( Inst.rs1 ), R->GetFP( Inst.rs2 ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Negated transfer sign bit +template +static bool fsgnjn( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, std::copysign( R->GetFP( Inst.rs1 ), negate( R->GetFP( Inst.rs2 ) ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Xor transfer sign bit +template +static bool fsgnjx( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + T rs1 = R->GetFP( Inst.rs1 ), rs2 = R->GetFP( Inst.rs2 ); + R->SetFP( Inst.rd, std::copysign( rs1, std::signbit( rs1 ) ? negate( rs2 ) : rs2 ) ); + R->AdvancePC( Inst ); + return true; +} + +// Move floating-point register to integer register +template +static bool fmvif( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + std::make_signed_t> i; + T fp = R->GetFP( Inst.rs1 ); // The FP value + static_assert( sizeof( i ) == sizeof( fp ) ); + memcpy( &i, &fp, sizeof( i ) ); // Reinterpreted as int + R->SetX( Inst.rd, i ); // Copied to the destination register + R->AdvancePC( Inst ); + return true; +} + +// Move integer register to floating-point register +template +static bool fmvfi( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + T fp; + auto i = R->GetX>( Inst.rs1 ); // The X register + static_assert( sizeof( i ) == sizeof( fp ) ); + memcpy( &fp, &i, sizeof( fp ) ); // Reinterpreted as FP + R->SetFP( Inst.rd, fp ); // Copied to the destination register + R->AdvancePC( Inst ); + return true; +} + +// Floating-point classify +template +static bool fclassify( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, fclass( R->GetFP( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Convert integer to floating point +template +static bool fcvtfi( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, static_cast( R->GetX( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); + return true; +} + +// Convert floating point to floating point +template +static bool fcvtff( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, static_cast( R->GetFP( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); return true; } -} // namespace SST:RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevInstTable.h b/include/RevInstTable.h index 27a29efc4..d1454dd95 100644 --- a/include/RevInstTable.h +++ b/include/RevInstTable.h @@ -1,7 +1,7 @@ // // _RevInstTable_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -11,6 +11,8 @@ #ifndef _SST_REVCPU_REVINSTTABLE_H_ #define _SST_REVCPU_REVINSTTABLE_H_ +#include "RevCommon.h" +#include "RevFCSR.h" #include #include #include @@ -21,72 +23,55 @@ #include #include -#include "RevRegFile.h" - -// Register Decoding Macros -#define DECODE_RD(x) (((x)>>(7))&(0b11111)) -#define DECODE_RS1(x) (((x)>>(15))&(0b11111)) -#define DECODE_RS2(x) (((x)>>(20))&(0b11111)) -#define DECODE_RS3(x) (((x)>>(27))&(0b11111)) -#define DECODE_IMM12(x) (((x)>>(20))&(0b111111111111)) -#define DECODE_IMM20(x) (((x)>>(12))&(0b11111111111111111111)) - -#define DECODE_LOWER_CRS2(x) (((x)>>(2))&(0b11111)) - -#define DECODE_FUNCT7(x) (((x)>>(25))&(0b1111111)) -#define DECODE_FUNCT2(x) (((x)>>(25))&(0b11)) -#define DECODE_FUNCT3(x) (((x)>>(12))&(0b111)) - -#define DECODE_RM(x) static_cast(DECODE_FUNCT3(x)) -#define DECODE_RL(x) (((x)>>(25))&(0b1)) -#define DECODE_AQ(x) (((x)>>(26))&(0b1)) - -namespace SST::RevCPU{ - -/* Ref: RISC-V Priviledged Spec (pg. 39) */ -enum EXCEPTION_CAUSE : uint32_t { - MISALIGNED_INST_ADDR = 0, - INST_ACCESS_FAULT = 1, - ILLEGAL_INST = 2, - BREAKPOINT = 3, - LOAD_ADDR_MISALIGNED = 4, - LOAD_ACCESS_FAULT = 5, - STORE_AMO_ADDR_MISALIGNED = 6, - STORE_AMO_ACCESS_FAULT = 7, - ECALL_USER_MODE = 8, - ECALL_SUPERVISOR_MODE = 9, - ECALL_MACHINE_MODE = 11, - INST_PAGE_FAULT = 12, - LOAD_PAGE_FAULT = 13, - STORE_AMO_PAGE_FAULT = 15, -}; - -enum RevInstF : int { ///< Rev CPU Instruction Formats - RVTypeUNKNOWN = 0, ///< RevInstf: Unknown format - RVTypeR = 1, ///< RevInstF: R-Type - RVTypeI = 2, ///< RevInstF: I-Type - RVTypeS = 3, ///< RevInstF: S-Type - RVTypeU = 4, ///< RevInstF: U-Type - RVTypeB = 5, ///< RevInstF: B-Type - RVTypeJ = 6, ///< RevInstF: J-Type - RVTypeR4 = 7, ///< RevInstF: R4-Type for AMOs +namespace SST::RevCPU { + +// Register Decoding functions +// clang-format off +constexpr auto DECODE_RD ( uint32_t Inst ) { return BitExtract< 7, 5>( Inst ); } +constexpr auto DECODE_RS1 ( uint32_t Inst ) { return BitExtract<15, 5>( Inst ); } +constexpr auto DECODE_RS2 ( uint32_t Inst ) { return BitExtract<20, 5>( Inst ); } +constexpr auto DECODE_RS3 ( uint32_t Inst ) { return BitExtract<27, 5>( Inst ); } +constexpr auto DECODE_IMM12 ( uint32_t Inst ) { return BitExtract<20, 12>( Inst ); } +constexpr auto DECODE_IMM20 ( uint32_t Inst ) { return BitExtract<12, 20>( Inst ); } +constexpr auto DECODE_LOWER_CRS2( uint32_t Inst ) { return BitExtract< 2, 5>( Inst ); } +constexpr auto DECODE_FUNCT7 ( uint32_t Inst ) { return BitExtract<25, 7>( Inst ); } +constexpr auto DECODE_FUNCT2 ( uint32_t Inst ) { return BitExtract<25, 2>( Inst ); } +constexpr auto DECODE_FUNCT3 ( uint32_t Inst ) { return BitExtract<12, 3>( Inst ); } +constexpr auto DECODE_RL ( uint32_t Inst ) { return BitExtract<25, 1>( Inst ); } +constexpr auto DECODE_AQ ( uint32_t Inst ) { return BitExtract<26, 1>( Inst ); } +constexpr auto DECODE_RM ( uint32_t Inst ) { return FRMode{ BitExtract<12, 3>( Inst ) }; } + +// clang-format on + +enum RevInstF : int { ///< Rev CPU Instruction Formats + RVTypeUNKNOWN = 0, ///< RevInstF: Unknown format + RVTypeR = 1, ///< RevInstF: R-Type + RVTypeI = 2, ///< RevInstF: I-Type + RVTypeS = 3, ///< RevInstF: S-Type + RVTypeU = 4, ///< RevInstF: U-Type + RVTypeB = 5, ///< RevInstF: B-Type + RVTypeJ = 6, ///< RevInstF: J-Type + RVTypeR4 = 7, ///< RevInstF: R4-Type for FMAs // -- Compressed Formats - RVCTypeCR = 10, ///< RevInstF: Compressed CR-Type - RVCTypeCI = 11, ///< RevInstF: Compressed CI-Type - RVCTypeCSS = 12, ///< RevInstF: Compressed CSS-Type - RVCTypeCIW = 13, ///< RevInstF: Compressed CIW-Type - RVCTypeCL = 14, ///< RevInstF: Compressed CL-Type - RVCTypeCS = 15, ///< RevInstF: Compressed CS-Type - RVCTypeCA = 16, ///< RevInstF: Compressed CA-Type - RVCTypeCB = 17, ///< RevInstF: Compressed CB-Type - RVCTypeCJ = 18, ///< RevInstF: Compressed CJ-Type + RVCTypeCR = 10, ///< RevInstF: Compressed CR-Type + RVCTypeCI = 11, ///< RevInstF: Compressed CI-Type + RVCTypeCSS = 12, ///< RevInstF: Compressed CSS-Type + RVCTypeCIW = 13, ///< RevInstF: Compressed CIW-Type + RVCTypeCL = 14, ///< RevInstF: Compressed CL-Type + RVCTypeCS = 15, ///< RevInstF: Compressed CS-Type + RVCTypeCA = 16, ///< RevInstF: Compressed CA-Type + RVCTypeCB = 17, ///< RevInstF: Compressed CB-Type + RVCTypeCJ = 18, ///< RevInstF: Compressed CJ-Type + // -- Vector Formats + RVVTypeOpv = 32, ///< RevInstF: OPV + RVVTypeLdSt = 33, ///< RevInstF: LOAD-FP/STORE-FP }; -enum RevImmFunc : int { ///< Rev Immediate Values - FUnk = 0, ///< RevRegClass: Imm12 is not used - FImm = 1, ///< RevRegClass: Imm12 is an immediate - FEnc = 2, ///< RevRegClass: Imm12 is an encoding value - FVal = 3, ///< RevRegClass: Imm12 is an incoming register value +enum class RevImmFunc { ///< Rev Immediate Values + FUnk = 0, ///< RevRegClass: Imm12 is not used + FImm = 1, ///< RevRegClass: Imm12 is an immediate + FEnc = 2, ///< RevRegClass: Imm12 is an encoding value + FVal = 3, ///< RevRegClass: Imm12 is an incoming register value }; /*! \struct RevInst @@ -96,84 +81,47 @@ enum RevImmFunc : int { ///< Rev Immediate Values * following a successful crack + decode * */ -struct RevInst { - uint8_t opcode = 0; ///< RevInst: opcode - uint8_t funct2 = 0; ///< RevInst: compressed funct2 value - uint8_t funct3 = 0; ///< RevInst: funct3 value - uint8_t funct4 = 0; ///< RevInst: compressed funct4 value - uint8_t funct6 = 0; ///< RevInst: compressed funct6 value - uint8_t funct2or7 = 0; ///< RevInst: uncompressed funct2 or funct7 value - uint64_t rd =~0; ///< RevInst: rd value - uint64_t rs1 =~0; ///< RevInst: rs1 value - uint64_t rs2 =~0; ///< RevInst: rs2 value - uint64_t rs3 =~0; ///< RevInst: rs3 value - uint64_t imm = 0; ///< RevInst: immediate value - FRMode rm{FRMode::None}; ///< RevInst: floating point rounding mode - uint8_t aq = 0; ///< RevInst: aq field for atomic instructions - uint8_t rl = 0; ///< RevInst: rl field for atomic instructions - uint16_t offset = 0; ///< RevInst: compressed offset - uint16_t jumpTarget = 0; ///< RevInst: compressed jumpTarget - uint8_t instSize = 0; ///< RevInst: size of the instruction in bytes - bool compressed = 0; ///< RevInst: determines if the instruction is compressed - uint32_t cost = 0; ///< RevInst: the cost to execute this instruction, in clock cycles - unsigned entry = 0; ///< RevInst: Where to find this instruction in the InstTables - uint16_t hart = 0; ///< RevInst: What hart is this inst being executed on - bool isCoProcInst = 0; ///< RevInst: whether instruction is coprocessor instruction - - explicit RevInst() = default; // prevent aggregate initialization +class RevInst { +public: + uint8_t opcode = 0; ///< RevInst: opcode + uint8_t funct2 = 0; ///< RevInst: compressed funct2 value + uint8_t funct3 = 0; ///< RevInst: funct3 value + uint8_t funct4 = 0; ///< RevInst: compressed funct4 value + uint8_t funct6 = 0; ///< RevInst: compressed funct6 value + uint8_t funct2or7 = 0; ///< RevInst: uncompressed funct2 or funct7 value + uint32_t rd = ~uint32_t{}; ///< RevInst: rd value + uint32_t rs1 = ~uint32_t{}; ///< RevInst: rs1 value + uint32_t rs2 = ~uint32_t{}; ///< RevInst: rs2 value + uint32_t rs3 = ~uint32_t{}; ///< RevInst: rs3 value + uint32_t imm = 0; ///< RevInst: immediate value + bool raisefpe = 0; ///< RevInst: raises FP exceptions + FRMode rm{ FRMode::None }; ///< RevInst: floating point rounding mode + bool aq = false; ///< RevInst: aqr field for atomic instructions + bool rl = false; ///< RevInst: rel field for atomic instructions + uint16_t offset = 0; ///< RevInst: compressed offset + uint16_t jumpTarget = 0; ///< RevInst: compressed jumpTarget + uint8_t instSize = 0; ///< RevInst: size of the instruction in bytes + bool compressed = 0; ///< RevInst: determines if the instruction is compressed + uint32_t cost = 0; ///< RevInst: the cost to execute this instruction, in clock cycles + uint32_t entry = 0; ///< RevInst: Where to find this instruction in the InstTables + uint16_t hart = 0; ///< RevInst: What hart is this inst being executed on + bool isCoProcInst = 0; ///< RevInst: whether instruction is coprocessor instruction + + explicit RevInst() = default; // prevent aggregate initialization ///< RevInst: Sign-extended immediate value - constexpr int32_t ImmSignExt(size_t bits) const { - return SignExt(imm, bits); - } -}; // RevInst - -#if 0 - -/// CRegMap: Holds the compressed index to normal index mapping -// TODO: Replace with macro below if mappings are trivial -inline const std::map CRegMap = -{ - {0b000, 8}, - {0b001, 9}, - {0b010, 10}, - {0b011, 11}, - {0b100, 12}, - {0b101, 13}, - {0b110, 14}, - {0b111, 15}, -}; + constexpr auto ImmSignExt( int bits ) const { return SignExt( imm, bits ); } +}; // RevInst /// CRegIdx: Maps the compressed index to normal index -#define CRegIdx(x) (CRegMap.at(x)) +template +constexpr auto CRegIdx( T x ) { + return x + 8; +} -#else - -/// CRegIdx: Maps the compressed index to normal index -#define CRegIdx(x) ((x) + 8) - -#endif - -struct RevInstDefaults { - static constexpr uint8_t opcode = 0b00000000; - static constexpr uint32_t cost = 1; - static constexpr uint8_t funct2 = 0b000; // compressed only - static constexpr uint8_t funct3 = 0b000; - static constexpr uint8_t funct4 = 0b000; // compressed only - static constexpr uint8_t funct6 = 0b000; // compressed only - static constexpr uint8_t funct2or7 = 0b0000000; - static constexpr uint16_t offset = 0b0000000; // compressed only - static constexpr uint16_t jumpTarget = 0b0000000; // compressed only - static constexpr RevRegClass rdClass = RevRegClass::RegGPR; - static constexpr RevRegClass rs1Class = RevRegClass::RegGPR; - static constexpr RevRegClass rs2Class = RevRegClass::RegGPR; - static constexpr RevRegClass rs3Class = RevRegClass::RegUNKNOWN; - static constexpr uint16_t imm12 = 0b000000000000; - static constexpr RevImmFunc imm = FUnk; - static constexpr RevInstF format = RVTypeR; - static constexpr bool compressed = false; - static constexpr uint8_t fpcvtOp = 0b00000; // overloaded rs2 field for R-type FP instructions -}; // RevInstDefaults +class RevFeature; +class RevRegFile; +class RevMem; /*! \struct RevInstEntry * \brief Rev instruction entry @@ -182,98 +130,79 @@ struct RevInstDefaults { * a target instruction as well as its cost function * */ -struct RevInstEntry{ +struct RevInstEntry { // disassembly - std::string mnemonic; ///< RevInstEntry: instruction mnemonic - uint32_t cost; ///< RevInstEntry: instruction code in cycles + std::string mnemonic = "nop"; ///< RevInstEntry: instruction mnemonic + uint32_t cost = 1; ///< RevInstEntry: instruction code in cycles // storage - uint8_t opcode; ///< RevInstEntry: opcode - uint8_t funct2; ///< RevInstentry: compressed funct2 value - uint8_t funct3; ///< RevInstEntry: funct3 value - uint8_t funct4; ///< RevInstentry: compressed funct4 value - uint8_t funct6; ///< RevInstentry: compressed funct6 value - uint8_t funct2or7; ///< RevInstEntry: uncompressed funct2 or funct7 value - uint16_t offset; ///< RevInstEntry: compressed offset value - uint16_t jumpTarget; ///< RevInstEntry: compressed jump target value + uint8_t opcode = 0; ///< RevInstEntry: opcode + uint8_t funct2 = 0; ///< RevInstentry: compressed funct2 value + uint8_t funct3 = 0; ///< RevInstEntry: funct3 value + uint8_t funct4 = 0; ///< RevInstentry: compressed funct4 value + uint8_t funct6 = 0; ///< RevInstentry: compressed funct6 value + uint8_t funct2or7 = 0; ///< RevInstEntry: uncompressed funct2 or funct7 value + uint16_t offset = 0; ///< RevInstEntry: compressed offset value + uint16_t jumpTarget = 0; ///< RevInstEntry: compressed jump target value // register encodings - RevRegClass rdClass; ///< RevInstEntry: Rd register class - RevRegClass rs1Class; ///< RevInstEntry: Rs1 register class - RevRegClass rs2Class; ///< RevInstEntry: Rs2 register class - RevRegClass rs3Class; ///< RevInstEntry: Rs3 register class - - uint16_t imm12; ///< RevInstEntry: imm12 value - - RevImmFunc imm; ///< RevInstEntry: does the imm12 exist? + RevRegClass rdClass = RevRegClass::RegGPR; ///< RevInstEntry: Rd register class + RevRegClass rs1Class = RevRegClass::RegGPR; ///< RevInstEntry: Rs1 register class + RevRegClass rs2Class = RevRegClass::RegGPR; ///< RevInstEntry: Rs2 register class + RevRegClass rs3Class = RevRegClass::RegUNKNOWN; ///< RevInstEntry: Rs3 register class + uint16_t imm12 = 0; ///< RevInstEntry: imm12 value + RevImmFunc imm = RevImmFunc::FUnk; ///< RevInstEntry: does the imm12 exist? // formatting - RevInstF format; ///< RevInstEntry: instruction format + RevInstF format = RVTypeR; ///< RevInstEntry: instruction format + bool compressed = false; ///< RevInstEntry: compressed instruction + uint8_t rs2fcvtOp = 0; /// -struct RevInstEntryBuilder : RevInstDefaultsPolicy{ - RevInstEntry InstEntry; - - RevInstEntryBuilder() : RevInstDefaultsPolicy() { - //Set default values - InstEntry.mnemonic = std::string("nop"); - InstEntry.func = NULL; - InstEntry.opcode = RevInstDefaultsPolicy::opcode; - InstEntry.cost = RevInstDefaultsPolicy::cost; - InstEntry.funct2 = RevInstDefaultsPolicy::funct2; - InstEntry.funct3 = RevInstDefaultsPolicy::funct3; - InstEntry.funct4 = RevInstDefaultsPolicy::funct4; - InstEntry.funct6 = RevInstDefaultsPolicy::funct6; - InstEntry.funct2or7 = RevInstDefaultsPolicy::funct2or7; - InstEntry.offset = RevInstDefaultsPolicy::offset; - InstEntry.jumpTarget= RevInstDefaultsPolicy::jumpTarget; - InstEntry.rdClass = RevInstDefaultsPolicy::rdClass; - InstEntry.rs1Class = RevInstDefaultsPolicy::rs1Class; - InstEntry.rs2Class = RevInstDefaultsPolicy::rs2Class; - InstEntry.rs3Class = RevInstDefaultsPolicy::rs3Class; - InstEntry.imm12 = RevInstDefaultsPolicy::imm12; - InstEntry.imm = RevInstDefaultsPolicy::imm; - InstEntry.format = RevInstDefaultsPolicy::format; - InstEntry.compressed= false; - InstEntry.fpcvtOp = RevInstDefaultsPolicy::fpcvtOp; - } + /// Predicate for enabling table entries for only certain encodings + bool ( *predicate )( uint32_t Inst ) = []( uint32_t ) { return true; }; // Begin Set() functions to allow call chaining - all Set() must return *this - auto& SetMnemonic(std::string m) { InstEntry.mnemonic = m; return *this;} - auto& SetCost(uint32_t c) { InstEntry.cost = c; return *this;} - auto& SetOpcode(uint8_t op) { InstEntry.opcode = op; return *this;} - auto& SetFunct2(uint8_t f2) { InstEntry.funct2 = f2; return *this;} - auto& SetFunct3(uint8_t f3) { InstEntry.funct3 = f3; return *this;} - auto& SetFunct4(uint8_t f4) { InstEntry.funct4 = f4; return *this;} - auto& SetFunct6(uint8_t f6) { InstEntry.funct6 = f6; return *this;} - auto& SetFunct2or7(uint8_t f27) { InstEntry.funct2or7 = f27;return *this;} - auto& SetOffset(uint16_t off) { InstEntry.offset = off; return *this;} - auto& SetJumpTarget(uint16_t jt) { InstEntry.jumpTarget = jt;return *this;} - auto& SetrdClass(RevRegClass rd) { InstEntry.rdClass = rd; return *this;} - auto& Setrs1Class(RevRegClass rs1) { InstEntry.rs1Class = rs1; return *this;} - auto& Setrs2Class(RevRegClass rs2) { InstEntry.rs2Class = rs2; return *this;} - auto& Setrs3Class(RevRegClass rs3) { InstEntry.rs3Class = rs3; return *this;} - auto& Setimm12(uint16_t imm12) { InstEntry.imm12 = imm12; return *this;} - auto& Setimm(RevImmFunc imm) { InstEntry.imm = imm; return *this;} - auto& SetFormat(RevInstF format) { InstEntry.format = format;return *this;} - auto& SetCompressed(bool c) { InstEntry.compressed = c; return *this;} - auto& SetfpcvtOp(uint8_t op) { InstEntry.fpcvtOp = op; return *this;} - - auto& SetImplFunc(bool func(RevFeature *, RevRegFile *, RevMem *, const RevInst&)){ - InstEntry.func = func; - return *this; - } - -}; // class RevInstEntryBuilder; + // clang-format off + auto& SetMnemonic(std::string m) { this->mnemonic = std::move(m); return *this; } + auto& SetCost(uint32_t c) { this->cost = c; return *this; } + auto& SetOpcode(uint8_t op) { this->opcode = op; return *this; } + auto& SetFunct2(uint8_t f2) { this->funct2 = f2; return *this; } + auto& SetFunct3(uint8_t f3) { this->funct3 = f3; return *this; } + auto& SetFunct4(uint8_t f4) { this->funct4 = f4; return *this; } + auto& SetFunct6(uint8_t f6) { this->funct6 = f6; return *this; } + auto& SetFunct2or7(uint8_t f27) { this->funct2or7 = f27; return *this; } + auto& SetOffset(uint16_t off) { this->offset = off; return *this; } + auto& SetJumpTarget(uint16_t jt) { this->jumpTarget = jt; return *this; } + auto& SetrdClass(RevRegClass rd) { this->rdClass = rd; return *this; } + auto& Setrs1Class(RevRegClass rs1) { this->rs1Class = rs1; return *this; } + auto& Setrs2Class(RevRegClass rs2) { this->rs2Class = rs2; return *this; } + auto& Setrs3Class(RevRegClass rs3) { this->rs3Class = rs3; return *this; } + auto& Setimm12(uint16_t imm12) { this->imm12 = imm12; return *this; } + auto& Setimm(RevImmFunc imm) { this->imm = imm; return *this; } + auto& SetFormat(RevInstF format) { this->format = format;return *this; } + auto& SetCompressed(bool c) { this->compressed = c; return *this; } + auto& Setrs2fcvtOp(uint8_t op) { this->rs2fcvtOp = op; return *this; } + auto& SetRaiseFPE(bool c) { this->raisefpe = c; return *this; } + auto& SetImplFunc( bool func( const RevFeature *, RevRegFile *, RevMem *, const RevInst& ) ) + { this->func = func; return *this; } + auto& SetPredicate( bool pred( uint32_t ) ) + { this->predicate = pred; return *this; } + + // clang-format on +}; // RevInstEntry + +// The default initialization for RevInstDefaults is the same as RevInstEntry +using RevInstDefaults = RevInstEntry; + +// Compressed instruction defaults +struct RevCInstDefaults : RevInstDefaults { + RevCInstDefaults() { SetCompressed( true ); } +}; -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevLoader.h b/include/RevLoader.h index 30913b818..c59ddcc4b 100644 --- a/include/RevLoader.h +++ b/include/RevLoader.h @@ -1,7 +1,7 @@ // // _RevLoader_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -12,17 +12,17 @@ #define _SST_REVCPU_REVLOADER_H_ // -- Standard Headers -#include +#include #include -#include -#include -#include #include +#include +#include +#include +#include #include -#include +#include #include -#include -#include +#include // -- SST Headers #include "SST.h" @@ -39,125 +39,123 @@ #endif /* Legal values for e_type (object file type). */ -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 /* Number of defined types */ -#define ET_LOOS 0xfe00 /* OS-specific range start */ -#define ET_HIOS 0xfeff /* OS-specific range end */ -#define ET_LOPROC 0xff00 /* Processor-specific range start */ -#define ET_HIPROC 0xffff /* Processor-specific range end */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ /* Legal values for e_machine (architecture). */ -#define EM_NONE 0 /* No machine */ -#define EM_RISCV 243 /* RISC-V */ +#define EM_NONE 0 /* No machine */ +#define EM_RISCV 243 /* RISC-V */ /* Legal values for e_version (version). */ -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 /* Special section indices. */ -#define SHN_UNDEF 0 /* Undefined section */ -#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ -#define SHN_LOPROC 0xff00 /* Start of processor-specific */ -#define SHN_HIPROC 0xff1f /* End of processor-specific */ -#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ -#define SHN_COMMON 0xfff2 /* Associated symbol is common */ -#define SHN_XINDEX 0xffff /* Index is in extra table. */ -#define SHN_HIRESERVE 0xffff /* End of reserved indices */ +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ /* Legal values for sh_type (section type). */ -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ -#define SHT_NUM 19 /* Number of defined types. */ -#define SHT_LOOS 0x60000000 /* Start OS-specific. */ -#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ -#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ -#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ -#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ -#define SHT_HIOS 0x6fffffff /* End OS-specific type */ -#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ -#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ -#define SHT_LOUSER 0x80000000 /* Start of application-specific */ -#define SHT_HIUSER 0x8fffffff /* End of application-specific */ +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ /* Legal values for sh_flags (section flags). */ -#define SHF_WRITE (1 << 0) /* Writable */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable */ -#define SHF_MERGE (1 << 4) /* Might be merged */ -#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ -#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ -#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ -#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling required */ -#define SHF_GROUP (1 << 9) /* Section is member of a group. */ -#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ -#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ -#define SHF_GNU_RETAIN (1 << 21) /* Not to be GCed by linker. */ +#define SHF_WRITE ( 1 << 0 ) /* Writable */ +#define SHF_ALLOC ( 1 << 1 ) /* Occupies memory during execution */ +#define SHF_EXECINSTR ( 1 << 2 ) /* Executable */ +#define SHF_MERGE ( 1 << 4 ) /* Might be merged */ +#define SHF_STRINGS ( 1 << 5 ) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK ( 1 << 6 ) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER ( 1 << 7 ) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING ( 1 << 8 ) /* Non-standard OS specific handling required */ +#define SHF_GROUP ( 1 << 9 ) /* Section is member of a group. */ +#define SHF_TLS ( 1 << 10 ) /* Section hold thread-local data. */ +#define SHF_COMPRESSED ( 1 << 11 ) /* Section with compressed data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_GNU_RETAIN ( 1 << 21 ) /* Not to be GCed by linker. */ /* Legal values for p_type (segment type). */ -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local storage segment */ -#define PT_NUM 8 /* Number of defined types */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ -#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ -#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_GNU_PROPERTY 0x6474e553 /* GNU property */ -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_GNU_PROPERTY 0x6474e553 /* GNU property */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ /* Legal values for p_flags (segment flags). */ -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKOS 0x0ff00000 /* OS-specific */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific */ - - +#define PF_X ( 1 << 0 ) /* Segment is executable */ +#define PF_W ( 1 << 1 ) /* Segment is writable */ +#define PF_R ( 1 << 2 ) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ /* Section group handling. */ -#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ //template static inline T from_le(T n) { return n; } -namespace SST::RevCPU{ +namespace SST::RevCPU { -struct Elf32_Ehdr{ +struct Elf32_Ehdr { uint8_t e_ident[16]; uint16_t e_type; uint16_t e_machine; @@ -174,7 +172,7 @@ struct Elf32_Ehdr{ uint16_t e_shstrndx; }; -struct Elf32_Shdr{ +struct Elf32_Shdr { uint32_t sh_name; uint32_t sh_type; uint32_t sh_flags; @@ -187,7 +185,7 @@ struct Elf32_Shdr{ uint32_t sh_entsize; }; -struct Elf32_Phdr{ +struct Elf32_Phdr { uint32_t p_type; uint32_t p_offset; uint32_t p_vaddr; @@ -198,7 +196,7 @@ struct Elf32_Phdr{ uint32_t p_align; }; -struct Elf32_Sym{ +struct Elf32_Sym { uint32_t st_name; uint32_t st_value; uint32_t st_size; @@ -207,7 +205,7 @@ struct Elf32_Sym{ uint16_t st_shndx; }; -struct Elf64_Ehdr{ +struct Elf64_Ehdr { uint8_t e_ident[16]; uint16_t e_type; uint16_t e_machine; @@ -224,7 +222,7 @@ struct Elf64_Ehdr{ uint16_t e_shstrndx; }; -struct Elf64_Shdr{ +struct Elf64_Shdr { uint32_t sh_name; uint32_t sh_type; uint64_t sh_flags; @@ -237,7 +235,7 @@ struct Elf64_Shdr{ uint64_t sh_entsize; }; -struct Elf64_Phdr{ +struct Elf64_Phdr { uint32_t p_type; uint32_t p_flags; uint64_t p_offset; @@ -248,7 +246,7 @@ struct Elf64_Phdr{ uint64_t p_align; }; -struct Elf64_Sym{ +struct Elf64_Sym { uint32_t st_name; uint8_t st_info; uint8_t st_other; @@ -257,19 +255,19 @@ struct Elf64_Sym{ uint64_t st_size; }; -struct ElfInfo{ - int phent; - int phnum; - int is_supervisor; - size_t phdr; - size_t phdr_size; - size_t bias; - size_t entry; - size_t brk_min; - size_t brk; - size_t brk_max; - size_t mmap_max; - size_t stack_top; +struct ElfInfo { + int phent; + int phnum; + int is_supervisor; + size_t phdr; + size_t phdr_size; + size_t bias; + size_t entry; + size_t brk_min; + size_t brk; + size_t brk_max; + size_t mmap_max; + size_t stack_top; uint64_t time0; uint64_t cycle0; uint64_t instret0; @@ -278,28 +276,27 @@ struct ElfInfo{ class RevLoader { public: /// RevLoader: standard constructor - RevLoader( std::string Exe, std::string Args, RevMem *Mem, SST::Output *Output ); + RevLoader( const std::string& exe, const std::vector& args, RevMem* mem, SST::Output* output ) + : mem( mem ), output( output ) { + if( !LoadElf( exe, args ) ) + output->fatal( CALL_INFO, -1, "Error: failed to load executable into memory\n" ); + } /// RevLoader: standard destructor - ~RevLoader(); - - /// RevLoader: retrieves the address for the target symbol; 0x00ull if the symbol doesn't exist - uint64_t GetSymbolAddr(std::string Symbol); + ~RevLoader() = default; - /// RevLoader: retrieves the value for 'argc' - auto GetArgc() { return argv.size(); } + /// RevLoader: disallow copying and assignment + RevLoader( const RevLoader& ) = delete; + RevLoader& operator=( const RevLoader& ) = delete; - /// RevLoader: retrieves the target value within the argv array - std::string GetArgv(unsigned entry); - - /// RevLoader: retrieve the entire argv vector - std::vector GetArgv() { return argv; } + /// RevLoader: retrieves the address for the target symbol; 0x00ull if the symbol doesn't exist + uint64_t GetSymbolAddr( std::string Symbol ); /// RevLoader: retrieves the elf info structure ElfInfo GetInfo() { return elfinfo; } /// RevLoader: symbol lookup for tracer - std::map* GetTraceSymbols(); + std::map* GetTraceSymbols(); /// RevLoader: Gets TLS base address const uint64_t& GetTLSBaseAddr() { return TLSBaseAddr; } @@ -310,29 +307,25 @@ class RevLoader { // friend std::ostream& operator<<(std::ostream &os, const Elf64_Ehdr &header){ }; private: - std::string exe; ///< RevLoader: binary executable - std::string args; ///< RevLoader: program args - RevMem *mem; ///< RevLoader: memory object - SST::Output *output; ///< RevLoader: output handler - - uint32_t RV32Entry; ///< RevLoader: RV32 entry - uint64_t RV64Entry; ///< RevLoader: RV64 entry + RevMem* mem{}; ///< RevLoader: memory object + SST::Output* output{}; ///< RevLoader: output handler - uint64_t TLSBaseAddr = 0; - uint64_t TLSSize = 0; + uint32_t RV32Entry{}; ///< RevLoader: RV32 entry + uint64_t RV64Entry{}; ///< RevLoader: RV64 entry - ElfInfo elfinfo; ///< RevLoader: elf info from the loaded program + uint64_t TLSBaseAddr{}; + uint64_t TLSSize{}; - std::map symtable; ///< RevLoader: loaded symbol table - std::map tracer_symbols; ///< RevLoader: address to symbol for tracer - - std::vector argv; ///< RevLoader: The actual argv table + ElfInfo elfinfo{}; ///< RevLoader: elf info from the loaded program + std::map symtable{}; ///< RevLoader: loaded symbol table + std::map tracer_symbols{}; ///< RevLoader: address to symbol for tracer /// Loads the target executable into memory - bool LoadElf(); + bool LoadElf( const std::string& exe, const std::vector& args ); /// Loads the target program arguments - bool LoadProgramArgs(); + template + bool LoadProgramArgs( const std::string& exe, const std::vector& args ); /// Determines if the target header is an Elf header bool IsElf( const Elf64_Ehdr eh64 ); @@ -350,23 +343,20 @@ class RevLoader { bool IsRVBig( const Elf64_Ehdr eh64 ); /// Loads a 32bit Elf binary - bool LoadElf32(char *MemBuf, size_t Size); + bool LoadElf32( char* MemBuf, size_t Size ); /// Loads a 64bit Elf binary - bool LoadElf64(char *MemBuf, size_t Size); - - ///< Splits a string into tokens - void splitStr(const std::string& s, char c, std::vector& v); + bool LoadElf64( char* MemBuf, size_t Size ); ///< Breaks bulk writes into cache lines - bool WriteCacheLine(uint64_t Addr, size_t Len, void *Data); + bool WriteCacheLine( uint64_t Addr, uint32_t Len, const void* Data ); ///< RevLoader: Replaces first MemSegment (initialized to entire memory space) with the static memory void InitStaticMem(); -}; // class Loader +}; // class Loader -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevMem.h b/include/RevMem.h index 60770b53b..c8f543814 100644 --- a/include/RevMem.h +++ b/include/RevMem.h @@ -1,7 +1,7 @@ // // _RevMem_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -35,180 +35,171 @@ #include "SST.h" // -- RevCPU Headers -#include "RevOpts.h" +#include "RevCommon.h" #include "RevMemCtrl.h" -#include "RevTracer.h" +#include "RevOpts.h" #include "RevRand.h" -#include "../common/include/RevCommon.h" +#include "RevTracer.h" #ifndef _REVMEM_BASE_ #define _REVMEM_BASE_ 0x00000000 #endif -#define _STACK_SIZE_ (size_t{1024*1024}) +#define _STACK_SIZE_ ( size_t{ 1024 * 1024 } ) -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RevMem{ +class RevMem { public: /// RevMem: standard constructor - RevMem( uint64_t MemSize, RevOpts *Opts, SST::Output *Output ); + RevMem( uint64_t MemSize, RevOpts* Opts, SST::Output* Output ); /// RevMem: standard memory controller constructor - RevMem( uint64_t MemSize, RevOpts *Opts, RevMemCtrl *Ctrl, SST::Output *Output ); + RevMem( uint64_t memSize, RevOpts* opts, RevMemCtrl* ctrl, SST::Output* output ); /// RevMem: standard destructor - ~RevMem(){ - delete[] physMem; - } + ~RevMem() { delete[] physMem; } + + /// RevMem: disallow copying and assignment + RevMem( const RevMem& ) = delete; + RevMem& operator=( const RevMem& ) = delete; /* Virtual Memory Blocks */ class MemSegment { public: - MemSegment(uint64_t baseAddr, uint64_t size) - : BaseAddr(baseAddr), Size(size) { - TopAddr = baseAddr + size; - } // Permissions(permissions) {} + MemSegment( uint64_t baseAddr, uint64_t size ) : BaseAddr( baseAddr ), Size( size ), TopAddr( baseAddr + size ) {} uint64_t getTopAddr() const { return BaseAddr + Size; } + uint64_t getBaseAddr() const { return BaseAddr; } + uint64_t getSize() const { return Size; } - void setBaseAddr(uint64_t baseAddr) { + void setBaseAddr( uint64_t baseAddr ) { BaseAddr = baseAddr; - if( Size ){ + if( Size ) { TopAddr = Size + BaseAddr; } } - void setSize(uint64_t size) { Size = size; TopAddr = BaseAddr + size; } + void setSize( uint64_t size ) { + Size = size; + TopAddr = BaseAddr + size; + } /// MemSegment: Check if vAddr is included in this segment - bool contains(const uint64_t& vAddr){ - return (vAddr >= BaseAddr && vAddr < TopAddr); - }; + bool contains( const uint64_t& vAddr ) { return ( vAddr >= BaseAddr && vAddr < TopAddr ); }; // Check if a given range is inside a segment - bool contains(const uint64_t& vBaseAddr, const uint64_t& Size){ + bool contains( const uint64_t& vBaseAddr, const uint64_t& Size ) { // exclusive top address uint64_t vTopAddr = vBaseAddr + Size - 1; - return (this->contains(vBaseAddr) && this->contains(vTopAddr)); + return contains( vBaseAddr ) && contains( vTopAddr ); }; + /// MemSegment: Override for easy std::cout << *Seg << std::endl; + friend std::ostream& operator<<( std::ostream& os, const MemSegment& Seg ) { + os << "| 0x" << std::hex << std::setw( 16 ) << std::setfill( '0' ) << Seg.getBaseAddr() << " | 0x" << std::hex + << std::setw( 16 ) << std::setfill( '0' ) << Seg.getTopAddr() << " | " << std::dec << std::setw( 10 ) + << std::setfill( ' ' ) << Seg.getSize() << " Bytes |"; - // Override for easy std::cout << *Seg << std::endl; - friend std::ostream& operator<<(std::ostream& os, const MemSegment& Seg) { - return os << " | BaseAddr: 0x" << std::hex << Seg.getBaseAddr() << " | TopAddr: 0x" << std::hex << Seg.getTopAddr() << " | Size: " << std::dec << Seg.getSize() << " Bytes"; + return os; } + /// MemSegment: Override the less than operator + bool operator<( const MemSegment& other ) const { return BaseAddr < other.BaseAddr; } + + /// MemSegment: Override the greater than operator + bool operator>( const MemSegment& other ) const { return BaseAddr > other.BaseAddr; } + + /// MemSegment: Override the equality operator + bool operator==( const MemSegment& other ) const { return BaseAddr == other.BaseAddr; } + + /// MemSegment: Override the not equal operator + bool operator!=( const MemSegment& other ) const { return BaseAddr != other.BaseAddr; } + + /// MemSegment: Override the less than or equal operator + bool operator<=( const MemSegment& other ) const { return BaseAddr <= other.BaseAddr; } + + /// MemSegment: Override the greater than or equal operator + bool operator>=( const MemSegment& other ) const { return BaseAddr >= other.BaseAddr; } + private: - uint64_t BaseAddr; - uint64_t Size; - uint64_t TopAddr; + uint64_t BaseAddr{}; ///< MemSegment: Base address of the memory segment + uint64_t Size{}; ///< MemSegment: Size of the memory segment + uint64_t TopAddr{}; ///< MemSegment: Top address of the memory segment }; /// RevMem: determine if there are any outstanding requests bool outstandingRqsts(); /// RevMem: handle incoming memory event - void handleEvent(Interfaces::StandardMem::Request* ev) { } + void handleEvent( Interfaces::StandardMem::Request* ev ) {} /// RevMem: handle memory injection - void HandleMemFault(unsigned width); + void HandleMemFault( uint32_t width ); /// RevMem: get the stack_top address uint64_t GetStackTop() { return stacktop; } /// RevMem: set the stack_top address - void SetStackTop(uint64_t Addr) { stacktop = Addr; } + void SetStackTop( uint64_t Addr ) { stacktop = Addr; } /// RevMem: tracer pointer - RevTracer *Tracer = nullptr; + RevTracer* Tracer = nullptr; /// RevMem: retrieve the address of the top of memory (not stack) - uint64_t GetMemTop() { return (_REVMEM_BASE_ + memSize); } + uint64_t GetMemTop() { return ( _REVMEM_BASE_ + memSize ); } /// RevMem: get the stack_top address uint64_t GetStackBottom() { return stacktop - _STACK_SIZE_; } /// RevMem: initiate a memory fence - bool FenceMem(unsigned Hart); + bool FenceMem( uint32_t Hart ); /// RevMem: retrieves the cache line size. Returns 0 if no cache is configured - unsigned getLineSize(){ return ctrl ? ctrl->getLineSize() : 64;} + uint32_t getLineSize() { return ctrl ? ctrl->getLineSize() : 64; } /// RevMem: Enable tracing of load and store instructions. - void SetTracer(RevTracer* tracer) { Tracer = tracer; } + void SetTracer( RevTracer* tracer ) { Tracer = tracer; } // ---------------------------------------------------- // ---- Base Memory Interfaces // ---------------------------------------------------- - /// RevMem: write to the target memory location - bool WriteMem( unsigned Hart, uint64_t Addr, size_t Len, const void *Data ); - /// RevMem: write to the target memory location with the target flags - bool WriteMem( unsigned Hart, uint64_t Addr, size_t Len, const void *Data, - RevFlag flags ); + bool WriteMem( uint32_t Hart, uint64_t Addr, uint32_t Len, const void* Data, RevFlag flags = RevFlag::F_NONE ); /// RevMem: read data from the target memory location - bool ReadMem( unsigned Hart, uint64_t Addr, size_t Len, void *Target, - const MemReq& req, - RevFlag flags); + bool ReadMem( uint32_t Hart, uint64_t Addr, uint32_t Len, void* Target, const MemReq& req, RevFlag flags = RevFlag::F_NONE ); /// RevMem: flush a cache line - bool FlushLine( unsigned Hart, uint64_t Addr ); + bool FlushLine( uint32_t Hart, uint64_t Addr ); /// RevMem: invalidate a cache line - bool InvLine( unsigned Hart, uint64_t Addr ); + bool InvLine( uint32_t Hart, uint64_t Addr ); /// RevMem: clean a line - bool CleanLine( unsigned Hart, uint64_t Addr ); - - /// RevMem: DEPRECATED: read data from the target memory location - [[deprecated("Simple RevMem interfaces have been deprecated")]] - bool ReadMem( uint64_t Addr, size_t Len, void *Data ); - - [[deprecated("ReadU* interfaces have been deprecated")]] - uint64_t ReadU64( uint64_t Addr ){ - uint64_t Value; - if( !ReadMem( Addr, sizeof(Value), &Value ) ) - output->fatal(CALL_INFO, -1, "Error: could not read memory (U64)\n"); - return Value; - } + bool CleanLine( uint32_t Hart, uint64_t Addr ); // ---------------------------------------------------- // ---- Read Memory Interfaces // ---------------------------------------------------- /// RevMem: template read memory interface - template - bool ReadVal( unsigned Hart, uint64_t Addr, T *Target, - const MemReq& req, - RevFlag flags){ - return ReadMem(Hart, Addr, sizeof(T), Target, req, flags); + template + bool ReadVal( uint32_t Hart, uint64_t Addr, T* Target, const MemReq& req, RevFlag flags ) { + return ReadMem( Hart, Addr, sizeof( T ), Target, req, flags ); } - /// RevMem: template LOAD RESERVE memory interface - template - bool LR( unsigned Hart, uint64_t Addr, T *Target, - uint8_t aq, uint8_t rl, const MemReq& req, - RevFlag flags){ - return LRBase(Hart, Addr, sizeof(T), Target, aq, rl, req, flags); - } + /// RevMem: LOAD RESERVE memory interface + void LR( uint32_t hart, uint64_t addr, size_t len, void* target, const MemReq& req, RevFlag flags ); - /// RevMem: template STORE CONDITIONAL memory interface - template - bool SC( unsigned Hart, uint64_t Addr, T *Data, T *Target, - uint8_t aq, uint8_t rl, - RevFlag flags){ - return SCBase(Hart, Addr, sizeof(T), Data, Target, aq, rl, flags); - } + /// RevMem: STORE CONDITIONAL memory interface + bool SC( uint32_t Hart, uint64_t addr, uint32_t len, void* data, RevFlag flags ); /// RevMem: template AMO memory interface - template - bool AMOVal( unsigned Hart, uint64_t Addr, T *Data, T *Target, - const MemReq& req, - RevFlag flags){ - return AMOMem(Hart, Addr, sizeof(T), Data, Target, req, flags); + template + bool AMOVal( uint32_t Hart, uint64_t Addr, T* Data, T* Target, const MemReq& req, RevFlag flags ) { + return AMOMem( Hart, Addr, uint32_t{ sizeof( T ) }, Data, Target, req, flags ); } // ---------------------------------------------------- @@ -216,38 +207,31 @@ class RevMem{ // ---------------------------------------------------- template - void Write( unsigned Hart, uint64_t Addr, T Value ){ - if( std::is_same_v){ + void Write( uint32_t Hart, uint64_t Addr, T Value ) { + if( std::is_same_v ) { memStats.floatsWritten++; - }else if(std::is_same_v){ + } else if( std::is_same_v ) { memStats.doublesWritten++; } - if( !WriteMem(Hart, Addr, sizeof(T), &Value) ){ - output->fatal(CALL_INFO, -1, std::is_floating_point_v ? - "Error: could not write memory (FP%zu)\n" : - "Error: could not write memory (U%zu)\n", - sizeof(T) * 8); + if( !WriteMem( Hart, Addr, sizeof( T ), &Value ) ) { + output->fatal( + CALL_INFO, + -1, + std::is_floating_point_v ? "Error: could not write memory (FP%zu)\n" : "Error: could not write memory (U%zu)\n", + sizeof( T ) * 8 + ); } } // ---------------------------------------------------- // ---- Atomic/Future/LRSC Interfaces // ---------------------------------------------------- - /// RevMem: Add a memory reservation for the target address - bool LRBase(unsigned Hart, uint64_t Addr, size_t Len, - void *Data, uint8_t aq, uint8_t rl, const MemReq& req, - RevFlag flags); - - /// RevMem: Clear a memory reservation for the target address - bool SCBase(unsigned Hart, uint64_t Addr, size_t Len, - void *Data, void *Target, uint8_t aq, uint8_t rl, - RevFlag flags); - /// RevMem: Initiated an AMO request - bool AMOMem(unsigned Hart, uint64_t Addr, size_t Len, - void *Data, void *Target, const MemReq& req, - RevFlag flags); + bool AMOMem( uint32_t Hart, uint64_t Addr, uint32_t Len, void* Data, void* Target, const MemReq& req, RevFlag flags ); + + /// RevMem: Invalidate Matching LR reservations + bool InvalidateLRReservations( uint32_t hart, uint64_t addr, size_t len ); /// RevMem: Initiates a future operation [RV64P only] bool SetFuture( uint64_t Addr ); @@ -259,67 +243,76 @@ class RevMem{ bool StatusFuture( uint64_t Addr ); /// RevMem: Randomly assign a memory cost - unsigned RandCost( unsigned Min, unsigned Max ) { return RevRand(Min, Max); } + uint32_t RandCost( uint32_t Min, uint32_t Max ) { return RevRand( Min, Max ); } /// RevMem: Used to access & incremenet the global software PID counter uint32_t GetNewThreadPID(); /// RevMem: Used to set the size of the TLBSize - void SetTLBSize(unsigned numEntries){ tlbSize = numEntries; } + void SetTLBSize( uint32_t numEntries ) { tlbSize = numEntries; } /// RevMem: Used to set the size of the TLBSize - void SetMaxHeapSize(const unsigned MaxHeapSize){ maxHeapSize = MaxHeapSize; } + void SetMaxHeapSize( uint64_t MaxHeapSize ) { maxHeapSize = MaxHeapSize; } /// RevMem: Get memSize value set in .py file uint64_t GetMemSize() const { return memSize; } - /// RevMem: Sets the next stack top address - void SetNextThreadMemAddr(const uint64_t& NextAddr){ NextThreadMemAddr = NextAddr; } - ///< RevMem: Get MemSegs vector - std::vector>& GetMemSegs(){ return MemSegs; } + std::vector>& GetMemSegs() { return MemSegs; } ///< RevMem: Get ThreadMemSegs vector - std::vector>& GetThreadMemSegs(){ return ThreadMemSegs; } + std::vector>& GetThreadMemSegs() { return ThreadMemSegs; } ///< RevMem: Get FreeMemSegs vector - std::vector>& GetFreeMemSegs(){ return FreeMemSegs; } + std::vector>& GetFreeMemSegs() { return FreeMemSegs; } + + ///< RevMem: Get DumpRanges vector + std::map>& GetDumpRanges() { return DumpRanges; } + + ///< RevMem: Get DumpRanges vector (const version) + const std::map>& GetDumpRanges() const { return DumpRanges; } /// RevMem: Add new MemSegment (anywhere) --- Returns BaseAddr of segment - uint64_t AddMemSeg(const uint64_t& SegSize); + uint64_t AddMemSeg( const uint64_t& SegSize ); /// RevMem: Add new thread mem (starting at TopAddr [growing down]) std::shared_ptr AddThreadMem(); /// RevMem: Add new MemSegment (starting at BaseAddr) - uint64_t AddMemSegAt(const uint64_t& BaseAddr, const uint64_t& SegSize); + uint64_t AddMemSegAt( const uint64_t& BaseAddr, const uint64_t& SegSize ); /// RevMem: Add new MemSegment (starting at BaseAddr) and round it up to the nearest page - uint64_t AddRoundedMemSeg(uint64_t BaseAddr, const uint64_t& SegSize, size_t RoundUpSize); + uint64_t AddRoundedMemSeg( uint64_t BaseAddr, const uint64_t& SegSize, size_t RoundUpSize ); + + /// RevMem: Add new MemSegment that will be dumped at the dump points specified in the configuration + void AddDumpRange( const std::string& Name, const uint64_t BaseAddr, const uint64_t SegSize ); /// RevMem: Removes or shrinks segment - uint64_t DeallocMem(uint64_t BaseAddr, uint64_t Size); + uint64_t DeallocMem( uint64_t BaseAddr, uint64_t Size ); /// RevMem: Removes or shrinks segment - uint64_t AllocMem(const uint64_t& Size); + uint64_t AllocMem( const uint64_t& Size ); /// RevMem: Attempts to allocate memory at a specific address - uint64_t AllocMemAt(const uint64_t& BaseAddr, const uint64_t& Size); + uint64_t AllocMemAt( const uint64_t& BaseAddr, const uint64_t& Size ); /// RevMem: Sets the HeapStart & HeapEnd to EndOfStaticData - void InitHeap(const uint64_t& EndOfStaticData); + void InitHeap( const uint64_t& EndOfStaticData ); + + void SetHeapStart( const uint64_t& HeapStart ) { heapstart = HeapStart; } - void SetHeapStart(const uint64_t& HeapStart){ heapstart = HeapStart; } - void SetHeapEnd(const uint64_t& HeapEnd){ heapend = HeapEnd; } - const uint64_t& GetHeapEnd(){ return heapend; } + void SetHeapEnd( const uint64_t& HeapEnd ) { heapend = HeapEnd; } - uint64_t ExpandHeap(uint64_t Size); + const uint64_t& GetHeapEnd() { return heapend; } - void SetTLSInfo(const uint64_t& BaseAddr, const uint64_t& Size); + uint64_t ExpandHeap( uint64_t Size ); + + void SetTLSInfo( const uint64_t& BaseAddr, const uint64_t& Size ); // RevMem: Used to get the TLS BaseAddr & Size - const uint64_t& GetTLSBaseAddr(){ return TLSBaseAddr; } - const uint64_t& GetTLSSize(){ return TLSSize; } + const uint64_t& GetTLSBaseAddr() { return TLSBaseAddr; } + + const uint64_t& GetTLSSize() { return TLSSize; } struct RevMemStats { uint64_t TLBHits; @@ -332,17 +325,17 @@ class RevMem{ uint64_t bytesWritten; }; - RevMemStats GetAndClearStats(){ + RevMemStats GetAndClearStats() { // Add each field from memStats into memStatsTotal - for(auto stat : { - &RevMemStats::TLBHits, - &RevMemStats::TLBMisses, - &RevMemStats::floatsRead, - &RevMemStats::floatsWritten, - &RevMemStats::doublesRead, - &RevMemStats::doublesWritten, - &RevMemStats::bytesRead, - &RevMemStats::bytesWritten}){ + for( auto stat : + { &RevMemStats::TLBHits, + &RevMemStats::TLBMisses, + &RevMemStats::floatsRead, + &RevMemStats::floatsWritten, + &RevMemStats::doublesRead, + &RevMemStats::doublesWritten, + &RevMemStats::bytesRead, + &RevMemStats::bytesWritten } ) { memStatsTotal.*stat += memStats.*stat; } @@ -351,65 +344,71 @@ class RevMem{ return ret; } -RevMemStats GetMemStatsTotal() const { - return memStatsTotal; - } + RevMemStats GetMemStatsTotal() const { return memStatsTotal; } + + /// RevMem: Dump the memory contents + void DumpMem( + const uint64_t startAddr, const uint64_t numBytes, const uint64_t bytesPerRow = 16, std::ostream& outputStream = std::cout + ); + + void DumpValidMem( const uint64_t bytesPerRow = 16, std::ostream& outputStream = std::cout ); + + void DumpMemSeg( + const std::shared_ptr& MemSeg, const uint64_t bytesPerRow = 16, std::ostream& outputStream = std::cout + ); + + void DumpThreadMem( const uint64_t bytesPerRow = 16, std::ostream& outputStream = std::cout ); protected: - char *physMem = nullptr; ///< RevMem: memory container + unsigned char* physMem = nullptr; ///< RevMem: memory container private: - RevMemStats memStats = {}; - RevMemStats memStatsTotal = {}; - - unsigned long memSize; ///< RevMem: size of the target memory - unsigned tlbSize; ///< RevMem: number of entries in the TLB - unsigned maxHeapSize; ///< RevMem: maximum size of the heap - std::unordered_map::iterator>> TLB; - std::list LRUQueue; ///< RevMem: List ordered by last access for implementing LRU policy when TLB fills up - RevOpts *opts; ///< RevMem: options object - RevMemCtrl *ctrl; ///< RevMem: memory controller object - SST::Output *output; ///< RevMem: output handler - - - std::vector> MemSegs; // Currently Allocated MemSegs - std::vector> FreeMemSegs; // MemSegs that have been unallocated - std::vector> ThreadMemSegs; // For each RevThread there is a corresponding MemSeg that contains TLS & Stack - - uint64_t TLSBaseAddr; ///< RevMem: TLS Base Address - uint64_t TLSSize = sizeof(uint32_t); ///< RevMem: TLS Size (minimum size is enough to write the TID) - uint64_t ThreadMemSize = _STACK_SIZE_; ///< RevMem: Size of a thread's memory segment (StackSize + TLSSize) - uint64_t NextThreadMemAddr = memSize-1024; ///< RevMem: Next top address for a new thread's memory (starts at the point the 1024 bytes for argc/argv ends) - - uint64_t SearchTLB(uint64_t vAddr); ///< RevMem: Used to check the TLB for an entry - void AddToTLB(uint64_t vAddr, uint64_t physAddr); ///< RevMem: Used to add a new entry to TLB & LRUQueue - void FlushTLB(); ///< RevMem: Used to flush the TLB & LRUQueue - uint64_t CalcPhysAddr(uint64_t pageNum, uint64_t vAddr); ///< RevMem: Used to calculate the physical address based on virtual address - bool isValidVirtAddr(uint64_t vAddr); ///< RevMem: Used to check if a virtual address exists in MemSegs - - std::map> pageMap; ///< RevMem: map of logical to pair - uint32_t pageSize; ///< RevMem: size of allocated pages - uint32_t addrShift; ///< RevMem: Bits to shift to caclulate page of address - uint32_t nextPage; ///< RevMem: next physical page to be allocated. Will result in index + RevMemStats memStats{}; + RevMemStats memStatsTotal{}; + + uint64_t memSize{}; ///< RevMem: size of the target memory + uint32_t tlbSize{}; ///< RevMem: number of entries in the TLB + uint64_t maxHeapSize{}; ///< RevMem: maximum size of the heap + std::unordered_map::iterator>> TLB{}; + std::list LRUQueue{}; ///< RevMem: List ordered by last access for implementing LRU policy when TLB fills up + RevOpts* opts{}; ///< RevMem: options object + RevMemCtrl* ctrl{}; ///< RevMem: memory controller object + SST::Output* output{}; ///< RevMem: output handler + + std::vector> MemSegs{}; // Currently Allocated MemSegs + std::vector> FreeMemSegs{}; // MemSegs that have been unallocated + std::vector> ThreadMemSegs{}; // For each RevThread there is a corresponding MemSeg (TLS & Stack) + std::map> DumpRanges{}; // Mem ranges to dump at points specified in the configuration + + uint64_t TLSBaseAddr = 0; ///< RevMem: TLS Base Address + uint64_t TLSSize = sizeof( uint32_t ); ///< RevMem: TLS Size (minimum size is enough to write the TID) + uint64_t ThreadMemSize = _STACK_SIZE_; ///< RevMem: Size of a thread's memory segment (StackSize + TLSSize) + uint64_t NextThreadMemAddr = memSize; ///< RevMem: Next top address for a new thread's memory + + uint64_t SearchTLB( uint64_t vAddr ); ///< RevMem: Used to check the TLB for an entry + void AddToTLB( uint64_t vAddr, uint64_t physAddr ); ///< RevMem: Used to add a new entry to TLB & LRUQueue + void FlushTLB(); ///< RevMem: Used to flush the TLB & LRUQueue + uint64_t + CalcPhysAddr( uint64_t pageNum, uint64_t vAddr ); ///< RevMem: Used to calculate the physical address based on virtual address + std::tuple + AdjPageAddr( uint64_t Addr, uint64_t Len ); ///< RevMem: Used to adjust address crossing pages + bool isValidVirtAddr( uint64_t vAddr ); ///< RevMem: Used to check if a virtual address exists in MemSegs + + std::map> pageMap{}; ///< RevMem: map of logical to pair + uint32_t pageSize{}; ///< RevMem: size of allocated pages + uint32_t addrShift{}; ///< RevMem: Bits to shift to caclulate page of address + uint32_t nextPage{}; ///< RevMem: next physical page to be allocated. Will result in index /// nextPage * pageSize into physMem - uint64_t heapend; ///< RevMem: top of the stack - uint64_t heapstart; ///< RevMem: top of the stack - uint64_t stacktop = 0; ///< RevMem: top of the stack - - std::vector FutureRes; ///< RevMem: future operation reservations - - // these are LRSC tuple index macros -#define LRSC_HART 0 -#define LRSC_ADDR 1 -#define LRSC_AQRL 2 -#define LRSC_VAL 3 - std::vector> LRSC; ///< RevMem: load reserve/store conditional vector + uint64_t heapend{}; ///< RevMem: top of the stack + uint64_t heapstart{}; ///< RevMem: top of the stack + uint64_t stacktop{}; ///< RevMem: top of the stack -}; // class RevMem + std::vector FutureRes{}; ///< RevMem: future operation reservations + std::unordered_map> LRSC{}; ///< RevMem: load reserve/store conditional set +}; // class RevMem -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevMemCtrl.h b/include/RevMemCtrl.h index 4c7f26823..f46ce3749 100644 --- a/include/RevMemCtrl.h +++ b/include/RevMemCtrl.h @@ -1,7 +1,7 @@ // // _RevMemCtrl_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -30,11 +29,11 @@ #include "SST.h" // -- RevCPU Headers +#include "RevCommon.h" #include "RevOpts.h" -#include "../common/include/RevCommon.h" #include "RevTracer.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { using namespace SST::Interfaces; @@ -42,86 +41,92 @@ using namespace SST::Interfaces; // Extended StandardMem::Request::Flag enums // ---------------------------------------- enum class RevFlag : uint32_t { - F_NONE = 0, /// no special operation - F_NONCACHEABLE = 1u<<1, /// non cacheable - F_BOXNAN = 1u << 16, /// NaN-box the 32-bit float - F_SEXT32 = 1u << 17, /// sign extend the 32bit result - F_SEXT64 = 1u << 18, /// sign extend the 64bit result - F_ZEXT32 = 1u << 19, /// zero extend the 32bit result - F_ZEXT64 = 1u << 20, /// zero extend the 64bit result - F_AMOADD = 1u << 21, /// AMO Add - F_AMOXOR = 1u << 22, /// AMO Xor - F_AMOAND = 1u << 23, /// AMO And - F_AMOOR = 1u << 24, /// AMO Or - F_AMOMIN = 1u << 25, /// AMO Min - F_AMOMAX = 1u << 26, /// AMO Max - F_AMOMINU= 1u << 27, /// AMO Minu - F_AMOMAXU= 1u << 28, /// AMO Maxu - F_AMOSWAP= 1u << 29, /// AMO Swap - F_AQ = 1u << 30, /// AMO AQ Flag - F_RL = 1u << 31, /// AMO RL Flag - F_ATOMIC = F_AMOADD | F_AMOXOR | F_AMOAND | F_AMOOR | F_AMOMIN | - F_AMOMAX | F_AMOMINU | F_AMOMAXU | F_AMOSWAP + F_NONE = 0, /// no special operation + F_NONCACHEABLE = 1u << 1, /// non cacheable + F_BOXNAN = 1u << 16, /// NaN-box the 32-bit float + F_SEXT32 = 1u << 17, /// sign extend the 32bit result + F_SEXT64 = 1u << 18, /// sign extend the 64bit result + F_ZEXT32 = 1u << 19, /// zero extend the 32bit result + F_ZEXT64 = 1u << 20, /// zero extend the 64bit result + F_AQ = 1u << 21, /// AMO AQ Flag + F_RL = 1u << 22, /// AMO RL Flag + F_AMOADD = 1u << 23, /// AMO Add + F_AMOXOR = 2u << 23, /// AMO Xor + F_AMOAND = 3u << 23, /// AMO And + F_AMOOR = 4u << 23, /// AMO Or + F_AMOMIN = 5u << 23, /// AMO Min + F_AMOMAX = 6u << 23, /// AMO Max + F_AMOMINU = 7u << 23, /// AMO Minu + F_AMOMAXU = 8u << 23, /// AMO Maxu + F_AMOSWAP = 9u << 23, /// AMO Swap + F_ATOMIC = 0xf << 23 /// Mask indicating atomic operations F_AMOADD through F_AMOSWAP }; // Ensure RevFlag is same underlying type as StandardMem::Request::flags_t -static_assert( std::is_same_v > ); +static_assert( std::is_same_v> ); + +/// RevFlag: determine if the request has certain flags set +constexpr bool RevFlagHas( RevFlag flag, RevFlag has ) { + return ( safe_static_cast( flag ) & safe_static_cast( has ) ) != 0; +} + +/// RevFlag: set certain flags +constexpr void RevFlagSet( RevFlag& flag, RevFlag set ) { + flag = RevFlag{ safe_static_cast( flag ) | safe_static_cast( set ) }; +} -/// RevFlag: determine if the request is an AMO -constexpr bool RevFlagHas(RevFlag flag, RevFlag has){ - return (static_cast(flag) & - static_cast(has)) != 0; +/// RevFlag: determine if the request is an AMO, and if so, return the operation; otherwise return 0 +constexpr auto RevFlagAtomic( RevFlag flag ) { + return safe_static_cast( flag ) & safe_static_cast( RevFlag::F_ATOMIC ); } +/// RevFlag: Handle flag response +void RevHandleFlagResp( void* target, size_t size, RevFlag flags ); + // ---------------------------------------- // RevMemOp // ---------------------------------------- class RevMemOp { public: - /// RevMemOp constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - MemOp Op, RevFlag flags ); + RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, MemOp Op, RevFlag flags ); /// RevMemOp constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - void *target, MemOp Op, - RevFlag flags ); + RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, MemOp Op, RevFlag flags ); /// RevMemOp overloaded constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - char *buffer, MemOp Op, - RevFlag flags ); + RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, MemOp Op, RevFlag flags ); /// RevMemOp overloaded constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - char *buffer, void *target, - MemOp Op, RevFlag flags ); + RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, void* target, MemOp Op, RevFlag flags + ); /// RevMemOp overloaded constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - std::vector buffer, - MemOp Op, RevFlag flags ); + RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, std::vector buffer, MemOp Op, RevFlag flags ); /// RevMemOp overloaded constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - void *target, unsigned CustomOpc, MemOp Op, - RevFlag flags ); + RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, uint32_t CustomOpc, MemOp Op, RevFlag flags + ); /// RevMemOp overloaded constructor - RevMemOp( unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - char *buffer, unsigned CustomOpc, MemOp Op, - RevFlag flags ); + RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, uint32_t CustomOpc, MemOp Op, RevFlag flags + ); /// RevMemOp default destructor - ~RevMemOp() = default; + ~RevMemOp() = default; + + /// Disallow copying and assignment + RevMemOp( const RevMemOp& ) = delete; + RevMemOp& operator=( const RevMemOp& ) = delete; /// RevMemOp: retrieve the memory operation type MemOp getOp() const { return Op; } /// RevMemOp: retrieve the custom opcode - unsigned getCustomOpc() const { return CustomOpc; } + uint32_t getCustomOpc() const { return CustomOpc; } /// RevMemOp: retrieve the target address uint64_t getAddr() const { return Addr; } @@ -142,58 +147,60 @@ class RevMemOp { RevFlag getFlags() const { return flags; } /// RevMemOp: retrieve the standard set of memory flags for MemEventBase - RevFlag getStdFlags() const { return RevFlag{static_cast(flags) & 0xFFFF}; } + RevFlag getStdFlags() const { return RevFlag{ safe_static_cast( flags ) & 0xFFFF }; } /// RevMemOp: retrieve the flags for MemEventBase without caching enable - RevFlag getNonCacheFlags() const { return RevFlag{static_cast(flags) & 0xFFFD}; } + RevFlag getNonCacheFlags() const { return RevFlag{ safe_static_cast( flags ) & 0xFFFD }; } /// RevMemOp: sets the number of split cache line requests - void setSplitRqst(unsigned S) { SplitRqst = S; } + void setSplitRqst( uint32_t S ) { SplitRqst = S; } /// RevMemOp: set the invalidate flag - void setInv(bool I) { Inv = I; } + void setInv( bool I ) { Inv = I; } /// RevMemOp: set the hart - void setHart(unsigned H) { Hart = H ;} + void setHart( uint32_t H ) { Hart = H; } /// RevMemOp: set the originating memory request - void setMemReq(const MemReq& req) { procReq = req;} + void setMemReq( const MemReq& req ) { procReq = req; } /// RevMemOp: set the temporary target buffer - void setTempT(std::vector T); + void setTempT( std::vector T ); /// RevMemOp: retrieve the invalidate flag bool getInv() const { return Inv; } /// RevMemOp: retrieve the number of split cache line requests - unsigned getSplitRqst() const { return SplitRqst; } + uint32_t getSplitRqst() const { return SplitRqst; } /// RevMemOp: retrieve the target address - void *getTarget() const { return target; } + void* getTarget() const { return target; } /// RevMemOp: retrieve the hart - unsigned getHart() const { return Hart; } + uint32_t getHart() const { return Hart; } /// RevMemOp: Get the originating proc memory request const MemReq& getMemReq() const { return procReq; } // RevMemOp: determine if the request is cache-able - bool isCacheable() const { return (static_cast(flags) & 0b10) == 0; } + bool isCacheable() const { + return ( safe_static_cast( flags ) & safe_static_cast( RevFlag::F_NONCACHEABLE ) ) == 0; + } private: - unsigned Hart; ///< RevMemOp: RISC-V Hart - uint64_t Addr; ///< RevMemOp: address - uint64_t PAddr; ///< RevMemOp: physical address (for RevMem I/O) - uint32_t Size; ///< RevMemOp: size of the memory operation in bytes - bool Inv; ///< RevMemOp: flush operation invalidate flag - MemOp Op; ///< RevMemOp: target memory operation - unsigned CustomOpc; ///< RevMemOp: custom memory opcode - unsigned SplitRqst; ///< RevMemOp: number of split cache line requests - std::vector membuf; ///< RevMemOp: buffer - std::vector tempT; ///< RevMemOp: temporary target buffer for R-M-W ops - RevFlag flags; ///< RevMemOp: request flags - void *target; ///< RevMemOp: target register pointer - MemReq procReq; ///< RevMemOp: original request from RevProc + uint32_t Hart{}; ///< RevMemOp: RISC-V Hart + uint64_t Addr{}; ///< RevMemOp: address + uint64_t PAddr{}; ///< RevMemOp: physical address (for RevMem I/O) + uint32_t Size{}; ///< RevMemOp: size of the memory operation in bytes + bool Inv{}; ///< RevMemOp: flush operation invalidate flag + MemOp Op{}; ///< RevMemOp: target memory operation + uint32_t CustomOpc{}; ///< RevMemOp: custom memory opcode + uint32_t SplitRqst{}; ///< RevMemOp: number of split cache line requests + std::vector membuf{}; ///< RevMemOp: buffer + std::vector tempT{}; ///< RevMemOp: temporary target buffer for R-M-W ops + RevFlag flags{}; ///< RevMemOp: request flags + void* target{}; ///< RevMemOp: target register pointer + MemReq procReq{}; ///< RevMemOp: original request from RevCore }; // ---------------------------------------- @@ -201,139 +208,143 @@ class RevMemOp { // ---------------------------------------- class RevMemCtrl : public SST::SubComponent { public: + SST_ELI_REGISTER_SUBCOMPONENT_API( SST::RevCPU::RevMemCtrl ) - SST_ELI_REGISTER_SUBCOMPONENT_API(SST::RevCPU::RevMemCtrl) - - SST_ELI_DOCUMENT_PARAMS({ "verbose", "Set the verbosity of output for the memory controller", "0" } ) + SST_ELI_DOCUMENT_PARAMS( { "verbose", "Set the verbosity of output for the memory controller", "0" } ) /// RevMemCtrl: constructor - RevMemCtrl( ComponentId_t id, const Params& params); + RevMemCtrl( ComponentId_t id, const Params& params ); /// RevMemCtrl: destructor virtual ~RevMemCtrl(); + /// RevMemCtrl: disallow copying and assignment + RevMemCtrl( const RevMemCtrl& ) = delete; + RevMemCtrl& operator=( const RevMemCtrl& ) = delete; + /// RevMemCtrl: initialization function - virtual void init(unsigned int phase) = 0; + void init( uint32_t phase ) override = 0; /// RevMemCtrl: setup function - virtual void setup() = 0; + void setup() override = 0; /// RevMemCtrl: finish function - virtual void finish() = 0; + void finish() override = 0; /// RevMemCtrl: determines if outstanding requests exist - virtual bool outstandingRqsts() = 0; + virtual bool outstandingRqsts() = 0; /// RevMemCtrl: send flush request - virtual bool sendFLUSHRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, bool Inv, - RevFlag flags) = 0; + virtual bool sendFLUSHRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, bool Inv, RevFlag flags ) = 0; /// RevMemCtrl: send a read request - virtual bool sendREADRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, const MemReq& req, - RevFlag flags) = 0; + virtual bool sendREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags + ) = 0; /// RevMemCtrl: send a write request - virtual bool sendWRITERequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags) = 0; + virtual bool + sendWRITERequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags ) = 0; /// RevMemCtrl: send an AMO request - virtual bool sendAMORequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, void *target, - const MemReq& req, - RevFlag flags) = 0; + virtual bool sendAMORequest( + uint32_t Hart, + uint64_t Addr, + uint64_t PAddr, + uint32_t Size, + unsigned char* buffer, + void* target, + const MemReq& req, + RevFlag flags + ) = 0; /// RevMemCtrl: send a readlock request - virtual bool sendREADLOCKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, const MemReq& req, - RevFlag flags) = 0; + virtual bool sendREADLOCKRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags + ) = 0; /// RevMemCtrl: send a writelock request - virtual bool sendWRITELOCKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags) = 0; + virtual bool + sendWRITELOCKRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags ) = 0; /// RevMemCtrl: send a loadlink request - virtual bool sendLOADLINKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, - RevFlag flags) = 0; + virtual bool sendLOADLINKRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, RevFlag flags ) = 0; /// RevMemCtrl: send a storecond request - virtual bool sendSTORECONDRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags) = 0; + virtual bool + sendSTORECONDRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags ) = 0; /// RevMemCtrl: send an void custom read memory request - virtual bool sendCUSTOMREADRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, - unsigned Opc, - RevFlag flags) = 0; + virtual bool sendCUSTOMREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, uint32_t Opc, RevFlag flags + ) = 0; /// RevMemCtrl: send a custom write request - virtual bool sendCUSTOMWRITERequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - unsigned Opc, - RevFlag flags) = 0; + virtual bool sendCUSTOMWRITERequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, uint32_t Opc, RevFlag flags + ) = 0; /// RevMemCtrl: send a FENCE request - virtual bool sendFENCE(unsigned Hart) = 0; + virtual bool sendFENCE( uint32_t Hart ) = 0; /// RevMemCtrl: handle a read response - virtual void handleReadResp(StandardMem::ReadResp* ev) = 0; + virtual void handleReadResp( StandardMem::ReadResp* ev ) = 0; /// RevMemCtrl: handle a write response - virtual void handleWriteResp(StandardMem::WriteResp* ev) = 0; + virtual void handleWriteResp( StandardMem::WriteResp* ev ) = 0; /// RevMemCtrl: handle a flush response - virtual void handleFlushResp(StandardMem::FlushResp* ev) = 0; + virtual void handleFlushResp( StandardMem::FlushResp* ev ) = 0; /// RevMemCtrl: handle a custom response - virtual void handleCustomResp(StandardMem::CustomResp* ev) = 0; + virtual void handleCustomResp( StandardMem::CustomResp* ev ) = 0; /// RevMemCtrl: handle an invalidate response - virtual void handleInvResp(StandardMem::InvNotify* ev) = 0; + virtual void handleInvResp( StandardMem::InvNotify* ev ) = 0; /// RevMemCtrl: handle RevMemCtrl flags for write responses - virtual void handleFlagResp(RevMemOp *op) = 0; + virtual void handleFlagResp( RevMemOp* op ) = 0; /// RevMemCtrl: handle an AMO for the target READ+MODIFY+WRITE triplet - virtual void handleAMO(RevMemOp *op) = 0; + virtual void handleAMO( RevMemOp* op ) = 0; /// RevMemCtrl: returns the cache line size - virtual unsigned getLineSize() = 0; + virtual uint32_t getLineSize() = 0; /// Assign processor tracer - virtual void setTracer(RevTracer *tracer) = 0; + virtual void setTracer( RevTracer* tracer ) = 0; protected: - SST::Output *output; ///< RevMemCtrl: sst output object - RevTracer *Tracer = nullptr; ///< RevMemCtrl: tracer pointer -}; // class RevMemCtrl + SST::Output* output{}; ///< RevMemCtrl: sst output object + RevTracer* Tracer{}; ///< RevMemCtrl: tracer pointer + +}; // class RevMemCtrl // ---------------------------------------- // RevBasicMemCtrl // ---------------------------------------- -class RevBasicMemCtrl : public RevMemCtrl{ +class RevBasicMemCtrl final : public RevMemCtrl { public: - SST_ELI_REGISTER_SUBCOMPONENT(RevBasicMemCtrl, "revcpu", - "RevBasicMemCtrl", - SST_ELI_ELEMENT_VERSION(1, 0, 0), - "RISC-V Rev basic memHierachy controller", - SST::RevCPU::RevMemCtrl - ) - - SST_ELI_DOCUMENT_PARAMS({ "verbose", "Set the verbosity of output for the memory controller", "0" }, + SST_ELI_REGISTER_SUBCOMPONENT( + RevBasicMemCtrl, + "revcpu", + "RevBasicMemCtrl", + SST_ELI_ELEMENT_VERSION( 1, 0, 0 ), + "RISC-V Rev basic memHierachy controller", + SST::RevCPU::RevMemCtrl + ) + + // clang-format off + SST_ELI_DOCUMENT_PARAMS({ "verbose", "Set the verbosity of output for the memory controller", "0" }, { "clock", "Sets the clock frequency of the memory conroller", "1Ghz" }, - { "max_loads", "Sets the maximum number of outstanding loads", "64"}, - { "max_stores", "Sets the maximum number of outstanding stores", "64"}, - { "max_flush", "Sets the maxmium number of oustanding flush events", "64"}, - { "max_llsc", "Sets the maximum number of outstanding LL/SC events", "64"}, - { "max_readlock", "Sets the maxmium number of outstanding readlock events", "64"}, - { "max_writeunlock", "Sets the maximum number of outstanding writeunlock events", "64"}, - { "max_custom", "Sets the maximum number of outstanding custom events", "64"}, - { "ops_per_cycle", "Sets the maximum number of operations to issue per cycle", "2" }, + { "max_loads", "Sets the maximum number of outstanding loads", "64" }, + { "max_stores", "Sets the maximum number of outstanding stores", "64" }, + { "max_flush", "Sets the maxmium number of oustanding flush events", "64" }, + { "max_llsc", "Sets the maximum number of outstanding LL/SC events", "64" }, + { "max_readlock", "Sets the maxmium number of outstanding readlock events", "64" }, + { "max_writeunlock","Sets the maximum number of outstanding writeunlock events", "64" }, + { "max_custom", "Sets the maximum number of outstanding custom events", "64" }, + { "ops_per_cycle", "Sets the maximum number of operations to issue per cycle", "2" }, ) SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS({ "memIface", "Set the interface to memory", "SST::Interfaces::StandardMem" }) @@ -341,48 +352,50 @@ class RevBasicMemCtrl : public RevMemCtrl{ SST_ELI_DOCUMENT_PORTS() SST_ELI_DOCUMENT_STATISTICS( - {"ReadInFlight", "Counts the number of reads in flight", "count", 1}, - {"ReadPending", "Counts the number of reads pending", "count", 1}, - {"ReadBytes", "Counts the number of bytes read", "bytes", 1}, - {"WriteInFlight", "Counts the number of writes in flight", "count", 1}, - {"WritePending", "Counts the number of writes pending", "count", 1}, - {"WriteBytes", "Counts the number of bytes written", "bytes", 1}, - {"FlushInFlight", "Counts the number of flushes in flight", "count", 1}, - {"FlushPending", "Counts the number of flushes pending", "count", 1}, - {"ReadLockInFlight", "Counts the number of readlocks in flight", "count", 1}, - {"ReadLockPending", "Counts the number of readlocks pending", "count", 1}, - {"ReadLockBytes", "Counts the number of readlock bytes read", "bytes", 1}, - {"WriteUnlockInFlight", "Counts the number of write unlocks in flight", "count", 1}, - {"WriteUnlockPending", "Counts the number of write unlocks pending", "count", 1}, - {"WriteUnlockBytes", "Counts the number of write unlock bytes written", "bytes", 1}, - {"LoadLinkInFlight", "Counts the number of loadlinks in flight", "count", 1}, - {"LoadLinkPending", "Counts the number of loadlinks pending", "count", 1}, - {"StoreCondInFlight", "Counts the number of storeconds in flight", "count", 1}, - {"StoreCondPending", "Counts the number of storeconds pending", "count", 1}, - {"CustomInFlight", "Counts the number of custom commands in flight", "count", 1}, - {"CustomPending", "Counts the number of custom commands pending", "count", 1}, + {"ReadInFlight", "Counts the number of reads in flight", "count", 1}, + {"ReadPending", "Counts the number of reads pending", "count", 1}, + {"ReadBytes", "Counts the number of bytes read", "bytes", 1}, + {"WriteInFlight", "Counts the number of writes in flight", "count", 1}, + {"WritePending", "Counts the number of writes pending", "count", 1}, + {"WriteBytes", "Counts the number of bytes written", "bytes", 1}, + {"FlushInFlight", "Counts the number of flushes in flight", "count", 1}, + {"FlushPending", "Counts the number of flushes pending", "count", 1}, + {"ReadLockInFlight", "Counts the number of readlocks in flight", "count", 1}, + {"ReadLockPending", "Counts the number of readlocks pending", "count", 1}, + {"ReadLockBytes", "Counts the number of readlock bytes read", "bytes", 1}, + {"WriteUnlockInFlight", "Counts the number of write unlocks in flight", "count", 1}, + {"WriteUnlockPending", "Counts the number of write unlocks pending", "count", 1}, + {"WriteUnlockBytes", "Counts the number of write unlock bytes written", "bytes", 1}, + {"LoadLinkInFlight", "Counts the number of loadlinks in flight", "count", 1}, + {"LoadLinkPending", "Counts the number of loadlinks pending", "count", 1}, + {"StoreCondInFlight", "Counts the number of storeconds in flight", "count", 1}, + {"StoreCondPending", "Counts the number of storeconds pending", "count", 1}, + {"CustomInFlight", "Counts the number of custom commands in flight", "count", 1}, + {"CustomPending", "Counts the number of custom commands pending", "count", 1}, {"CustomBytes", "Counts the number of bytes in custom transactions", "bytes", 1}, - {"FencePending", "Counts the number of fence operations pending", "count", 1}, + {"FencePending", "Counts the number of fence operations pending", "count", 1}, {"AMOAddBytes", "Counts the number of bytes in AMOAdd transactions", "bytes", 1}, - {"AMOAddPending", "Counts the number of AMOAdd operations pending", "count", 1}, + {"AMOAddPending", "Counts the number of AMOAdd operations pending", "count", 1}, {"AMOXorBytes", "Counts the number of bytes in AMOXor transactions", "bytes", 1}, - {"AMOXorPending", "Counts the number of AMOXor operations pending", "count", 1}, + {"AMOXorPending", "Counts the number of AMOXor operations pending", "count", 1}, {"AMOAndBytes", "Counts the number of bytes in AMOAnd transactions", "bytes", 1}, - {"AMOAndPending", "Counts the number of AMOAnd operations pending", "count", 1}, - {"AMOOrBytes", "Counts the number of bytes in AMOOr transactions", "bytes", 1}, - {"AMOOrPending", "Counts the number of AMOOr operations pending", "count", 1}, + {"AMOAndPending", "Counts the number of AMOAnd operations pending", "count", 1}, + {"AMOOrBytes", "Counts the number of bytes in AMOOr transactions", "bytes", 1}, + {"AMOOrPending", "Counts the number of AMOOr operations pending", "count", 1}, {"AMOMinBytes", "Counts the number of bytes in AMOMin transactions", "bytes", 1}, - {"AMOMinPending", "Counts the number of AMOMin operations pending", "count", 1}, + {"AMOMinPending", "Counts the number of AMOMin operations pending", "count", 1}, {"AMOMaxBytes", "Counts the number of bytes in AMOMax transactions", "bytes", 1}, - {"AMOMaxPending", "Counts the number of AMOMax operations pending", "count", 1}, - {"AMOMinuBytes", "Counts the number of bytes in AMOMinu transactions", "bytes", 1}, + {"AMOMaxPending", "Counts the number of AMOMax operations pending", "count", 1}, + {"AMOMinuBytes", "Counts the number of bytes in AMOMinu transactions","bytes", 1}, {"AMOMinuPending", "Counts the number of AMOMinu operations pending", "count", 1}, - {"AMOMaxuBytes", "Counts the number of bytes in AMOMaxu transactions", "bytes", 1}, + {"AMOMaxuBytes", "Counts the number of bytes in AMOMaxu transactions","bytes", 1}, {"AMOMaxuPending", "Counts the number of AMOMaxu operations pending", "count", 1}, - {"AMOSwapBytes", "Counts the number of bytes in AMOSwap transactions", "bytes", 1}, + {"AMOSwapBytes", "Counts the number of bytes in AMOSwap transactions","bytes", 1}, {"AMOSwapPending", "Counts the number of AMOSwap operations pending", "count", 1}, ) + // clang-format on + enum MemCtrlStats : uint32_t { ReadInFlight = 0, ReadPending = 1, @@ -427,226 +440,242 @@ class RevBasicMemCtrl : public RevMemCtrl{ }; /// RevBasicMemCtrl: constructor - RevBasicMemCtrl(ComponentId_t id, const Params& params); + RevBasicMemCtrl( ComponentId_t id, const Params& params ); /// RevBasicMemCtrl: destructor - virtual ~RevBasicMemCtrl(); + ~RevBasicMemCtrl() final; + + /// RevBasicMemCtrl: disallow copying and assignment + RevBasicMemCtrl( const RevBasicMemCtrl& ) = delete; + RevBasicMemCtrl& operator=( const RevBasicMemCtrl& ) = delete; /// RevBasicMemCtrl: initialization function - virtual void init(unsigned int phase) override; + void init( uint32_t phase ) final; /// RevBasicMemCtrl: setup function - virtual void setup() override; + void setup() final; /// RevBasicMemCtrl: finish function - virtual void finish() override; + void finish() final; /// RevBasicMemCtrl: clock tick function - virtual bool clockTick(Cycle_t cycle); + virtual bool clockTick( Cycle_t cycle ); /// RevBasicMemCtrl: determines if outstanding requests exist - bool outstandingRqsts() override; + bool outstandingRqsts() final; /// RevBasicMemCtrl: returns the cache line size - unsigned getLineSize() override { return lineSize; } + uint32_t getLineSize() final { return lineSize; } /// RevBasicMemCtrl: memory event processing handler - void processMemEvent(StandardMem::Request* ev); + void processMemEvent( StandardMem::Request* ev ); /// RevBasicMemCtrl: send a flush request - virtual bool sendFLUSHRequest(unsigned Hart, uint64_t Addr, uint64_t PAdr, uint32_t Size, - bool Inv, - RevFlag flags) override; + bool sendFLUSHRequest( uint32_t Hart, uint64_t Addr, uint64_t PAdr, uint32_t Size, bool Inv, RevFlag flags ) final; /// RevBasicMemCtrl: send a read request - virtual bool sendREADRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, const MemReq& req, - RevFlag flags) override; + bool sendREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags + ) final; /// RevBasicMemCtrl: send a write request - virtual bool sendWRITERequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags = RevFlag::F_NONE) override; + bool sendWRITERequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags = RevFlag::F_NONE + ) final; /// RevBasicMemCtrl: send an AMO request - virtual bool sendAMORequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, void *target, - const MemReq& req, - RevFlag flags) override; + bool sendAMORequest( + uint32_t Hart, + uint64_t Addr, + uint64_t PAddr, + uint32_t Size, + unsigned char* buffer, + void* target, + const MemReq& req, + RevFlag flags + ) final; // RevBasicMemCtrl: send a readlock request - virtual bool sendREADLOCKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, const MemReq& req, - RevFlag flags) override; + bool sendREADLOCKRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags + ) final; // RevBasicMemCtrl: send a writelock request - virtual bool sendWRITELOCKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags) override; + bool + sendWRITELOCKRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags ) final; // RevBasicMemCtrl: send a loadlink request - virtual bool sendLOADLINKRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, - RevFlag flags) override; + bool sendLOADLINKRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, RevFlag flags ) final; // RevBasicMemCtrl: send a storecond request - virtual bool sendSTORECONDRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - RevFlag flags) override; + bool + sendSTORECONDRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags ) final; // RevBasicMemCtrl: send an void custom read memory request - virtual bool sendCUSTOMREADRequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, - unsigned Opc, - RevFlag flags) override; + bool sendCUSTOMREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, uint32_t Opc, RevFlag flags + ) final; // RevBasicMemCtrl: send a custom write request - virtual bool sendCUSTOMWRITERequest(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - unsigned Opc, - RevFlag flags) override; + bool sendCUSTOMWRITERequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, uint32_t Opc, RevFlag flags + ) final; // RevBasicMemCtrl: send a FENCE request - virtual bool sendFENCE(unsigned Hart) override; + bool sendFENCE( uint32_t Hart ) final; /// RevBasicMemCtrl: handle a read response - virtual void handleReadResp(StandardMem::ReadResp* ev) override; + void handleReadResp( StandardMem::ReadResp* ev ) final; /// RevBasicMemCtrl: handle a write response - virtual void handleWriteResp(StandardMem::WriteResp* ev) override; + void handleWriteResp( StandardMem::WriteResp* ev ) final; /// RevBasicMemCtrl: handle a flush response - virtual void handleFlushResp(StandardMem::FlushResp* ev) override; + void handleFlushResp( StandardMem::FlushResp* ev ) final; /// RevBasicMemCtrl: handle a custom response - virtual void handleCustomResp(StandardMem::CustomResp* ev) override; + void handleCustomResp( StandardMem::CustomResp* ev ) final; /// RevBasicMemCtrl: handle an invalidate response - virtual void handleInvResp(StandardMem::InvNotify* ev) override; + void handleInvResp( StandardMem::InvNotify* ev ) final; /// RevBasicMemCtrl: handle RevMemCtrl flags for write responses - virtual void handleFlagResp(RevMemOp *op) override; + void handleFlagResp( RevMemOp* op ) final { RevHandleFlagResp( op->getTarget(), op->getSize(), op->getFlags() ); } /// RevBasicMemCtrl: handle an AMO for the target READ+MODIFY+WRITE triplet - virtual void handleAMO(RevMemOp *op) override; + void handleAMO( RevMemOp* op ) final; /// RevBasicMemCtrl: assign tracer pointer - virtual void setTracer(RevTracer *tracer) override; + void setTracer( RevTracer* tracer ) final; protected: // ---------------------------------------- // RevStdMemHandlers // ---------------------------------------- - class RevStdMemHandlers : public Interfaces::StandardMem::RequestHandler { + class RevStdMemHandlers final : public Interfaces::StandardMem::RequestHandler { public: friend class RevBasicMemCtrl; /// RevStdMemHandlers: constructor - RevStdMemHandlers( RevBasicMemCtrl* Ctrl, SST::Output* output); + RevStdMemHandlers( RevBasicMemCtrl* Ctrl, SST::Output* output ); /// RevStdMemHandlers: destructor - virtual ~RevStdMemHandlers(); + ~RevStdMemHandlers() final; + + /// RevStdMemHandlers: disallow copying and assignment + RevStdMemHandlers( const RevStdMemHandlers& ) = delete; + RevStdMemHandlers& operator=( const RevStdMemHandlers& ) = delete; /// RevStdMemHandlers: handle read response - virtual void handle(StandardMem::ReadResp* ev); + void handle( StandardMem::ReadResp* ev ) final; /// RevStdMemhandlers: handle write response - virtual void handle(StandardMem::WriteResp* ev); + void handle( StandardMem::WriteResp* ev ) final; /// RevStdMemHandlers: handle flush response - virtual void handle(StandardMem::FlushResp* ev); + void handle( StandardMem::FlushResp* ev ) final; /// RevStdMemHandlers: handle custom response - virtual void handle(StandardMem::CustomResp* ev); + void handle( StandardMem::CustomResp* ev ) final; /// RevStdMemHandlers: handle invalidate response - virtual void handle(StandardMem::InvNotify* ev); + void handle( StandardMem::InvNotify* ev ) final; private: - RevBasicMemCtrl *Ctrl; ///< RevStdMemHandlers: memory controller object - }; // class RevStdMemHandlers + RevBasicMemCtrl* Ctrl{}; ///< RevStdMemHandlers: memory controller object -private: + }; // class RevStdMemHandlers +private: /// RevBasicMemCtrl: process the next memory request - bool processNextRqst(unsigned &t_max_loads, unsigned &t_max_stores, - unsigned &t_max_flush, unsigned &t_max_llsc, - unsigned &t_max_readlock, unsigned &t_max_writeunlock, - unsigned &t_max_custom, unsigned &t_max_ops); + bool processNextRqst( + uint32_t& t_max_loads, + uint32_t& t_max_stores, + uint32_t& t_max_flush, + uint32_t& t_max_llsc, + uint32_t& t_max_readlock, + uint32_t& t_max_writeunlock, + uint32_t& t_max_custom, + uint32_t& t_max_ops + ); /// RevBasicMemCtrl: determine if we can instantiate the target memory operation - bool isMemOpAvail(RevMemOp *Op, unsigned &t_max_loads, unsigned &t_max_stores, - unsigned &t_max_flush, unsigned &t_max_llsc, - unsigned &t_max_readlock, unsigned &t_max_writeunlock, - unsigned &t_max_custom); + bool isMemOpAvail( + RevMemOp* Op, + uint32_t& t_max_loads, + uint32_t& t_max_stores, + uint32_t& t_max_flush, + uint32_t& t_max_llsc, + uint32_t& t_max_readlock, + uint32_t& t_max_writeunlock, + uint32_t& t_max_custom + ); /// RevBasicMemCtrl: build a standard memory request - bool buildStandardMemRqst(RevMemOp *op, bool &Success); + bool buildStandardMemRqst( RevMemOp* op, bool& Success ); /// RevBasicMemCtrl: build raw memory requests with a 1-to-1 mapping to RevMemOps' - bool buildRawMemRqst(RevMemOp *op, RevFlag TmpFlags); + bool buildRawMemRqst( RevMemOp* op, RevFlag TmpFlags ); /// RevBasicMemCtrl: build cache-aligned requests - bool buildCacheMemRqst(RevMemOp *op, bool &Success); + bool buildCacheMemRqst( RevMemOp* op, bool& Success ); /// RevBasicMemCtrl: determine if there are any pending AMOs that would prevent a request from dispatching - bool isPendingAMO(unsigned Slot); + bool isPendingAMO( uint32_t Slot ); /// RevBasicMemCtrl: determine if we need to utilize AQ ordering semantics - bool isAQ(unsigned Slot, unsigned Hart); + bool isAQ( uint32_t Slot, uint32_t Hart ); /// RevBasicMemCtrl: determine if we need to utilize RL ordering semantics - bool isRL(unsigned Slot, unsigned Hart); + bool isRL( uint32_t Slot, uint32_t Hart ); /// RevBasicMemCtrl: register statistics void registerStats(); /// RevBasicMemCtrl: inject statistics data for the target metric - void recordStat(MemCtrlStats Stat, uint64_t Data); + void recordStat( MemCtrlStats Stat, uint64_t Data ); /// RevBasicMemCtrl: returns the total number of outstanding requests uint64_t getTotalRqsts(); /// RevBasicMemCtrl: Determine the number of cache lines are required - unsigned getNumCacheLines(uint64_t Addr, uint32_t Size); + uint32_t getNumCacheLines( uint64_t Addr, uint32_t Size ); /// RevBasicMemCtrl: Retrieve the base cache line request size - unsigned getBaseCacheLineSize(uint64_t Addr, uint32_t Size); + uint32_t getBaseCacheLineSize( uint64_t Addr, uint32_t Size ); /// RevBasicMemCtrl: retrieve the number of outstanding requests on the wire - unsigned getNumSplitRqsts(RevMemOp *op); + uint32_t getNumSplitRqsts( RevMemOp* op ); /// RevBasicMemCtrl: perform the MODIFY portion of the AMO (READ+MODIFY+WRITE) - void performAMO(std::tuple Entry); + void performAMO( std::tuple Entry ); // -- private data members - StandardMem* memIface; ///< StandardMem memory interface - RevStdMemHandlers* stdMemHandlers; ///< StandardMem interface response handlers - bool hasCache; ///< detects whether cache layers are present - unsigned lineSize; ///< cache line size - unsigned max_loads; ///< maximum number of outstanding loads - unsigned max_stores; ///< maximum number of outstanding stores - unsigned max_flush; ///< maximum number of oustanding flush events - unsigned max_llsc; ///< maximum number of outstanding llsc events - unsigned max_readlock; ///< maximum number of oustanding readlock events - unsigned max_writeunlock; ///< maximum number of oustanding writelock events - unsigned max_custom; ///< maximum number of oustanding custom events - unsigned max_ops; ///< maximum number of ops to issue per cycle - - uint64_t num_read; ///< number of outstanding read requests - uint64_t num_write; ///< number of outstanding write requests - uint64_t num_flush; ///< number of outstanding flush requests - uint64_t num_llsc; ///< number of outstanding LL/SC requests - uint64_t num_readlock; ///< number of oustanding readlock requests - uint64_t num_writeunlock; ///< number of oustanding writelock requests - uint64_t num_custom; ///< number of outstanding custom requests - uint64_t num_fence; ///< number of oustanding fence requests - - std::vector requests; ///< outstanding StandardMem requests - std::vector rqstQ; ///< queued memory requests - std::map outstanding; ///< map of outstanding requests + StandardMem* memIface{}; ///< StandardMem memory interface + RevStdMemHandlers* stdMemHandlers{}; ///< StandardMem interface response handlers + bool hasCache{}; ///< detects whether cache layers are present + uint32_t lineSize{}; ///< cache line size + uint32_t max_loads{}; ///< maximum number of outstanding loads + uint32_t max_stores{}; ///< maximum number of outstanding stores + uint32_t max_flush{}; ///< maximum number of oustanding flush events + uint32_t max_llsc{}; ///< maximum number of outstanding llsc events + uint32_t max_readlock{}; ///< maximum number of oustanding readlock events + uint32_t max_writeunlock{}; ///< maximum number of oustanding writelock events + uint32_t max_custom{}; ///< maximum number of oustanding custom events + uint32_t max_ops{}; ///< maximum number of ops to issue per cycle + + uint32_t num_read{}; ///< number of outstanding read requests + uint32_t num_write{}; ///< number of outstanding write requests + uint32_t num_flush{}; ///< number of outstanding flush requests + uint32_t num_llsc{}; ///< number of outstanding LL/SC requests + uint32_t num_readlock{}; ///< number of oustanding readlock requests + uint32_t num_writeunlock{}; ///< number of oustanding writelock requests + uint32_t num_custom{}; ///< number of outstanding custom requests + uint32_t num_fence{}; ///< number of oustanding fence requests + + std::vector requests{}; ///< outstanding StandardMem requests + std::vector rqstQ{}; ///< queued memory requests + std::map outstanding{}; ///< map of outstanding requests #define AMOTABLE_HART 0 #define AMOTABLE_BUFFER 1 @@ -654,30 +683,26 @@ class RevBasicMemCtrl : public RevMemCtrl{ #define AMOTABLE_FLAGS 3 #define AMOTABLE_MEMOP 4 #define AMOTABLE_IN 5 - std::multimap> AMOTable; ///< map of amo operations to memory addresses - std::vector*> stats; ///< statistics vector + /// RevBasicMemCtrl: map of amo operations to memory addresses + std::multimap> AMOTable{}; -}; // RevBasicMemCtrl + std::vector*> stats{}; ///< statistics vector +}; // RevBasicMemCtrl ///< Apply Atomic Memory Operation /// The operation described by "flags" is applied to memory "Target" with value "value" template -void ApplyAMO(RevFlag flags, void* Target, T value){ - // Target and value cast to signed and unsigned versions - auto* TmpTarget = static_cast*>(Target); - auto* TmpTargetU = static_cast*>(Target); - auto TmpBuf = static_cast >(value); - auto TmpBufU = static_cast >(value); +void ApplyAMO( RevFlag flags, void* Target, T value ) { + // Target and value cast to signed and uint32_t versions + auto* TmpTarget = static_cast*>( Target ); + auto* TmpTargetU = static_cast*>( Target ); + auto TmpBuf = static_cast>( value ); + auto TmpBufU = static_cast>( value ); // Table mapping atomic operations to executable code + // clang-format off static const std::pair> table[] = { { RevFlag::F_AMOADD, [&]{ *TmpTarget += TmpBuf; } }, { RevFlag::F_AMOXOR, [&]{ *TmpTarget ^= TmpBuf; } }, @@ -689,15 +714,16 @@ void ApplyAMO(RevFlag flags, void* Target, T value){ { RevFlag::F_AMOMINU, [&]{ *TmpTargetU = std::min(*TmpTargetU, TmpBufU); } }, { RevFlag::F_AMOMAXU, [&]{ *TmpTargetU = std::max(*TmpTargetU, TmpBufU); } }, }; - - for (auto& [ flag, op ] : table){ - if( RevFlagHas(flags, flag) ){ + // clang-format on + RevFlag amo{ RevFlagAtomic( flags ) }; + for( const auto& [flag, op] : table ) { + if( amo == flag ) { op(); break; } } } -} // namespace SST::RevCPU +} // namespace SST::RevCPU -#endif // _SST_REVCPU_REVMEMCTRL_H_ +#endif // _SST_REVCPU_REVMEMCTRL_H_ diff --git a/include/RevNIC.h b/include/RevNIC.h index 76c98a391..c84f216f3 100644 --- a/include/RevNIC.h +++ b/include/RevNIC.h @@ -12,29 +12,28 @@ #define _SST_REVNIC_H_ // -- Standard Headers -#include #include -#include -#include #include +#include #include +#include +#include // -- SST Headers #include "SST.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { /** * nicEvent : inherited class to handle the individual network events for RevNIC */ -class nicEvent : public SST::Event{ +class nicEvent final : public SST::Event { public: /// nicEvent: standard constructor - explicit nicEvent(std::string name) : Event(), SrcName(std::move(name)) { } + explicit nicEvent( std::string name ) : Event(), SrcName( std::move( name ) ) {} /// nicEvent: extended constructor - nicEvent(std::string name, std::vector data) - : Event(), SrcName(std::move(name)), Data(std::move(data)) { } + nicEvent( std::string name, std::vector data ) : Event(), SrcName( std::move( name ) ), Data( std::move( data ) ) {} /// nicEvent: retrieve the source name std::string getSource() { return SrcName; } @@ -43,143 +42,132 @@ class nicEvent : public SST::Event{ std::vector getData() { return Data; } /// nicEvent: virtual function to clone an event - virtual Event* clone(void) override{ - nicEvent* ev = new nicEvent(*this); + Event* clone() final { + nicEvent* ev = new nicEvent( *this ); return ev; } private: - std::string SrcName; ///< nicEvent: Name of the sending device - std::vector Data; ///< nicEvent: Data payload + std::string SrcName{}; ///< nicEvent: Name of the sending device + std::vector Data{}; ///< nicEvent: Data payload public: /// nicEvent: secondary constructor - nicEvent() : Event() {} + nicEvent() = default; + ~nicEvent() final = default; /// nicEvent: event serializer - void serialize_order(SST::Core::Serialization::serializer &ser) override{ - Event::serialize_order(ser); - ser & SrcName; - ser & Data; + void serialize_order( SST::Core::Serialization::serializer& ser ) final { + Event::serialize_order( ser ); + ser& SrcName; + ser& Data; } /// nicEvent: implements the NIC serialization - ImplementSerializable(SST::RevCPU::nicEvent); + ImplementSerializable( SST::RevCPU::nicEvent ); }; // end nicEvent - /** * nicAPI : Handles the subcomponent NIC API */ -class nicAPI: public SST::SubComponent{ +class nicAPI : public SST::SubComponent { public: - SST_ELI_REGISTER_SUBCOMPONENT_API(SST::RevCPU::nicAPI) + SST_ELI_REGISTER_SUBCOMPONENT_API( SST::RevCPU::nicAPI ) /// nicEvent: constructor - nicAPI(ComponentId_t id, Params& params) : SubComponent(id) { } + nicAPI( ComponentId_t id, Params& ) : SubComponent( id ) {} /// nicEvent: default destructor - virtual ~nicAPI() = default; + ~nicAPI() override = default; /// nicEvent: registers the event handler with the core - virtual void setMsgHandler(Event::HandlerBase* handler) = 0; + virtual void setMsgHandler( Event::HandlerBase* handler ) = 0; /// nicEvent: initializes the network - virtual void init(unsigned int phase) = 0; + void init( uint32_t phase ) override = 0; /// nicEvent: setup the network - virtual void setup() { } + void setup() override = 0; /// nicEvent: send a message on the network - virtual void send(nicEvent *ev, int dest) = 0; + virtual void send( nicEvent* ev, int dest ) = 0; /// nicEvent: retrieve the number of potential destinations - virtual int getNumDestinations() = 0; + virtual int getNumDestinations() = 0; /// nicEvent: returns the NIC's network address virtual SST::Interfaces::SimpleNetwork::nid_t getAddress() = 0; -}; /// end nicAPI +}; /// end nicAPI /** * RevNIC: the Rev network interface controller subcomponent */ -class RevNIC : public nicAPI { +class RevNIC final : public nicAPI { public: - // Register with the SST Core SST_ELI_REGISTER_SUBCOMPONENT( - RevNIC, - "revcpu", - "RevNIC", - SST_ELI_ELEMENT_VERSION(1, 0, 0), - "RISC-V SST NIC", - SST::RevCPU::nicAPI - ) + RevNIC, "revcpu", "RevNIC", SST_ELI_ELEMENT_VERSION( 1, 0, 0 ), "RISC-V SST NIC", SST::RevCPU::nicAPI + ) // Register the parameters SST_ELI_DOCUMENT_PARAMS( - {"clock", "Clock frequency of the NIC", "1Ghz"}, - {"port", "Port to use, if loaded as an anonymous subcomponent", "network"}, - {"verbose", "Verbosity for output (0 = nothing)", "0"}, - ) + { "clock", "Clock frequency of the NIC", "1Ghz" }, + { "port", "Port to use, if loaded as an anonymous subcomponent", "network" }, + { "verbose", "Verbosity for output (0 = nothing)", "0" }, + ) // Register the ports - SST_ELI_DOCUMENT_PORTS( - {"network", "Port to network", {"simpleNetworkExample.nicEvent"} } - ) + SST_ELI_DOCUMENT_PORTS( { "network", "Port to network", { "simpleNetworkExample.nicEvent" } } ) // Register the subcomponent slots - SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( - {"iface", "SimpleNetwork interface to a network", "SST::Interfaces::SimpleNetwork"} - ) + SST_ELI_DOCUMENT_SUBCOMPONENT_SLOTS( { "iface", "SimpleNetwork interface to a network", "SST::Interfaces::SimpleNetwork" } ) /// RevNIC: constructor - RevNIC(ComponentId_t id, Params& params); + RevNIC( ComponentId_t id, Params& params ); /// RevNIC: destructor - virtual ~RevNIC(); + ~RevNIC() final; /// RevNIC: Callback to parent on received messages - virtual void setMsgHandler(Event::HandlerBase* handler); + void setMsgHandler( Event::HandlerBase* handler ) final; /// RevNIC: initialization function - virtual void init(unsigned int phase); + void init( uint32_t phase ) final; /// RevNIC: setup function - virtual void setup(); + void setup() final; /// RevNIC: send event to the destination id - virtual void send(nicEvent *ev, int dest); + void send( nicEvent* ev, int dest ) final; /// RevNIC: retrieve the number of destinations - virtual int getNumDestinations(); + int getNumDestinations() final; /// RevNIC: get the endpoint's network address - virtual SST::Interfaces::SimpleNetwork::nid_t getAddress(); + SST::Interfaces::SimpleNetwork::nid_t getAddress() final; /// RevNIC: callback function for the SimpleNetwork interface - bool msgNotify(int virtualNetwork); + bool msgNotify( int virtualNetwork ); /// RevNIC: clock function - virtual bool clockTick(Cycle_t cycle); + virtual bool clockTick( Cycle_t cycle ); protected: - SST::Output *output; ///< RevNIC: SST output object - - SST::Interfaces::SimpleNetwork * iFace; ///< RevNIC: SST network interface - - SST::Event::HandlerBase *msgHandler; ///< RevNIC: SST message handler - - bool initBroadcastSent; ///< RevNIC: has the init bcast been sent? - - int numDest; ///< RevNIC: number of SST destinations + SST::Output* output{}; ///< RevNIC: SST output object + SST::Interfaces::SimpleNetwork* iFace{}; ///< RevNIC: SST network interface + SST::Event::HandlerBase* msgHandler{}; ///< RevNIC: SST message handler + bool initBroadcastSent{}; ///< RevNIC: has the init bcast been sent? + int numDest{}; ///< RevNIC: number of SST destinations - std::queue sendQ; ///< RevNIC: buffered send queue + std::queue sendQ{}; ///< RevNIC: buffered send queue -}; // end RevNIC + /// RevNIC: disallow copying and assignment + RevNIC( const RevNIC& ) = delete; + RevNIC& operator=( const RevNIC& ) = delete; +}; // end RevNIC -} // namespace SST::RevCPU +} // namespace SST::RevCPU -#endif // _SST_REVNIC_H_ +#endif // _SST_REVNIC_H_ // EOF diff --git a/include/RevOpts.h b/include/RevOpts.h index 21cff9f3a..0734ca837 100644 --- a/include/RevOpts.h +++ b/include/RevOpts.h @@ -15,94 +15,150 @@ #include "SST.h" // -- Standard Headers +#include "RevCommon.h" #include #include -#include #include +#include +#include +#include #include +#include + +namespace SST::RevCPU { + +class RevOpts { + + // Queries whether type is a std::vector type + template + struct is_vector : std::false_type {}; + + template + struct is_vector> : std::true_type {}; + + // Return a property by looking up its table + // VAL is a universal reference so that either an lvalue reference or an assignable rvalue reference such as std::tie can be used + template + bool GetProperty( uint32_t Core, const MAP& Map, VAL&& Val ) const { + if constexpr( is_vector::value ) { + // If MAP is a vector + return Core < numCores ? Val = Map[Core], true : false; + } else { + // If MAP is a map/unordered_map + auto it = Map.find( Core ); + return it != Map.end() ? Val = it->second, true : false; + } + } + + template + bool InitPropertyMap( const std::vector& Opts, VEC& map ); -namespace SST::RevCPU{ + template + bool InitPropertyMapCores( const std::vector& Opts, VEC& map ); -class RevOpts{ public: /// RevOpts: options constructor - RevOpts( unsigned NumCores, unsigned NumHarts, const int Verbosity); + RevOpts( uint32_t NumCores, uint32_t NumHarts, int Verbosity ) + : numCores( NumCores ), numHarts( NumHarts ), verbosity( Verbosity ) {} + + /// RevOpts: Disallow copying and assignment + RevOpts( const RevOpts& ) = delete; + RevOpts( RevOpts&& ) = delete; + RevOpts& operator=( const RevOpts& ) = delete; + RevOpts& operator=( RevOpts&& ) = delete; /// RevOpts: options destructor - ~RevOpts(); + ~RevOpts() = default; /// RevOpts: retrieve the number of configured cores - unsigned GetNumCores() { return numCores; } + uint32_t GetNumCores() const { return numCores; } /// RevOpts: retrieve the number of configured harts per core - unsigned GetNumHarts() { return numHarts; } + uint32_t GetNumHarts() const { return numHarts; } /// RevOpts: retrieve the verbosity level - int GetVerbosity() { return verbosity; } + int GetVerbosity() const { return verbosity; } /// RevOpts: initialize the set of starting addresses - bool InitStartAddrs( std::vector StartAddrs ); + bool InitStartAddrs( const std::vector& StartAddrs ); /// RevOpts: initialize the set of potential starting symbols - bool InitStartSymbols( std::vector StartSymbols ); + bool InitStartSymbols( const std::vector& StartSymbols ); /// RevOpts: initialize the set of machine models - bool InitMachineModels( std::vector Machines ); + bool InitMachineModels( const std::vector& Machines ); /// RevOpts: initalize the set of instruction tables - bool InitInstTables( std::vector InstTables ); + bool InitInstTables( const std::vector& InstTables ); /// RevOpts: initialize the memory latency cost tables - bool InitMemCosts( std::vector MemCosts ); + bool InitMemCosts( const std::vector& MemCosts ); /// RevOpts: initialize the prefetch depths - bool InitPrefetchDepth( std::vector Depths ); + bool InitPrefetchDepth( const std::vector& Depths ); /// RevOpts: retrieve the start address for the target core - bool GetStartAddr( unsigned Core, uint64_t &StartAddr ); + bool GetStartAddr( uint32_t Core, uint64_t& StartAddr ) const { return GetProperty( Core, startAddr, StartAddr ); } /// RevOpts: retrieve the start symbol for the target core - bool GetStartSymbol( unsigned Core, std::string &Symbol ); + bool GetStartSymbol( uint32_t Core, std::string& Symbol ) const { return GetProperty( Core, startSym, Symbol ); } /// RevOpts: retrieve the machine model string for the target core - bool GetMachineModel( unsigned Core, std::string &MachModel ); + bool GetMachineModel( uint32_t Core, std::string& MachModel ) const { return GetProperty( Core, machine, MachModel ); } /// RevOpts: retrieve instruction table for the target core - bool GetInstTable( unsigned Core, std::string &Table ); + bool GetInstTable( uint32_t Core, std::string& Table ) const { return GetProperty( Core, table, Table ); } /// RevOpts: retrieve the memory cost range for the target core - bool GetMemCost( unsigned Core, unsigned &Min, unsigned &Max ); + bool GetMemCost( uint32_t Core, uint32_t& Min, uint32_t& Max ) const { + return GetProperty( Core, memCosts, std::tie( Min, Max ) ); + } /// RevOpts: retrieve the prefetch depth for the target core - bool GetPrefetchDepth( unsigned Core, unsigned &Depth ); + bool GetPrefetchDepth( uint32_t Core, uint32_t& Depth ) const { return GetProperty( Core, prefetchDepth, Depth ); } - /// RevOpts: set the argv arrary - void SetArgs(std::vector A){ Argv = A; } + /// RevOpts: set the argv array + void SetArgs( const SST::Params& params ); /// RevOpts: retrieve the argv array - std::vector GetArgv() { return Argv; } - -private: - unsigned numCores; ///< RevOpts: number of initialized cores - unsigned numHarts; ///< RevOpts: number of harts per core - int verbosity; ///< RevOpts: verbosity level - - std::map startAddr; ///< RevOpts: map of core id to starting address - std::map startSym; ///< RevOpts: map of core id to starting symbol - std::map machine; ///< RevOpts: map of core id to machine model - std::map table; ///< RevOpts: map of core id to inst table - std::map prefetchDepth; ///< RevOpts: map of core id to prefretch depth - - std::vector> memCosts; ///< RevOpts: vector of memory cost ranges - - std::vector Argv; ///< RevOpts: vector of function arguments + const std::vector& GetArgv() const { return Argv; } /// RevOpts: splits a string into tokens - void splitStr(const std::string& s, char c, std::vector& v); + static void splitStr( std::string s, const char* delim, std::vector& v ) { + char* ptr = s.data(); + char* saveptr = nullptr; + for( v.clear(); char* token = strtok_r( ptr, delim, &saveptr ); ptr = nullptr ) + v.push_back( token ); + } -}; // class RevOpts - -} // namespace SST::RevCPU +private: + uint32_t const numCores; ///< RevOpts: number of initialized cores + uint32_t const numHarts; ///< RevOpts: number of harts per core + int const verbosity; ///< RevOpts: verbosity level + + // init all the standard options + // -- startAddr = 0x00000000 + // -- machine = "G" aka, "IMAFD" + // -- table = internal + // -- memCosts[core] = 0:10 + // -- prefetch depth = 16 + // -- pipeLine = 5 ??? + + // clang-format off + std::vector startAddr{decltype( startAddr )( numCores, 0 )}; ///< RevOpts: starting address + std::vector machine{decltype( machine )( numCores, "G" )}; ///< RevOpts: machine model + std::vector table{decltype( table )( numCores, "_REV_INTERNAL_" )}; ///< RevOpts: inst table + std::vector> memCosts{decltype( memCosts )( numCores, {0, 10} )}; ///< RevOpts: memory cost range + std::vector prefetchDepth{decltype( prefetchDepth )( numCores, 16 )}; ///< RevOpts: prefretch depth + // clang-format on + + std::unordered_map startSym; ///< RevOpts: starting symbol + std::vector Argv; ///< RevOpts: vector of function arguments + std::vector MemDumpRanges; ///< RevOpts: vector of function arguments + +}; // class RevOpts + +} // namespace SST::RevCPU #endif diff --git a/include/RevPrefetcher.h b/include/RevPrefetcher.h index 162b2584a..d7a16dd6c 100644 --- a/include/RevPrefetcher.h +++ b/include/RevPrefetcher.h @@ -13,58 +13,65 @@ #include #include -#include -#include #include +#include -#include "RevMem.h" #include "RevFeature.h" +#include "RevMem.h" #include "RevRegFile.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { #define REVPREF_INIT_ADDR 0xDEADBEEF -class RevPrefetcher{ +class RevPrefetcher { public: /// RevPrefetcher: constructor - RevPrefetcher(RevMem *Mem, RevFeature *Feature, unsigned Depth, - std::shared_ptr> lsq, - std::function func) - : mem(Mem), feature(Feature), depth(Depth), LSQueue(lsq), MarkLoadAsComplete(func), OutstandingFetchQ(){} + RevPrefetcher( + RevMem* Mem, + RevFeature* Feature, + uint32_t Depth, + std::shared_ptr> lsq, + std::function func + ) + : mem( Mem ), feature( Feature ), depth( Depth ), LSQueue( lsq ), MarkLoadAsComplete( func ), OutstandingFetchQ() {} + + /// RevPrefetcher: disallow copying and assignment + RevPrefetcher( const RevPrefetcher& ) = delete; + RevPrefetcher& operator=( const RevPrefetcher& ) = delete; /// RevPrefetcher: destructor - ~RevPrefetcher() = default; + ~RevPrefetcher() = default; /// RevPrefetcher: fetch the next instruction - bool InstFetch(uint64_t Addr, bool &Fetched, uint32_t &Inst); + bool InstFetch( uint64_t Addr, bool& Fetched, uint32_t& Inst ); /// RevPrefetcher: determines in the target instruction is already cached in a stream - bool IsAvail(uint64_t Addr); + bool IsAvail( uint64_t Addr ); /// RevPrefetcher: Mark Instruction fill as complete - void MarkInstructionLoadComplete(const MemReq& req); + void MarkInstructionLoadComplete( const MemReq& req ); private: - RevMem *mem; ///< RevMem object - RevFeature *feature; ///< RevFeature object - unsigned depth; ///< Depth of each prefetcher stream - std::vector baseAddr; ///< Vector of base addresses for each stream - std::vector> iStack; ///< Vector of instruction vectors - std::shared_ptr> LSQueue; - std::function MarkLoadAsComplete; - std::vector OutstandingFetchQ; + RevMem* mem{}; ///< RevMem object + RevFeature* feature{}; ///< RevFeature object + uint32_t depth{}; ///< Depth of each prefetcher stream + std::vector baseAddr{}; ///< Vector of base addresses for each stream + std::vector> iStack{}; ///< Vector of instruction vectors + std::shared_ptr> LSQueue{}; + std::function MarkLoadAsComplete{}; + std::vector OutstandingFetchQ{}; /// fills a missed stream cache instruction - void Fill(uint64_t Addr); + void Fill( uint64_t Addr ); /// deletes the target stream buffer - void DeleteStream(size_t i); + void DeleteStream( size_t i ); /// attempts to fetch the upper half of a 32bit word of an unaligned base address - bool FetchUpper(uint64_t Addr, bool &Fetched, uint32_t &UInst); + bool FetchUpper( uint64_t Addr, bool& Fetched, uint32_t& UInst ); }; -} // namespace SST::RevCPU +} // namespace SST::RevCPU -#endif // _SST_REVCPU_REVPREFETCHER_H_ +#endif // _SST_REVCPU_REVPREFETCHER_H_ diff --git a/include/RevProc.h b/include/RevProc.h deleted file mode 100644 index f23b961a0..000000000 --- a/include/RevProc.h +++ /dev/null @@ -1,823 +0,0 @@ -// -// _RevProc_h_ -// -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC -// All Rights Reserved -// contact@tactcomplabs.com -// -// See LICENSE in the top level directory for licensing details -// - -#ifndef _SST_REVCPU_REVPROC_H_ -#define _SST_REVCPU_REVPROC_H_ - -// -- SST Headers -#include "SST.h" - -// -- Standard Headers -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -- RevCPU Headers -#include "RevOpts.h" -#include "RevMem.h" -#include "RevFeature.h" -#include "RevLoader.h" -#include "RevInstTable.h" -#include "AllRevInstTables.h" -#include "RevPrefetcher.h" -#include "RevCoProc.h" -#include "RevTracer.h" -#include "RevThread.h" -#include "RevRand.h" -#include "RevProcPasskey.h" -#include "RevHart.h" -#define SYSCALL_TYPES_ONLY -#include "../common/syscalls/syscalls.h" -#include "../common/include/RevCommon.h" - -namespace SST::RevCPU{ -class RevCoProc; - -class RevProc{ -public: - /// RevProc: standard constructor - RevProc( unsigned Id, RevOpts *Opts, unsigned NumHarts, RevMem *Mem, RevLoader *Loader, - std::function GetNewThreadID, SST::Output *Output ); - - /// RevProc: standard destructor - ~RevProc() = default; - - /// RevProc: per-processor clock function - bool ClockTick( SST::Cycle_t currentCycle ); - - /// RevProc: Called by RevCPU when there is no more work to do (ie. All RevThreads are ThreadState::DONE ) - void PrintStatSummary(); - - /// RevProc: halt the CPU - bool Halt(); - - /// RevProc: resume the CPU - bool Resume(); - - /// RevProc: execute a single step - bool SingleStepHart(); - - /// RevProc: retrieve the local PC for the correct feature set - uint64_t GetPC() const { return RegFile->GetPC(); } - - /// RevProc: set time converter for RTC - void SetTimeConverter(TimeConverter* tc) { timeConverter = tc; } - - /// RevProc: Debug mode read a register - bool DebugReadReg(unsigned Idx, uint64_t *Value) const; - - /// RevProc: Debug mode write a register - bool DebugWriteReg(unsigned Idx, uint64_t Value) const; - - /// RevProc: Is this an RV32 machine? - bool DebugIsRV32() { return feature->IsRV32(); } - - /// RevProc: Set an optional tracer - void SetTracer(RevTracer *T) { Tracer = T; } - - /// RevProc: Retrieve a random memory cost value - unsigned RandCost() { return mem->RandCost(feature->GetMinCost(), feature->GetMaxCost()); } - - /// RevProc: Handle register faults - void HandleRegFault(unsigned width); - - /// RevProc: Handle crack+decode faults - void HandleCrackFault(unsigned width); - - /// RevProc: Handle ALU faults - void HandleALUFault(unsigned width); - - /// RevProc: Handle ALU faults - void InjectALUFault(std::pair EToE, RevInst& Inst); - - struct RevProcStats { - uint64_t totalCycles; - uint64_t cyclesBusy; - uint64_t cyclesIdle_Total; - uint64_t cyclesStalled; - uint64_t floatsExec; - uint64_t cyclesIdle_Pipeline; - uint64_t cyclesIdle_MemoryFetch; - uint64_t retired; - }; - - auto GetAndClearStats() { - // Add each field from Stats into StatsTotal - for(auto stat : { - &RevProcStats::totalCycles, - &RevProcStats::cyclesBusy, - &RevProcStats::cyclesIdle_Total, - &RevProcStats::cyclesStalled, - &RevProcStats::floatsExec, - &RevProcStats::cyclesIdle_Pipeline, - &RevProcStats::retired}){ - StatsTotal.*stat += Stats.*stat; - } - - auto memStats = mem->GetAndClearStats(); - auto ret = std::make_pair(Stats, memStats); - Stats = {}; // Zero out Stats - return ret; - } - - RevMem& GetMem() const { return *mem; } - - ///< RevProc: Called by RevCPU to handle the state changes threads may have happened during this Proc's ClockTick - auto TransferThreadsThatChangedState() { - return std::move(ThreadsThatChangedState); - } - - ///< RevProc: Add - void AddThreadsThatChangedState(std::unique_ptr&& thread){ - ThreadsThatChangedState.push_back(std::move(thread)); - } - - ///< RevProc: SpawnThread creates a new thread and returns its ThreadID - void CreateThread(uint32_t NewTid, uint64_t fn, void* arg); - - ///< RevProc: Returns the current HartToExecID active pid - uint32_t GetActiveThreadID(){ return Harts.at(HartToDecodeID)->GetAssignedThreadID(); } - - ///< RevProc: Get this Proc's feature - RevFeature* GetRevFeature() const { return feature; } - - ///< RevProc: Mark a current request as complete - void MarkLoadComplete(const MemReq& req); - - ///< RevProc: Get pointer to Load / Store queue used to track memory operations - std::shared_ptr> GetLSQueue() const { return LSQueue; } - - ///< RevProc: Add a co-processor to the RevProc - void SetCoProc(RevCoProc* coproc); - - //--------------- External Interface for use with Co-Processor ------------------------- - ///< RevProc: Allow a co-processor to query the bits in scoreboard. Note the RevProcPassKey may only - /// be created by a RevCoProc (or a class derived from RevCoProc) so this function may not be called from even within - /// RevProc - bool ExternalDepCheck(RevProcPasskey, uint16_t HartID, uint16_t reg, bool IsFloat){ - RevRegClass regClass = IsFloat ? RevRegClass::RegFLOAT : RevRegClass::RegGPR; - const RevRegFile* regFile = GetRegFile(HartID); - return LSQCheck(HartID, regFile, reg, regClass) || ScoreboardCheck(regFile, reg, regClass); - } - - ///< RevProc: Allow a co-processor to manipulate the scoreboard by setting a bit. Note the RevProcPassKey may only - /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within - /// RevProc - void ExternalDepSet(RevProcPasskey, uint16_t HartID, uint16_t RegNum, bool isFloat, bool value = true){ - DependencySet(HartID, RegNum, isFloat, value); - } - - ///< RevProc: Allow a co-processor to manipulate the scoreboard by clearing a bit. Note the RevProcPassKey may only - /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within - /// RevProc - void ExternalDepClear(RevProcPasskey, uint16_t HartID, uint16_t RegNum, bool isFloat){ - DependencyClear(HartID, RegNum, isFloat); - } - - ///< RevProc: Allow a co-processor to stall the pipeline of this proc and hold it in a stall condition - /// unitl ExternalReleaseHart() is called. Note the RevProcPassKey may only - /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within - /// RevProc - void ExternalStallHart(RevProcPasskey, uint16_t HartID); - - ///< RevProc: Allow a co-processor to release the pipeline of this proc and allow a hart to continue - /// execution (this un-does the ExternalStallHart() function ). Note the RevProcPassKey may only - /// be created by a RevCoProc (or a class derived from RevCoProc) so this funciton may not be called from even within - /// RevProc - void ExternalReleaseHart(RevProcPasskey, uint16_t HartID); - //------------- END External Interface ------------------------------- - - ///< RevProc: Used for loading a software thread into a RevHart - void AssignThread(std::unique_ptr ThreadToAssign); - - ///< RevProc: - void UpdateStatusOfHarts(); - - ///< RevProc: Returns the id of an idle hart (or _INVALID_HART_ID_ if none are idle) - unsigned FindIdleHartID() const ; - - ///< RevProc: Returns true if all harts are available (ie. There is nothing executing on this Proc) - bool HasNoBusyHarts() const { return IdleHarts == ValidHarts; } - - ///< RevProc: Used by RevCPU to determine if it can disable this proc - /// based on the criteria there are no threads assigned to it and the - /// CoProc is done - bool HasNoWork() const; - - ///< RevProc: Returns true if there are any IdleHarts - bool HasIdleHart() const { return IdleHarts.any(); } - -private: - bool Halted; ///< RevProc: determines if the core is halted - bool Stalled; ///< RevProc: determines if the core is stalled on instruction fetch - bool SingleStep; ///< RevProc: determines if we are in a single step - bool CrackFault; ///< RevProc: determiens if we need to handle a crack fault - bool ALUFault; ///< RevProc: determines if we need to handle an ALU fault - unsigned fault_width; ///< RevProc: the width of the target fault - unsigned id; ///< RevProc: processor id - uint64_t ExecPC; ///< RevProc: executing PC - unsigned HartToDecodeID; ///< RevProc: Current executing ThreadID - unsigned HartToExecID; ///< RevProc: Thread to dispatch instruction - - std::vector> Harts; ///< RevProc: vector of Harts without a thread assigned to them - std::bitset<_MAX_HARTS_> IdleHarts; ///< RevProc: bitset of Harts with no thread assigned - std::bitset<_MAX_HARTS_> ValidHarts; ///< RevProc: Bits 0 -> numHarts are 1 - std::bitset<_MAX_HARTS_> HartsClearToDecode; ///< RevProc: Thread is clear to start (proceed with decode) - std::bitset<_MAX_HARTS_> HartsClearToExecute; ///< RevProc: Thread is clear to execute (no register dependencides) - - unsigned numHarts; ///< RevProc: Number of Harts for this core - RevOpts *opts; ///< RevProc: options object - RevMem *mem; ///< RevProc: memory object - RevCoProc* coProc; ///< RevProc: attached co-processor - RevLoader *loader; ///< RevProc: loader object - - // Function pointer to the GetNewThreadID function in RevCPU (monotonically increasing thread ID counter) - std::function GetNewThreadID; - - // If a given assigned thread experiences a change of state, it sets the corresponding bit - std::vector> ThreadsThatChangedState; ///< RevProc: used to signal to RevCPU that the thread assigned to HART has changed state - - SST::Output *output; ///< RevProc: output handler - std::unique_ptr featureUP; ///< RevProc: feature handler - RevFeature* feature; - RevProcStats Stats{}; ///< RevProc: collection of performance stats - RevProcStats StatsTotal{}; ///< RevProc: collection of total performance stats - std::unique_ptr sfetch; ///< RevProc: stream instruction prefetcher - - std::shared_ptr> LSQueue; ///< RevProc: Load / Store queue used to track memory operations. Currently only tracks outstanding loads. - TimeConverter* timeConverter; ///< RevProc: Time converter for RTC - - RevRegFile* RegFile = nullptr; ///< RevProc: Initial pointer to HartToDecodeID RegFile - uint32_t ActiveThreadID = _INVALID_TID_; ///< Software ThreadID (Not the Hart) that belongs to the Hart currently decoding - - RevTracer* Tracer = nullptr; ///< RevProc: Tracer object - - std::bitset<_MAX_HARTS_> CoProcStallReq; - ///< RevProc: Utility function for system calls that involve reading a string from memory - EcallStatus EcallLoadAndParseString(RevInst& inst, uint64_t straddr, std::function); - - // - Many of these are not implemented - // - Their existence in the ECalls table is solely to not throw errors - // - This _should_ be a comprehensive list of system calls supported on RISC-V - // - Beside each function declaration is the system call code followed by its corresponding declaration - // that you can find in `common/syscalls.h` (the file to be included to use system calls inside of rev) - // - EcallStatus ECALL_io_setup(RevInst& inst); // 0, rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) - EcallStatus ECALL_io_destroy(RevInst& inst); // 1, rev_io_destroy(aio_context_t ctx) - EcallStatus ECALL_io_submit(RevInst& inst); // 2, rev_io_submit(aio_context_t, long, struct iocb * *) - EcallStatus ECALL_io_cancel(RevInst& inst); // 3, rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) - EcallStatus ECALL_io_getevents(RevInst& inst); // 4, rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) - EcallStatus ECALL_setxattr(RevInst& inst); // 5, rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) - EcallStatus ECALL_lsetxattr(RevInst& inst); // 6, rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) - EcallStatus ECALL_fsetxattr(RevInst& inst); // 7, rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) - EcallStatus ECALL_getxattr(RevInst& inst); // 8, rev_getxattr(const char *path, const char *name, void *value, size_t size) - EcallStatus ECALL_lgetxattr(RevInst& inst); // 9, rev_lgetxattr(const char *path, const char *name, void *value, size_t size) - EcallStatus ECALL_fgetxattr(RevInst& inst); // 10, rev_fgetxattr(int fd, const char *name, void *value, size_t size) - EcallStatus ECALL_listxattr(RevInst& inst); // 11, rev_listxattr(const char *path, char *list, size_t size) - EcallStatus ECALL_llistxattr(RevInst& inst); // 12, rev_llistxattr(const char *path, char *list, size_t size) - EcallStatus ECALL_flistxattr(RevInst& inst); // 13, rev_flistxattr(int fd, char *list, size_t size) - EcallStatus ECALL_removexattr(RevInst& inst); // 14, rev_removexattr(const char *path, const char *name) - EcallStatus ECALL_lremovexattr(RevInst& inst); // 15, rev_lremovexattr(const char *path, const char *name) - EcallStatus ECALL_fremovexattr(RevInst& inst); // 16, rev_fremovexattr(int fd, const char *name) - EcallStatus ECALL_getcwd(RevInst& inst); // 17, rev_getcwd(char *buf, unsigned long size) - EcallStatus ECALL_lookup_dcookie(RevInst& inst); // 18, rev_lookup_dcookie(u64 cookie64, char *buf, size_t len) - EcallStatus ECALL_eventfd2(RevInst& inst); // 19, rev_eventfd2(unsigned int count, int flags) - EcallStatus ECALL_epoll_create1(RevInst& inst); // 20, rev_epoll_create1(int flags) - EcallStatus ECALL_epoll_ctl(RevInst& inst); // 21, rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - EcallStatus ECALL_epoll_pwait(RevInst& inst); // 22, rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) - EcallStatus ECALL_dup(RevInst& inst); // 23, rev_dup(unsigned int fildes) - EcallStatus ECALL_dup3(RevInst& inst); // 24, rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) - EcallStatus ECALL_fcntl64(RevInst& inst); // 25, rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) - EcallStatus ECALL_inotify_init1(RevInst& inst); // 26, rev_inotify_init1(int flags) - EcallStatus ECALL_inotify_add_watch(RevInst& inst); // 27, rev_inotify_add_watch(int fd, const char *path, u32 mask) - EcallStatus ECALL_inotify_rm_watch(RevInst& inst); // 28, rev_inotify_rm_watch(int fd, __s32 wd) - EcallStatus ECALL_ioctl(RevInst& inst); // 29, rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) - EcallStatus ECALL_ioprio_set(RevInst& inst); // 30, rev_ioprio_set(int which, int who, int ioprio) - EcallStatus ECALL_ioprio_get(RevInst& inst); // 31, rev_ioprio_get(int which, int who) - EcallStatus ECALL_flock(RevInst& inst); // 32, rev_flock(unsigned int fd, unsigned int cmd) - EcallStatus ECALL_mknodat(RevInst& inst); // 33, rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) - EcallStatus ECALL_mkdirat(RevInst& inst); // 34, rev_mkdirat(int dfd, const char * pathname, umode_t mode) - EcallStatus ECALL_unlinkat(RevInst& inst); // 35, rev_unlinkat(int dfd, const char * pathname, int flag) - EcallStatus ECALL_symlinkat(RevInst& inst); // 36, rev_symlinkat(const char * oldname, int newdfd, const char * newname) - EcallStatus ECALL_linkat(RevInst& inst); // 37, rev_unlinkat(int dfd, const char * pathname, int flag) - EcallStatus ECALL_renameat(RevInst& inst); // 38, rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) - EcallStatus ECALL_umount(RevInst& inst); // 39, rev_umount(char *name, int flags) - EcallStatus ECALL_mount(RevInst& inst); // 40, rev_umount(char *name, int flags) - EcallStatus ECALL_pivot_root(RevInst& inst); // 41, rev_pivot_root(const char *new_root, const char *put_old) - EcallStatus ECALL_ni_syscall(RevInst& inst); // 42, rev_ni_syscall(void) - EcallStatus ECALL_statfs64(RevInst& inst); // 43, rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) - EcallStatus ECALL_fstatfs64(RevInst& inst); // 44, rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf) - EcallStatus ECALL_truncate64(RevInst& inst); // 45, rev_truncate64(const char *path, loff_t length) - EcallStatus ECALL_ftruncate64(RevInst& inst); // 46, rev_ftruncate64(unsigned int fd, loff_t length) - EcallStatus ECALL_fallocate(RevInst& inst); // 47, rev_fallocate(int fd, int mode, loff_t offset, loff_t len) - EcallStatus ECALL_faccessat(RevInst& inst); // 48, rev_faccessat(int dfd, const char *filename, int mode) - EcallStatus ECALL_chdir(RevInst& inst); // 49, rev_chdir(const char *filename) - EcallStatus ECALL_fchdir(RevInst& inst); // 50, rev_fchdir(unsigned int fd) - EcallStatus ECALL_chroot(RevInst& inst); // 51, rev_chroot(const char *filename) - EcallStatus ECALL_fchmod(RevInst& inst); // 52, rev_fchmod(unsigned int fd, umode_t mode) - EcallStatus ECALL_fchmodat(RevInst& inst); // 53, rev_fchmodat(int dfd, const char * filename, umode_t mode) - EcallStatus ECALL_fchownat(RevInst& inst); // 54, rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) - EcallStatus ECALL_fchown(RevInst& inst); // 55, rev_fchown(unsigned int fd, uid_t user, gid_t group) - EcallStatus ECALL_openat(RevInst& inst); // 56, rev_openat(int dfd, const char *filename, int flags, umode_t mode) - EcallStatus ECALL_close(RevInst& inst); // 57, rev_close(unsigned int fd) - EcallStatus ECALL_vhangup(RevInst& inst); // 58, rev_vhangup(void) - EcallStatus ECALL_pipe2(RevInst& inst); // 59, rev_pipe2(int *fildes, int flags) - EcallStatus ECALL_quotactl(RevInst& inst); // 60, rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) - EcallStatus ECALL_getdents64(RevInst& inst); // 61, rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) - EcallStatus ECALL_lseek(RevInst& inst); // 62, rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) - EcallStatus ECALL_read(RevInst& inst); // 63, rev_read(unsigned int fd, char *buf, size_t count) - EcallStatus ECALL_write(RevInst& inst); // 64, rev_write(unsigned int fd, const char *buf, size_t count) - EcallStatus ECALL_readv(RevInst& inst); // 65, rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) - EcallStatus ECALL_writev(RevInst& inst); // 66, rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) - EcallStatus ECALL_pread64(RevInst& inst); // 67, rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) - EcallStatus ECALL_pwrite64(RevInst& inst); // 68, rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) - EcallStatus ECALL_preadv(RevInst& inst); // 69, rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) - EcallStatus ECALL_pwritev(RevInst& inst); // 70, rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) - EcallStatus ECALL_sendfile64(RevInst& inst); // 71, rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) - EcallStatus ECALL_pselect6_time32(RevInst& inst); // 72, rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *) - EcallStatus ECALL_ppoll_time32(RevInst& inst); // 73, rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t) - EcallStatus ECALL_signalfd4(RevInst& inst); // 74, rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) - EcallStatus ECALL_vmsplice(RevInst& inst); // 75, rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) - EcallStatus ECALL_splice(RevInst& inst); // 76, rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) - EcallStatus ECALL_tee(RevInst& inst); // 77, rev_tee(int fdin, int fdout, size_t len, unsigned int flags) - EcallStatus ECALL_readlinkat(RevInst& inst); // 78, rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) - EcallStatus ECALL_newfstatat(RevInst& inst); // 79, rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) - EcallStatus ECALL_newfstat(RevInst& inst); // 80, rev_newfstat(unsigned int fd, struct stat *statbuf) - EcallStatus ECALL_sync(RevInst& inst); // 81, rev_sync(void) - EcallStatus ECALL_fsync(RevInst& inst); // 82, rev_fsync(unsigned int fd) - EcallStatus ECALL_fdatasync(RevInst& inst); // 83, rev_fdatasync(unsigned int fd) - EcallStatus ECALL_sync_file_range2(RevInst& inst); // 84, rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) - EcallStatus ECALL_sync_file_range(RevInst& inst); // 84, rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) - EcallStatus ECALL_timerfd_create(RevInst& inst); // 85, rev_timerfd_create(int clockid, int flags) - EcallStatus ECALL_timerfd_settime(RevInst& inst); // 86, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) - EcallStatus ECALL_timerfd_gettime(RevInst& inst); // 87, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) - EcallStatus ECALL_utimensat(RevInst& inst); // 88, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) - EcallStatus ECALL_acct(RevInst& inst); // 89, rev_acct(const char *name) - EcallStatus ECALL_capget(RevInst& inst); // 90, rev_capget(cap_user_header_t header, cap_user_data_t dataptr) - EcallStatus ECALL_capset(RevInst& inst); // 91, rev_capset(cap_user_header_t header, const cap_user_data_t data) - EcallStatus ECALL_personality(RevInst& inst); // 92, rev_personality(unsigned int personality) - EcallStatus ECALL_exit(RevInst& inst); // 93, rev_exit(int error_code) - EcallStatus ECALL_exit_group(RevInst& inst); // 94, rev_exit_group(int error_code) - EcallStatus ECALL_waitid(RevInst& inst); // 95, rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) - EcallStatus ECALL_set_tid_address(RevInst& inst); // 96, rev_set_tid_address(int *tidptr) - EcallStatus ECALL_unshare(RevInst& inst); // 97, rev_unshare(unsigned long unshare_flags) - EcallStatus ECALL_futex(RevInst& inst); // 98, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) - EcallStatus ECALL_set_robust_list(RevInst& inst); // 99, rev_set_robust_list(struct robust_list_head *head, size_t len) - EcallStatus ECALL_get_robust_list(RevInst& inst); // 100, rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) - EcallStatus ECALL_nanosleep(RevInst& inst); // 101, rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - EcallStatus ECALL_getitimer(RevInst& inst); // 102, rev_getitimer(int which, struct __kernel_old_itimerval *value) - EcallStatus ECALL_setitimer(RevInst& inst); // 103, rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) - EcallStatus ECALL_kexec_load(RevInst& inst); // 104, rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) - EcallStatus ECALL_init_module(RevInst& inst); // 105, rev_init_module(void *umod, unsigned long len, const char *uargs) - EcallStatus ECALL_delete_module(RevInst& inst); // 106, rev_delete_module(const char *name_user, unsigned int flags) - EcallStatus ECALL_timer_create(RevInst& inst); // 107, rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) - EcallStatus ECALL_timer_gettime(RevInst& inst); // 108, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) - EcallStatus ECALL_timer_getoverrun(RevInst& inst); // 109, rev_timer_getoverrun(timer_t timer_id) - EcallStatus ECALL_timer_settime(RevInst& inst); // 110, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) - EcallStatus ECALL_timer_delete(RevInst& inst); // 111, rev_timer_delete(timer_t timer_id) - EcallStatus ECALL_clock_settime(RevInst& inst); // 112, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) - EcallStatus ECALL_clock_gettime(RevInst& inst); // 113, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) - EcallStatus ECALL_clock_getres(RevInst& inst); // 114, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) - EcallStatus ECALL_clock_nanosleep(RevInst& inst); // 115, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - EcallStatus ECALL_syslog(RevInst& inst); // 116, rev_syslog(int type, char *buf, int len) - EcallStatus ECALL_ptrace(RevInst& inst); // 117, rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) - EcallStatus ECALL_sched_setparam(RevInst& inst); // 118, rev_sched_setparam(pid_t pid, struct sched_param *param) - EcallStatus ECALL_sched_setscheduler(RevInst& inst); // 119, rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) - EcallStatus ECALL_sched_getscheduler(RevInst& inst); // 120, rev_sched_getscheduler(pid_t pid) - EcallStatus ECALL_sched_getparam(RevInst& inst); // 121, rev_sched_getparam(pid_t pid, struct sched_param *param) - EcallStatus ECALL_sched_setaffinity(RevInst& inst); // 122, rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) - EcallStatus ECALL_sched_getaffinity(RevInst& inst); // 123, rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) - EcallStatus ECALL_sched_yield(RevInst& inst); // 124, rev_sched_yield(void) - EcallStatus ECALL_sched_get_priority_max(RevInst& inst); // 125, rev_sched_get_priority_max(int policy) - EcallStatus ECALL_sched_get_priority_min(RevInst& inst); // 126, rev_sched_get_priority_min(int policy) - EcallStatus ECALL_sched_rr_get_interval(RevInst& inst); // 127, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) - EcallStatus ECALL_restart_syscall(RevInst& inst); // 128, rev_restart_syscall(void) - EcallStatus ECALL_kill(RevInst& inst); // 129, rev_kill(pid_t pid, int sig) - EcallStatus ECALL_tkill(RevInst& inst); // 130, rev_tkill(pid_t pid, int sig) - EcallStatus ECALL_tgkill(RevInst& inst); // 131, rev_tgkill(pid_t tgid, pid_t pid, int sig) - EcallStatus ECALL_sigaltstack(RevInst& inst); // 132, rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) - EcallStatus ECALL_rt_sigsuspend(RevInst& inst); // 133, rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) - EcallStatus ECALL_rt_sigaction(RevInst& inst); // 134, rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) - EcallStatus ECALL_rt_sigprocmask(RevInst& inst); // 135, rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) - EcallStatus ECALL_rt_sigpending(RevInst& inst); // 136, rev_rt_sigpending(sigset_t *set, size_t sigsetsize) - EcallStatus ECALL_rt_sigtimedwait_time32(RevInst& inst); // 137, rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) - EcallStatus ECALL_rt_sigqueueinfo(RevInst& inst); // 138, rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) - EcallStatus ECALL_setpriority(RevInst& inst); // 140, rev_setpriority(int which, int who, int niceval) - EcallStatus ECALL_getpriority(RevInst& inst); // 141, rev_getpriority(int which, int who) - EcallStatus ECALL_reboot(RevInst& inst); // 142, rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) - EcallStatus ECALL_setregid(RevInst& inst); // 143, rev_setregid(gid_t rgid, gid_t egid) - EcallStatus ECALL_setgid(RevInst& inst); // 144, rev_setgid(gid_t gid) - EcallStatus ECALL_setreuid(RevInst& inst); // 145, rev_setreuid(uid_t ruid, uid_t euid) - EcallStatus ECALL_setuid(RevInst& inst); // 146, rev_setuid(uid_t uid) - EcallStatus ECALL_setresuid(RevInst& inst); // 147, rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) - EcallStatus ECALL_getresuid(RevInst& inst); // 148, rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) - EcallStatus ECALL_setresgid(RevInst& inst); // 149, rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) - EcallStatus ECALL_getresgid(RevInst& inst); // 150, rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) - EcallStatus ECALL_setfsuid(RevInst& inst); // 151, rev_setfsuid(uid_t uid) - EcallStatus ECALL_setfsgid(RevInst& inst); // 152, rev_setfsgid(gid_t gid) - EcallStatus ECALL_times(RevInst& inst); // 153, rev_times(struct tms *tbuf) - EcallStatus ECALL_setpgid(RevInst& inst); // 154, rev_setpgid(pid_t pid, pid_t pgid) - EcallStatus ECALL_getpgid(RevInst& inst); // 155, rev_getpgid(pid_t pid) - EcallStatus ECALL_getsid(RevInst& inst); // 156, rev_getsid(pid_t pid) - EcallStatus ECALL_setsid(RevInst& inst); // 157, rev_setsid(void) - EcallStatus ECALL_getgroups(RevInst& inst); // 158, rev_getgroups(int gidsetsize, gid_t *grouplist) - EcallStatus ECALL_setgroups(RevInst& inst); // 159, rev_setgroups(int gidsetsize, gid_t *grouplist) - EcallStatus ECALL_newuname(RevInst& inst); // 160, rev_newuname(struct new_utsname *name) - EcallStatus ECALL_sethostname(RevInst& inst); // 161, rev_sethostname(char *name, int len) - EcallStatus ECALL_setdomainname(RevInst& inst); // 162, rev_setdomainname(char *name, int len) - EcallStatus ECALL_getrlimit(RevInst& inst); // 163, rev_getrlimit(unsigned int resource, struct rlimit *rlim) - EcallStatus ECALL_setrlimit(RevInst& inst); // 164, rev_setrlimit(unsigned int resource, struct rlimit *rlim) - EcallStatus ECALL_getrusage(RevInst& inst); // 165, rev_getrusage(int who, struct rusage *ru) - EcallStatus ECALL_umask(RevInst& inst); // 166, rev_umask(int mask) - EcallStatus ECALL_prctl(RevInst& inst); // 167, rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) - EcallStatus ECALL_getcpu(RevInst& inst); // 168, rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) - EcallStatus ECALL_gettimeofday(RevInst& inst); // 169, rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) - EcallStatus ECALL_settimeofday(RevInst& inst); // 170, rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) - EcallStatus ECALL_adjtimex(RevInst& inst); // 171, rev_adjtimex(struct __kernel_timex *txc_p) - EcallStatus ECALL_getpid(RevInst& inst); // 172, rev_getpid(void) - EcallStatus ECALL_getppid(RevInst& inst); // 173, rev_getppid(void) - EcallStatus ECALL_getuid(RevInst& inst); // 174, rev_getuid(void) - EcallStatus ECALL_geteuid(RevInst& inst); // 175, rev_geteuid(void) - EcallStatus ECALL_getgid(RevInst& inst); // 176, rev_getgid(void) - EcallStatus ECALL_getegid(RevInst& inst); // 177, rev_getegid(void) - EcallStatus ECALL_gettid(RevInst& inst); // 178, rev_gettid(void) - EcallStatus ECALL_sysinfo(RevInst& inst); // 179, rev_sysinfo(struct sysinfo *info) - EcallStatus ECALL_mq_open(RevInst& inst); // 180, rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) - EcallStatus ECALL_mq_unlink(RevInst& inst); // 181, rev_mq_unlink(const char *name) - EcallStatus ECALL_mq_timedsend(RevInst& inst); // 182, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) - EcallStatus ECALL_mq_timedreceive(RevInst& inst); // 183, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) - EcallStatus ECALL_mq_notify(RevInst& inst); // 184, rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) - EcallStatus ECALL_mq_getsetattr(RevInst& inst); // 185, rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) - EcallStatus ECALL_msgget(RevInst& inst); // 186, rev_msgget(key_t key, int msgflg) - EcallStatus ECALL_msgctl(RevInst& inst); // 187, rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) - EcallStatus ECALL_msgrcv(RevInst& inst); // 188, rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) - EcallStatus ECALL_msgsnd(RevInst& inst); // 189, rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) - EcallStatus ECALL_semget(RevInst& inst); // 190, rev_semget(key_t key, int nsems, int semflg) - EcallStatus ECALL_semctl(RevInst& inst); // 191, rev_semctl(int semid, int semnum, int cmd, unsigned long arg) - EcallStatus ECALL_semtimedop(RevInst& inst); // 192, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) - EcallStatus ECALL_semop(RevInst& inst); // 193, rev_semop(int semid, struct sembuf *sops, unsigned nsops) - EcallStatus ECALL_shmget(RevInst& inst); // 194, rev_shmget(key_t key, size_t size, int flag) - EcallStatus ECALL_shmctl(RevInst& inst); // 195, rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) - EcallStatus ECALL_shmat(RevInst& inst); // 196, rev_shmat(int shmid, char *shmaddr, int shmflg) - EcallStatus ECALL_shmdt(RevInst& inst); // 197, rev_shmdt(char *shmaddr) - EcallStatus ECALL_socket(RevInst& inst); // 198, rev_socket(int, int, int) - EcallStatus ECALL_socketpair(RevInst& inst); // 199, rev_socketpair(int, int, int, int *) - EcallStatus ECALL_bind(RevInst& inst); // 200, rev_bind(int, struct sockaddr *, int) - EcallStatus ECALL_listen(RevInst& inst); // 201, rev_listen(int, int) - EcallStatus ECALL_accept(RevInst& inst); // 202, rev_accept(int, struct sockaddr *, int *) - EcallStatus ECALL_connect(RevInst& inst); // 203, rev_connect(int, struct sockaddr *, int) - EcallStatus ECALL_getsockname(RevInst& inst); // 204, rev_getsockname(int, struct sockaddr *, int *) - EcallStatus ECALL_getpeername(RevInst& inst); // 205, rev_getpeername(int, struct sockaddr *, int *) - EcallStatus ECALL_sendto(RevInst& inst); // 206, rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int) - EcallStatus ECALL_recvfrom(RevInst& inst); // 207, rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *) - EcallStatus ECALL_setsockopt(RevInst& inst); // 208, rev_setsockopt(int fd, int level, int optname, char *optval, int optlen) - EcallStatus ECALL_getsockopt(RevInst& inst); // 209, rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen) - EcallStatus ECALL_shutdown(RevInst& inst); // 210, rev_shutdown(int, int) - EcallStatus ECALL_sendmsg(RevInst& inst); // 211, rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags) - EcallStatus ECALL_recvmsg(RevInst& inst); // 212, rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags) - EcallStatus ECALL_readahead(RevInst& inst); // 213, rev_readahead(int fd, loff_t offset, size_t count) - EcallStatus ECALL_brk(RevInst& inst); // 214, rev_brk(unsigned long brk) - EcallStatus ECALL_munmap(RevInst& inst); // 215, rev_munmap(unsigned long addr, size_t len) - EcallStatus ECALL_mremap(RevInst& inst); // 216, rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) - EcallStatus ECALL_add_key(RevInst& inst); // 217, rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) - EcallStatus ECALL_request_key(RevInst& inst); // 218, rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) - EcallStatus ECALL_keyctl(RevInst& inst); // 219, rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) - EcallStatus ECALL_clone(RevInst& inst); // 220, rev_clone(unsigned long, unsigned long, int *, unsigned long, int *) - EcallStatus ECALL_execve(RevInst& inst); // 221, rev_execve(const char *filename, const char *const *argv, const char *const *envp) - EcallStatus ECALL_mmap(RevInst& inst); // 222, rev_old_mmap(struct mmap_arg_struct *arg) - EcallStatus ECALL_fadvise64_64(RevInst& inst); // 223, rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) - EcallStatus ECALL_swapon(RevInst& inst); // 224, rev_swapon(const char *specialfile, int swap_flags) - EcallStatus ECALL_swapoff(RevInst& inst); // 225, rev_swapoff(const char *specialfile) - EcallStatus ECALL_mprotect(RevInst& inst); // 226, rev_mprotect(unsigned long start, size_t len, unsigned long prot) - EcallStatus ECALL_msync(RevInst& inst); // 227, rev_msync(unsigned long start, size_t len, int flags) - EcallStatus ECALL_mlock(RevInst& inst); // 228, rev_mlock(unsigned long start, size_t len) - EcallStatus ECALL_munlock(RevInst& inst); // 229, rev_munlock(unsigned long start, size_t len) - EcallStatus ECALL_mlockall(RevInst& inst); // 230, rev_mlockall(int flags) - EcallStatus ECALL_munlockall(RevInst& inst); // 231, rev_munlockall(void) - EcallStatus ECALL_mincore(RevInst& inst); // 232, rev_mincore(unsigned long start, size_t len, unsigned char * vec) - EcallStatus ECALL_madvise(RevInst& inst); // 233, rev_madvise(unsigned long start, size_t len, int behavior) - EcallStatus ECALL_remap_file_pages(RevInst& inst); // 234, rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) - EcallStatus ECALL_mbind(RevInst& inst); // 235, rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) - EcallStatus ECALL_get_mempolicy(RevInst& inst); // 236, rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) - EcallStatus ECALL_set_mempolicy(RevInst& inst); // 237, rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) - EcallStatus ECALL_migrate_pages(RevInst& inst); // 238, rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) - EcallStatus ECALL_move_pages(RevInst& inst); // 239, rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) - EcallStatus ECALL_rt_tgsigqueueinfo(RevInst& inst); // 240, rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) - EcallStatus ECALL_perf_event_open(RevInst& inst); // 241, rev_perf_event_open(") - EcallStatus ECALL_accept4(RevInst& inst); // 242, rev_accept4(int, struct sockaddr *, int *, int) - EcallStatus ECALL_recvmmsg_time32(RevInst& inst); // 243, rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout) - EcallStatus ECALL_wait4(RevInst& inst); // 260, rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) - EcallStatus ECALL_prlimit64(RevInst& inst); // 261, rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) - EcallStatus ECALL_fanotify_init(RevInst& inst); // 262, rev_fanotify_init(unsigned int flags, unsigned int event_f_flags) - EcallStatus ECALL_fanotify_mark(RevInst& inst); // 263, rev_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char *pathname) - EcallStatus ECALL_name_to_handle_at(RevInst& inst); // 264, rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) - EcallStatus ECALL_open_by_handle_at(RevInst& inst); // 265, rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) - EcallStatus ECALL_clock_adjtime(RevInst& inst); // 266, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) - EcallStatus ECALL_syncfs(RevInst& inst); // 267, rev_syncfs(int fd) - EcallStatus ECALL_setns(RevInst& inst); // 268, rev_setns(int fd, int nstype) - EcallStatus ECALL_sendmmsg(RevInst& inst); // 269, rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) - EcallStatus ECALL_process_vm_readv(RevInst& inst); // 270, rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) - EcallStatus ECALL_process_vm_writev(RevInst& inst); // 271, rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) - EcallStatus ECALL_kcmp(RevInst& inst); // 272, rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) - EcallStatus ECALL_finit_module(RevInst& inst); // 273, rev_finit_module(int fd, const char *uargs, int flags) - EcallStatus ECALL_sched_setattr(RevInst& inst); // 274, rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) - EcallStatus ECALL_sched_getattr(RevInst& inst); // 275, rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) - EcallStatus ECALL_renameat2(RevInst& inst); // 276, rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) - EcallStatus ECALL_seccomp(RevInst& inst); // 277, rev_seccomp(unsigned int op, unsigned int flags, void *uargs) - EcallStatus ECALL_getrandom(RevInst& inst); // 278, rev_getrandom(char *buf, size_t count, unsigned int flags) - EcallStatus ECALL_memfd_create(RevInst& inst); // 279, rev_memfd_create(const char *uname_ptr, unsigned int flags) - EcallStatus ECALL_bpf(RevInst& inst); // 280, rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) - EcallStatus ECALL_execveat(RevInst& inst); // 281, rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) - EcallStatus ECALL_userfaultfd(RevInst& inst); // 282, rev_userfaultfd(int flags) - EcallStatus ECALL_membarrier(RevInst& inst); // 283, rev_membarrier(int cmd, unsigned int flags, int cpu_id) - EcallStatus ECALL_mlock2(RevInst& inst); // 284, rev_mlock2(unsigned long start, size_t len, int flags) - EcallStatus ECALL_copy_file_range(RevInst& inst); // 285, rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) - EcallStatus ECALL_preadv2(RevInst& inst); // 286, rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) - EcallStatus ECALL_pwritev2(RevInst& inst); // 287, rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) - EcallStatus ECALL_pkey_mprotect(RevInst& inst); // 288, rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey) - EcallStatus ECALL_pkey_alloc(RevInst& inst); // 289, rev_pkey_alloc(unsigned long flags, unsigned long init_val) - EcallStatus ECALL_pkey_free(RevInst& inst); // 290, rev_pkey_free(int pkey) - EcallStatus ECALL_statx(RevInst& inst); // 291, rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) - EcallStatus ECALL_io_pgetevents(RevInst& inst); // 292, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) - EcallStatus ECALL_rseq(RevInst& inst); // 293, rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) - EcallStatus ECALL_kexec_file_load(RevInst& inst); // 294, rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) - // EcallStatus ECALL_clock_gettime(RevInst& inst); // 403, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) - // EcallStatus ECALL_clock_settime(RevInst& inst); // 404, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) - // EcallStatus ECALL_clock_adjtime(RevInst& inst); // 405, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) - // EcallStatus ECALL_clock_getres(RevInst& inst); // 406, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) - // EcallStatus ECALL_clock_nanosleep(RevInst& inst); // 407, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - // EcallStatus ECALL_timer_gettime(RevInst& inst); // 408, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) - // EcallStatus ECALL_timer_settime(RevInst& inst); // 409, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) - // EcallStatus ECALL_timerfd_gettime(RevInst& inst); // 410, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) - // EcallStatus ECALL_timerfd_settime(RevInst& inst); // 411, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) - // EcallStatus ECALL_utimensat(RevInst& inst); // 412, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) - // EcallStatus ECALL_io_pgetevents(RevInst& inst); // 416, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) - // EcallStatus ECALL_mq_timedsend(RevInst& inst); // 418, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) - // EcallStatus ECALL_mq_timedreceive(RevInst& inst); // 419, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) - // EcallStatus ECALL_semtimedop(RevInst& inst); // 420, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) - // EcallStatus ECALL_futex(RevInst& inst); // 422, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) - // EcallStatus ECALL_sched_rr_get_interval(RevInst& inst); // 423, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) - EcallStatus ECALL_pidfd_send_signal(RevInst& inst); // 424, rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) - EcallStatus ECALL_io_uring_setup(RevInst& inst); // 425, rev_io_uring_setup(u32 entries, struct io_uring_params *p) - EcallStatus ECALL_io_uring_enter(RevInst& inst); // 426, rev_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const sigset_t *sig, size_t sigsz) - EcallStatus ECALL_io_uring_register(RevInst& inst); // 427, rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args) - EcallStatus ECALL_open_tree(RevInst& inst); // 428, rev_open_tree(int dfd, const char *path, unsigned flags) - EcallStatus ECALL_move_mount(RevInst& inst); // 429, rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) - EcallStatus ECALL_fsopen(RevInst& inst); // 430, rev_fsopen(const char *fs_name, unsigned int flags) - EcallStatus ECALL_fsconfig(RevInst& inst); // 431, rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) - EcallStatus ECALL_fsmount(RevInst& inst); // 432, rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) - EcallStatus ECALL_fspick(RevInst& inst); // 433, rev_fspick(int dfd, const char *path, unsigned int flags) - EcallStatus ECALL_pidfd_open(RevInst& inst); // 434, rev_pidfd_open(pid_t pid, unsigned int flags) - EcallStatus ECALL_clone3(RevInst& inst); // 435, rev_clone3(struct clone_args *uargs, size_t size) - EcallStatus ECALL_close_range(RevInst& inst); // 436, rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags) - EcallStatus ECALL_openat2(RevInst& inst); // 437, rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) - EcallStatus ECALL_pidfd_getfd(RevInst& inst); // 438, rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) - EcallStatus ECALL_faccessat2(RevInst& inst); // 439, rev_faccessat2(int dfd, const char *filename, int mode, int flags) - EcallStatus ECALL_process_madvise(RevInst& inst); // 440, rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) - - // =============== REV specific functions - EcallStatus ECALL_cpuinfo(RevInst& inst); // 500, rev_cpuinfo(struct rev_cpuinfo *info); - EcallStatus ECALL_perf_stats(RevInst& inst); // 501, rev_perf_stats(struct rev_stats *stats); - - // =============== REV pthread functions - EcallStatus ECALL_pthread_create(RevInst& inst); // 1000, rev_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) - EcallStatus ECALL_pthread_join(RevInst& inst); // 1001, rev_pthread_join(pthread_t thread, void **retval); - EcallStatus ECALL_pthread_exit(RevInst& inst); // 1002, rev_pthread_exit(void* retval); - - /// RevProc: Table of ecall codes w/ corresponding function pointer implementations - std::unordered_map> Ecalls; - - /// RevProc: Initialize all of the ecalls inside the above table - void InitEcallTable(); - - /// RevProc: Execute the Ecall based on the code loaded in RegFile->RV64_SCAUSE - void ExecEcall(RevInst &inst); - - /// RevProc: Get a pointer to the register file loaded into Hart w/ HartID - RevRegFile* GetRegFile(unsigned HartID) const; - - std::vector InstTable; ///< RevProc: target instruction table - - std::vector> Extensions; ///< RevProc: vector of enabled extensions - - //std::vector> Pipeline; ///< RevProc: pipeline of instructions - std::deque> Pipeline; ///< RevProc: pipeline of instructions - std::map NameToEntry; ///< RevProc: instruction mnemonic to table entry mapping - std::map EncToEntry; ///< RevProc: instruction encoding to table entry mapping - std::map CEncToEntry; ///< RevProc: compressed instruction encoding to table entry mapping - - std::map> EntryToExt; ///< RevProc: instruction entry to extension object mapping - /// first = Master table entry number - /// second = pair - - /// RevProc: splits a string into tokens - void splitStr(const std::string& s, char c, std::vector& v); - - /// RevProc: parses the feature string for the target core - bool ParseFeatureStr(std::string Feature); - - /// RevProc: loads the instruction table using the target features - bool LoadInstructionTable(); - - /// RevProc: see the instruction table the target features - bool SeedInstTable(); - - /// RevProc: enable the target extension by merging its instruction table with the master - bool EnableExt(RevExt *Ext, bool Opt); - - /// RevProc: initializes the internal mapping tables - bool InitTableMapping(); - - /// RevProc: read in the user defined cost tables - bool ReadOverrideTables(); - - /// RevProc: compresses the encoding structure to a single value - uint32_t CompressEncoding(RevInstEntry Entry); - - /// RevProc: compressed the compressed encoding structure to a single value - uint32_t CompressCEncoding(RevInstEntry Entry); - - /// RevProc: extracts the instruction mnemonic from the table entry - std::string ExtractMnemonic(RevInstEntry Entry); - - /// RevProc: reset the core and its associated features - bool Reset(); - - /// RevProc: set the PC - void SetPC(uint64_t PC) { RegFile->SetPC(PC); } - - /// RevProc: prefetch the next instruction - bool PrefetchInst(); - - /// RevProc: decode the instruction at the current PC - RevInst FetchAndDecodeInst(); - - /// RevProc: decode a particular instruction opcode - RevInst DecodeInst(uint32_t Inst) const; - - /// RevProc: decode a compressed instruction - RevInst DecodeCompressed(uint32_t Inst) const; - - /// RevProc: decode an R-type instruction - RevInst DecodeRInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode an I-type instruction - RevInst DecodeIInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode an S-type instruction - RevInst DecodeSInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode a U-type instruction - RevInst DecodeUInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode a B-type instruction - RevInst DecodeBInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode a J-type instruction - RevInst DecodeJInst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode an R4-type instruction - RevInst DecodeR4Inst(uint32_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CR-type isntruction - RevInst DecodeCRInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CI-type isntruction - RevInst DecodeCIInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CSS-type isntruction - RevInst DecodeCSSInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CIW-type isntruction - RevInst DecodeCIWInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CL-type isntruction - RevInst DecodeCLInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CS-type isntruction - RevInst DecodeCSInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CA-type isntruction - RevInst DecodeCAInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CB-type isntruction - RevInst DecodeCBInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: decode a compressed CJ-type isntruction - RevInst DecodeCJInst(uint16_t Inst, unsigned Entry) const; - - /// RevProc: determine if the instruction is floating-point - bool IsFloat(unsigned Entry) const { - // Note: This is crude and looks for ANY FP register operands; - // InstTable[...].rClass should be used when doing hazard - // detection on particular registers, since some instructions - // combine integer and FP register operands. See DependencySet(). - return( InstTable[Entry].rdClass == RevRegClass::RegFLOAT || - InstTable[Entry].rs1Class == RevRegClass::RegFLOAT || - InstTable[Entry].rs2Class == RevRegClass::RegFLOAT || - InstTable[Entry].rs3Class == RevRegClass::RegFLOAT ); - } - - /// RevProc: Determine next thread to execute - unsigned GetNextHartToDecodeID() const; - - /// RevProc: Whether any scoreboard bits are set - bool AnyDependency(unsigned HartID, bool isFloat) const { - const RevRegFile* regFile = GetRegFile(HartID); - return isFloat ? regFile->FP_Scoreboard.any() : regFile->RV_Scoreboard.any(); - } - - /// RevProc: Whether any scoreboard bits are set - bool AnyDependency(unsigned HartID) const { - const auto& RegFile = Harts.at(HartID)->RegFile; - return RegFile->FP_Scoreboard.any() || RegFile->RV_Scoreboard.any(); - } - - /// RevProc: Check LS queue for outstanding load - ignore r0 - bool LSQCheck(unsigned HartID, const RevRegFile* regFile, - uint16_t reg, RevRegClass regClass) const { - return (reg != 0 || regClass != RevRegClass::RegGPR) && - regFile->GetLSQueue()->count(LSQHash(reg, regClass, HartID)) > 0; - } - - /// RevProc: Check scoreboard for a source register dependency - bool ScoreboardCheck(const RevRegFile* regFile, uint16_t reg, RevRegClass regClass) const { - return reg < _REV_NUM_REGS_ && - ( (regClass == RevRegClass::RegFLOAT && regFile->FP_Scoreboard[reg]) || - (regClass == RevRegClass::RegGPR && reg != 0 && regFile->RV_Scoreboard[reg]) ); - } - - bool HartHasNoDependencies(unsigned HartID) const { - return !AnyDependency(HartID); - } - - ///< Removes thread from Hart and returns it - std::unique_ptr PopThreadFromHart(unsigned HartID); - - /// RevProc: Check scoreboard for pipeline hazards - bool DependencyCheck(unsigned HartID, const RevInst* Inst) const; - - /// RevProc: Set or clear scoreboard based on instruction destination - void DependencySet(unsigned HartID, const RevInst* Inst, bool value = true){ - DependencySet(HartID, - Inst->rd, - InstTable[Inst->entry].rdClass == RevRegClass::RegFLOAT, - value); - } - - /// RevProc: Clear scoreboard on instruction retirement - void DependencyClear(unsigned HartID, const RevInst* Inst){ - DependencySet(HartID, Inst, false); - } - - /// RevProc: Set or clear scoreboard based on register number and floating point. - template - void DependencySet(unsigned HartID, T RegNum, - bool isFloat, bool value = true){ - if( size_t(RegNum) < _REV_NUM_REGS_ ){ - RevRegFile* regFile = GetRegFile(HartID); - if(isFloat){ - regFile->FP_Scoreboard[size_t(RegNum)] = value; - }else if( size_t(RegNum) != 0 ){ - regFile->RV_Scoreboard[size_t(RegNum)] = value; - } - } - } - - /// RevProc: Clear scoreboard on instruction retirement - template - void DependencyClear(unsigned HartID, T RegNum, bool isFloat){ - DependencySet(HartID, RegNum, isFloat, false); - } - -}; // class RevProc - -} // namespace SST::RevCPU - -#endif - -// EOF diff --git a/include/RevRand.h b/include/RevRand.h index ecaa79feb..aad5b35e8 100644 --- a/include/RevRand.h +++ b/include/RevRand.h @@ -20,33 +20,35 @@ #include #include -namespace SST::RevCPU{ +namespace SST::RevCPU { /// Wrapper class to SST::RNG::MersenneRNG -class RevRNG{ - SST::RNG::MersenneRNG SSTRNG; +class RevRNG { + SST::RNG::MersenneRNG SSTRNG{}; // Hardware random seed is different from run to run but fixed during run // so that distribution of HWSeed ^ ThreadSeed is uniform - static uint32_t HWSeed(){ + static uint32_t HWSeed() { static const uint32_t RevHWRNG = std::random_device{}(); return RevHWRNG; } // Thread seed is based on thread ID of host - static uint32_t ThreadSeed(){ - return uint32_t(std::hash{}(std::this_thread::get_id())); - } + static uint32_t ThreadSeed() { return uint32_t( std::hash{}( std::this_thread::get_id() ) ); } public: using result_type = uint64_t; + static constexpr result_type min() { return std::numeric_limits::min(); } + static constexpr result_type max() { return std::numeric_limits::max(); } + result_type operator()() { return SSTRNG.generateNextUInt64(); } - void seed(result_type seed) { *this = RevRNG(seed); } + + void seed( result_type seed ) { *this = RevRNG( seed ); } // Default seed is combination of HWSeed and ThreadSeed - explicit RevRNG(result_type seed = HWSeed() ^ ThreadSeed()) : SSTRNG(uint32_t(seed)) {} + explicit RevRNG( result_type seed = HWSeed() ^ ThreadSeed() ) : SSTRNG( uint32_t( seed ) ) {} // Not implemented: // discard() @@ -59,17 +61,17 @@ class RevRNG{ /// Random Number Generator // Returns a value in [min, max] (integer) or [min, max) (floating-point) template -inline auto RevRand(T min, U max){ +inline auto RevRand( T min, U max ) { // Thread-local RNG which is seeded differently for each thread thread_local RevRNG RNG; using TU = std::common_type_t; - if constexpr(std::is_floating_point_v){ - return std::uniform_real_distribution(min, max)(RNG); - }else{ - return std::uniform_int_distribution(min, max)(RNG); + if constexpr( std::is_floating_point_v ) { + return std::uniform_real_distribution( TU( min ), TU( max ) )( RNG ); + } else { + return std::uniform_int_distribution( TU( min ), TU( max ) )( RNG ); } } -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevRegFile.h b/include/RevRegFile.h index c4c88da40..59c648590 100644 --- a/include/RevRegFile.h +++ b/include/RevRegFile.h @@ -23,26 +23,82 @@ #include #include -#include "RevFeature.h" -#include "RevMem.h" -#include "../common/include/RevCommon.h" +#include "RevCSR.h" +#include "RevCommon.h" +#include "RevTracer.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -struct RevInst; +// Mappings from floating point to same-sized integer types +template +struct uint_type {}; -/// BoxNaN: Store a boxed float inside a double -inline void BoxNaN(double* dest, const void* value){ - uint32_t i32; - memcpy(&i32, value, sizeof(float)); // The FP32 value - uint64_t i64 = uint64_t{i32} | ~uint64_t{0} << 32; // Boxed NaN value - memcpy(dest, &i64, sizeof(double)); // Store in FP64 register +template<> +struct uint_type { + using type = uint64_t; + static_assert( sizeof( type ) == sizeof( double ) ); +}; + +template<> +struct uint_type { + using type = uint32_t; + static_assert( sizeof( type ) == sizeof( float ) ); +}; + +#if 0 +template<> +struct uint_type { + using type = uint16_t; + static_assert( sizeof( type ) == sizeof( float16 ) ); +}; +#endif + +template +using uint_type_t = typename uint_type::type; + +/// BoxNaN: Store a boxed floating point value inside a possibly larger one +template= sizeof( U )>> +inline void BoxNaN( T* dest, const U* value ) { + if constexpr( sizeof( T ) == sizeof( U ) ) { + *dest = *value; + } else { + uint_type_t i; + memcpy( &i, value, sizeof( i ) ); // The value + uint_type_t box = uint_type_t{ i } | ~uint_type_t{ 0 } << sizeof( U ) * 8; // Boxed NaN value + memcpy( dest, &box, sizeof( box ) ); // Store in larger register + static_assert( sizeof( i ) == sizeof( U ) && sizeof( box ) == sizeof( T ) ); + } +} + +/// UnBoxNaN: Unbox a floating point value into a possibly smaller one +// The second argument indicates whether it is a FMV/FS move/store +// instruction which just transfers bits and not care about NaN-Boxing. +template> +inline T UnBoxNaN( const U* val ) { + if constexpr( sizeof( T ) == sizeof( U ) ) { + return *val; + } else { + uint_type_t i; + memcpy( &i, val, sizeof( i ) ); + static_assert( sizeof( i ) == sizeof( val ) ); + T fp; + if( !FMV_FS && ~i >> sizeof( T ) * 8 ) { + fp = std::numeric_limits::quiet_NaN(); + } else { + auto ifp = static_cast>( i ); + memcpy( &fp, &ifp, sizeof( fp ) ); + static_assert( sizeof( ifp ) == sizeof( fp ) ); + } + return fp; + } } /// RISC-V Register Mneumonics +// clang-format off enum class RevReg : uint16_t { zero = 0, ra = 1, sp = 2, gp = 3, tp = 4, t0 = 5, t1 = 6, t2 = 7, s0 = 8, s1 = 9, a0 = 10, a1 = 11, a2 = 12, a3 = 13, a4 = 14, a5 = 15, + fp = 8, a6 = 16, a7 = 17, s2 = 18, s3 = 19, s4 = 20, s5 = 21, s6 = 22, s7 = 23, s8 = 24, s9 = 25, s10 = 26, s11 = 27, t3 = 28, t4 = 29, t5 = 30, t6 = 31, ft0 = 0, ft1 = 1, ft2 = 2, ft3 = 3, ft4 = 4, ft5 = 5, ft6 = 6, ft7 = 7, @@ -50,88 +106,73 @@ enum class RevReg : uint16_t { fa6 = 16, fa7 = 17, fs2 = 18, fs3 = 19, fs4 = 20, fs5 = 21, fs6 = 22, fs7 = 23, fs8 = 24, fs9 = 25, fs10 = 26, fs11 = 27, ft8 = 28, ft9 = 29, ft10 = 30, ft11 = 31, }; - -/// Floating-Point Rounding Mode -enum class FRMode : uint8_t { - None = 0xff, - RNE = 0, // Round to Nearest, ties to Even - RTZ = 1, // Round towards Zero - RDN = 2, // Round Down (towards -Inf) - RUP = 3, // Round Up (towards +Inf) - RMM = 4, // Round to Nearest, ties to Max Magnitude - DYN = 7, // In instruction's rm field, selects dynamic rounding mode; invalid in FCSR -}; - -/// Floating-point control register -// fcsr.NX, fcsr.UF, fcsr.OF, fcsr.DZ, fcsr.NV, fcsr.frm -struct FCSR{ - uint32_t NX : 1; - uint32_t UF : 1; - uint32_t OF : 1; - uint32_t DZ : 1; - uint32_t NV : 1; - uint32_t frm : 3; - uint32_t : 24; +// clang-format on + +// Ref: RISC-V Privileged Spec (pg. 39) +enum class RevExceptionCause : int32_t { + NONE = -1, + MISALIGNED_INST_ADDR = 0, + INST_ACCESS_FAULT = 1, + ILLEGAL_INST = 2, + BREAKPOINT = 3, + LOAD_ADDR_MISALIGNED = 4, + LOAD_ACCESS_FAULT = 5, + STORE_AMO_ADDR_MISALIGNED = 6, + STORE_AMO_ACCESS_FAULT = 7, + ECALL_USER_MODE = 8, + ECALL_SUPERVISOR_MODE = 9, + ECALL_MACHINE_MODE = 11, + INST_PAGE_FAULT = 12, + LOAD_PAGE_FAULT = 13, + STORE_AMO_PAGE_FAULT = 15, }; -class RevRegFile { -public: - const bool IsRV32; ///< RevRegFile: Cached copy of Features->IsRV32() - const bool HasD; ///< RevRegFile: Cached copy of Features->HasD() - -private: - bool trigger{}; ///< RevRegFile: Has the instruction been triggered? - unsigned Entry{}; ///< RevRegFile: Instruction entry - uint32_t cost{}; ///< RevRegFile: Cost of the instruction - RevTracer *Tracer = nullptr; ///< RegRegFile: Tracer object - - union{ // Anonymous union. We zero-initialize the largest member - uint32_t RV32_PC; ///< RevRegFile: RV32 PC - uint64_t RV64_PC{}; ///< RevRegFile: RV64 PC +class RevCore; +class RevTracer; + +class RevRegFile final : public RevCSR { + RevCore* const Core; ///< RevRegFile: Owning core of this register file's hart + const bool IsRV64_v; ///< RevRegFile: Cached copy of Features->IsRV64() + const bool HasD_v; ///< RevRegFile: Cached copy of Features->HasD() + bool trigger{}; ///< RevRegFile: Has the instruction been triggered? + uint32_t Entry{}; ///< RevRegFile: Instruction entry + uint32_t cost{}; ///< RevRegFile: Cost of the instruction + RevTracer* Tracer{}; ///< RegRegFile: Tracer object + + union { // Anonymous union. We zero-initialize the largest member + uint32_t RV32_PC; ///< RevRegFile: RV32 PC + uint64_t RV64_PC{}; ///< RevRegFile: RV64 PC }; - FCSR fcsr{}; ///< RevRegFile: FCSR - std::shared_ptr> LSQueue{}; - std::function MarkLoadCompleteFunc{}; + std::function MarkLoadCompleteFunc{}; - union{ // Anonymous union. We zero-initialize the largest member - uint32_t RV32[_REV_NUM_REGS_]; ///< RevRegFile: RV32I register file - uint64_t RV64[_REV_NUM_REGS_]{}; ///< RevRegFile: RV64I register file + union { // Anonymous union. We zero-initialize the largest member + uint32_t RV32[_REV_NUM_REGS_]; ///< RevRegFile: RV32I register file + uint64_t RV64[_REV_NUM_REGS_]{}; ///< RevRegFile: RV64I register file }; - union{ // Anonymous union. We zero-initialize the largest member - float SPF[_REV_NUM_REGS_]; ///< RevRegFile: RVxxF register file - double DPF[_REV_NUM_REGS_]{}; ///< RevRegFile: RVxxD register file + union { // Anonymous union. We zero-initialize the largest member + float SPF[_REV_NUM_REGS_]; ///< RevRegFile: RVxxF register file + double DPF[_REV_NUM_REGS_]{}; ///< RevRegFile: RVxxD register file }; - std::bitset<_REV_NUM_REGS_> RV_Scoreboard{}; ///< RevRegFile: Scoreboard for RV32/RV64 RF to manage pipeline hazard - std::bitset<_REV_NUM_REGS_> FP_Scoreboard{}; ///< RevRegFile: Scoreboard for SPF/DPF RF to manage pipeline hazard + std::bitset<_REV_NUM_REGS_> RV_Scoreboard{}; ///< RevRegFile: Scoreboard for RV32/RV64 RF to manage pipeline hazard + std::bitset<_REV_NUM_REGS_> FP_Scoreboard{}; ///< RevRegFile: Scoreboard for SPF/DPF RF to manage pipeline hazard - // Supervisor Mode CSRs -#if 0 // not used - union{ // Anonymous union. We zero-initialize the largest member - uint64_t RV64_SSTATUS{}; // During ecall, previous priviledge mode is saved in this register (Incomplete) - uint32_t RV32_SSTATUS; - }; -#endif - - union{ // Anonymous union. We zero-initialize the largest member - uint64_t RV64_SEPC{}; // Holds address of instruction that caused the exception (ie. ECALL) + union { // Anonymous union. We zero-initialize the largest member + uint64_t RV64_SEPC{}; // Holds address of instruction that caused the exception (ie. ECALL) uint32_t RV32_SEPC; }; - union{ // Anonymous union. We zero-initialize the largest member - uint64_t RV64_SCAUSE{}; // Used to store cause of exception (ie. ECALL_USER_EXCEPTION)/ - uint32_t RV32_SCAUSE; - }; + RevExceptionCause SCAUSE = RevExceptionCause::NONE; // Used to store cause of exception (ie. ECALL_USER_EXCEPTION) - union{ // Anonymous union. We zero-initialize the largest member - uint64_t RV64_STVAL{}; // Used to store additional info about exception (ECALL does not use this and sets value to 0) + union { // Anonymous union. We zero-initialize the largest member + uint64_t RV64_STVAL{}; // Used to store additional info about exception (ECALL does not use this and sets value to 0) uint32_t RV32_STVAL; }; -#if 0 // not used +#if 0 // not used union{ // Anonymous union. We zero-initialize the largest member uint64_t RV64_STVEC{}; // Holds the base address of the exception handling routine (trap handler) that the processor jumps to when and exception occurs uint32_t RV32_STVEC; @@ -139,151 +180,152 @@ class RevRegFile { #endif public: - // Constructor which takes a RevFeature - explicit RevRegFile(const RevFeature* feature) - : IsRV32(feature->IsRV32()), HasD(feature->HasD()) { - } + // Constructor which takes a RevCore to indicate its hart's parent core + // Template allows RevCore to be an incomplete type now + // std::enable_if_t<...> makes the constructor only match CORE == RevCore + template>> + explicit RevRegFile( CORE* Core ) + : Core( Core ), IsRV64_v( Core->GetRevFeature()->IsRV64() ), HasD_v( Core->GetRevFeature()->HasD() ) {} - // Getters/Setters + /// RevRegFile: disallow copying and assignment + RevRegFile( const RevRegFile& ) = delete; + RevRegFile& operator=( const RevRegFile& ) = delete; + + /// RevRegFile: standard destructor + ~RevRegFile() final = default; + + ///< RevRegFile: Return the core owning this hart + RevCore* GetCore() const final { return Core; } + + // Feature tests + ///< RevRegFile: Whether it is RV64 + bool IsRV64() const final { return IsRV64_v; } + ///< RevRegFile: Whenter it is D + bool HasD() const { return HasD_v; } + + // Getters/Setters /// Get cost of the instruction const uint32_t& GetCost() const { return cost; } + uint32_t& GetCost() { return cost; } /// Set cost of the instruction - void SetCost(uint32_t c) { cost = c; } + void SetCost( uint32_t c ) { cost = c; } /// Get whether the instruction has been triggered bool GetTrigger() const { return trigger; } /// Set whether the instruction has been triggered - void SetTrigger(bool t) { trigger = t; } + void SetTrigger( bool t ) { trigger = t; } /// Get the instruction entry - unsigned GetEntry() const { return Entry; } + uint32_t GetEntry() const { return Entry; } /// Set the instruction entry - void SetEntry(unsigned e) { Entry = e; } + void SetEntry( uint32_t e ) { Entry = e; } /// Get the Load/Store Queue const auto& GetLSQueue() const { return LSQueue; } /// Set the Load/Store Queue - void SetLSQueue(std::shared_ptr> lsq){ - LSQueue = std::move(lsq); - } + void SetLSQueue( std::shared_ptr> lsq ) { LSQueue = std::move( lsq ); } /// Set the current tracer - void SetTracer(RevTracer *t) { Tracer = t; } + void SetTracer( RevTracer* t ) { Tracer = t; } /// Get the MarkLoadComplete function - const std::function& GetMarkLoadComplete() const { - return MarkLoadCompleteFunc; - } + const std::function& GetMarkLoadComplete() const { return MarkLoadCompleteFunc; } /// Set the MarkLoadComplete function - void SetMarkLoadComplete(std::function func){ - MarkLoadCompleteFunc = std::move(func); - } + void SetMarkLoadComplete( std::function func ) { MarkLoadCompleteFunc = std::move( func ); } /// Invoke the MarkLoadComplete function - void MarkLoadComplete(const MemReq& req) const { - MarkLoadCompleteFunc(req); - } - - /// Return the Floating-Point Rounding Mode - FRMode GetFPRound() const{ - return static_cast(fcsr.frm); - } + void MarkLoadComplete( const MemReq& req ) const { MarkLoadCompleteFunc( req ); } /// Capture the PC of current instruction which raised exception - void SetSEPC(){ - if( IsRV32 ){ - RV32_SEPC = RV32_PC; - }else{ + void SetSEPC() { + if( IsRV64() ) { RV64_SEPC = RV64_PC; + } else { + RV32_SEPC = RV32_PC; } } ///Set the value for extra information about exception /// (ECALL doesn't use it and sets it to 0) template - void SetSTVAL(T val){ - if( IsRV32 ){ - RV32_STVAL = val; - }else{ - RV64_STVAL = val; + void SetSTVAL( T val ) { + if( IsRV64() ) { + RV64_STVAL = uint64_t( val ); + } else { + RV32_STVAL = uint32_t( val ); } } /// Set the exception cause - template - void SetSCAUSE(T val){ - if( IsRV32 ){ - RV32_SCAUSE = val; - }else{ - RV64_SCAUSE = val; - } - } + void SetSCAUSE( RevExceptionCause val ) { SCAUSE = val; } + + /// Get the exception cause + RevExceptionCause GetSCAUSE() const { return SCAUSE; } /// GetX: Get the specifed X register cast to a specific integral type template - T GetX(U rs) const { + T GetX( U rs ) const { T res; - if( IsRV32 ){ - res = RevReg(rs) != RevReg::zero ? T(RV32[size_t(rs)]) : 0; - TRACE_REG_READ(size_t(rs), uint32_t(res)); - }else{ - res = RevReg(rs) != RevReg::zero ? T(RV64[size_t(rs)]) : 0; - TRACE_REG_READ(size_t(rs),uint64_t(res)); + if( IsRV64() ) { + res = RevReg( rs ) != RevReg::zero ? T( RV64[size_t( rs )] ) : 0; + TRACE_REG_READ( size_t( rs ), uint64_t( res ) ); + } else { + res = RevReg( rs ) != RevReg::zero ? T( RV32[size_t( rs )] ) : 0; + TRACE_REG_READ( size_t( rs ), uint32_t( res ) ); } return res; } /// SetX: Set the specifed X register to a specific value template - void SetX(U rd, T val) { - T res; - if( IsRV32 ){ - res = RevReg(rd) != RevReg::zero ? uint32_t(val) : 0; - RV32[size_t(rd)] = res; - TRACE_REG_WRITE(size_t(rd), uint32_t(res)); - }else{ - res = RevReg(rd) != RevReg::zero ? uint64_t(val) : 0; - RV64[size_t(rd)] = res; - TRACE_REG_WRITE(size_t(rd), uint64_t(res)); + void SetX( U rd, T val ) { + if( IsRV64() ) { + uint64_t res = RevReg( rd ) != RevReg::zero ? uint64_t( val ) : 0; + RV64[size_t( rd )] = res; + TRACE_REG_WRITE( size_t( rd ), res ); + } else { + uint32_t res = RevReg( rd ) != RevReg::zero ? uint32_t( val ) : 0; + RV32[size_t( rd )] = res; + TRACE_REG_WRITE( size_t( rd ), res ); } } /// GetPC: Get the Program Counter - uint64_t GetPC() const { - if( IsRV32 ){ - return RV32_PC; - }else{ + uint64_t GetPC() const final { + if( IsRV64() ) { return RV64_PC; + } else { + return RV32_PC; } } /// SetPC: Set the Program Counter to a specific value template - void SetPC(T val) { - if( IsRV32 ){ - RV32_PC = static_cast(val); - TRACE_PC_WRITE(RV32_PC); - }else{ - RV64_PC = static_cast(val); - TRACE_PC_WRITE(RV64_PC); + void SetPC( T val ) { + if( IsRV64() ) { + RV64_PC = static_cast( val ); + TRACE_PC_WRITE( RV64_PC ); + } else { + RV32_PC = static_cast( val ); + TRACE_PC_WRITE( RV32_PC ); } } /// AdvancePC: Advance the program counter to the next instruction // Note: This does not create tracer events like SetPC() does - template // Used to allow RevInst to be incomplete type right now - void AdvancePC(const T& Inst) { - if ( IsRV32 ) { - RV32_PC += Inst.instSize; - }else{ + template // Used to allow RevInst to be incomplete type right now + void AdvancePC( const T& Inst ) { + if( IsRV64() ) { RV64_PC += Inst.instSize; + } else { + RV32_PC += Inst.instSize; } } @@ -291,69 +333,57 @@ class RevRegFile { // The second argument indicates whether it is a FMV/FS move/store // instruction which just transfers bits and not care about NaN-Boxing. template - T GetFP(U rs) const { - if constexpr(std::is_same_v){ - return DPF[size_t(rs)]; // The FP64 register's value - }else{ - float fp32; - if( !HasD ){ - fp32 = SPF[size_t(rs)]; // The FP32 register's value - }else{ - uint64_t i64; - memcpy(&i64, &DPF[size_t(rs)], sizeof(i64)); // The FP64 register's value - if (!FMV_FS && ~i64 >> 32){ // Check for boxed NaN unless FMV/FS - fp32 = NAN; // Return NaN if it's not boxed - }else{ - auto i32 = static_cast(i64); // For endian independence on host - memcpy(&fp32, &i32, sizeof(fp32)); // The bottom half of FP64 - } - } - return fp32; // Reinterpreted as FP32 + T GetFP( U rs ) const { + if constexpr( std::is_same_v ) { + return DPF[size_t( rs )]; + } else if( HasD() ) { + return UnBoxNaN( &DPF[size_t( rs )] ); + } else { + return UnBoxNaN( &SPF[size_t( rs )] ); } } /// SetFP: Set a specific FP register to a floating-point value template - void SetFP(U rd, T value) - { - if constexpr(std::is_same_v){ - DPF[size_t(rd)] = value; // Store in FP64 register - }else if( HasD ){ - BoxNaN(&DPF[size_t(rd)], &value); // Store NaN-boxed float in FP64 register - }else { - SPF[size_t(rd)] = value; // Store in FP32 register + void SetFP( U rd, T value ) { + if constexpr( std::is_same_v ) { + DPF[size_t( rd )] = value; + } else if( HasD() ) { + BoxNaN( &DPF[size_t( rd )], &value ); + } else { + BoxNaN( &SPF[size_t( rd )], &value ); } } // Friend functions and classes to access internal register state - template - friend bool CvtFpToInt(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + template + friend bool fcvtif( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template - friend bool load(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool load( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template - friend bool store(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool store( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template - friend bool fload(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool fload( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template - friend bool fstore(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool fstore( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template class OP> - friend bool foper(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool foper( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); template class OP> - friend bool fcondop(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst); + friend bool fcondop( const class RevFeature* F, RevRegFile* R, class RevMem* M, const class RevInst& Inst ); - friend std::ostream& operator<<(std::ostream& os, const RevRegFile& regFile); + friend std::ostream& operator<<( std::ostream& os, const RevRegFile& regFile ); - friend class RevProc; - friend class RV32A; - friend class RV64A; -}; // class RevRegFile + friend class RevCore; + friend class Zaamo; + friend class Zalrsc; +}; // class RevRegFile -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevSysCalls.h b/include/RevSysCalls.h index d75c660d9..8167d6cce 100644 --- a/include/RevSysCalls.h +++ b/include/RevSysCalls.h @@ -20,32 +20,30 @@ #include // -- RevCPU Headers -#include "../common/include/RevCommon.h" +#include "RevCommon.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -enum class EcallStatus{ - SUCCESS = 0, - CONTINUE = EXCEPTION_CAUSE::ECALL_USER_MODE, - ERROR = 255, +enum class EcallStatus { + SUCCESS, + CONTINUE, + ERROR, }; // State information for ECALLs struct EcallState { - std::array buf; - std::string string; - std::string path_string; - size_t bytesRead = 0; + std::array buf{}; + std::string string{}; + std::string path_string{}; + size_t bytesRead{}; - void clear(){ + void clear() { string.clear(); path_string.clear(); bytesRead = 0; - buf[0] = '\0'; } - EcallState() { - buf[0] = '\0'; - } -}; -} + + explicit EcallState() = default; +}; // struct EcallState +} // namespace SST::RevCPU #endif diff --git a/include/RevThread.h b/include/RevThread.h index d18323e1e..69c584cbe 100644 --- a/include/RevThread.h +++ b/include/RevThread.h @@ -21,71 +21,71 @@ // -- Rev Headers #include "RevInstTable.h" #include "RevMem.h" +#include "RevRegFile.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { class RevThread { public: using RevVirtRegState = RevRegFile; ///< RevThread: Constructor - RevThread(uint32_t ID, uint32_t ParentID, - std::shared_ptr& ThreadMem, - std::unique_ptr VirtRegState) - : ID(ID), ParentID(ParentID), - ThreadMem(ThreadMem), VirtRegState(std::move(VirtRegState)){} + RevThread( + uint32_t ID, uint32_t ParentID, std::shared_ptr& ThreadMem, std::unique_ptr VirtRegState + ) + : ID( ID ), ParentID( ParentID ), ThreadMem( ThreadMem ), VirtRegState( std::move( VirtRegState ) ) {} ///< RevThread: Destructor - ~RevThread(){ + ~RevThread() { // Check if any fildes are still open // and close them if so - for(auto fd : fildes){ - if(fd > 2){ - close(fd); + for( auto fd : fildes ) { + if( fd > 2 ) { + close( fd ); } } } + ///< RevThread: disallow copying and assignment + RevThread( const RevThread& ) = delete; + RevThread& operator=( const RevThread& ) = delete; + ///< RevThread: Get this thread's ID uint32_t GetID() const { return ID; } ///< RevThread: Set this thread's ID - void SetID(const uint32_t NewID) { ID = NewID; } + void SetID( const uint32_t NewID ) { ID = NewID; } ///< RevThread: Get the parent of this thread's TID uint32_t GetParentID() const { return ParentID; } ///< RevThread: Set the parent of this thread's TID - void SetParentID(const uint32_t NewParentID) { ParentID = NewParentID; } + void SetParentID( const uint32_t NewParentID ) { ParentID = NewParentID; } ///< RevThread: Get the TID of the thread that this thread is waiting to join uint32_t GetWaitingToJoinTID() const { return WaitingToJoinTID; } ///< RevThread: Set the TID of the thread that this thread is waiting to join - void SetWaitingToJoinTID(const uint32_t ThreadToWaitOn) { WaitingToJoinTID = ThreadToWaitOn; } + void SetWaitingToJoinTID( const uint32_t ThreadToWaitOn ) { WaitingToJoinTID = ThreadToWaitOn; } ///< RevThread: Add new file descriptor to this thread (ie. rev_open) - void AddFD(int fd){ fildes.insert(fd); } + void AddFD( int fd ) { fildes.insert( fd ); } ///< RevThread: Remove file descriptor from this thread (ie. rev_close) - void RemoveFD(int fd){ fildes.erase(fd); } + void RemoveFD( int fd ) { fildes.erase( fd ); } ///< See if file descriptor exists/is owned by this thread - bool FindFD(int fd){ return fildes.count(fd); } + bool FindFD( int fd ) { return fildes.count( fd ); } ///< RevThread: Get the fildes valid for this thread - const std::unordered_set& GetFildes(){ return fildes; } + const std::unordered_set& GetFildes() { return fildes; } ///< RevThread: Update this thread's virtual register state - void UpdateVirtRegState(std::unique_ptr vRegState){ - VirtRegState = std::move(vRegState); - } + void UpdateVirtRegState( std::unique_ptr vRegState ) { VirtRegState = std::move( vRegState ); } ///< RevThread: Transfers the pointer of this Thread's register state /// (Used for loading reg state into a Hart's RegFile) - std::unique_ptr TransferVirtRegState(){ - return std::move(VirtRegState); - } + std::unique_ptr TransferVirtRegState() { return std::move( VirtRegState ); } ///< RevThread: Get the RevFeature this thread was created with RevFeature* GetFeature() const { return Feature; } @@ -94,16 +94,16 @@ class RevThread { ThreadState GetState() const { return State; } ///< RevThread: Set this thread's ThreadState - void SetState(ThreadState newState) { State = std::move(newState); } + void SetState( ThreadState newState ) { State = std::move( newState ); } ///< RevThread: Add a child to this thread id - void AddChildID(uint32_t tid){ ChildrenIDs.insert(tid); } + void AddChildID( uint32_t tid ) { ChildrenIDs.insert( tid ); } ///< RevThread: Remove a child thread ID from this thread - void RemoveChildID(uint32_t tid){ ChildrenIDs.erase(tid); } + void RemoveChildID( uint32_t tid ) { ChildrenIDs.erase( tid ); } ///< RevThread: Overload the ostream printing - friend std::ostream& operator<<(std::ostream& os, const RevThread& Thread); + friend std::ostream& operator<<( std::ostream& os, const RevThread& Thread ); ///< RevThread: Overload the to_string method std::string to_string() const { @@ -113,23 +113,23 @@ class RevThread { } private: - uint32_t ID; // Thread ID - uint32_t ParentID; // Parent ID - uint64_t StackPtr; // Initial stack pointer - uint64_t FirstPC; // Initial PC - std::shared_ptr ThreadMem; // TLS and Stack memory - RevFeature* Feature; // Feature set for this thread - uint64_t ThreadPtr; // Thread pointer - ThreadState State = ThreadState::START; // Thread state - std::unique_ptr VirtRegState; // Register file - std::unordered_set ChildrenIDs = {}; // Child thread IDs - std::unordered_set fildes = {0, 1, 2}; // Default file descriptors + uint32_t ID{}; // Thread ID + uint32_t ParentID{}; // Parent ID + // uint64_t StackPtr{}; // Initial stack pointer + // uint64_t FirstPC{}; // Initial PC + std::shared_ptr ThreadMem{}; // TLS and Stack memory + RevFeature* Feature{}; // Feature set for this thread + // uint64_t ThreadPtr{}; // Thread pointer + ThreadState State{ ThreadState::START }; // Thread state + std::unique_ptr VirtRegState{}; // Register file + std::unordered_set ChildrenIDs{}; // Child thread IDs + std::unordered_set fildes{ 0, 1, 2 }; // Default file descriptors ///< RevThread: ID of the thread this thread is waiting to join uint32_t WaitingToJoinTID = _INVALID_TID_; -}; // class RevThread +}; // class RevThread -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/RevTracer.h b/include/RevTracer.h index dae3a75c1..2218eddd6 100644 --- a/include/RevTracer.h +++ b/include/RevTracer.h @@ -1,7 +1,7 @@ // // _RevTracer_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -17,10 +17,10 @@ // -- Standard Headers #include -#include -#include #include #include +#include +#include #include // -- Rev Headers @@ -35,18 +35,26 @@ #ifdef __GNUC__ #undef UNUSED #endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" + #include "riscv/disasm.h" + +#pragma GCC diagnostic pop + #endif // Tracing macros +// clang-format off #ifndef NO_REV_TRACER -#define TRACE_REG_READ(R,V) { if (Tracer) Tracer->regRead( (R), (V) ); } -#define TRACE_REG_WRITE(R,V) { if (Tracer) Tracer->regWrite( (R), (V) ); } -#define TRACE_PC_WRITE(PC) { if (Tracer) Tracer->pcWrite( (PC) ); } -#define TRACE_MEM_WRITE(ADR, LEN, DATA) { if (Tracer) Tracer->memWrite( (ADR), (LEN), (DATA) ); } -#define TRACE_MEM_READ(ADR, LEN, DATA) { if (Tracer) Tracer->memRead( (ADR), (LEN), (DATA) ); } -#define TRACE_MEMH_SENDREAD(ADR, LEN, REG) { if (Tracer) Tracer->memhSendRead( (ADR), (LEN), (REG) ); } -#define TRACE_MEM_READ_RESPONSE(LEN, DATA, REQ) { if (Tracer) Tracer->memReadResponse( (LEN), (DATA), (REQ) ); } +#define TRACE_REG_READ(R,V) do{ if (Tracer) Tracer->regRead( (R), (V) ); }while(0) +#define TRACE_REG_WRITE(R,V) do{ if (Tracer) Tracer->regWrite( (R), (V) ); }while(0) +#define TRACE_PC_WRITE(PC) do{ if (Tracer) Tracer->pcWrite( (PC) ); }while(0) +#define TRACE_MEM_WRITE(ADR, LEN, DATA) do{ if (Tracer) Tracer->memWrite( (ADR), (LEN), (DATA) ); }while(0) +#define TRACE_MEM_READ(ADR, LEN, DATA) do{ if (Tracer) Tracer->memRead( (ADR), (LEN), (DATA) ); }while(0) +#define TRACE_MEMH_SENDREAD(ADR, LEN, REG) do{ if (Tracer) Tracer->memhSendRead( (ADR), (LEN), (REG) ); }while(0) +#define TRACE_MEM_READ_RESPONSE(LEN, DATA, REQ) do{ if (Tracer) Tracer->memReadResponse( (LEN), (DATA), (REQ) ); }while(0) #else #define TRACE_REG_READ(R,V) #define TRACE_REG_WRITE(R,V) @@ -56,236 +64,241 @@ #define TRACE_MEMH_SENDREAD(ADR, LEN, REG) #define TRACE_MEM_READ_RESPONSE(LEN, DATA, REQ) #endif +// clang-format on -namespace SST::RevCPU{ - - // Tracing controls are using custom hint SLTI rd = x0 - // See unpriv-isa-asiidoc.pdf Section 2.9 HINT Instruction - // OP RD Space Assembly Encoding - // SLTI rd=x0 2^17 slti x0, x0, ? 0x00?02013 // - // SLTIU rd=x0 2^17 sltiu x0, x0, ? 0x00?03013 // - // SLLI rd=x0 2^10 slli x0, x0, ? 0x00?01013 // Default - // SRLI rd=x0 2^10 srli x0, x0, ? 0x00?05013 // - // SRAI rd=x0 2^10 srai x0, x0, ? 0x40?05013 // - // SLT rd=x0 2^10 slt x0, x0, x? 0x00?02033 // Not supported - // SLTU rd=x0 2^10 sltu x0, x0, x? 0x00?03033 // Not supported - const std::map s2op { - {"slti", 0x00002013}, - {"sltiu", 0x00003013}, - {"slli", 0x00001013}, - {"srli", 0x00005013}, - {"srai", 0x40005013}, - }; - const std::string TRC_OP_DEFAULT = "slli"; - const int TRC_OP_POS = 20; - - // Position of fully formed instruction in 'nops' array - enum class TRC_CMD_IDX : unsigned { - TRACE_OFF = 0, - TRACE_ON = 1, - TRACE_PUSH_OFF = 2, - TRACE_PUSH_ON = 3, - TRACE_POP = 4, - }; +namespace SST::RevCPU { - constexpr unsigned NOP_COUNT = 5; // must match TRC_CMD_IDX size - - enum class EVENT_SYMBOL : unsigned { - OK = 0x0, - STALL = 0x1, - FLUSH = 0x2, - TRACE_ON = 0x100, - TRACE_OFF = 0x102, - }; +// Tracing controls are using custom hint SLTI rd = x0 +// See unpriv-isa-asiidoc.pdf Section 2.9 HINT Instruction +// OP RD Space Assembly Encoding +// SLTI rd=x0 2^17 slti x0, x0, ? 0x00?02013 // +// SLTIU rd=x0 2^17 sltiu x0, x0, ? 0x00?03013 // +// SLLI rd=x0 2^10 slli x0, x0, ? 0x00?01013 // Default +// SRLI rd=x0 2^10 srli x0, x0, ? 0x00?05013 // +// SRAI rd=x0 2^10 srai x0, x0, ? 0x40?05013 // +// SLT rd=x0 2^10 slt x0, x0, x? 0x00?02033 // Not supported +// SLTU rd=x0 2^10 sltu x0, x0, x? 0x00?03033 // Not supported +const std::map s2op{ + { "slti", 0x00002013}, + {"sltiu", 0x00003013}, + { "slli", 0x00001013}, + { "srli", 0x00005013}, + { "srai", 0x40005013}, +}; +const std::string TRC_OP_DEFAULT = "slli"; +const int TRC_OP_POS = 20; - const std::map event2char { - {EVENT_SYMBOL::OK,' '}, - {EVENT_SYMBOL::STALL,'#'}, - {EVENT_SYMBOL::FLUSH,'!'}, - {EVENT_SYMBOL::TRACE_ON,'+'}, - {EVENT_SYMBOL::TRACE_OFF,'-'} - }; - - union TraceEvents_t { - uint64_t v = 0; - struct { - // define 1 bit per stall type - uint64_t stall : 1; // [0] - uint64_t stall_sources : 15; // [15:1] - uint64_t flush : 1; // [16] - uint64_t flush_sources : 15; // [31:17] - uint64_t spare : 31; // [62:32] - uint64_t trc_ctl : 1; // [63] indicate change in trace controls - } f; - }; +// Position of fully formed instruction in 'nops' array +enum class TRC_CMD_IDX : uint32_t { + TRACE_OFF = 0, + TRACE_ON = 1, + TRACE_PUSH_OFF = 2, + TRACE_PUSH_ON = 3, + TRACE_POP = 4, +}; - enum TraceKeyword_t { - RegRead, // register read (non-fp) - RegWrite, // register write (non-fp) - MemLoad, // issue load request (simple mem) - MemStore, // issue store request (simple mem) - MemhSendLoad, // issue load request (memh) - PcWrite, // write program counter - }; - - // Generic record so we can preserve code ordering of events in trace - // // register memory memh - // a; // reg adr adr - // b; // value len len - // c; // origin(TODO) data (limit 8 bytes) reg - struct TraceRec_t { - TraceKeyword_t key; - // register memory memh - uint64_t a; // reg adr adr - uint64_t b; // value len len - uint64_t c; // origin(TODO) data (limited 8 bytes) reg - TraceRec_t(TraceKeyword_t Key, uint64_t A, uint64_t B, uint64_t C=0) - : key(Key), a(A), b(B), c(C) {}; - }; +constexpr uint32_t NOP_COUNT = 5; // must match TRC_CMD_IDX size - struct InstHeader_t { - size_t cycle; - unsigned id; - unsigned hart; - unsigned tid; - std::string defaultMnem = "?"; - std::string& fallbackMnemonic = defaultMnem; - bool valid = false; - void set(size_t _cycle, unsigned _id, unsigned _hart, unsigned _tid, const std::string& _fallback) { - cycle = _cycle; - id = _id; - hart = _hart; - tid = _tid; - fallbackMnemonic = _fallback; - valid = true; - }; - void clear() { valid = false; } - }; +enum class EVENT_SYMBOL : uint32_t { + OK = 0x0, + STALL = 0x1, + FLUSH = 0x2, + TRACE_ON = 0x100, + TRACE_OFF = 0x102, +}; + +const std::map event2char{ + { EVENT_SYMBOL::OK, ' '}, + { EVENT_SYMBOL::STALL, '#'}, + { EVENT_SYMBOL::FLUSH, '!'}, + { EVENT_SYMBOL::TRACE_ON, '+'}, + {EVENT_SYMBOL::TRACE_OFF, '-'} +}; + +union TraceEvents_t { + uint64_t v = 0; - // aggregate read completion (memh) - struct CompletionRec_t { - unsigned int hart; - uint16_t destReg; - size_t len; - uint64_t addr; - uint64_t data; // first 8 bytes max - bool isFloat = false; - bool wait4Completion = false; - CompletionRec_t(unsigned int hart, uint16_t destReg, size_t len, uint64_t addr, - void *data, RevRegClass regClass) - : hart(hart), destReg(destReg), len(len), addr(addr), - isFloat(regClass == RevRegClass::RegFLOAT), wait4Completion(true) - { - memcpy(&this->data, data, len > sizeof(this->data) ? sizeof(this->data) : len); - } + struct { + // define 1 bit per stall type + uint64_t stall : 1; // [0] + uint64_t stall_sources : 15; // [15:1] + uint64_t flush : 1; // [16] + uint64_t flush_sources : 15; // [31:17] + uint64_t spare : 31; // [62:32] + uint64_t trc_ctl : 1; // [63] indicate change in trace controls + } f; +}; + +enum TraceKeyword_t { + RegRead, // register read (non-fp) + RegWrite, // register write (non-fp) + MemLoad, // issue load request (simple mem) + MemStore, // issue store request (simple mem) + MemhSendLoad, // issue load request (memh) + PcWrite, // write program counter +}; + +// Generic record so we can preserve code ordering of events in trace +// // register memory memh +// a; // reg adr adr +// b; // value len len +// c; // origin(TODO) data (limit 8 bytes) reg +struct TraceRec_t { + TraceKeyword_t key{}; + // register memory memh + uint64_t a{}; // reg adr adr + uint64_t b{}; // value len len + uint64_t c{}; // origin(TODO) data (limited 8 bytes) reg + TraceRec_t( TraceKeyword_t Key, uint64_t A, uint64_t B, uint64_t C = 0 ) : key( Key ), a( A ), b( B ), c( C ){}; +}; + +struct InstHeader_t { + size_t cycle{}; + uint32_t id{}; + uint32_t hart{}; + uint32_t tid{}; + std::string defaultMnem = "?"; + std::string& fallbackMnemonic = defaultMnem; + bool valid = false; + + void set( size_t _cycle, uint32_t _id, uint32_t _hart, uint32_t _tid, const std::string& _fallback ) { + cycle = _cycle; + id = _id; + hart = _hart; + tid = _tid; + fallbackMnemonic = _fallback; + valid = true; }; - class RevTracer{ - public: - /// RevTracer: standard constructor standard constructor - RevTracer(std::string Name, SST::Output* output); - /// RevTracer:standard destructor - ~RevTracer(); - - /// RevTracer: assign disassembler. Returns 0 if successful - int SetDisassembler(std::string machine); - /// RevTracer: assign trace symbol lookup map - void SetTraceSymbols(std::map* TraceSymbols); - /// RevTracer: assign cycle where trace will start (user param) - void SetStartCycle(uint64_t c); - /// RevTracer: assign maximum output lines (user param) - void SetCycleLimit(uint64_t c); - /// RevTracer:assign instruction used for trace controls - void SetCmdTemplate(std::string cmd); - /// RevTracer: capture instruction to be traced - void SetFetchedInsn(uint64_t _pc, uint32_t _insn); - /// RevTracer: capture register read - void regRead(size_t r, uint64_t v); - /// RevTracer: capture register write. - void regWrite(size_t r, uint64_t v); - /// RevTracer: capture memory write. - void memWrite(uint64_t adr, size_t len, const void *data); - /// RevTracer: capture memory read - void memRead(uint64_t adr, size_t len, void *data); - /// RevTracer: memh read request - void memhSendRead(uint64_t addr, size_t len, uint16_t reg); - /// RevTracer: data returning from memory read (memh) - void memReadResponse(size_t len, void *data, const MemReq* req); - /// RevTracer: capture 32-bit program counter - void pcWrite(uint32_t newpc); - /// RevTracer: capture 64-bit program counter - void pcWrite(uint64_t newpc); - /// RevTracer: render instruction execution trace to output stream and update tracer state - void Exec(size_t cycle, unsigned id, unsigned hart, unsigned tid, const std::string& fallbackMnemonic); - /// RevTracer: Render captured states - void Render(size_t cycle); - /// RevTracer: control whether to render captured states - void SetOutputEnable(bool e) { outputEnabled=e; } - /// Reset trace state - void Reset(); - - private: - - /// RevTracer: clear instruction trace capture buffer and reset trace state - void InstTraceReset(); - - /// RevTracer: instance name - std::string name; - #ifdef REV_USE_SPIKE - /// RevTracer: instruction parser used by disassembler - isa_parser_t* isaParser; - /// RevTracer: disassembler - disassembler_t* diasm; - #endif - /// RevTracer: pointer to output stream - SST::Output *pOutput; - /// RevTracer: control whether output is printed or not ( sampling continues ) - bool outputEnabled = false; - /// RevTracer: Instruction header captured at execution phase. - InstHeader_t instHeader; - /// RevTracer: Special affecting trace output - TraceEvents_t events; - /// RevTracer: buffer for captured states - std::vector traceRecs; - /// RevTracer: Completion records - std::vector completionRecs; - /// RevTracer: saved program counter - uint64_t pc = 0; - /// RevTracer: previous program counter for branch determination - uint64_t lastPC = 0; - /// RevTracer: saved instruction - uint32_t insn = 0; - /// RevTracer: map of instruction addresses to symbols - std::map* traceSymbols = nullptr; - /// RevTracer: Array of supported "NOP" instructions avaible for trace controls - uint32_t nops[NOP_COUNT]; - /// RevTracer: Check current state against user settings and update state - void CheckUserControls(uint64_t cycle); - /// RevTracer: determine if this buffer should be rendered - bool OutputOK(); - /// RevTracer: format register address for rendering - std::string fmt_reg(uint8_t r); - /// RevTracer: Format data associated with memory access - std::string fmt_data(unsigned len, uint64_t data); - /// RevTracer: Generate string from captured state - std::string RenderExec(const std::string& fallbackMnemonic); - /// RevTracer: User setting: starting cycle of trace (overrides programmtic control) - uint64_t startCycle = 0; - /// RevTracer: User setting: maximum number of lines to print - uint64_t cycleLimit = 0; - /// RevTracer: support for trace control push/pop - std::vector enableQ; - /// RevTracer: current pointer into trace controls queue - unsigned enableQindex; - /// RevTracer: wraparound limit for trace controls queue - const unsigned MAX_ENABLE_Q = 100; - /// RevTracer: count of lines rendered - uint64_t traceCycles = 0; - /// RevTracer: Hard disable for output - bool disabled = 0; - - }; // class RevTracer - -} //namespace SST::RevCPU - -#endif // _SST_REVCPU_REVTRACER_H_ + void clear() { valid = false; } +}; + +// aggregate read completion (memh) +struct CompletionRec_t { + uint32_t hart{}; + uint16_t destReg{}; + size_t len{}; + uint64_t addr{}; + uint64_t data{}; // first 8 bytes max + bool isFloat{}; + bool wait4Completion{}; + + CompletionRec_t( uint32_t hart, uint16_t destReg, size_t len, uint64_t addr, void* data, RevRegClass regClass ) + : hart( hart ), destReg( destReg ), len( len ), addr( addr ), isFloat( regClass == RevRegClass::RegFLOAT ), + wait4Completion( true ) { + memcpy( &this->data, data, len > sizeof( this->data ) ? sizeof( this->data ) : len ); + } +}; + +class RevTracer { +public: + /// RevTracer: standard constructor standard constructor + RevTracer( std::string Name, SST::Output* output ); + /// RevTracer:standard destructor + ~RevTracer(); + + /// RevTracer: assign disassembler. Returns 0 if successful + int SetDisassembler( std::string machine ); + /// RevTracer: assign trace symbol lookup map + void SetTraceSymbols( std::map* TraceSymbols ); + /// RevTracer: assign cycle where trace will start (user param) + void SetStartCycle( uint64_t c ); + /// RevTracer: assign maximum output lines (user param) + void SetCycleLimit( uint64_t c ); + /// RevTracer:assign instruction used for trace controls + void SetCmdTemplate( std::string cmd ); + /// RevTracer: capture instruction to be traced + void SetFetchedInsn( uint64_t _pc, uint32_t _insn ); + /// RevTracer: capture register read + void regRead( uint64_t r, uint64_t v ); + /// RevTracer: capture register write. + void regWrite( uint64_t r, uint64_t v ); + /// RevTracer: capture memory write. + void memWrite( uint64_t adr, size_t len, const void* data ); + /// RevTracer: capture memory read + void memRead( uint64_t adr, size_t len, void* data ); + /// RevTracer: memh read request + void memhSendRead( uint64_t addr, size_t len, uint16_t reg ); + /// RevTracer: data returning from memory read (memh) + void memReadResponse( size_t len, void* data, const MemReq* req ); + /// RevTracer: capture 32-bit program counter + void pcWrite( uint32_t newpc ); + /// RevTracer: capture 64-bit program counter + void pcWrite( uint64_t newpc ); + /// RevTracer: render instruction execution trace to output stream and update tracer state + void Exec( size_t cycle, uint32_t id, uint32_t hart, uint32_t tid, const std::string& fallbackMnemonic ); + /// RevTracer: Render captured states + void Render( size_t cycle ); + + /// RevTracer: control whether to render captured states + void SetOutputEnable( bool e ) { outputEnabled = e; } + + /// Reset trace state + void Reset(); + +private: + /// RevTracer: clear instruction trace capture buffer and reset trace state + void InstTraceReset(); + + /// RevTracer: instance name + std::string name{}; +#ifdef REV_USE_SPIKE + /// RevTracer: instruction parser used by disassembler + isa_parser_t* isaParser{}; + /// RevTracer: disassembler + disassembler_t* diasm{}; +#endif + /// RevTracer: pointer to output stream + SST::Output* pOutput{}; + /// RevTracer: control whether output is printed or not ( sampling continues ) + bool outputEnabled{}; + /// RevTracer: Instruction header captured at execution phase. + InstHeader_t instHeader{}; + /// RevTracer: Special affecting trace output + TraceEvents_t events{}; + /// RevTracer: buffer for captured states + std::vector traceRecs{}; + /// RevTracer: Completion records + std::vector completionRecs{}; + /// RevTracer: saved program counter + uint64_t pc{}; + /// RevTracer: previous program counter for branch determination + uint64_t lastPC{}; + /// RevTracer: saved instruction + uint32_t insn{}; + /// RevTracer: map of instruction addresses to symbols + std::map* traceSymbols{}; + /// RevTracer: Array of supported "NOP" instructions avaible for trace controls + uint32_t nops[NOP_COUNT]{}; + /// RevTracer: Check current state against user settings and update state + void CheckUserControls( uint64_t cycle ); + /// RevTracer: determine if this buffer should be rendered + bool OutputOK(); + /// RevTracer: format register address for rendering + std::string fmt_reg( uint64_t r ); + /// RevTracer: Format data associated with memory access + std::string fmt_data( size_t len, uint64_t data ); + /// RevTracer: Generate string from captured state + std::string RenderExec( const std::string& fallbackMnemonic ); + /// RevTracer: User setting: starting cycle of trace (overrides programmtic control) + uint64_t startCycle = 0; + /// RevTracer: User setting: maximum number of lines to print + uint64_t cycleLimit = 0; + /// RevTracer: support for trace control push/pop + std::vector enableQ{}; + /// RevTracer: current pointer into trace controls queue + uint32_t enableQindex{}; + /// RevTracer: wraparound limit for trace controls queue + const uint32_t MAX_ENABLE_Q = 100; + /// RevTracer: count of lines rendered + uint64_t traceCycles{}; + /// RevTracer: Hard disable for output + bool disabled{}; + /// RevTracer: Disasllow copying and assignment + RevTracer( const RevTracer& ) = delete; + RevTracer& operator=( const RevTracer& ) = delete; +}; // class RevTracer + +} //namespace SST::RevCPU + +#endif // _SST_REVCPU_REVTRACER_H_ diff --git a/include/RevZicntr.h b/include/RevZicntr.h new file mode 100644 index 000000000..3903076ef --- /dev/null +++ b/include/RevZicntr.h @@ -0,0 +1,98 @@ +// +// _RevZicntr_h_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVZICNTR_H_ +#define _SST_REVZICNTR_H_ + +#include +#include + +// Zicntr performance counters + +namespace SST::RevCPU { + +class RevCore; + +class RevZicntr { + uint64_t InstRet{}; ///< RevZicntr: Number of instructions retired + +protected: + /// RevZicntr: Get the core owning this hart + virtual RevCore* GetCore() const = 0; + + /// RevZicntr: Get the Program Counter + virtual uint64_t GetPC() const = 0; + + /// RevZicntr: Is this RV64? + virtual bool IsRV64() const = 0; + + // Performance counters + // Template allows RevCore to be an incomplete type now + + template + void fatal( const T* msg ) const { + return make_dependent( GetCore() )->output->fatal( CALL_INFO, -1, msg, GetPC() ); + } + +protected: + RevZicntr() = default; + RevZicntr( const RevZicntr& ) = delete; + RevZicntr( RevZicntr&& ) = default; + RevZicntr& operator=( const RevZicntr& ) = delete; + RevZicntr& operator=( RevZicntr&& ) = delete; + + template + static uint64_t rdcycle( const ZICNTR* Zicntr ) { + return Zicntr->GetCore()->GetCycles(); + } + + template + static uint64_t rdtime( const ZICNTR* Zicntr ) { + return Zicntr->GetCore()->GetCurrentSimCycle(); + } + + template + static uint64_t rdinstret( const ZICNTR* Zicntr ) { + return Zicntr->InstRet; + } + + enum class Half { Lo, Hi }; + + /// Performance Counter template + // Passed a COUNTER function which gets the 64-bit value of a performance counter + template + XLEN GetPerfCounter() const { + if( !make_dependent( GetCore() )->GetRevFeature()->IsModeEnabled( RV_ZICNTR ) ) { + fatal( "Illegal instruction at PC = 0x%" PRIx64 ": Zicntr extension not available\n" ); + return 0; + } else if( IsRV64() ) { + if constexpr( HALF == Half::Hi ) { + fatal( "Illegal instruction at PC = 0x%" PRIx64 ": High half of Zicntr register not available on RV64\n" ); + return 0; + } else { + return XLEN( COUNTER( this ) ); + } + } else { + if constexpr( HALF == Half::Hi ) { + return XLEN( COUNTER( this ) >> 32 ); + } else { + return XLEN( COUNTER( this ) & 0xffffffff ); + } + } + } + +public: + /// RevZicntr: Increment the number of retired instructions + void IncrementInstRet() { ++InstRet; } +}; // class RevZicntr + +} // namespace SST::RevCPU + +#endif diff --git a/include/SST.h b/include/SST.h index 210525e26..908d6947d 100644 --- a/include/SST.h +++ b/include/SST.h @@ -1,7 +1,7 @@ // // _SST_h_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -17,7 +17,18 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wsuggest-override" +#pragma GCC diagnostic ignored "-Wdouble-promotion" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined( __GNUC__ ) && !defined( __clang__ ) +#pragma GCC diagnostic ignored "-Wsuggest-final-methods" +#pragma GCC diagnostic ignored "-Wsuggest-final-types" +#endif + +// The #include order is important, so we prevent clang-format from reordering +// clang-format off #include #include #include @@ -30,6 +41,7 @@ #include #include #include +// clang-format on #pragma GCC diagnostic pop diff --git a/include/insns/CMakeLists.txt b/include/insns/CMakeLists.txt deleted file mode 100644 index 13be465d8..000000000 --- a/include/insns/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(InstructionSrcs - RV32A.h - RV32D.h - RV32F.h - RV32I.h - RV32M.h - RV64A.h - RV64D.h - RV64F.h - RV64I.h - RV64M.h - RV64P.h - Zicbom.h -) diff --git a/include/insns/RV32A.h b/include/insns/RV32A.h deleted file mode 100644 index 58720c03f..000000000 --- a/include/insns/RV32A.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// _RV32A_h_ -// -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC -// All Rights Reserved -// contact@tactcomplabs.com -// -// See LICENSE in the top level directory for licensing details -// - -#ifndef _SST_REVCPU_RV32A_H_ -#define _SST_REVCPU_RV32A_H_ - -#include "../RevInstHelpers.h" -#include "../RevExt.h" - -#include - -namespace SST::RevCPU{ - -class RV32A : public RevExt { - - static bool lrw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( R->IsRV32 ){ - MemReq req(uint64_t(R->RV32[Inst.rs1]), Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete()); - R->LSQueue->insert( req.LSQHashPair() ); - M->LR(F->GetHartToExecID(), uint64_t(R->RV32[Inst.rs1]), - &R->RV32[Inst.rd], - Inst.aq, Inst.rl, req, - RevFlag::F_SEXT32); - }else{ - MemReq req(R->RV64[Inst.rs1], Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete()); - R->LSQueue->insert( req.LSQHashPair() ); - M->LR(F->GetHartToExecID(), R->RV64[Inst.rs1], - reinterpret_cast(&R->RV64[Inst.rd]), - Inst.aq, Inst.rl, req, - RevFlag::F_SEXT64); - } - R->cost += M->RandCost(F->GetMinCost(), F->GetMaxCost()); - R->AdvancePC(Inst); - return true; - } - - static bool scw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - if( R->IsRV32 ){ - M->SC(F->GetHartToExecID(), R->RV32[Inst.rs1], - &R->RV32[Inst.rs2], - &R->RV32[Inst.rd], - Inst.aq, Inst.rl, - RevFlag::F_SEXT32); - }else{ - M->SC(F->GetHartToExecID(), R->RV64[Inst.rs1], - reinterpret_cast(&R->RV64[Inst.rs2]), - reinterpret_cast(&R->RV64[Inst.rd]), - Inst.aq, Inst.rl, - RevFlag::F_SEXT64); - } - R->AdvancePC(Inst); - return true; - } - - template - static bool amooper(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - uint32_t flags = static_cast(F_AMO); - - if( Inst.aq && Inst.rl){ - flags |= uint32_t(RevFlag::F_AQ) | uint32_t(RevFlag::F_RL); - }else if( Inst.aq ){ - flags |= uint32_t(RevFlag::F_AQ); - }else if( Inst.rl ){ - flags |= uint32_t(RevFlag::F_RL); - } - - if( R->IsRV32 ){ - MemReq req(R->RV32[Inst.rs1], - Inst.rd, - RevRegClass::RegGPR, - F->GetHartToExecID(), - MemOp::MemOpAMO, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert( req.LSQHashPair() ); - M->AMOVal(F->GetHartToExecID(), - R->RV32[Inst.rs1], - &R->RV32[Inst.rs2], - &R->RV32[Inst.rd], - req, - RevFlag{flags}); - }else{ - flags |= uint32_t(RevFlag::F_SEXT64); - MemReq req(R->RV64[Inst.rs1], - Inst.rd, - RevRegClass::RegGPR, - F->GetHartToExecID(), - MemOp::MemOpAMO, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert( req.LSQHashPair() ); - M->AMOVal(F->GetHartToExecID(), - R->RV64[Inst.rs1], - reinterpret_cast(&R->RV64[Inst.rs2]), - reinterpret_cast(&R->RV64[Inst.rd]), - req, - RevFlag{flags}); - } - // update the cost - R->cost += M->RandCost(F->GetMinCost(), F->GetMaxCost()); - R->AdvancePC(Inst); - return true; - } - - static constexpr auto& amoswapw = amooper; - static constexpr auto& amoaddw = amooper; - static constexpr auto& amoxorw = amooper; - static constexpr auto& amoandw = amooper; - static constexpr auto& amoorw = amooper; - static constexpr auto& amominw = amooper; - static constexpr auto& amomaxw = amooper; - static constexpr auto& amominuw = amooper; - static constexpr auto& amomaxuw = amooper; - - // ---------------------------------------------------------------------- - // - // RISC-V RV32A Instructions - // - // Format: - // - // - // ---------------------------------------------------------------------- - std::vector RV32ATable = { - {RevInstEntryBuilder().SetMnemonic("lr.w %rd, (%rs1)").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b00010).SetImplFunc( &lrw).Setrs2Class(RevRegClass::RegUNKNOWN).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sc.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b00011).SetImplFunc( &scw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoswap.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b00001).SetImplFunc( &amoswapw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoadd.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b00000).SetImplFunc( &amoaddw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoxor.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b00100).SetImplFunc( &amoxorw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoand.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b01100).SetImplFunc( &amoandw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoor.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b01000).SetImplFunc( &amoorw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomin.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b10000).SetImplFunc( &amominw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomax.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b10100).SetImplFunc( &amomaxw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amominu.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b11000).SetImplFunc( &amominuw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomaxu.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b010).SetFunct2or7( 0b11100).SetImplFunc( &amomaxuw ).InstEntry}, - }; - -public: - /// RV32A: standard constructor - RV32A( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32A", Feature, RevMem, Output) { - SetTable(std::move(RV32ATable)); - } - -}; // end class RV32I - -} // namespace SST::RevCPU - -#endif diff --git a/include/insns/RV32D.h b/include/insns/RV32D.h index 7c8b4dd27..a3f54a9ac 100644 --- a/include/insns/RV32D.h +++ b/include/insns/RV32D.h @@ -11,44 +11,18 @@ #ifndef _SST_REVCPU_RV32D_H_ #define _SST_REVCPU_RV32D_H_ -#include "../RevInstHelpers.h" -#include "../RevExt.h" +#include "./RevExt.h" +#include "./RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ - -class RV32D : public RevExt{ - - // Compressed instructions - static bool cfldsp(RevFeature *F, RevRegFile *R, - RevMem *M, const RevInst& Inst) { - // c.flwsp rd, $imm = lw rd, x2, $imm - return fld(F, R, M, Inst); - } - - static bool cfsdsp(RevFeature *F, RevRegFile *R, - RevMem *M, const RevInst& Inst) { - // c.fsdsp rs2, $imm = fsd rs2, x2, $imm - return fsd(F, R, M, Inst); - } - - static bool cfld(RevFeature *F, RevRegFile *R, - RevMem *M, const RevInst& Inst) { - // c.fld %rd, %rs1, $imm = flw %rd, %rs1, $imm - return fld(F, R, M, Inst); - } - - static bool cfsd(RevFeature *F, RevRegFile *R, - RevMem *M, const RevInst& Inst) { - // c.fsd rs2, rs1, $imm = fsd rs2, $imm(rs1) - return fsd(F, R, M, Inst); - } +namespace SST::RevCPU { +class RV32D : public RevExt { // Standard instructions - static constexpr auto& fld = fload; - static constexpr auto& fsd = fstore; + static constexpr auto& fld = fload; + static constexpr auto& fsd = fstore; // FMA instructions static constexpr auto& fmaddd = fmadd; @@ -57,141 +31,113 @@ class RV32D : public RevExt{ static constexpr auto& fnmaddd = fnmadd; // Binary FP instructions - static constexpr auto& faddd = foper; - static constexpr auto& fsubd = foper; - static constexpr auto& fmuld = foper; - static constexpr auto& fdivd = foper; - static constexpr auto& fmind = foper; - static constexpr auto& fmaxd = foper; + static constexpr auto& faddd = foper; + static constexpr auto& fsubd = foper; + static constexpr auto& fmuld = foper; + static constexpr auto& fdivd = foper; + static constexpr auto& fmind = foper; + static constexpr auto& fmaxd = foper; // FP Comparison instructions - static constexpr auto& feqd = fcondop; - static constexpr auto& fltd = fcondop; - static constexpr auto& fled = fcondop; + static constexpr auto& feqd = fcondop; + static constexpr auto& fltd = fcondop; + static constexpr auto& fled = fcondop; // FP to Integer Conversion instructions - static constexpr auto& fcvtwd = CvtFpToInt; - static constexpr auto& fcvtwud = CvtFpToInt; - - static bool fsqrtd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::sqrt(R->GetFP(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + static constexpr auto& fcvtwd = fcvtif; + static constexpr auto& fcvtwud = fcvtif; - static bool fsgnjd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::copysign(R->GetFP(Inst.rs1), R->GetFP(Inst.rs2))); - R->AdvancePC(Inst); - return true; - } + // Square root + static constexpr auto& fsqrtd = fsqrt; - static bool fsgnjnd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::copysign(R->GetFP(Inst.rs1), -R->GetFP(Inst.rs2))); - R->AdvancePC(Inst); - return true; - } + // Sign transfer + static constexpr auto& fsgnjd = fsgnj; + static constexpr auto& fsgnjnd = fsgnjn; + static constexpr auto& fsgnjxd = fsgnjx; - static bool fsgnjxd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - double rs1 = R->GetFP(Inst.rs1), rs2 = R->GetFP(Inst.rs2); - R->SetFP(Inst.rd, std::copysign(rs1, std::signbit(rs1) ? -rs2 : rs2)); - R->AdvancePC(Inst); - return true; - } + // Conversions between single and double precision FP + static constexpr auto& fcvtsd = fcvtff; + static constexpr auto& fcvtds = fcvtff; - static bool fcvtsd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetFP(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // FP Classify + static constexpr auto& fclassd = fclassify; - static bool fcvtds(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetFP(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // Conversion from integer to double + static constexpr auto& fcvtdw = fcvtfi; + static constexpr auto& fcvtdwu = fcvtfi; - static bool fclassd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - double fp64 = R->GetFP(Inst.rs1); - uint64_t i64; - memcpy(&i64, &fp64, sizeof(i64)); - bool quietNaN = (i64 & uint64_t{1}<<51) != 0; - R->SetX(Inst.rd, fclass(fp64, quietNaN)); - R->AdvancePC(Inst); - return true; - } - - static bool fcvtdw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } - - static bool fcvtdwu(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // Compressed instructions + static constexpr auto& cfldsp = fld; + static constexpr auto& cfsdsp = fsd; + static constexpr auto& cfld = fld; + static constexpr auto& cfsd = fsd; // ---------------------------------------------------------------------- // // RISC-V RV32D Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev32DInstDefaults : RevInstDefaults { - static constexpr RevRegClass rdClass = RevRegClass::RegFLOAT; - static constexpr RevRegClass rs1Class = RevRegClass::RegFLOAT; - static constexpr RevRegClass rs2Class = RevRegClass::RegFLOAT; + Rev32DInstDefaults() { + SetOpcode( 0b1010011 ); + SetrdClass( RevRegClass::RegFLOAT ); + Setrs1Class( RevRegClass::RegFLOAT ); + Setrs2Class( RevRegClass::RegFLOAT ); + SetRaiseFPE( true ); + } }; + + // clang-format off std::vector RV32DTable = { - {RevInstEntryBuilder().SetMnemonic("fld %rd, $imm(%rs1)" ).SetOpcode( 0b0000111).SetFunct3(0b011 ).SetFunct2or7(0b0000000 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegGPR).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeI).SetImplFunc(&fld ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsd %rs2, $imm(%rs1)" ).SetOpcode( 0b0100111).SetFunct3(0b011 ).SetFunct2or7(0b0000000 ).SetrdClass(RevRegClass::RegIMM ).Setrs1Class(RevRegClass::RegFLOAT ).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeS).SetImplFunc(&fsd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmadd.d %rd, %rs1, %rs2, %rs3" ).SetOpcode( 0b1000011).SetFunct3(0b0 ).SetFunct2or7(0b01 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegFLOAT ).SetFormat(RVTypeR4).SetImplFunc(&fmaddd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmsub.d %rd, %rs1, %rs2, %rs3" ).SetOpcode( 0b1000111).SetFunct3(0b0 ).SetFunct2or7(0b01 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegFLOAT ).SetFormat(RVTypeR4).SetImplFunc(&fmsubd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fnmsub.d %rd, %rs1, %rs2, %rs3").SetOpcode( 0b1001011).SetFunct3(0b0 ).SetFunct2or7(0b01 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegFLOAT ).SetFormat(RVTypeR4).SetImplFunc(&fnmsubd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fnmadd.d %rd, %rs1, %rs2, %rs3").SetOpcode( 0b1001111).SetFunct3(0b0 ).SetFunct2or7(0b01 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegFLOAT ).SetFormat(RVTypeR4).SetImplFunc(&fnmaddd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fadd.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0000001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&faddd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsub.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0000101 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsubd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmul.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0001001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmuld ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fdiv.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0001101 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fdivd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsqrt.d %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0101101 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsqrtd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmin.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b000 ).SetFunct2or7(0b0010101 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmind ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmax.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b001 ).SetFunct2or7(0b0010101 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmaxd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnj.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b000 ).SetFunct2or7(0b0010001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnjn.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b001 ).SetFunct2or7(0b0010001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjnd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnjx.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b010 ).SetFunct2or7(0b0010001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjxd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.s.d %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0100000 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b01).SetImplFunc(&fcvtsd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.d.s %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b0100001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b00).SetImplFunc(&fcvtds ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("feq.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b010 ).SetFunct2or7(0b1010001 ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&feqd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("flt.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b001 ).SetFunct2or7(0b1010001 ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fltd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fle.d %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3(0b000 ).SetFunct2or7(0b1010001 ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class( RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fled ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fclass.d %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b001 ).SetFunct2or7(0b1110001 ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fclassd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.w.d %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b1100001 ).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b00).SetImplFunc(&fcvtwd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.wu.d %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b1100001 ).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b01).SetImplFunc(&fcvtwud ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.d.w %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b1101001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b00).SetImplFunc(&fcvtdw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.d.wu %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3(0b0 ).SetFunct2or7(0b1101001 ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b01).SetImplFunc(&fcvtdwu ).InstEntry}, + Rev32DInstDefaults().SetMnemonic("fld %rd, $imm(%rs1)" ).SetFunct3(0b011).SetFunct2or7(0b0000000).SetImplFunc(fld ).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVTypeI).SetOpcode(0b0000111).SetRaiseFPE(false), + Rev32DInstDefaults().SetMnemonic("fsd %rs2, $imm(%rs1)" ).SetFunct3(0b011).SetFunct2or7(0b0000000).SetImplFunc(fsd ).Setrs1Class(RevRegClass::RegGPR).SetrdClass (RevRegClass::RegIMM).SetFormat(RVTypeS).SetOpcode(0b0100111).SetRaiseFPE(false), + + Rev32DInstDefaults().SetMnemonic("fmadd.d %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b0000001).SetImplFunc(fmaddd ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode(0b1000011), + Rev32DInstDefaults().SetMnemonic("fmsub.d %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b0000001).SetImplFunc(fmsubd ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode(0b1000111), + Rev32DInstDefaults().SetMnemonic("fnmsub.d %rd, %rs1, %rs2, %rs3").SetFunct3(0b000).SetFunct2or7(0b0000001).SetImplFunc(fnmsubd).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode(0b1001011), + Rev32DInstDefaults().SetMnemonic("fnmadd.d %rd, %rs1, %rs2, %rs3").SetFunct3(0b000).SetFunct2or7(0b0000001).SetImplFunc(fnmaddd).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode(0b1001111), + + Rev32DInstDefaults().SetMnemonic("fadd.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0000001).SetImplFunc(faddd ), + Rev32DInstDefaults().SetMnemonic("fsub.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0000101).SetImplFunc(fsubd ), + Rev32DInstDefaults().SetMnemonic("fmul.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0001001).SetImplFunc(fmuld ), + Rev32DInstDefaults().SetMnemonic("fdiv.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0001101).SetImplFunc(fdivd ), + Rev32DInstDefaults().SetMnemonic("fsqrt.d %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b0101101).SetImplFunc(fsqrtd ).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32DInstDefaults().SetMnemonic("fmin.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0010101).SetImplFunc(fmind ), + Rev32DInstDefaults().SetMnemonic("fmax.d %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b0010101).SetImplFunc(fmaxd ), + Rev32DInstDefaults().SetMnemonic("fsgnj.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0010001).SetImplFunc(fsgnjd ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fmv.d %rd, %rs" ).SetFunct3(0b000).SetFunct2or7(0b0010001).SetImplFunc(fsgnjd ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fsgnjn.d %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b0010001).SetImplFunc(fsgnjnd).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fneg.d %rd, %rs" ).SetFunct3(0b001).SetFunct2or7(0b0010001).SetImplFunc(fsgnjnd).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fsgnjx.d %rd, %rs1, %rs2" ).SetFunct3(0b010).SetFunct2or7(0b0010001).SetImplFunc(fsgnjxd).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fabs.d %rd, %rs" ).SetFunct3(0b010).SetFunct2or7(0b0010001).SetImplFunc(fsgnjxd).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fcvt.s.d %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b0100000).SetImplFunc(fcvtsd ).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs2fcvtOp(0b01), + Rev32DInstDefaults().SetMnemonic("fcvt.d.s %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b0100001).SetImplFunc(fcvtds ).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs2fcvtOp(0b00), + Rev32DInstDefaults().SetMnemonic("feq.d %rd, %rs1, %rs2" ).SetFunct3(0b010).SetFunct2or7(0b1010001).SetImplFunc(feqd ).SetrdClass (RevRegClass::RegGPR), + Rev32DInstDefaults().SetMnemonic("flt.d %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b1010001).SetImplFunc(fltd ).SetrdClass (RevRegClass::RegGPR), + Rev32DInstDefaults().SetMnemonic("fle.d %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b1010001).SetImplFunc(fled ).SetrdClass (RevRegClass::RegGPR), + Rev32DInstDefaults().SetMnemonic("fclass.d %rd, %rs1" ).SetFunct3(0b001).SetFunct2or7(0b1110001).SetImplFunc(fclassd).SetrdClass (RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fcvt.w.d %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1100001).SetImplFunc(fcvtwd ).SetrdClass (RevRegClass::RegGPR).Setrs2fcvtOp(0b00).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32DInstDefaults().SetMnemonic("fcvt.wu.d %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1100001).SetImplFunc(fcvtwud).SetrdClass (RevRegClass::RegGPR).Setrs2fcvtOp(0b01).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32DInstDefaults().SetMnemonic("fcvt.d.w %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1101001).SetImplFunc(fcvtdw ).Setrs1Class(RevRegClass::RegGPR).Setrs2fcvtOp(0b00).Setrs2Class(RevRegClass::RegUNKNOWN).SetRaiseFPE( false ), + Rev32DInstDefaults().SetMnemonic("fcvt.d.wu %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1101001).SetImplFunc(fcvtdwu).Setrs1Class(RevRegClass::RegGPR).Setrs2fcvtOp(0b01).Setrs2Class(RevRegClass::RegUNKNOWN).SetRaiseFPE( false ), }; std::vector RV32DCTable = { - {RevInstEntryBuilder().SetMnemonic("c.fldsp %rd, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b001).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&cfldsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.fsdsp %rs1, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b101).Setrs2Class(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCSS).SetImplFunc(&cfsdsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.fld %rd, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b001).Setrs1Class(RevRegClass::RegGPR).SetrdClass(RevRegClass::RegFLOAT).Setimm(FVal).SetFormat(RVCTypeCL).SetImplFunc(&cfld).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.fsd %rs2, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b101).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCS).SetImplFunc(&cfsd).SetCompressed(true).InstEntry}, + RevCInstDefaults().SetMnemonic("c.fldsp %rd, $imm" ).SetOpcode(0b10).SetFunct3(0b001).SetImplFunc(cfldsp).SetrdClass (RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ), + RevCInstDefaults().SetMnemonic("c.fsdsp %rs1, $imm" ).SetOpcode(0b10).SetFunct3(0b101).SetImplFunc(cfsdsp).Setrs1Class(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegFLOAT).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCSS), + RevCInstDefaults().SetMnemonic("c.fld %rd, %rs1, $imm" ).SetOpcode(0b00).SetFunct3(0b001).SetImplFunc(cfld ).SetrdClass (RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCL ), + RevCInstDefaults().SetMnemonic("c.fsd %rs2, %rs1, $imm").SetOpcode(0b00).SetFunct3(0b101).SetImplFunc(cfsd ).Setrs1Class(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegFLOAT).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCS ), }; + // clang-format on public: /// RV32D: standard constructor - RV32D( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32D", Feature, RevMem, Output) { - SetTable(std::move(RV32DTable)); - SetCTable(std::move(RV32DCTable)); + RV32D( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV32D", Feature, RevMem, Output ) { + SetTable( std::move( RV32DTable ) ); + SetCTable( std::move( RV32DCTable ) ); } -}; // end class RV32I +}; // end class RV32I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV32F.h b/include/insns/RV32F.h index b8d404c1b..75f221ef5 100644 --- a/include/insns/RV32F.h +++ b/include/insns/RV32F.h @@ -11,40 +11,18 @@ #ifndef _SST_REVCPU_RV32F_H_ #define _SST_REVCPU_RV32F_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ - -class RV32F : public RevExt{ - - // Compressed instructions - static bool cflwsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - // c.flwsp rd, $imm = lw rd, x2, $imm - return flw(F, R, M, Inst); - } - - static bool cfswsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - // c.swsp rs2, $imm = sw rs2, x2, $imm - return fsw(F, R, M, Inst); - } - - static bool cflw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - // c.flw %rd, %rs1, $imm = flw %rd, %rs1, $imm - return flw(F, R, M, Inst); - } - - static bool cfsw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - // c.fsw rs2, rs1, $imm = fsw rs2, $imm(rs1) - return fsw(F, R, M, Inst); - } +namespace SST::RevCPU { +class RV32F : public RevExt { // Standard instructions - static constexpr auto& flw = fload; - static constexpr auto& fsw = fstore; + static constexpr auto& flw = fload; + static constexpr auto& fsw = fstore; // FMA instructions static constexpr auto& fmadds = fmadd; @@ -53,148 +31,119 @@ class RV32F : public RevExt{ static constexpr auto& fnmadds = fnmadd; // Binary FP instructions - static constexpr auto& fadds = foper; - static constexpr auto& fsubs = foper; - static constexpr auto& fmuls = foper; - static constexpr auto& fdivs = foper; - static constexpr auto& fmins = foper; - static constexpr auto& fmaxs = foper; + static constexpr auto& fadds = foper; + static constexpr auto& fsubs = foper; + static constexpr auto& fmuls = foper; + static constexpr auto& fdivs = foper; + static constexpr auto& fmins = foper; + static constexpr auto& fmaxs = foper; // FP Comparison instructions - static constexpr auto& feqs = fcondop; - static constexpr auto& flts = fcondop; - static constexpr auto& fles = fcondop; + static constexpr auto& feqs = fcondop; + static constexpr auto& flts = fcondop; + static constexpr auto& fles = fcondop; // FP to Integer Conversion instructions - static constexpr auto& fcvtws = CvtFpToInt; - static constexpr auto& fcvtwus = CvtFpToInt; - - static bool fsqrts(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, sqrtf( R->GetFP(Inst.rs1) )); - R->AdvancePC(Inst); - return true; - } - - static bool fsgnjs(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::copysign( R->GetFP(Inst.rs1), R->GetFP(Inst.rs2) )); - R->AdvancePC(Inst); - return true; - } + static constexpr auto& fcvtws = fcvtif; + static constexpr auto& fcvtwus = fcvtif; - static bool fsgnjns(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, std::copysign( R->GetFP(Inst.rs1), -R->GetFP(Inst.rs2) )); - R->AdvancePC(Inst); - return true; - } + // Square root + static constexpr auto& fsqrts = fsqrt; - static bool fsgnjxs(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - float rs1 = R->GetFP(Inst.rs1), rs2 = R->GetFP(Inst.rs2); - R->SetFP(Inst.rd, std::copysign(rs1, std::signbit(rs1) ? -rs2 : rs2)); - R->AdvancePC(Inst); - return true; - } + // Sign transfer + static constexpr auto& fsgnjs = fsgnj; + static constexpr auto& fsgnjns = fsgnjn; + static constexpr auto& fsgnjxs = fsgnjx; - static bool fmvxw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - int32_t i32; - float fp32 = R->GetFP(Inst.rs1); // The FP32 value - memcpy(&i32, &fp32, sizeof(i32)); // Reinterpreted as int32_t - R->SetX(Inst.rd, i32); // Copied to the destination register - R->AdvancePC(Inst); - return true; - } + // Transfers between integer and FP registers + static constexpr auto& fmvxw = fmvif; + static constexpr auto& fmvwx = fmvfi; - static bool fmvwx(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - float fp32; - auto i32 = R->GetX(Inst.rs1); // The X register as a 32-bit value - memcpy(&fp32, &i32, sizeof(fp32)); // Reinterpreted as float - R->SetFP(Inst.rd, fp32); // Copied to the destination register - R->AdvancePC(Inst); - return true; - } + // FP classification + static constexpr auto& fclasss = fclassify; - static bool fclasss(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - float fp32 = R->GetFP(Inst.rs1); - uint32_t i32; - memcpy(&i32, &fp32, sizeof(i32)); - bool quietNaN = (i32 & uint32_t{1}<<22) != 0; - R->SetX(Inst.rd, fclass(fp32, quietNaN)); - R->AdvancePC(Inst); - return true; - } + // Conversion from integer to float + static constexpr auto& fcvtsw = fcvtfi; + static constexpr auto& fcvtswu = fcvtfi; - static bool fcvtsw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } - - static bool fcvtswu(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // Compressed instructions + static constexpr auto& cflwsp = flw; + static constexpr auto& cfswsp = fsw; + static constexpr auto& cflw = flw; + static constexpr auto& cfsw = fsw; // ---------------------------------------------------------------------- // // RISC-V RV32F Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev32FInstDefaults : RevInstDefaults { - static constexpr RevRegClass rdClass = RevRegClass::RegFLOAT; - static constexpr RevRegClass rs1Class = RevRegClass::RegFLOAT; - static constexpr RevRegClass rs2Class = RevRegClass::RegFLOAT; + Rev32FInstDefaults() { + SetOpcode( 0b1010011 ); + SetrdClass( RevRegClass::RegFLOAT ); + Setrs1Class( RevRegClass::RegFLOAT ); + Setrs2Class( RevRegClass::RegFLOAT ); + SetRaiseFPE( true ); + } }; - std::vectorRV32FTable = { - {RevInstEntryBuilder().SetMnemonic("flw %rd, $imm(%rs1)" ).SetOpcode( 0b0000111).SetFunct3( 0b010 ).SetFunct2or7(0b000000).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeI).SetImplFunc( &flw).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsw %rs2, $imm(%rs1)" ).SetOpcode( 0b0100111).SetFunct3( 0b010 ).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegFLOAT).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeS).SetImplFunc(&fsw).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmadd.s %rd, %rs1, %rs2, %rs3" ).SetOpcode( 0b1000011).SetFunct3( 0b0 ).SetFunct2or7(0b00 ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetImplFunc(&fmadds ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmsub.s %rd, %rs1, %rs2, %rs3" ).SetOpcode( 0b1000111).SetFunct3( 0b0 ).SetFunct2or7(0b00 ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetImplFunc(&fmsubs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fnmsub.s %rd, %rs1, %rs2, %rs3").SetOpcode( 0b1001011).SetFunct3( 0b0 ).SetFunct2or7(0b00 ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetImplFunc(&fnmsubs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fnmadd.s %rd, %rs1, %rs2, %rs3").SetOpcode( 0b1001111).SetFunct3( 0b0 ).SetFunct2or7(0b00 ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetImplFunc(&fnmadds ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fadd.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b000000).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fadds ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsub.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b0000100).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsubs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmul.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b0001000).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmuls ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fdiv.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b0001100).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fdivs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsqrt.s %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b0101100).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsqrts ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmin.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b000 ).SetFunct2or7(0b0010100).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmins ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmax.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b001 ).SetFunct2or7(0b0010100).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmaxs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnj.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b000 ).SetFunct2or7(0b0010000).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnjn.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b001 ).SetFunct2or7(0b0010000).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjns ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fsgnjx.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b010 ).SetFunct2or7(0b0010000).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fsgnjxs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.w.s %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b1100000).SetfpcvtOp(0b00000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b00).SetImplFunc(&fcvtws ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.wu.s %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b1100000).SetfpcvtOp(0b00001).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b01).SetImplFunc(&fcvtwus ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmv.x.w %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b000 ).SetFunct2or7(0b1110000).Setrs1Class(RevRegClass::RegFLOAT).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmvxw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("feq.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b010 ).SetFunct2or7(0b1010000).SetrdClass(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&feqs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("flt.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b001 ).SetFunct2or7(0b1010000).SetrdClass(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&flts ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fle.s %rd, %rs1, %rs2" ).SetOpcode( 0b1010011).SetFunct3( 0b000 ).SetFunct2or7(0b1010000).SetrdClass(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegFLOAT ).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fles ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fclass.s %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b001 ).SetFunct2or7(0b1110000).SetrdClass(RevRegClass::RegGPR ).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fclasss ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.s.w %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b1101000).SetfpcvtOp(0b00000).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b00).SetImplFunc(&fcvtsw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.s.wu %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b0 ).SetFunct2or7(0b1101000).SetfpcvtOp(0b00001).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetfpcvtOp(0b01).SetImplFunc(&fcvtswu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmv.w.x %rd, %rs1" ).SetOpcode( 0b1010011).SetFunct3( 0b000 ).SetFunct2or7(0b1111000).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeR).SetImplFunc(&fmvwx ).InstEntry}, + // clang-format off + std::vector RV32FTable = { + Rev32FInstDefaults().SetMnemonic("flw %rd, $imm(%rs1)" ).SetFunct3(0b010).SetFunct2or7(0b0000000).SetImplFunc(flw ).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetFormat(RVTypeI).SetOpcode( 0b0000111).SetRaiseFPE(false), + Rev32FInstDefaults().SetMnemonic("fsw %rs2, $imm(%rs1)" ).SetFunct3(0b010).SetFunct2or7(0b0000000).SetImplFunc(fsw ).SetrdClass(RevRegClass::RegIMM ).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegFLOAT ).SetFormat(RVTypeS).SetOpcode( 0b0100111).SetRaiseFPE(false), + + Rev32FInstDefaults().SetMnemonic("fmadd.s %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b00 ).SetImplFunc(fmadds ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode( 0b1000011), + Rev32FInstDefaults().SetMnemonic("fmsub.s %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b00 ).SetImplFunc(fmsubs ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode( 0b1000111), + Rev32FInstDefaults().SetMnemonic("fnmsub.s %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b00 ).SetImplFunc(fnmsubs ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode( 0b1001011), + Rev32FInstDefaults().SetMnemonic("fnmadd.s %rd, %rs1, %rs2, %rs3" ).SetFunct3(0b000).SetFunct2or7(0b00 ).SetImplFunc(fnmadds ).Setrs3Class(RevRegClass::RegFLOAT).SetFormat(RVTypeR4).SetOpcode( 0b1001111), + + Rev32FInstDefaults().SetMnemonic("fadd.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0000000).SetImplFunc(fadds ), + Rev32FInstDefaults().SetMnemonic("fsub.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0000100).SetImplFunc(fsubs ), + Rev32FInstDefaults().SetMnemonic("fmul.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0001000).SetImplFunc(fmuls ), + Rev32FInstDefaults().SetMnemonic("fdiv.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0001100).SetImplFunc(fdivs ), + Rev32FInstDefaults().SetMnemonic("fsqrt.s %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b0101100).SetImplFunc(fsqrts ).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fmin.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0010100).SetImplFunc(fmins ), + Rev32FInstDefaults().SetMnemonic("fmax.s %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b0010100).SetImplFunc(fmaxs ), + Rev32FInstDefaults().SetMnemonic("fsgnj.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b0010000).SetImplFunc(fsgnjs ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fmv.s %rd, %rs" ).SetFunct3(0b000).SetFunct2or7(0b0010000).SetImplFunc(fsgnjs ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fsgnjn.s %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b0010000).SetImplFunc(fsgnjns ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fneg.s %rd, %rs" ).SetFunct3(0b001).SetFunct2or7(0b0010000).SetImplFunc(fsgnjns ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fsgnjx.s %rd, %rs1, %rs2" ).SetFunct3(0b010).SetFunct2or7(0b0010000).SetImplFunc(fsgnjxs ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fabs.s %rd, %rs" ).SetFunct3(0b010).SetFunct2or7(0b0010000).SetImplFunc(fsgnjxs ).SetRaiseFPE(false).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == DECODE_RS2( Inst ); } ), + Rev32FInstDefaults().SetMnemonic("fcvt.w.s %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1100000).SetImplFunc(fcvtws ).SetrdClass (RevRegClass::RegGPR).Setrs2fcvtOp(0b00).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fcvt.wu.s %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1100000).SetImplFunc(fcvtwus ).SetrdClass (RevRegClass::RegGPR).Setrs2fcvtOp(0b01).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fmv.x.w %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1110000).SetImplFunc(fmvxw ).SetrdClass (RevRegClass::RegGPR).SetRaiseFPE(false).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("feq.s %rd, %rs1, %rs2" ).SetFunct3(0b010).SetFunct2or7(0b1010000).SetImplFunc(feqs ).SetrdClass (RevRegClass::RegGPR), + Rev32FInstDefaults().SetMnemonic("flt.s %rd, %rs1, %rs2" ).SetFunct3(0b001).SetFunct2or7(0b1010000).SetImplFunc(flts ).SetrdClass (RevRegClass::RegGPR), + Rev32FInstDefaults().SetMnemonic("fle.s %rd, %rs1, %rs2" ).SetFunct3(0b000).SetFunct2or7(0b1010000).SetImplFunc(fles ).SetrdClass (RevRegClass::RegGPR), + Rev32FInstDefaults().SetMnemonic("fclass.s %rd, %rs1" ).SetFunct3(0b001).SetFunct2or7(0b1110000).SetImplFunc(fclasss ).SetrdClass (RevRegClass::RegGPR).SetRaiseFPE(false).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fcvt.s.w %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1101000).SetImplFunc(fcvtsw ).Setrs1Class(RevRegClass::RegGPR).Setrs2fcvtOp(0b00).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fcvt.s.wu %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1101000).SetImplFunc(fcvtswu ).Setrs1Class(RevRegClass::RegGPR).Setrs2fcvtOp(0b01).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev32FInstDefaults().SetMnemonic("fmv.w.x %rd, %rs1" ).SetFunct3(0b000).SetFunct2or7(0b1111000).SetImplFunc(fmvwx ).Setrs1Class(RevRegClass::RegGPR).SetRaiseFPE(false).Setrs2Class(RevRegClass::RegUNKNOWN), }; - std::vector RV32FCOTable = { - {RevInstEntryBuilder().SetMnemonic("c.flwsp %rd, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b011).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&cflwsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.fswsp %rs2, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b111).Setrs2Class(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCSS).SetImplFunc(&cfswsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.flw %rd, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b011).Setrs1Class(RevRegClass::RegGPR).SetrdClass(RevRegClass::RegFLOAT).Setimm(FVal).SetFormat(RVCTypeCL).SetImplFunc(&cflw).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.fsw %rs2, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b111).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegFLOAT).Setimm(FVal).SetFormat(RVCTypeCS).SetImplFunc(&cfsw).SetCompressed(true).InstEntry}, - }; + static std::vector RV32FCOTable() { + return { + RevCInstDefaults().SetMnemonic("c.flwsp %rd, $imm" ).SetFunct3(0b011).SetImplFunc(cflwsp).Setimm(RevImmFunc::FVal).SetrdClass(RevRegClass::RegFLOAT ) .SetFormat(RVCTypeCI ).SetOpcode(0b10), + RevCInstDefaults().SetMnemonic("c.fswsp %rs2, $imm" ).SetFunct3(0b111).SetImplFunc(cfswsp).Setimm(RevImmFunc::FVal).SetrdClass(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegFLOAT).SetFormat(RVCTypeCSS).SetOpcode(0b10), + RevCInstDefaults().SetMnemonic("c.flw %rd, %rs1, $imm" ).SetFunct3(0b011).SetImplFunc(cflw ).Setimm(RevImmFunc::FVal).SetrdClass(RevRegClass::RegFLOAT ).Setrs1Class(RevRegClass::RegGPR) .SetFormat(RVCTypeCL ).SetOpcode(0b00), + RevCInstDefaults().SetMnemonic("c.fsw %rs2, %rs1, $imm").SetFunct3(0b111).SetImplFunc(cfsw ).Setimm(RevImmFunc::FVal).SetrdClass(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegFLOAT).SetFormat(RVCTypeCS ).SetOpcode(0b00), + }; + } + + // clang-format on public: /// RV32F: standard constructor - RV32F( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32F", Feature, RevMem, Output) { - SetTable(std::move(RV32FTable)); - SetOTable(std::move(RV32FCOTable)); + RV32F( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV32F", Feature, RevMem, Output ) { + SetTable( std::move( RV32FTable ) ); + if( !Feature->IsRV64() && !Feature->HasD() ) { + // RV32FC-only instructions + SetCTable( RV32FCOTable() ); + } } -}; // end class RV32F +}; // end class RV32F -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV32I.h b/include/insns/RV32I.h index 18438e518..0aa17fa05 100644 --- a/include/insns/RV32I.h +++ b/include/insns/RV32I.h @@ -11,379 +11,100 @@ #ifndef _SST_REVCPU_RV32I_H_ #define _SST_REVCPU_RV32I_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include #include +#include -namespace SST::RevCPU{ +namespace SST::RevCPU { class RV32I : public RevExt { - - // Compressed instructions - static bool caddi4spn(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.addi4spn rd, $imm == addi rd, x2, $imm - //Inst.rs1 = 2; //Removed - Set in Decode - //Inst.rd = CRegIdx(Inst.rd); //Set in Decode - - // if Inst.imm == 0; this is a HINT instruction - // this is effectively a NOP - if( Inst.imm == 0x00 ){ - R->AdvancePC(Inst); - return true; - } - //Inst.imm = (Inst.imm & 0b011111111)*4; - Inst.imm = (Inst.imm & 0b11111111)*4; - return addi(F, R, M, Inst); - } - - static bool clwsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.lwsp rd, $imm = lw rd, x2, $imm - //Inst.rs1 = 2; //Removed - set in decode - //Inst.imm = ((Inst.imm & 0b111111)*4); - Inst.imm = (Inst.imm & 0b11111111); // Immd is 8 bits - bits placed correctly in decode, no need to scale - - return lw(F, R, M, Inst); - } - - static bool cswsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.swsp rs2, $imm = sw rs2, x2, $imm - //Inst.rs1 = 2; //Removed - set in decode - //Inst.imm = ((Inst.imm & 0b111111)*4); - Inst.imm = (Inst.imm & 0b11111111); // Immd is 8 bits - zero extended, bits placed correctly in decode, no need to scale - - return sw(F, R, M, Inst); - } - - static bool clw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.lw rd, rs1, $imm = lw rd, $imm(rs1) - //Inst.rd = CRegIdx(Inst.rd); //Removed - Scaled in decode - //Inst.rs1 = CRegIdx(Inst.rs1); //Removed - Scaled in decode - //Inst.imm = ((Inst.imm & 0b11111)*4); - Inst.imm = (Inst.imm & 0b1111111); // Immd is 7 bits, zero extended, bits placed correctly in decode, no need to scale - - return lw(F, R, M, Inst); - } - - static bool csw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.sw rs2, rs1, $imm = sw rs2, $imm(rs1) - //Inst.rs2 = CRegIdx(Inst.rd); //Removed - Scaled in Decode - //Inst.rs1 = CRegIdx(Inst.rs1); //Removed - Scaled in Decode - //Inst.imm = ((Inst.imm & 0b11111)*4); - Inst.imm = (Inst.imm & 0b1111111); //Immd is 7-bits, zero extended, bits placed correctly in decode, no need to scale - - return sw(F, R, M, Inst); - } - - static bool cj(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.j $imm = jal x0, $imm - Inst.rd = 0; // x0 - - Inst.imm = Inst.jumpTarget; - Inst.imm = Inst.ImmSignExt(12); - return jal(F, R, M, Inst); - } - - static bool cjal(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.jal $imm = jal x0, $imm - //Inst.rd = 1; // x1 //Removed - set in decode - Inst.imm = Inst.jumpTarget; - - return jal(F, R, M, Inst); - } - - static bool CRFUNC_1000(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst){ - if( Inst.rs2 != 0 ){ - return cmv(F, R, M, Inst); - } - return cjr(F, R, M, Inst); - } - - static bool CRFUNC_1001(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst){ - RevInst Inst = CInst; - - if( (Inst.rs1 == 0) && (Inst.rd == 0) ){ - return ebreak(F, R, M, Inst); - }else if( (Inst.rs2 == 0) && (Inst.rd != 0) ){ - Inst.rd = 1; //C.JALR expands to jalr x1, 0(rs1), so force update of x1 / ra - return jalr(F, R, M, Inst); - }else{ - return add(F, R, M, Inst); - } - } - - static bool cjr(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.jr %rs1 = jalr x0, 0(%rs1) - Inst.rs2 = 0; - return jalr(F, R, M, Inst); - } - - static bool cmv(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - //Inst.rs1 = 0; //Removed - performed in decode // expands to add rd, x0, rs2, so force rs1 to zero - return add(F, R, M, Inst); - } - - static bool cadd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - Inst.rs1 = Inst.rd; - return add(F, R, M, Inst); - } - - static bool cjalr(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.jalr %rs1 = jalr x1, 0(%rs1) - Inst.rs2 = 1; - return jalr(F, R, M, Inst); - } - - static bool cbeqz(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.beqz %rs1, $imm = beq %rs1, x0, $imm - Inst.rs2 = 0; - // Inst.rs1 = CRegIdx(Inst.rs1); // removed - scaled in decode - Inst.imm = Inst.offset; - Inst.imm = Inst.ImmSignExt(9); - //Inst.imm = Inst.offset & 0b111111; - //SEXT(Inst.imm, Inst.offset&0b111111111, 9); //Immd is signed 9-bit, scaled in decode - //SEXT(Inst.imm, Inst.offset, 6); - - return beq(F, R, M, Inst); - } - - static bool cbnez(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.bnez %rs1, $imm = bne %rs1, x0, $imm - //Inst.rs2 = 0; //removed - set in decode - // Inst.rs1 = CRegIdx(Inst.rs1); //removed - scaled in decode - Inst.imm = Inst.offset; - Inst.imm = Inst.ImmSignExt(9); //Immd is signed 9-bit, scaled in decode - //Inst.imm = Inst.offset & 0b111111; - //SEXT(Inst.imm, Inst.offset, 6); - //SEXT(Inst.imm, Inst.offset&0b111111111, 9); //Immd is signed 9-bit, scaled in decode - - return bne(F, R, M, Inst); - } - - static bool cli(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.li %rd, $imm = addi %rd, x0, $imm - //Inst.rs1 = 0; //removed - set in decode - // SEXT(Inst.imm, (Inst.imm & 0b111111), 6); - Inst.imm = Inst.ImmSignExt(6); - return addi(F, R, M, Inst); - } - - static bool CIFUNC(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - if( Inst.rd == 2 ){ - // c.addi16sp - //SEXT(Inst.imm, (Inst.imm & 0b011111111)*16, 32); - //SEXT(Inst.imm, (Inst.imm & 0b111111)*16, 6); - // SEXT(Inst.imm, (Inst.imm & 0b1111111111), 10); // Immd is 10 bits, sign extended and scaled in decode - Inst.imm = Inst.ImmSignExt(10); - return addi(F, R, M, Inst); - }else{ - // c.lui %rd, $imm = addi %rd, x0, $imm - Inst.imm = Inst.ImmSignExt(17); - return lui(F, R, M, Inst); - } - } - - static bool caddi(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.addi %rd, $imm = addi %rd, %rd, $imm - // uint32_t tmp = Inst.imm & 0b111111; - Inst.imm = Inst.ImmSignExt(6); - //Inst.rs1 = Inst.rd; //Removed, set in decode - return addi(F, R, M, Inst); - } - - static bool cslli(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.slli %rd, $imm = slli %rd, %rd, $imm - // Inst.rs1 = Inst.rd; //removed - set in decode - return slli(F, R, M, Inst); - } - - static bool csrli(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.srli %rd, $imm = srli %rd, %rd, $imm - //Inst.rd = CRegIdx(Inst.rd); //removed - set in decode - Inst.rs1 = Inst.rd; - return srli(F, R, M, Inst); - } - - static bool csrai(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.srai %rd, $imm = srai %rd, %rd, $imm - // Inst.rd = CRegIdx(Inst.rd); //removed - set in decode - // Inst.rs1 = Inst.rd; //Removed - set in decode - return srai(F, R, M, Inst); - } - - static bool candi(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.andi %rd, $imm = sandi %rd, %rd, $imm - // Inst.rd = CRegIdx(Inst.rd); //removed - scaled in decode - // Inst.rs1 = Inst.rd; //removed - set in decode - Inst.imm = Inst.ImmSignExt(6); //immd is 6 bits, sign extended no scaling needed - return andi(F, R, M, Inst); - } - - static bool cand(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.and %rd, %rs2 = and %rd, %rd, %rs2 - // Inst.rd = CRegIdx(Inst.rd);//removed - scaled in decode - // Inst.rs1 = Inst.rd;//removed - scaled in decode - // Inst.rs2 = CRegIdx(Inst.rs2);//removed - scaled in decode - return f_and(F, R, M, Inst); - } - - static bool cor(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.or %rd, %rs2 = or %rd, %rd, %rs2 - //Inst.rd = CRegIdx(Inst.rd);//removed - scaled in decode - //Inst.rs1 = Inst.rd;//removed - scaled in decode - //Inst.rs2 = CRegIdx(Inst.rs2);//removed - scaled in decode - return f_or(F, R, M, Inst); - } - - static bool cxor(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.xor %rd, %rs2 = xor %rd, %rd, %rs2 - //Inst.rd = CRegIdx(Inst.rd);//removed - scaled in decode - //Inst.rs1 = Inst.rd;//removed - scaled in decode - //Inst.rs2 = CRegIdx(Inst.rs2);//removed - scaled in decode - return f_xor(F, R, M, Inst); - } - - static bool csub(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.sub %rd, %rs2 = sub %rd, %rd, %rs2 - //Inst.rd = CRegIdx(Inst.rd);//removed - scaled in decode - //Inst.rs1 = Inst.rd;//removed - scaled in decode - //Inst.rs2 = CRegIdx(Inst.rs2);//removed - scaled in decode - return sub(F, R, M, Inst); + // Standard instructions + static bool nop( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->AdvancePC( Inst ); + return true; } - // Standard instructions - static bool lui(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetX(Inst.rd, static_cast(Inst.imm << 12)); - R->AdvancePC(Inst); + static bool lui( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, static_cast( Inst.imm << 12 ) ); + R->AdvancePC( Inst ); return true; } - static bool auipc(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - auto ui = static_cast(Inst.imm << 12); - R->SetX(Inst.rd, ui + R->GetPC()); - R->AdvancePC(Inst); + static bool auipc( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + auto ui = static_cast( Inst.imm << 12 ); + R->SetX( Inst.rd, uint64_t( ui ) + R->GetPC() ); + R->AdvancePC( Inst ); return true; } - static bool jal(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetX(Inst.rd, R->GetPC() + Inst.instSize); - R->SetPC(R->GetPC() + Inst.ImmSignExt(21)); + static bool jal( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, R->GetPC() + Inst.instSize ); + R->SetPC( R->GetPC() + uint64_t( Inst.ImmSignExt( 21 ) ) ); return true; } - static bool jalr(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { + static bool jalr( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { auto ret = R->GetPC() + Inst.instSize; - R->SetPC((R->GetX(Inst.rs1) + Inst.ImmSignExt(12)) & -2); - R->SetX(Inst.rd, ret); + R->SetPC( ( R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ) ) & ~uint64_t{ 1 } ); + R->SetX( Inst.rd, ret ); return true; } // Conditional branches - static constexpr auto& beq = bcond; - static constexpr auto& bne = bcond; - static constexpr auto& blt = bcond; - static constexpr auto& bltu = bcond; - static constexpr auto& bge = bcond; - static constexpr auto& bgeu = bcond; + static constexpr auto& beq = bcond; + static constexpr auto& bne = bcond; + static constexpr auto& blt = bcond; + static constexpr auto& bltu = bcond; + static constexpr auto& bge = bcond; + static constexpr auto& bgeu = bcond; // Loads - static constexpr auto& lb = load; - static constexpr auto& lh = load; - static constexpr auto& lw = load; - static constexpr auto& lbu = load; - static constexpr auto& lhu = load; + static constexpr auto& lb = load; + static constexpr auto& lh = load; + static constexpr auto& lw = load; + static constexpr auto& lbu = load; + static constexpr auto& lhu = load; // Stores - static constexpr auto& sb = store; - static constexpr auto& sh = store; - static constexpr auto& sw = store; + static constexpr auto& sb = store; + static constexpr auto& sh = store; + static constexpr auto& sw = store; // Arithmetic operators - static constexpr auto& add = oper; - static constexpr auto& addi = oper; - static constexpr auto& sub = oper; + static constexpr auto& add = oper; + static constexpr auto& addi = oper; + static constexpr auto& sub = oper; static constexpr auto& f_xor = oper; static constexpr auto& xori = oper; - static constexpr auto& f_or = oper; - static constexpr auto& ori = oper; + static constexpr auto& f_or = oper; + static constexpr auto& ori = oper; static constexpr auto& f_and = oper; static constexpr auto& andi = oper; // Boolean test and set operators - static constexpr auto& slt = oper; - static constexpr auto& slti = oper; - static constexpr auto& sltu = oper; - static constexpr auto& sltiu = oper; + static constexpr auto& slt = oper; + static constexpr auto& slti = oper; + static constexpr auto& sltu = oper; + static constexpr auto& sltiu = oper; // Shift operators - static constexpr auto& slli = oper; - static constexpr auto& srli = oper; - static constexpr auto& srai = oper; - static constexpr auto& sll = oper; - static constexpr auto& srl = oper; - static constexpr auto& sra = oper; - - static bool fence(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - M->FenceMem(F->GetHartToExecID()); - R->AdvancePC(Inst); - return true; // temporarily disabled - } - - static bool fencei(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - M->FenceMem(F->GetHartToExecID()); - R->AdvancePC(Inst); + static constexpr auto& slli = oper; + static constexpr auto& srli = oper; + static constexpr auto& srai = oper; + static constexpr auto& sll = oper; + static constexpr auto& srl = oper; + static constexpr auto& sra = oper; + + static bool fence( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + M->FenceMem( F->GetHartToExecID() ); + R->AdvancePC( Inst ); return true; // temporarily disabled } - static bool ecall(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst){ + static bool ecall( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { /* * In reality this should be getting/setting a LOT of bits inside the * CSRs however because we are only concerned with ecall right now it's @@ -393,165 +114,173 @@ class RV32I : public RevExt { * to worry about machine mode with the ecalls we are supporting */ - R->SetSEPC(); // Save PC of instruction that raised exception - R->SetSTVAL(0); // MTVAL/STVAL unused for ecall and is set to 0 - R->SetSCAUSE(EXCEPTION_CAUSE::ECALL_USER_MODE); + R->SetSEPC(); // Save PC of instruction that raised exception + R->SetSTVAL( 0 ); // MTVAL/STVAL unused for ecall and is set to 0 + R->SetSCAUSE( RevExceptionCause::ECALL_USER_MODE ); /* * Trap Handler is not implemented because we only have one exception * So we don't have to worry about setting `mtvec` reg */ - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } - static bool ebreak(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } + static constexpr auto& ebreak = nop; - static bool csrrw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } - - static bool csrrs(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } - - static bool csrrc(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } - - static bool csrrwi(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } - - static bool csrrsi(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } + // Compressed instructions - static bool csrrci(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->AdvancePC(Inst); - return true; - } + // c.addi4spn %rd, $imm == addi %rd, x2, $imm, $imm != 0 + static constexpr auto& caddi4spn = addi; + + // c.mv and c.jr. If c.mv %rd == x0 it is a HINT instruction + static constexpr auto& cmv = add; + static constexpr auto& cjr = jalr; + + // c.add, c.jalr and c.ebreak. If c.add %rd == x0 then it is a HINT instruction + static constexpr auto& cadd = add; + static constexpr auto& cjalr = jalr; + static constexpr auto& cebreak = ebreak; + + // c.lui and c.addi16sp + static constexpr auto& clui = lui; + static constexpr auto& caddi16sp = addi; + + static constexpr auto& clwsp = lw; + static constexpr auto& cswsp = sw; + static constexpr auto& clw = lw; + static constexpr auto& csw = sw; + static constexpr auto& cj = jal; + static constexpr auto& cjal = jal; + static constexpr auto& cbeqz = beq; + static constexpr auto& cbnez = bne; + static constexpr auto& cli = addi; + static constexpr auto& caddi = addi; + static constexpr auto& cslli = slli; + static constexpr auto& csrli = srli; + static constexpr auto& csrai = srai; + static constexpr auto& candi = andi; + static constexpr auto& cand = f_and; + static constexpr auto& cor = f_or; + static constexpr auto& cxor = f_xor; + static constexpr auto& csub = sub; // ---------------------------------------------------------------------- // // RISC-V RV32I Instructions // - // Format: - // - // // ---------------------------------------------------------------------- + + // clang-format off std::vector RV32ITable = { - {RevInstEntryBuilder().SetMnemonic("lui %rd, $imm" ).SetCost(1).SetOpcode(0b0110111).SetFunct3(0b0).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeU).SetImplFunc(&lui ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("auipc %rd, $imm").SetCost(1).SetOpcode(0b0010111).SetFunct3(0b0).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeU).SetImplFunc(&auipc ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("jal %rd, $imm" ).SetCost(1).SetOpcode(0b1101111).SetFunct3(0b0 ).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeJ).SetImplFunc(&jal ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("jalr %rd, %rs1, $imm").SetCost(1).SetOpcode(0b1100111).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&jalr ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("beq %rs1, %rs2, $imm" ).SetCost(1).SetOpcode(0b1100011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&beq ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("bne %rs1, %rs2, $imm" ).SetCost(1).SetOpcode(0b1100011).SetFunct3(0b001).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&bne ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("blt %rs1, %rs2, $imm" ).SetCost(1).SetOpcode(0b1100011).SetFunct3(0b100).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&blt ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("bge %rs1, %rs2, $imm" ).SetCost(1).SetOpcode(0b1100011).SetFunct3(0b101).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&bge ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("bltu %rs1, %rs2, $imm").SetCost(1).SetOpcode(0b1100011).SetFunct3(0b110).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&bltu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("bgeu %rs1, %rs2, $imm").SetCost(1).SetOpcode(0b1100011).SetFunct3(0b111).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeB).SetImplFunc(&bgeu ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("lb %rd, $imm(%rs1)" ).SetCost(1).SetOpcode(0b0000011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lb ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("lh %rd, $imm(%rs1)" ).SetCost(1).SetOpcode(0b0000011).SetFunct3(0b001).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lh ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("lw %rd, $imm(%rs1)" ).SetCost(1).SetOpcode(0b0000011).SetFunct3(0b010).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("lbu %rd, $imm(%rs1)").SetCost(1).SetOpcode(0b0000011).SetFunct3(0b100).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lbu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("lhu %rd, $imm(%rs1)").SetCost(1).SetOpcode(0b0000011).SetFunct3(0b101).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lhu ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("sb %rs2, $imm(%rs1)").SetCost(1).SetOpcode(0b0100011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeS).SetImplFunc(&sb ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sh %rs2, $imm(%rs1)").SetCost(1).SetOpcode(0b0100011).SetFunct3(0b001).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeS).SetImplFunc(&sh ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sw %rs2, $imm(%rs1)").SetCost(1).SetOpcode(0b0100011).SetFunct3(0b010).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeS).SetImplFunc(&sw ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("addi %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b0010011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&addi ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("slti %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b0010011).SetFunct3(0b010).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&slti ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sltiu %rd, %rs1, $imm").SetCost(1).SetOpcode(0b0010011).SetFunct3(0b011).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&sltiu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("xori %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b0010011).SetFunct3(0b100).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&xori ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("ori %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b0010011).SetFunct3(0b110).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&ori ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("andi %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b0010011).SetFunct3(0b111).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&andi ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("slli %rd, %rs1, $imm").SetCost(1).SetOpcode(0b0010011).SetFunct3(0b001).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&slli ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("srli %rd, %rs1, $imm").SetCost(1).SetOpcode(0b0010011).SetFunct3(0b101).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&srli ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("srai %rd, %rs1, $imm").SetCost(1).SetOpcode(0b0010011).SetFunct3(0b101).SetFunct2or7(0b0010000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&srai ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("add %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b000).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&add ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sub %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b000).SetFunct2or7(0b0100000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sub ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sll %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b001).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sll ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("slt %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b010).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&slt ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sltu %rd, %rs1, %rs2").SetCost(1).SetOpcode(0b0110011).SetFunct3(0b011).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sltu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("xor %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b100).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&f_xor ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("srl %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b101).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&srl ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sra %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b101).SetFunct2or7(0b0100000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sra ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("or %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b110).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&f_or ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("and %rd, %rs1, %rs2" ).SetCost(1).SetOpcode(0b0110011).SetFunct3(0b111).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&f_and ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("fence" ).SetCost(1).SetOpcode(0b0001111).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeI).SetImplFunc(&fence ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fence.i").SetCost(1).SetOpcode(0b0001111).SetFunct3(0b001).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FUnk).SetFormat(RVTypeI).SetImplFunc(&fencei ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("ecall" ).SetCost(1).SetOpcode(0b1110011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b000000000000).Setimm(FEnc).SetFormat(RVTypeI).SetImplFunc(&ecall ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("ebreak").SetCost(1).SetOpcode(0b1110011).SetFunct3(0b000).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b000000000001).Setimm(FEnc).SetFormat(RVTypeI).SetImplFunc(&ebreak ).InstEntry}, - - {RevInstEntryBuilder().SetMnemonic("csrrw %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b1110011).SetFunct3(0b001).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("csrrs %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b1110011).SetFunct3(0b010).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrs ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("csrrc %rd, %rs1, $imm" ).SetCost(1).SetOpcode(0b1110011).SetFunct3(0b011).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrc ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("csrrwi %rd, %rs1, $imm").SetCost(1).SetOpcode(0b1110011).SetFunct3(0b101).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrwi ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("csrrsi %rd, %rs1, $imm").SetCost(1).SetOpcode(0b1110011).SetFunct3(0b110).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrsi ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("csrrci %rd, %rs1, $imm").SetCost(1).SetOpcode(0b1110011).SetFunct3(0b111).SetFunct2or7(0b0).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm12(0b0).Setimm(FVal).SetFormat(RVTypeU).SetImplFunc(&csrrci ).InstEntry}, + RevInstDefaults().SetMnemonic("lui %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(lui ).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeU).SetOpcode(0b0110111), + RevInstDefaults().SetMnemonic("auipc %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(auipc ).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeU).SetOpcode(0b0010111), + RevInstDefaults().SetMnemonic("jal %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(jal ).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeJ).SetOpcode(0b1101111).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0 && DECODE_RD( Inst ) != 1; } ), + RevInstDefaults().SetMnemonic("jal $imm" ).SetFunct3( 0b000).SetImplFunc(jal ).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeJ).SetOpcode(0b1101111).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0 && DECODE_RD( Inst ) == 1; } ), + RevInstDefaults().SetMnemonic("j $imm" ).SetFunct3( 0b000).SetImplFunc(jal ).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeJ).SetOpcode(0b1101111).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + RevInstDefaults().SetMnemonic("jalr %rd, %rs1, $imm" ).SetFunct3( 0b000).SetImplFunc(jalr ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b1100111).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) != 0 || DECODE_RD( Inst ) > 1; } ), + RevInstDefaults().SetMnemonic("jalr %rs1" ).SetFunct3( 0b000).SetImplFunc(jalr ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b1100111).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) == 0 && DECODE_RD( Inst ) == 1; } ), + RevInstDefaults().SetMnemonic("jr %rs1" ).SetFunct3( 0b000).SetImplFunc(jalr ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b1100111).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) == 0 && DECODE_RD( Inst ) == 0 && DECODE_RS1( Inst ) != 1; } ), + RevInstDefaults().SetMnemonic("ret" ).SetFunct3( 0b000).SetImplFunc(jalr ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b1100111).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) == 0 && DECODE_RD( Inst ) == 0 && DECODE_RS1( Inst ) == 1; } ), + RevInstDefaults().SetMnemonic("beq %rs1, %rs2, $imm" ).SetFunct3( 0b000).SetImplFunc(beq ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + RevInstDefaults().SetMnemonic("bne %rs1, %rs2, $imm" ).SetFunct3( 0b001).SetImplFunc(bne ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + RevInstDefaults().SetMnemonic("blt %rs1, %rs2, $imm" ).SetFunct3( 0b100).SetImplFunc(blt ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + RevInstDefaults().SetMnemonic("bge %rs1, %rs2, $imm" ).SetFunct3( 0b101).SetImplFunc(bge ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + RevInstDefaults().SetMnemonic("bltu %rs1, %rs2, $imm").SetFunct3( 0b110).SetImplFunc(bltu ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + RevInstDefaults().SetMnemonic("bgeu %rs1, %rs2, $imm").SetFunct3( 0b111).SetImplFunc(bgeu ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeB).SetOpcode(0b1100011), + + RevInstDefaults().SetMnemonic("lb %rd, $imm(%rs1)" ).SetFunct3( 0b000).SetImplFunc(lb ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0000011), + RevInstDefaults().SetMnemonic("lh %rd, $imm(%rs1)" ).SetFunct3( 0b001).SetImplFunc(lh ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0000011), + RevInstDefaults().SetMnemonic("lw %rd, $imm(%rs1)" ).SetFunct3( 0b010).SetImplFunc(lw ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0000011), + RevInstDefaults().SetMnemonic("lbu %rd, $imm(%rs1)" ).SetFunct3( 0b100).SetImplFunc(lbu ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0000011), + RevInstDefaults().SetMnemonic("lhu %rd, $imm(%rs1)" ).SetFunct3( 0b101).SetImplFunc(lhu ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0000011), + + RevInstDefaults().SetMnemonic("sb %rs2, $imm(%rs1)" ).SetFunct3( 0b000).SetImplFunc(sb ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeS).SetOpcode(0b0100011), + RevInstDefaults().SetMnemonic("sh %rs2, $imm(%rs1)" ).SetFunct3( 0b001).SetImplFunc(sh ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeS).SetOpcode(0b0100011), + RevInstDefaults().SetMnemonic("sw %rs2, $imm(%rs1)" ).SetFunct3( 0b010).SetImplFunc(sw ).SetrdClass(RevRegClass::RegIMM) .SetFormat(RVTypeS).SetOpcode(0b0100011), + + RevInstDefaults().SetMnemonic("addi %rd, %rs1, $imm" ).SetFunct3( 0b000).SetImplFunc(addi ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) != 0; } ), + RevInstDefaults().SetMnemonic("mv %rd, %rs1" ).SetFunct3( 0b000).SetImplFunc(addi ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) == 0 && ( DECODE_RS1( Inst ) != 0 || DECODE_RD( Inst ) != 0 ); } ), + RevInstDefaults().SetMnemonic("nop" ).SetFunct3( 0b000).SetImplFunc(addi ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12( Inst ) == 0 && ( DECODE_RS1( Inst ) == 0 && DECODE_RD( Inst ) == 0 ); } ), + RevInstDefaults().SetMnemonic("slti %rd, %rs1, $imm" ).SetFunct3( 0b010).SetImplFunc(slti ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011), + RevInstDefaults().SetMnemonic("sltiu %rd, %rs1, $imm").SetFunct3( 0b011).SetImplFunc(sltiu ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ) { return DECODE_IMM12( Inst ) != 1; } ), + RevInstDefaults().SetMnemonic("seqz %rd, %rs" ).SetFunct3( 0b011).SetImplFunc(sltiu ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ) { return DECODE_IMM12( Inst ) == 1; } ), + RevInstDefaults().SetMnemonic("xori %rd, %rs1, $imm" ).SetFunct3( 0b100).SetImplFunc(xori ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ) { return SignExt( DECODE_IMM12( Inst ), 12 ) != -1; } ), + RevInstDefaults().SetMnemonic("not %rd, %rs" ).SetFunct3( 0b100).SetImplFunc(xori ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011).SetPredicate( []( uint32_t Inst ) { return SignExt( DECODE_IMM12( Inst ), 12 ) == -1; } ), + RevInstDefaults().SetMnemonic("ori %rd, %rs1, $imm" ).SetFunct3( 0b110).SetImplFunc(ori ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011), + RevInstDefaults().SetMnemonic("andi %rd, %rs1, $imm" ).SetFunct3( 0b111).SetImplFunc(andi ).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm) .SetFormat(RVTypeI).SetOpcode(0b0010011), + + RevInstDefaults().SetMnemonic("slli %rd, %rs1, $imm" ).SetFunct3( 0b001).SetImplFunc(slli ).SetFunct2or7(0b0000000).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0010011), + RevInstDefaults().SetMnemonic("srli %rd, %rs1, $imm" ).SetFunct3( 0b101).SetImplFunc(srli ).SetFunct2or7(0b0000000).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0010011), + RevInstDefaults().SetMnemonic("srai %rd, %rs1, $imm" ).SetFunct3( 0b101).SetImplFunc(srai ).SetFunct2or7(0b0010000).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0010011), + + RevInstDefaults().SetMnemonic("add %rd, %rs1, %rs2" ).SetFunct3( 0b000).SetImplFunc(add ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("sub %rd, %rs1, %rs2" ).SetFunct3( 0b000).SetImplFunc(sub ).SetFunct2or7(0b0100000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("sll %rd, %rs1, %rs2" ).SetFunct3( 0b001).SetImplFunc(sll ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("slt %rd, %rs1, %rs2" ).SetFunct3( 0b010).SetImplFunc(slt ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("sltu %rd, %rs1, %rs2" ).SetFunct3( 0b011).SetImplFunc(sltu ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != 0; } ), + RevInstDefaults().SetMnemonic("snez %rd, %rs" ).SetFunct3( 0b011).SetImplFunc(sltu ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0; } ), + RevInstDefaults().SetMnemonic("xor %rd, %rs1, %rs2" ).SetFunct3( 0b100).SetImplFunc(f_xor ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("srl %rd, %rs1, %rs2" ).SetFunct3( 0b101).SetImplFunc(srl ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("sra %rd, %rs1, %rs2" ).SetFunct3( 0b101).SetImplFunc(sra ).SetFunct2or7(0b0100000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("or %rd, %rs1, %rs2" ).SetFunct3( 0b110).SetImplFunc(f_or ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("and %rd, %rs1, %rs2" ).SetFunct3( 0b111).SetImplFunc(f_and ).SetFunct2or7(0b0000000) .SetFormat(RVTypeR).SetOpcode(0b0110011), + RevInstDefaults().SetMnemonic("fence" ).SetFunct3( 0b000).SetImplFunc(fence ).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeI).SetOpcode(0b0001111).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm(RevImmFunc::FVal), + RevInstDefaults().SetMnemonic("ecall" ).SetFunct3( 0b000).SetImplFunc(ecall ).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeI).SetOpcode(0b1110011).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm12(0b000000000000).Setimm(RevImmFunc::FEnc), + RevInstDefaults().SetMnemonic("ebreak" ).SetFunct3( 0b000).SetImplFunc(ebreak).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN) .SetFormat(RVTypeI).SetOpcode(0b1110011).Setrs2Class(RevRegClass::RegUNKNOWN).Setimm12(0b000000000001).Setimm(RevImmFunc::FEnc), }; // RV32C table std::vector RV32ICTable = { - {RevInstEntryBuilder().SetMnemonic("c.addi4spn %rd, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b000).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCIW).SetImplFunc(&caddi4spn).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.lwsp %rd, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b010).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&clwsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.swsp %rs2, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b110).Setrs2Class(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCSS).SetImplFunc(&cswsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.lw %rd, $rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b010).Setrs1Class(RevRegClass::RegGPR).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCL).SetImplFunc(&clw).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.sw %rs2, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b110).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCS).SetImplFunc(&csw).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.j $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b101).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCJ).SetImplFunc(&cj).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.jr %rs1").SetCost(1).SetOpcode(0b10).SetFunct4(0b1000).Setrs1Class(RevRegClass::RegGPR).SetFormat(RVCTypeCR).SetImplFunc(&CRFUNC_1000).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.jalr %rs1").SetCost(1).SetOpcode(0b10).SetFunct4(0b1001).Setrs1Class(RevRegClass::RegGPR).SetFormat(RVCTypeCR).SetImplFunc(&CRFUNC_1001).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.beqz %rs1, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b110).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCB).SetImplFunc(&cbeqz).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.bnez %rs1, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b111).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCB).SetImplFunc(&cbnez).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.li %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b010).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&cli).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.lui %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b011).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&CIFUNC).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.addi %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b000).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&caddi).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.slli %rd, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b000).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&cslli).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.srli %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b100).SetFunct2(0b00).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCB).SetImplFunc(&csrli).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.srai %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b100).SetFunct2(0b01).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCB).SetImplFunc(&csrai).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.andi %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b100).SetFunct2(0b10).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCB).SetImplFunc(&candi).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.and %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100011).SetFunct2(0b11).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&cand).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.or %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100011).SetFunct2(0b10).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&cor).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.xor %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100011).SetFunct2(0b01).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&cxor).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.sub %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100011).SetFunct2(0b00).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&csub).SetCompressed(true).InstEntry}, - }; - - // RV32C-Only table - std::vector RV32ICOTable = { - {RevInstEntryBuilder().SetMnemonic("c.jal $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b001).SetrdClass(RevRegClass::RegGPR).SetFormat(RVCTypeCJ).SetImplFunc(&cjal).SetCompressed(true).InstEntry}, + RevCInstDefaults().SetMnemonic("c.addi4spn %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(caddi4spn ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCIW).SetOpcode(0b00).SetPredicate( []( uint32_t Inst ){ return ( ( Inst >> 5 ) & 0xff ) != 0; } ), + RevCInstDefaults().SetMnemonic("c.lwsp %rd, $imm" ).SetFunct3( 0b010).SetImplFunc(clwsp ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevCInstDefaults().SetMnemonic("c.swsp %rs2, $imm" ).SetFunct3( 0b110).SetImplFunc(cswsp ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCSS).SetOpcode(0b10), + RevCInstDefaults().SetMnemonic("c.lw %rd, $rs1, $imm" ).SetFunct3( 0b010).SetImplFunc(clw ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCL ).SetOpcode(0b00), + RevCInstDefaults().SetMnemonic("c.sw %rs2, %rs1, $imm").SetFunct3( 0b110).SetImplFunc(csw ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCS ).SetOpcode(0b00), + RevCInstDefaults().SetMnemonic("c.j $imm" ).SetFunct3( 0b101).SetImplFunc(cj ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCJ ).SetOpcode(0b01), + RevCInstDefaults().SetMnemonic("c.jr %rs1" ).SetFunct4( 0b1000).SetImplFunc(cjr ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) == 0 && DECODE_RD( Inst ) != 0 && DECODE_RD( Inst ) != 1; } ), + RevCInstDefaults().SetMnemonic("ret" ).SetFunct4( 0b1000).SetImplFunc(cjr ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) == 0 && DECODE_RD( Inst ) == 1; } ), + RevCInstDefaults().SetMnemonic("c.mv %rd, %rs2" ).SetFunct4( 0b1000).SetImplFunc(cmv ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) != 0; } ), + RevCInstDefaults().SetMnemonic("c.add %rd, %rs1" ).SetFunct4( 0b1001).SetImplFunc(cadd ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) != 0; } ), + RevCInstDefaults().SetMnemonic("c.jalr %rs1" ).SetFunct4( 0b1001).SetImplFunc(cjalr ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) == 0 && DECODE_RD(Inst) != 0; } ), + RevCInstDefaults().SetMnemonic("c.ebreak" ).SetFunct4( 0b1001).SetImplFunc(cebreak ) .SetFormat(RVCTypeCR ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ){ return DECODE_LOWER_CRS2( Inst ) == 0 && DECODE_RD(Inst) == 0; } ), + RevCInstDefaults().SetMnemonic("c.beqz %rs1, $imm" ).SetFunct3( 0b110).SetImplFunc(cbeqz ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCB ).SetOpcode(0b01), + RevCInstDefaults().SetMnemonic("c.bnez %rs1, $imm" ).SetFunct3( 0b111).SetImplFunc(cbnez ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCB ).SetOpcode(0b01), + RevCInstDefaults().SetMnemonic("c.li %rd, $imm" ).SetFunct3( 0b010).SetImplFunc(cli ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01), + RevCInstDefaults().SetMnemonic("c.lui %rd, $imm" ).SetFunct3( 0b011).SetImplFunc(clui ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 2; } ), + RevCInstDefaults().SetMnemonic("c.addi16sp $imm" ).SetFunct3( 0b011).SetImplFunc(caddi16sp ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 2; } ), + RevCInstDefaults().SetMnemonic("c.addi %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(caddi ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevCInstDefaults().SetMnemonic("c.nop" ).SetFunct3( 0b000).SetImplFunc(nop ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + RevCInstDefaults().SetMnemonic("c.slli %rd, $imm" ).SetFunct3( 0b000).SetImplFunc(cslli ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b10), + RevCInstDefaults().SetMnemonic("c.srli %rd, $imm" ).SetFunct3( 0b100).SetImplFunc(csrli ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCB ).SetOpcode(0b01).SetFunct2(0b00), + RevCInstDefaults().SetMnemonic("c.srai %rd, $imm" ).SetFunct3( 0b100).SetImplFunc(csrai ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCB ).SetOpcode(0b01).SetFunct2(0b01), + RevCInstDefaults().SetMnemonic("c.andi %rd, $imm" ).SetFunct3( 0b100).SetImplFunc(candi ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCB ).SetOpcode(0b01).SetFunct2(0b10), + RevCInstDefaults().SetMnemonic("c.and %rd, %rs1" ).SetFunct6(0b100011).SetImplFunc(cand ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct2(0b11), + RevCInstDefaults().SetMnemonic("c.or %rd, %rs1" ).SetFunct6(0b100011).SetImplFunc(cor ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct2(0b10), + RevCInstDefaults().SetMnemonic("c.xor %rd, %rs1" ).SetFunct6(0b100011).SetImplFunc(cxor ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct2(0b01), + RevCInstDefaults().SetMnemonic("c.sub %rd, %rs1" ).SetFunct6(0b100011).SetImplFunc(csub ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct2(0b00), }; + // clang-format on public: /// RV32I: standard constructor - RV32I( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32I", Feature, RevMem, Output ) { - SetTable(std::move(RV32ITable)); - SetCTable(std::move(RV32ICTable)); - SetOTable(std::move(RV32ICOTable)); + RV32I( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV32I", Feature, RevMem, Output ) { + if( !Feature->IsRV64() ) { + // RV32C-Only instruction + RV32ICTable.push_back( RevCInstDefaults() + .SetMnemonic( "c.jal $imm" ) + .SetOpcode( 0b01 ) + .SetFunct3( 0b001 ) + .SetFormat( RVCTypeCJ ) + .SetImplFunc( cjal ) ); + } + SetTable( std::move( RV32ITable ) ); + SetCTable( std::move( RV32ICTable ) ); } -}; // end class RV32I +}; // end class RV32I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV32M.h b/include/insns/RV32M.h index e5797d91f..8c819e395 100644 --- a/include/insns/RV32M.h +++ b/include/insns/RV32M.h @@ -11,21 +11,21 @@ #ifndef _SST_REVCPU_RV32M_H_ #define _SST_REVCPU_RV32M_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" #include +#include #include #include -#include -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RV32M : public RevExt{ +class RV32M : public RevExt { // Multiplication High instructions based on signedness of arguments - static constexpr auto& mulh = uppermul; + static constexpr auto& mulh = uppermul; static constexpr auto& mulhu = uppermul; - static constexpr auto& mulhsu = uppermul; + static constexpr auto& mulhsu = uppermul; /// Computes the LOWER half of multiplication, which does not depend on signedness static constexpr auto& mul = oper; @@ -42,36 +42,41 @@ class RV32M : public RevExt{ // // RISC-V RV32M Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct RevMInstDefaults : RevInstDefaults { - static constexpr uint8_t funct2or7 = 0b0000001; - static constexpr uint8_t opcode = 0b0110011; + RevMInstDefaults() { + SetOpcode( 0b0110011 ); + SetFunct2or7( 0b0000001 ); + } }; + // clang-format off std::vector RV32MTable = { - {RevInstEntryBuilder().SetMnemonic("mul %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc( &mul ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("mulh %rd, %rs1, %rs2" ).SetFunct3(0b001).SetImplFunc( &mulh ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("mulhsu %rd, %rs1, %rs2").SetFunct3(0b010).SetImplFunc( &mulhsu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("mulhu %rd, %rs1, %rs2" ).SetFunct3(0b011).SetImplFunc( &mulhu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("div %rd, %rs1, %rs2" ).SetFunct3(0b100).SetImplFunc( &div ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("divu %rd, %rs1, %rs2" ).SetFunct3(0b101).SetImplFunc( &divu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("rem %rd, %rs1, %rs2" ).SetFunct3(0b110).SetImplFunc( &rem ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("remu %rd, %rs1, %rs20" ).SetFunct3(0b111).SetImplFunc( &remu ).InstEntry}, + RevMInstDefaults().SetMnemonic("mul %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc(mul ), + RevMInstDefaults().SetMnemonic("mulh %rd, %rs1, %rs2" ).SetFunct3(0b001).SetImplFunc(mulh ), + RevMInstDefaults().SetMnemonic("mulhsu %rd, %rs1, %rs2").SetFunct3(0b010).SetImplFunc(mulhsu), + RevMInstDefaults().SetMnemonic("mulhu %rd, %rs1, %rs2" ).SetFunct3(0b011).SetImplFunc(mulhu ), }; + std::vector RV32DivTable = { + RevMInstDefaults().SetMnemonic("div %rd, %rs1, %rs2" ).SetFunct3(0b100).SetImplFunc(div ), + RevMInstDefaults().SetMnemonic("divu %rd, %rs1, %rs2" ).SetFunct3(0b101).SetImplFunc(divu ), + RevMInstDefaults().SetMnemonic("rem %rd, %rs1, %rs2" ).SetFunct3(0b110).SetImplFunc(rem ), + RevMInstDefaults().SetMnemonic("remu %rd, %rs1, %rs20" ).SetFunct3(0b111).SetImplFunc(remu ), + }; + + // clang-format on + public: /// RV32M: standard constructor - RV32M( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV32M", Feature, RevMem, Output) { - SetTable(std::move(RV32MTable)); + RV32M( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV32M", Feature, RevMem, Output ) { + if( Feature->IsModeEnabled( RV_M ) ) { + RV32MTable.insert( RV32MTable.end(), RV32DivTable.begin(), RV32DivTable.end() ); + } + SetTable( std::move( RV32MTable ) ); } -}; // end class RV32I +}; // end class RV32I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV64A.h b/include/insns/RV64A.h deleted file mode 100644 index 68ed7d787..000000000 --- a/include/insns/RV64A.h +++ /dev/null @@ -1,133 +0,0 @@ -// -// _RV64A_h_ -// -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC -// All Rights Reserved -// contact@tactcomplabs.com -// -// See LICENSE in the top level directory for licensing details -// - -#ifndef _SST_REVCPU_RV64A_H_ -#define _SST_REVCPU_RV64A_H_ - -#include "../RevInstHelpers.h" -#include "../RevExt.h" - -#include - -namespace SST::RevCPU{ - -class RV64A : public RevExt { - - static bool lrd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - MemReq req(R->RV64[Inst.rs1], Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete() ); - R->LSQueue->insert( req.LSQHashPair() ); - M->LR(F->GetHartToExecID(), - R->RV64[Inst.rs1], - &R->RV64[Inst.rd], - Inst.aq, Inst.rl, req, - RevFlag::F_SEXT64); - R->AdvancePC(Inst); - return true; - } - - static bool scd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - M->SC(F->GetHartToExecID(), - R->RV64[Inst.rs1], - &R->RV64[Inst.rs2], - &R->RV64[Inst.rd], - Inst.aq, Inst.rl, - RevFlag::F_SEXT64); - R->AdvancePC(Inst); - return true; - } - - /// Atomic Memory Operations - template - static bool amooperd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - uint32_t flags = static_cast(F_AMO); - - if( Inst.aq && Inst.rl ){ - flags |= uint32_t(RevFlag::F_AQ) | uint32_t(RevFlag::F_RL); - }else if( Inst.aq ){ - flags |= uint32_t(RevFlag::F_AQ); - }else if( Inst.rl ){ - flags |= uint32_t(RevFlag::F_RL); - } - - MemReq req(R->RV64[Inst.rs1], - Inst.rd, - RevRegClass::RegGPR, - F->GetHartToExecID(), - MemOp::MemOpAMO, - true, - R->GetMarkLoadComplete()); - R->LSQueue->insert( req.LSQHashPair() ); - M->AMOVal(F->GetHartToExecID(), - R->RV64[Inst.rs1], - &R->RV64[Inst.rs2], - &R->RV64[Inst.rd], - req, - RevFlag{flags}); - - R->AdvancePC(Inst); - - // update the cost - R->cost += M->RandCost(F->GetMinCost(), F->GetMaxCost()); - return true; - } - - static constexpr auto& amoaddd = amooperd; - static constexpr auto& amoswapd = amooperd; - static constexpr auto& amoxord = amooperd; - static constexpr auto& amoandd = amooperd; - static constexpr auto& amoord = amooperd; - static constexpr auto& amomind = amooperd; - static constexpr auto& amomaxd = amooperd; - static constexpr auto& amominud = amooperd; - static constexpr auto& amomaxud = amooperd; - - // ---------------------------------------------------------------------- - // - // RISC-V RV64A Instructions - // - // Format: - // - // - // ---------------------------------------------------------------------- - struct Rev64AInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b0101111; - static constexpr uint8_t funct3 = 0b011; - static constexpr RevRegClass rs2Class = RevRegClass::RegUNKNOWN; - }; - std::vector RV64ATable = { - {RevInstEntryBuilder().SetMnemonic("lr.d %rd, (%rs1)" ).SetFunct2or7(0b00010). - Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(&lrd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sc.d %rd, %rs1, %rs2" ).SetFunct2or7(0b00011). - SetImplFunc(&scd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoswap.d %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b00001).SetImplFunc( &amoswapd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoadd.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b00000).SetImplFunc( &amoaddd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoxor.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b00100).SetImplFunc( &amoxord ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoand.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b01100).SetImplFunc( &amoandd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amoor.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b01000).SetImplFunc( &amoord ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomin.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b10000).SetImplFunc( &amomind ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomax.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b10100).SetImplFunc( &amomaxd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amominu.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b11000).SetImplFunc( &amominud ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("amomaxu.w %rd, %rs1, %rs2").SetCost( 1).SetOpcode( 0b0101111).SetFunct3(0b011).SetFunct2or7( 0b11100).SetImplFunc( &amomaxud ).InstEntry}, - }; - - -public: - /// RV64A: standard constructor - RV64A( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64A", Feature, RevMem, Output) { - SetTable(std::move(RV64ATable)); - } -}; // end class RV64A - -} // namespace SST::RevCPU - -#endif diff --git a/include/insns/RV64D.h b/include/insns/RV64D.h index 97a04b38d..741039969 100644 --- a/include/insns/RV64D.h +++ b/include/insns/RV64D.h @@ -11,79 +11,58 @@ #ifndef _SST_REVCPU_RV64D_H_ #define _SST_REVCPU_RV64D_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ +namespace SST::RevCPU { class RV64D : public RevExt { - static constexpr auto& fcvtld = CvtFpToInt; - static constexpr auto& fcvtlud = CvtFpToInt; - - static bool fcvtdl(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // Conversion from double to integer + static constexpr auto& fcvtld = fcvtif; + static constexpr auto& fcvtlud = fcvtif; - static bool fcvtdlu(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + // Conversion from integer to double + static constexpr auto& fcvtdl = fcvtfi; + static constexpr auto& fcvtdlu = fcvtfi; - static bool fmvxd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - uint64_t u64; - double fp = R->GetFP(Inst.rs1); - memcpy(&u64, &fp, sizeof(u64)); - R->SetX(Inst.rd, u64); - R->AdvancePC(Inst); - return true; - } - - static bool fmvdx(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - uint64_t u64 = R->GetX(Inst.rs1); - double fp; - memcpy(&fp, &u64, sizeof(fp)); - R->SetFP(Inst.rd, fp); - R->AdvancePC(Inst); - return true; - } + // Moves between FP and integer registers + static constexpr auto& fmvxd = fmvif; + static constexpr auto& fmvdx = fmvfi; // ---------------------------------------------------------------------- // // RISC-V RV64D Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev64DInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b1010011; + Rev64DInstDefaults() { + SetOpcode( 0b1010011 ); + Setrs2Class( RevRegClass::RegUNKNOWN ); + SetRaiseFPE( true ); + } }; + // clang-format off std::vector RV64DTable = { - {RevInstEntryBuilder().SetMnemonic("fcvt.l.d %rd, %rs1" ).SetFunct2or7(0b1100001).SetfpcvtOp(0b10).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fcvtld ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.lu.d %rd, %rs1" ).SetFunct2or7(0b1100001).SetfpcvtOp(0b11).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fcvtlud ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.d.l %rd, %rs1" ).SetFunct2or7(0b1101001).SetfpcvtOp(0b10).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fcvtdl ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.d.lu %rd, %rs1" ).SetFunct2or7(0b1101001).SetfpcvtOp(0b11).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fcvtdlu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmv.x.d %rd, %rs1" ).SetFunct2or7(0b1110001).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fmvxd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fmv.d.x %rd, %rs1" ).SetFunct2or7(0b1111001).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc( &fmvdx ).InstEntry}, + Rev64DInstDefaults().SetMnemonic("fcvt.l.d %rd, %rs1" ).SetFunct2or7(0b1100001).SetImplFunc(fcvtld ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2fcvtOp(0b10), + Rev64DInstDefaults().SetMnemonic("fcvt.lu.d %rd, %rs1").SetFunct2or7(0b1100001).SetImplFunc(fcvtlud).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2fcvtOp(0b11), + Rev64DInstDefaults().SetMnemonic("fcvt.d.l %rd, %rs1" ).SetFunct2or7(0b1101001).SetImplFunc(fcvtdl ).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setrs2fcvtOp(0b10), + Rev64DInstDefaults().SetMnemonic("fcvt.d.lu %rd, %rs1").SetFunct2or7(0b1101001).SetImplFunc(fcvtdlu).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setrs2fcvtOp(0b11), + Rev64DInstDefaults().SetMnemonic("fmv.x.d %rd, %rs1" ).SetFunct2or7(0b1110001).SetImplFunc(fmvxd ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).SetRaiseFPE(false), + Rev64DInstDefaults().SetMnemonic("fmv.d.x %rd, %rs1" ).SetFunct2or7(0b1111001).SetImplFunc(fmvdx ).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).SetRaiseFPE(false), }; + // clang-format on public: /// RV364D: standard constructor - RV64D( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64D", Feature, RevMem, Output) { - SetTable(std::move(RV64DTable)); + RV64D( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV64D", Feature, RevMem, Output ) { + SetTable( std::move( RV64DTable ) ); } -}; // end class RV32I +}; // end class RV32I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV64F.h b/include/insns/RV64F.h index 71a19cdef..b20b6ac34 100644 --- a/include/insns/RV64F.h +++ b/include/insns/RV64F.h @@ -11,59 +11,49 @@ #ifndef _SST_REVCPU_RV64F_H_ #define _SST_REVCPU_RV64F_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ +namespace SST::RevCPU { class RV64F : public RevExt { - static constexpr auto& fcvtls = CvtFpToInt; - static constexpr auto& fcvtlus = CvtFpToInt; - - static bool fcvtsl(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } - - static bool fcvtslu(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetFP(Inst.rd, static_cast(R->GetX(Inst.rs1))); - R->AdvancePC(Inst); - return true; - } + static constexpr auto& fcvtls = fcvtif; + static constexpr auto& fcvtlus = fcvtif; + static constexpr auto& fcvtsl = fcvtfi; + static constexpr auto& fcvtslu = fcvtfi; // ---------------------------------------------------------------------- // // RISC-V RV64F Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev64FInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b1010011; + Rev64FInstDefaults() { + SetOpcode( 0b1010011 ); + Setrs2Class( RevRegClass::RegUNKNOWN ); + SetRaiseFPE( true ); + } }; + // clang-format off std::vector RV64FTable = { - {RevInstEntryBuilder().SetMnemonic("fcvt.l.s %rd, %rs1").SetFunct2or7( 0b1100000).SetfpcvtOp(0b10).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(&fcvtls ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.lu.s %rd, %rs1").SetFunct2or7( 0b1100000).SetfpcvtOp(0b11).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegFLOAT).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(&fcvtlus ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.s.l %rd, %rs1" ).SetFunct2or7( 0b1101000).SetfpcvtOp(0b10).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(&fcvtsl ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("fcvt.s.lu %rd, %rs1").SetFunct2or7( 0b1101000).SetfpcvtOp(0b11).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(&fcvtslu ) .InstEntry}, + Rev64FInstDefaults().SetMnemonic("fcvt.l.s %rd, %rs1").SetFunct2or7(0b1100000).SetImplFunc(fcvtls ).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2fcvtOp(0b00010), + Rev64FInstDefaults().SetMnemonic("fcvt.lu.s %rd, %rs1").SetFunct2or7(0b1100000).SetImplFunc(fcvtlus).SetrdClass(RevRegClass::RegGPR ).Setrs1Class(RevRegClass::RegFLOAT).Setrs2fcvtOp(0b00011), + Rev64FInstDefaults().SetMnemonic("fcvt.s.l %rd, %rs1").SetFunct2or7(0b1101000).SetImplFunc(fcvtsl ).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setrs2fcvtOp(0b00010), + Rev64FInstDefaults().SetMnemonic("fcvt.s.lu %rd, %rs1").SetFunct2or7(0b1101000).SetImplFunc(fcvtslu).SetrdClass(RevRegClass::RegFLOAT).Setrs1Class(RevRegClass::RegGPR ).Setrs2fcvtOp(0b00011), }; + // clang-format on public: /// RV364F: standard constructor - RV64F( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64F", Feature, RevMem, Output) { - SetTable(std::move(RV64FTable)); + RV64F( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV64F", Feature, RevMem, Output ) { + SetTable( std::move( RV64FTable ) ); } -}; // end class RV64F +}; // end class RV64F -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV64I.h b/include/insns/RV64I.h index 3ad11d712..0f12c0a71 100644 --- a/include/insns/RV64I.h +++ b/include/insns/RV64I.h @@ -15,146 +15,81 @@ #include -namespace SST::RevCPU{ - -class RV64I : public RevExt{ - - // Compressed instructions - static bool cldsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.ldsp rd, $imm = lw rd, x2, $imm - // Inst.rs1 = 2; //Removed - set in decode - //ZEXT(Inst.imm, ((Inst.imm&0b111111))*8, 32); - //Inst.imm = ((Inst.imm & 0b111111)*8); - Inst.imm = ((Inst.imm & 0b111111111)); //Bits placed correctly in decode, no need to scale - return ld(F, R, M, Inst); - } - - static bool csdsp(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.swsp rs2, $imm = sw rs2, x2, $imm - // Inst.rs1 = 2; //Removed - set in decode - //ZEXT(Inst.imm, ((Inst.imm&0b111111))*8, 32); - //Inst.imm = ((Inst.imm & 0b111111)*8); - Inst.imm = ((Inst.imm & 0b1111111111)); // bits placed correctly in decode, no need to scale - return sd(F, R, M, Inst); - } - - static bool cld(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.ld %rd, %rs1, $imm = ld %rd, %rs1, $imm - //Inst.rd = CRegIdx(Inst.rd); //Removed - scaled in decode - //Inst.rs1 = CRegIdx(Inst.rs1); //Removed - scaled in decode - //Inst.imm = ((Inst.imm&0b11111)*8); - Inst.imm = (Inst.imm&0b11111111); //8-bit immd, zero-extended, scaled at decode - return ld(F, R, M, Inst); - } - - static bool csd(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.sd rs2, rs1, $imm = sd rs2, $imm(rs1) - //Inst.rs2 = CRegIdx(Inst.rs2); //Removed - scaled in decode - //Inst.rs1 = CRegIdx(Inst.rs1); // Removed - scaled in decode - Inst.imm = (Inst.imm&0b11111111); //imm is 8-bits, zero extended, decoder pre-aligns bits, no scaling needed - return sd(F, R, M, Inst); - } - - static bool caddiw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.addiw %rd, $imm = addiw %rd, %rd, $imm - // Inst.rs1 = Inst.rd; //Removed - set in decode - // uint64_t tmp = Inst.imm & 0b111111; - // SEXT(Inst.imm, tmp, 6); - Inst.imm = Inst.ImmSignExt(6); - return addiw(F, R, M, Inst); - } - - static bool caddw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.addw %rd, %rs2 = addw %rd, %rd, %rs2 - //Inst.rd = CRegIdx(Inst.rd); //Removed - set in decode - //Inst.rs1 = Inst.rd; //Removed - set in decode - //Inst.rs2 = CRegIdx(Inst.rs2); //Removed - set in decode - return addw(F, R, M, Inst); - } - - static bool csubw(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& CInst) { - RevInst Inst = CInst; - - // c.subw %rd, %rs2 = subw %rd, %rd, %rs2 - //Inst.rd = CRegIdx(Inst.rd); //Removed - set in decode - //Inst.rs1 = Inst.rd; //Removed - set in decode - //Inst.rs2 = CRegIdx(Inst.rs2); //Removed - set in decode - return subw(F, R, M, Inst); - } +namespace SST::RevCPU { +class RV64I : public RevExt { // Standard instructions - static constexpr auto& ld = load; - static constexpr auto& lwu = load; - static constexpr auto& sd = store; + static constexpr auto& ld = load; + static constexpr auto& lwu = load; + static constexpr auto& sd = store; // 32-bit arithmetic operators - static constexpr auto& addw = oper; - static constexpr auto& subw = oper; - static constexpr auto& addiw = oper; + static constexpr auto& addw = oper; + static constexpr auto& subw = oper; + static constexpr auto& addiw = oper; // Shift operators - static constexpr auto& slliw = oper; - static constexpr auto& srliw = oper; - static constexpr auto& sraiw = oper; - static constexpr auto& sllw = oper; - static constexpr auto& srlw = oper; - static constexpr auto& sraw = oper; + static constexpr auto& slliw = oper; + static constexpr auto& srliw = oper; + static constexpr auto& sraiw = oper; + static constexpr auto& sllw = oper; + static constexpr auto& srlw = oper; + static constexpr auto& sraw = oper; + + // Compressed instructions + static constexpr auto& cldsp = ld; + static constexpr auto& csdsp = sd; + static constexpr auto& cld = ld; + static constexpr auto& csd = sd; + static constexpr auto& caddiw = addiw; + static constexpr auto& caddw = addw; + static constexpr auto& csubw = subw; // ---------------------------------------------------------------------- // // RISC-V RV64I Instructions // - // Format: - // - // // ---------------------------------------------------------------------- - std::vector RV64ITable = { - {RevInstEntryBuilder().SetMnemonic("lwu %rd, $imm(%rs1)" ).SetCost(1).SetOpcode( 0b0000011).SetFunct3(0b110).SetFunct2or7(0b0 ).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&lwu ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("ld %rd, $imm(%rs1)" ).SetCost(1).SetOpcode( 0b0000011).SetFunct3(0b011).SetFunct2or7(0b0 ).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&ld ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sd %rs2, $imm(%rs1)" ).SetCost(1).SetOpcode( 0b0100011).SetFunct3(0b011).SetFunct2or7(0b0 ).SetrdClass(RevRegClass::RegIMM).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeS).SetImplFunc(&sd ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("addiw %rd, %rs1, $imm").SetCost(1).SetOpcode( 0b0011011).SetFunct3(0b000).SetFunct2or7(0b0 ).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&addiw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("slliw %rd, %rs1, $imm").SetCost(1).SetOpcode( 0b0011011).SetFunct3(0b001).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&slliw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("srliw %rd, %rs1, $imm").SetCost(1).SetOpcode( 0b0011011).SetFunct3(0b101).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&srliw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sraiw %rd, %rs1, $imm").SetCost(1).SetOpcode( 0b0011011).SetFunct3(0b101).SetFunct2or7(0b0100000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegUNKNOWN).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FImm).SetFormat(RVTypeI).SetImplFunc(&sraiw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("addw %rd, %rs1, %rs2" ).SetCost(1).SetOpcode( 0b0111011).SetFunct3(0b000).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&addw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("subw %rd, %rs1, %rs2" ).SetCost(1).SetOpcode( 0b0111011).SetFunct3(0b000).SetFunct2or7(0b0100000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&subw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sllw %rd, %rs1, %rs2" ).SetCost(1).SetOpcode( 0b0111011).SetFunct3(0b001).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sllw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("srlw %rd, %rs1, %rs2" ).SetCost(1).SetOpcode( 0b0111011).SetFunct3(0b101).SetFunct2or7(0b0000000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&srlw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sraw %rd, %rs1, %rs2" ).SetCost(1).SetOpcode( 0b0111011).SetFunct3(0b101).SetFunct2or7(0b0100000).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR ).Setrs3Class(RevRegClass::RegUNKNOWN).Setimm(FUnk).SetFormat(RVTypeR).SetImplFunc(&sraw ).InstEntry}, + + struct Rev64InstDefaults : RevInstDefaults { + Rev64InstDefaults() { SetOpcode( 0b0111011 ); } + }; + + // clang-format off + std::vector RV64ITable = { + Rev64InstDefaults().SetMnemonic("lwu %rd, $imm(%rs1)" ).SetFunct3(0b110).SetImplFunc(lwu ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0000011).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev64InstDefaults().SetMnemonic("ld %rd, $imm(%rs1)" ).SetFunct3(0b011).SetImplFunc(ld ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0000011).Setrs2Class(RevRegClass::RegUNKNOWN), + Rev64InstDefaults().SetMnemonic("sd %rs2, $imm(%rs1)" ).SetFunct3(0b011).SetImplFunc(sd ) .SetFormat(RVTypeS).SetOpcode(0b0100011).SetrdClass (RevRegClass::RegIMM ), + Rev64InstDefaults().SetMnemonic("addiw %rd, %rs1, $imm" ).SetFunct3(0b000).SetImplFunc(addiw ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0011011).Setrs2Class(RevRegClass::RegUNKNOWN).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12(Inst) != 0; } ), + Rev64InstDefaults().SetMnemonic("sext.w %rd, %rs" ).SetFunct3(0b000).SetImplFunc(addiw ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0011011).Setrs2Class(RevRegClass::RegUNKNOWN).SetPredicate( []( uint32_t Inst ){ return DECODE_IMM12(Inst) == 0; } ), + Rev64InstDefaults().SetMnemonic("slliw %rd, %rs1, $imm" ).SetFunct3(0b001).SetImplFunc(slliw ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0011011).Setrs2Class(RevRegClass::RegUNKNOWN).SetPredicate( []( uint32_t Inst ){ return ( Inst & 0x2000000 ) == 0; } ), + Rev64InstDefaults().SetMnemonic("srliw %rd, %rs1, $imm" ).SetFunct3(0b101).SetImplFunc(srliw ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0011011).Setrs2Class(RevRegClass::RegUNKNOWN).SetPredicate( []( uint32_t Inst ){ return ( Inst & 0x2000000 ) == 0; } ), + Rev64InstDefaults().SetMnemonic("sraiw %rd, %rs1, $imm" ).SetFunct3(0b101).SetImplFunc(sraiw ).Setimm(RevImmFunc::FImm).SetFormat(RVTypeI).SetOpcode(0b0011011).Setrs2Class(RevRegClass::RegUNKNOWN).SetFunct2or7(0b0100000).SetPredicate( []( uint32_t Inst ){ return ( Inst & 0x2000000 ) == 0; } ), + Rev64InstDefaults().SetMnemonic("addw %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc(addw ), + Rev64InstDefaults().SetMnemonic("subw %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc(subw ).SetFunct2or7(0b0100000), + Rev64InstDefaults().SetMnemonic("sllw %rd, %rs1, %rs2" ).SetFunct3(0b001).SetImplFunc(sllw ), + Rev64InstDefaults().SetMnemonic("srlw %rd, %rs1, %rs2" ).SetFunct3(0b101).SetImplFunc(srlw ), + Rev64InstDefaults().SetMnemonic("sraw %rd, %rs1, %rs2" ).SetFunct3(0b101).SetImplFunc(sraw ).SetFunct2or7(0b0100000), }; std::vector RV64ICTable = { - {RevInstEntryBuilder().SetMnemonic("c.ldsp %rd, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b011).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&cldsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.sdsp %rs2, $imm").SetCost(1).SetOpcode(0b10).SetFunct3(0b111).Setrs2Class(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCSS).SetImplFunc(&csdsp).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.ld %rd, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b011).SetrdClass(RevRegClass::RegGPR).Setrs1Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCL).SetImplFunc(&cld).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.sd %rs2, %rs1, $imm").SetCost(1).SetOpcode(0b00).SetFunct3(0b111).Setrs1Class(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCS).SetImplFunc(&csd).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.addiw %rd, $imm").SetCost(1).SetOpcode(0b01).SetFunct3(0b001).Setrs1Class(RevRegClass::RegGPR).SetrdClass(RevRegClass::RegGPR).Setimm(FVal).SetFormat(RVCTypeCI).SetImplFunc(&caddiw).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.addw %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100111).SetFunct2(0b01).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&caddw).SetCompressed(true).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("c.subw %rd, %rs1").SetCost(1).SetOpcode(0b01).SetFunct6(0b100111).SetFunct2(0b00).SetrdClass(RevRegClass::RegGPR).Setrs2Class(RevRegClass::RegGPR).SetFormat(RVCTypeCA).SetImplFunc(&csubw).SetCompressed(true).InstEntry}, + RevCInstDefaults().SetMnemonic("c.ldsp %rd, $imm " ).SetFunct3(0b011).SetImplFunc(cldsp ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b10).SetPredicate( []( uint32_t Inst ) { return DECODE_RD(Inst) != 0; } ), + RevCInstDefaults().SetMnemonic("c.sdsp %rs2, $imm" ).SetFunct3(0b111).SetImplFunc(csdsp ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCSS).SetOpcode(0b10), + RevCInstDefaults().SetMnemonic("c.ld %rd, %rs1, $imm" ).SetFunct3(0b011).SetImplFunc(cld ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCL ).SetOpcode(0b00), + RevCInstDefaults().SetMnemonic("c.sd %rs2, %rs1, $imm" ).SetFunct3(0b111).SetImplFunc(csd ).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCS ).SetOpcode(0b00), + RevCInstDefaults().SetMnemonic("c.addiw %rd, $imm" ).SetFunct3(0b001).SetImplFunc(caddiw).Setimm(RevImmFunc::FVal).SetFormat(RVCTypeCI ).SetOpcode(0b01).SetPredicate( []( uint32_t Inst ) { return DECODE_RD(Inst) != 0; } ), + RevCInstDefaults().SetMnemonic("c.addw %rd, %rs1" ).SetFunct2( 0b01).SetImplFunc(caddw ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct6(0b100111), + RevCInstDefaults().SetMnemonic("c.subw %rd, %rs1" ).SetFunct2( 0b00).SetImplFunc(csubw ) .SetFormat(RVCTypeCA ).SetOpcode(0b01).SetFunct6(0b100111), }; + // clang-format on public: /// RV64I: standard constructor - RV64I( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64I", Feature, RevMem, Output ) { - SetTable(std::move(RV64ITable)); - SetCTable(std::move(RV64ICTable)); + RV64I( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV64I", Feature, RevMem, Output ) { + SetTable( std::move( RV64ITable ) ); + SetCTable( std::move( RV64ICTable ) ); } -}; // end class RV64I -} // namespace SST::RevCPU +}; // end class RV64I +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV64M.h b/include/insns/RV64M.h index 06cc2fac6..c22f368a4 100644 --- a/include/insns/RV64M.h +++ b/include/insns/RV64M.h @@ -11,57 +11,61 @@ #ifndef _SST_REVCPU_RV64M_H_ #define _SST_REVCPU_RV64M_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RV64M : public RevExt{ +class RV64M : public RevExt { // 32-bit Multiplication static constexpr auto& mulw = oper; // 32-bit Division - static constexpr auto& divw = divrem; + static constexpr auto& divw = divrem; static constexpr auto& divuw = divrem; // 32-bit Remainder - static constexpr auto& remw = divrem; + static constexpr auto& remw = divrem; static constexpr auto& remuw = divrem; // ---------------------------------------------------------------------- // // RISC-V RV64M Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev64MInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b0111011; - static constexpr uint8_t funct2or7 = 0b0000001; + Rev64MInstDefaults() { + SetOpcode( 0b0111011 ); + SetFunct2or7( 0b0000001 ); + } + }; + + // clang-format off + std::vector RV64MTable = { + Rev64MInstDefaults().SetMnemonic("mulw %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc(mulw) , }; - std::vector RV64MTable = { - {RevInstEntryBuilder().SetMnemonic("mulw %rd, %rs1, %rs2" ).SetFunct3(0b000).SetImplFunc(&mulw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("divw %rd, %rs1, %rs2" ).SetFunct3(0b100).SetImplFunc(&divw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("divuw %rd, %rs1, %rs2").SetFunct3(0b101).SetImplFunc(&divuw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("remw %rd, %rs1, %rs2" ).SetFunct3(0b110).SetImplFunc(&remw ).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("remuw %rd, %rs1, %rs2").SetFunct3(0b111).SetImplFunc(&remuw ).InstEntry}, + std::vector RV64DivTable = { + Rev64MInstDefaults().SetMnemonic("divw %rd, %rs1, %rs2" ).SetFunct3(0b100).SetImplFunc(divw) , + Rev64MInstDefaults().SetMnemonic("divuw %rd, %rs1, %rs2").SetFunct3(0b101).SetImplFunc(divuw), + Rev64MInstDefaults().SetMnemonic("remw %rd, %rs1, %rs2" ).SetFunct3(0b110).SetImplFunc(remw) , + Rev64MInstDefaults().SetMnemonic("remuw %rd, %rs1, %rs2").SetFunct3(0b111).SetImplFunc(remuw), }; + // clang-format on public: /// RV64M: standard constructor - RV64M( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64M", Feature, RevMem, Output) { - SetTable(std::move(RV64MTable)); + RV64M( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV64M", Feature, RevMem, Output ) { + if( Feature->IsModeEnabled( RV_M ) ) { + RV64MTable.insert( RV64MTable.end(), RV64DivTable.begin(), RV64DivTable.end() ); + } + SetTable( std::move( RV64MTable ) ); } -}; // end class RV32I +}; // end class RV32I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/RV64P.h b/include/insns/RV64P.h index dbd17151e..6a92abcd2 100644 --- a/include/insns/RV64P.h +++ b/include/insns/RV64P.h @@ -15,22 +15,25 @@ #include -namespace SST::RevCPU{ +namespace SST::RevCPU { -class RV64P : public RevExt{ +class RV64P : public RevExt { - static bool future(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetX(Inst.rd, !!M->SetFuture(R->GetX(Inst.rs1) + Inst.ImmSignExt(12))); + static bool future( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, !!M->SetFuture( R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ) ) ); + // R->AdvancePC(Inst); return true; } - static bool rfuture(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetX(Inst.rd, !!M->RevokeFuture(R->GetX(Inst.rs1) + Inst.ImmSignExt(12))); + static bool rfuture( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, !!M->RevokeFuture( R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ) ) ); + // R->AdvancePC(Inst); return true; } - static bool sfuture(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - R->SetX(Inst.rd, !!M->StatusFuture(R->GetX(Inst.rs1) + Inst.ImmSignExt(12))); + static bool sfuture( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetX( Inst.rd, !!M->StatusFuture( R->GetX( Inst.rs1 ) + uint64_t( Inst.ImmSignExt( 12 ) ) ) ); + // R->AdvancePC(Inst); return true; } @@ -38,33 +41,31 @@ class RV64P : public RevExt{ // // RISC-V RV64P Instructions // - // Format: - // - // // ---------------------------------------------------------------------- struct Rev64PInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b1110111; - static constexpr RevRegClass rs2Class = RevRegClass::RegUNKNOWN; - static constexpr RevImmFunc imm = FImm; - static constexpr RevInstF format = RVTypeI; + Rev64PInstDefaults() { + SetOpcode( 0b1110111 ); + Setrs2Class( RevRegClass::RegUNKNOWN ); + Setimm( RevImmFunc::FImm ); + SetFormat( RVTypeI ); + } }; + // clang-format off std::vector RV64PTable = { - {RevInstEntryBuilder().SetMnemonic("future %rd, $imm(%rs1)" ).SetFunct3(0b111).SetImplFunc(&future).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("rfuture %rd, $imm(%rs1)").SetFunct3(0b101).SetImplFunc(&rfuture).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("sfuture %rd, $imm(%rs1)").SetFunct3(0b100).SetImplFunc(&sfuture).InstEntry}, + Rev64PInstDefaults().SetMnemonic( "future %rd, $imm(%rs1)").SetFunct3(0b111).SetImplFunc( future), + Rev64PInstDefaults().SetMnemonic("rfuture %rd, $imm(%rs1)").SetFunct3(0b101).SetImplFunc(rfuture), + Rev64PInstDefaults().SetMnemonic("sfuture %rd, $imm(%rs1)").SetFunct3(0b100).SetImplFunc(sfuture), }; + // clang-format on public: /// RV64P: standard constructor - RV64P( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "RV64P", Feature, RevMem, Output ) { - SetTable(std::move(RV64PTable)); + RV64P( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "RV64P", Feature, RevMem, Output ) { + SetTable( std::move( RV64PTable ) ); } -}; // end class RV64I +}; // end class RV64I -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/Zaamo.h b/include/insns/Zaamo.h new file mode 100644 index 000000000..b9e3791d5 --- /dev/null +++ b/include/insns/Zaamo.h @@ -0,0 +1,130 @@ +// +// _Zaamo_h_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVCPU_Zaamo_H_ +#define _SST_REVCPU_Zaamo_H_ + +#include "../RevExt.h" +#include "../RevInstHelpers.h" + +namespace SST::RevCPU { + +class Zaamo : public RevExt { + template + static bool amooper( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + static_assert( std::is_unsigned_v, "XLEN must be unsigned integral type" ); + + RevFlag flags{ F_AMO }; + + if( Inst.aq ) { + RevFlagSet( flags, RevFlag::F_AQ ); + } + if( Inst.rl ) { + RevFlagSet( flags, RevFlag::F_RL ); + } + + if( !F->IsRV64() ) { + MemReq req( + R->RV32[Inst.rs1], Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete() + ); + R->LSQueue->insert( req.LSQHashPair() ); + M->AMOVal( F->GetHartToExecID(), R->RV32[Inst.rs1], &R->RV32[Inst.rs2], &R->RV32[Inst.rd], req, flags ); + } else { + flags = RevFlag{ uint32_t( flags ) | uint32_t( RevFlag::F_SEXT64 ) }; + MemReq req( + R->RV64[Inst.rs1], Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete() + ); + R->LSQueue->insert( req.LSQHashPair() ); + M->AMOVal( + F->GetHartToExecID(), + R->RV64[Inst.rs1], + reinterpret_cast*>( &R->RV64[Inst.rs2] ), + reinterpret_cast*>( &R->RV64[Inst.rd] ), + req, + flags + ); + } + // update the cost + R->cost += M->RandCost( F->GetMinCost(), F->GetMaxCost() ); + R->AdvancePC( Inst ); + return true; + } + + static constexpr auto& amoaddw = amooper; + static constexpr auto& amoandw = amooper; + static constexpr auto& amomaxuw = amooper; + static constexpr auto& amomaxw = amooper; + static constexpr auto& amominuw = amooper; + static constexpr auto& amominw = amooper; + static constexpr auto& amoorw = amooper; + static constexpr auto& amoswapw = amooper; + static constexpr auto& amoxorw = amooper; + + static constexpr auto& amoaddd = amooper; + static constexpr auto& amoandd = amooper; + static constexpr auto& amomaxd = amooper; + static constexpr auto& amomaxud = amooper; + static constexpr auto& amomind = amooper; + static constexpr auto& amominud = amooper; + static constexpr auto& amoord = amooper; + static constexpr auto& amoswapd = amooper; + static constexpr auto& amoxord = amooper; + + // ---------------------------------------------------------------------- + // + // RISC-V Zaamo Instructions + // + // ---------------------------------------------------------------------- + struct ZaamoInstDefaults : RevInstDefaults { + ZaamoInstDefaults() { SetOpcode( 0b0101111 ); } + }; + + // clang-format off + std::vector ZaamoTable = { + ZaamoInstDefaults().SetMnemonic( "amoswap.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0000001 ).SetImplFunc( amoswapw ), + ZaamoInstDefaults().SetMnemonic( "amoadd.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0000000 ).SetImplFunc( amoaddw ), + ZaamoInstDefaults().SetMnemonic( "amoxor.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0000100 ).SetImplFunc( amoxorw ), + ZaamoInstDefaults().SetMnemonic( "amoand.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0001100 ).SetImplFunc( amoandw ), + ZaamoInstDefaults().SetMnemonic( "amoor.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0001000 ).SetImplFunc( amoorw ), + ZaamoInstDefaults().SetMnemonic( "amomin.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0010000 ).SetImplFunc( amominw ), + ZaamoInstDefaults().SetMnemonic( "amomax.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0010100 ).SetImplFunc( amomaxw ), + ZaamoInstDefaults().SetMnemonic( "amominu.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0011000 ).SetImplFunc( amominuw ), + ZaamoInstDefaults().SetMnemonic( "amomaxu.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0011100 ).SetImplFunc( amomaxuw ), + }; + + static std::vector RV64Table() { return { + ZaamoInstDefaults().SetMnemonic( "amoswap.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0000001 ).SetImplFunc( amoswapd ), + ZaamoInstDefaults().SetMnemonic( "amoadd.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0000000 ).SetImplFunc( amoaddd ), + ZaamoInstDefaults().SetMnemonic( "amoxor.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0000100 ).SetImplFunc( amoxord ), + ZaamoInstDefaults().SetMnemonic( "amoand.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0001100 ).SetImplFunc( amoandd ), + ZaamoInstDefaults().SetMnemonic( "amoor.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0001000 ).SetImplFunc( amoord ), + ZaamoInstDefaults().SetMnemonic( "amomin.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0010000 ).SetImplFunc( amomind ), + ZaamoInstDefaults().SetMnemonic( "amomax.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0010100 ).SetImplFunc( amomaxd ), + ZaamoInstDefaults().SetMnemonic( "amominu.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0011000 ).SetImplFunc( amominud ), + ZaamoInstDefaults().SetMnemonic( "amomaxu.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0011100 ).SetImplFunc( amomaxud ), + }; } + + // clang-format on + +public: + /// Zaamo: standard constructor + Zaamo( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zaamo", Feature, RevMem, Output ) { + if( Feature->IsRV64() ) { + auto Table{ RV64Table() }; + ZaamoTable.insert( ZaamoTable.end(), std::move_iterator( Table.begin() ), std::move_iterator( Table.end() ) ); + } + SetTable( std::move( ZaamoTable ) ); + } + +}; // end class Zaamo + +} // namespace SST::RevCPU + +#endif diff --git a/include/insns/Zalrsc.h b/include/insns/Zalrsc.h new file mode 100644 index 000000000..a91162176 --- /dev/null +++ b/include/insns/Zalrsc.h @@ -0,0 +1,120 @@ +// +// _Zalrsc_h_ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVCPU_ZALRSC_H_ +#define _SST_REVCPU_ZALRSC_H_ + +#include "../RevExt.h" +#include "../RevInstHelpers.h" + +namespace SST::RevCPU { + +class Zalrsc : public RevExt { + + // Load Reserved instruction + template + static bool lr( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + static_assert( std::is_unsigned_v, "TYPE must be unsigned integral type" ); + auto addr = R->GetX( Inst.rs1 ); + + // Create the load request + MemReq req{ addr, Inst.rd, RevRegClass::RegGPR, F->GetHartToExecID(), MemOp::MemOpAMO, true, R->GetMarkLoadComplete() }; + R->LSQueue->insert( req.LSQHashPair() ); + + // Flags for LR memory load + RevFlag flags = RevFlag::F_NONE; + if( sizeof( TYPE ) < sizeof( int64_t ) && F->IsRV64() ) + RevFlagSet( flags, RevFlag::F_SEXT64 ); + if( Inst.aq ) + RevFlagSet( flags, RevFlag::F_AQ ); + if( Inst.rl ) + RevFlagSet( flags, RevFlag::F_RL ); + + // Where the data will eventually end up + void* target; + if( sizeof( TYPE ) >= sizeof( int64_t ) || F->IsRV64() ) { + target = &R->RV64[Inst.rd]; + } else { + target = &R->RV32[Inst.rd]; + } + + // Create a reservation and load the data + M->LR( F->GetHartToExecID(), addr, sizeof( TYPE ), target, req, flags ); + R->cost += M->RandCost( F->GetMinCost(), F->GetMaxCost() ); + R->AdvancePC( Inst ); + return true; + } + + // Store Conditional instruction + template + static bool sc( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + static_assert( std::is_unsigned_v, "TYPE must be unsigned integral type" ); + auto addr = R->GetX( Inst.rs1 ); + auto val = R->GetX( Inst.rs2 ); + + // Flags for SC Store Conditional + RevFlag flags = RevFlag::F_NONE; + if( Inst.aq ) + RevFlagSet( flags, RevFlag::F_AQ ); + if( Inst.rl ) + RevFlagSet( flags, RevFlag::F_RL ); + + // Conditionally store the data, unconditionally removing any reservation + bool sc = M->SC( F->GetHartToExecID(), addr, sizeof( TYPE ), &val, flags ); + + // If the SC succeeded, store 0 in the destination register; otherwise store 1 + R->SetX( Inst.rd, !sc ); + R->AdvancePC( Inst ); + return true; + } + + static constexpr auto& lrw = lr; + static constexpr auto& scw = sc; + static constexpr auto& lrd = lr; + static constexpr auto& scd = sc; + + // ---------------------------------------------------------------------- + // + // RISC-V Zalrsc Instructions + // + // ---------------------------------------------------------------------- + struct ZalrscInstDefaults : RevInstDefaults { + ZalrscInstDefaults() { SetOpcode( 0b0101111 ); } + }; + + // clang-format off + std::vector ZalrscTable = { + ZalrscInstDefaults().SetMnemonic( "lr.w %rd, (%rs1)" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0000010 ).SetImplFunc( lrw ).Setrs2Class( RevRegClass::RegUNKNOWN ), + ZalrscInstDefaults().SetMnemonic( "sc.w %rd, %rs1, %rs2" ).SetFunct3( 0b010 ).SetFunct2or7( 0b0000011 ).SetImplFunc( scw ), + }; + + std::vector RV64ZalrscTable() { return { + ZalrscInstDefaults().SetMnemonic( "lr.d %rd, (%rs1)" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0000010 ).SetImplFunc( lrd ).Setrs2Class( RevRegClass::RegUNKNOWN ), + ZalrscInstDefaults().SetMnemonic( "sc.d %rd, %rs1, %rs2" ).SetFunct3( 0b011 ).SetFunct2or7( 0b0000011 ).SetImplFunc( scd ), + }; + } + + // clang-format on + +public: + /// Zalrsc: standard constructor + Zalrsc( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zalrsc", Feature, RevMem, Output ) { + if( Feature->IsRV64() ) { + auto Table{ RV64ZalrscTable() }; + ZalrscTable.insert( ZalrscTable.end(), std::move_iterator( Table.begin() ), std::move_iterator( Table.end() ) ); + } + SetTable( std::move( ZalrscTable ) ); + } + +}; // end class Zalrsc + +} // namespace SST::RevCPU + +#endif diff --git a/include/insns/Zfa.h b/include/insns/Zfa.h new file mode 100644 index 000000000..5731b110c --- /dev/null +++ b/include/insns/Zfa.h @@ -0,0 +1,333 @@ +// +// _Zfa_h_ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVCPU_ZFA_H_ +#define _SST_REVCPU_ZFA_H_ + +#include "../RevExt.h" +#include "../RevInstHelpers.h" + +namespace SST::RevCPU { + +class Zfa : public RevExt { + + // Round to integer without inexact exceptions + template + static bool fround( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, std::nearbyint( R->GetFP( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); + return true; + } + + // Round to integer with inexact exceptions + template + static bool froundnx( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + R->SetFP( Inst.rd, std::rint( R->GetFP( Inst.rs1 ) ) ); + R->AdvancePC( Inst ); + return true; + } + + /// Floating-point is less functor + /// If any arguments are NaN, no exceptions are raised + template + struct isLess { + template + auto operator()( T x, T y ) const { + return std::isless( x, y ); + } + }; + + /// Floating-point is less or equal functor + /// If any arguments are NaN, no exceptions are raised + template + struct isLessEqual { + template + auto operator()( T x, T y ) const { + return std::islessequal( x, y ); + } + }; + + /// Floating-point minimum/maximum + /// If either argument is NaN, the result is NaN + template class MINMAX> + static bool fminmaxm( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + T x = R->GetFP( Inst.rs1 ); + T y = R->GetFP( Inst.rs2 ); + T res = std::isunordered( x, y ) ? std::numeric_limits::quiet_NaN() : MINMAX()( x, y ); + R->SetFP( Inst.rd, res ); + R->AdvancePC( Inst ); + return true; + } + + // Move the high 32 bits of floating-point double to a XLEN==32 register + static bool fmvhxd( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + double fp = R->GetFP( Inst.rs1 ); + uint64_t ifp; + memcpy( &ifp, &fp, sizeof( ifp ) ); + static_assert( sizeof( fp ) == sizeof( ifp ) ); + R->SetX( Inst.rd, static_cast( ifp >> 32 ) ); + R->AdvancePC( Inst ); + return true; + } + + // Move a pair of XLEN==32 registers to a floating-point double + static bool fmvpdx( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + uint64_t ifp = R->GetX( Inst.rs1 ) | R->GetX( Inst.rs2 ) << 32; + double fp; + memcpy( &fp, &ifp, sizeof( fp ) ); + static_assert( sizeof( fp ) == sizeof( ifp ) ); + R->SetFP( Inst.rd, fp ); + R->AdvancePC( Inst ); + return true; + } + + // Convert double precision floating point to 32-bit signed integer modulo 2^32 + // Always truncates (rounds toward 0) regardless of rounding mode + // Raises the same exceptions as fcvt.w.d but the result is always modulo 2^32 + static bool fcvtmodwd( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + + double fp = R->GetFP( Inst.rs1 ); + uint64_t ifp; + static_assert( sizeof( fp ) == sizeof( ifp ) ); + memcpy( &ifp, &fp, sizeof( ifp ) ); + + // clang-format off + uint32_t exp{ static_cast( ifp >> 52 & 0x7ff ) }; + uint64_t sig{ ( ifp & ~uint64_t{ 0 } >> 12 ) | uint64_t{ 1 } << 52 }; + bool nv{ exp == 0x7ff }; + bool nx{ }; + uint64_t res{ !nv && exp > 1011 && exp < 1139 ? + exp < 1075 ? + nx = sig << ( exp - 1011 ), + sig >> ( 1075 - exp ) + : + sig << ( exp - 1075 ) + : + 0 }; + // clang-format on + + if( nv || exp > 1054 || res > ( ifp >> 63 ) + 0x7fffffff ) { + std::feraiseexcept( FE_INVALID ); + } else if( nx ) { + std::feraiseexcept( FE_INEXACT ); + } + + R->SetX( Inst.rd, SignExt( res, 32 ) ); + R->AdvancePC( Inst ); + return true; + } + + static constexpr auto& fminms = fminmaxm; + static constexpr auto& fminmd = fminmaxm; + + static constexpr auto& fmaxms = fminmaxm; + static constexpr auto& fmaxmd = fminmaxm; + + static constexpr auto& froundnxs = froundnx; + static constexpr auto& froundnxd = froundnx; + + static constexpr auto& frounds = fround; + static constexpr auto& froundd = fround; + + static constexpr auto& fleqs = fcondop; + static constexpr auto& fleqd = fcondop; + + static constexpr auto& fltqs = fcondop; + static constexpr auto& fltqd = fcondop; + + // ---------------------------------------------------------------------- + // + // RISC-V Zfa Instructions + // + // ---------------------------------------------------------------------- + struct RevZfaInstDefaults : RevInstDefaults { + RevZfaInstDefaults() { + SetOpcode( 0b1010011 ); + SetFunct3( 0b000 ); + SetFunct2or7( 0b1111000 ); + Setrs2fcvtOp( 0b00001 ); + SetrdClass( RevRegClass::RegFLOAT ); + Setrs1Class( RevRegClass::RegIMM ); + Setrs2Class( RevRegClass::RegIMM ); + } + }; + + // Macro to generate FLI entries +#define FLI( index, mnemonic, value ) \ + SetMnemonic( #mnemonic " %rd, " #value ) \ + .SetPredicate( []( uint32_t Inst ) { return DECODE_RS1( Inst ) == ( index ); } ) \ + .SetImplFunc( []( auto*, auto* R, auto*, auto& Inst ) { \ + R->SetFP( Inst.rd, value ); \ + R->AdvancePC( Inst ); \ + return true; \ + } ) + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Single-Precision Instructions + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#undef min +#undef inf +#undef nan +#define min std::numeric_limits::min() +#define inf std::numeric_limits::infinity() +#define nan std::numeric_limits::quiet_NaN() + + // clang-format off + std::vector ZfaTable = { + // Load Immediates + RevZfaInstDefaults().FLI( 0, fli.s, -0x1p+0f ), + RevZfaInstDefaults().FLI( 1, fli.s, min ), + RevZfaInstDefaults().FLI( 2, fli.s, 0x1p-16f ), + RevZfaInstDefaults().FLI( 3, fli.s, 0x1p-15f ), + RevZfaInstDefaults().FLI( 4, fli.s, 0x1p-8f ), + RevZfaInstDefaults().FLI( 5, fli.s, 0x1p-7f ), + RevZfaInstDefaults().FLI( 6, fli.s, 0x1p-4f ), + RevZfaInstDefaults().FLI( 7, fli.s, 0x1p-3f ), + RevZfaInstDefaults().FLI( 8, fli.s, 0x1p-2f ), + RevZfaInstDefaults().FLI( 9, fli.s, 0x1.4p-2f ), + RevZfaInstDefaults().FLI( 10, fli.s, 0x1.8p-2f ), + RevZfaInstDefaults().FLI( 11, fli.s, 0x1.cp-2f ), + RevZfaInstDefaults().FLI( 12, fli.s, 0x1p-1f ), + RevZfaInstDefaults().FLI( 13, fli.s, 0x1.4p-1f ), + RevZfaInstDefaults().FLI( 14, fli.s, 0x1.8p-1f ), + RevZfaInstDefaults().FLI( 15, fli.s, 0x1.cp-1f ), + RevZfaInstDefaults().FLI( 16, fli.s, 0x1p+0f ), + RevZfaInstDefaults().FLI( 17, fli.s, 0x1.4p+0f ), + RevZfaInstDefaults().FLI( 18, fli.s, 0x1.8p+0f ), + RevZfaInstDefaults().FLI( 19, fli.s, 0x1.cp+0f ), + RevZfaInstDefaults().FLI( 20, fli.s, 0x1p+1f ), + RevZfaInstDefaults().FLI( 21, fli.s, 0x1.4p+1f ), + RevZfaInstDefaults().FLI( 22, fli.s, 0x1.8p+1f ), + RevZfaInstDefaults().FLI( 23, fli.s, 0x1p+2f ), + RevZfaInstDefaults().FLI( 24, fli.s, 0x1p+3f ), + RevZfaInstDefaults().FLI( 25, fli.s, 0x1p+4f ), + RevZfaInstDefaults().FLI( 26, fli.s, 0x1p+7f ), + RevZfaInstDefaults().FLI( 27, fli.s, 0x1p+8f ), + RevZfaInstDefaults().FLI( 28, fli.s, 0x1p+15f ), + RevZfaInstDefaults().FLI( 29, fli.s, 0x1p+16f ), + RevZfaInstDefaults().FLI( 30, fli.s, inf ), + RevZfaInstDefaults().FLI( 31, fli.s, nan ), + + // FP Minimum and Maximum with NaN returned if any argument is NaN + RevZfaInstDefaults().SetMnemonic( "fminm.s %rd, %rs1, %rs2" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ).SetRaiseFPE( true ).SetFunct3( 0b010 ).SetFunct2or7( 0b0010100 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fminms ), + RevZfaInstDefaults().SetMnemonic( "fmaxm.s %rd, %rs1, %rs2" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ).SetRaiseFPE( true ).SetFunct3( 0b011 ).SetFunct2or7( 0b0010100 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fmaxms ), + + // FP Round To Integer with and without inexact exception + RevZfaInstDefaults().SetMnemonic( "fround.s %rd, %rs1" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegUNKNOWN ).SetRaiseFPE( true ).SetFunct2or7( 0b0100000 ).Setrs2fcvtOp( 0b00100 ).SetImplFunc( frounds ), + RevZfaInstDefaults().SetMnemonic( "froundnx.s %rd, %rs1" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegUNKNOWN ).SetRaiseFPE( true ).SetFunct2or7( 0b0100000 ).Setrs2fcvtOp( 0b00101 ).SetImplFunc( froundnxs ), + + // Quiet FP ordered comparison without raising exceptions on NaN inputs + RevZfaInstDefaults().SetMnemonic( "fltq.s %rd, %rs1, %rs2" ).SetFunct3( 0b101 ).SetFunct2or7( 0b1010000 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fltqs ).SetrdClass( RevRegClass::RegGPR ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ), + RevZfaInstDefaults().SetMnemonic( "fleq.s %rd, %rs1, %rs2" ).SetFunct3( 0b100 ).SetFunct2or7( 0b1010000 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fleqs ).SetrdClass( RevRegClass::RegGPR ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ), + + }; + + // clang-format on + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Double-Precision Instructions + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + struct RevZfaDInstDefaults : RevZfaInstDefaults { + RevZfaDInstDefaults() { SetFunct2or7( 0b1111001 ); } + }; + +#undef min +#undef inf +#undef nan +#define min std::numeric_limits::min() +#define inf std::numeric_limits::infinity() +#define nan std::numeric_limits::quiet_NaN() + + // clang-format off + static std::vector ZfaTableD() { return { + // Load Immediates + RevZfaDInstDefaults().FLI( 0, fli.d, -0x1p+0 ), + RevZfaDInstDefaults().FLI( 1, fli.d, min ), + RevZfaDInstDefaults().FLI( 2, fli.d, 0x1p-16 ), + RevZfaDInstDefaults().FLI( 3, fli.d, 0x1p-15 ), + RevZfaDInstDefaults().FLI( 4, fli.d, 0x1p-8 ), + RevZfaDInstDefaults().FLI( 5, fli.d, 0x1p-7 ), + RevZfaDInstDefaults().FLI( 6, fli.d, 0x1p-4 ), + RevZfaDInstDefaults().FLI( 7, fli.d, 0x1p-3 ), + RevZfaDInstDefaults().FLI( 8, fli.d, 0x1p-2 ), + RevZfaDInstDefaults().FLI( 9, fli.d, 0x1.4p-2 ), + RevZfaDInstDefaults().FLI( 10, fli.d, 0x1.8p-2 ), + RevZfaDInstDefaults().FLI( 11, fli.d, 0x1.cp-2 ), + RevZfaDInstDefaults().FLI( 12, fli.d, 0x1p-1 ), + RevZfaDInstDefaults().FLI( 13, fli.d, 0x1.4p-1 ), + RevZfaDInstDefaults().FLI( 14, fli.d, 0x1.8p-1 ), + RevZfaDInstDefaults().FLI( 15, fli.d, 0x1.cp-1 ), + RevZfaDInstDefaults().FLI( 16, fli.d, 0x1p+0 ), + RevZfaDInstDefaults().FLI( 17, fli.d, 0x1.4p+0 ), + RevZfaDInstDefaults().FLI( 18, fli.d, 0x1.8p+0 ), + RevZfaDInstDefaults().FLI( 19, fli.d, 0x1.cp+0 ), + RevZfaDInstDefaults().FLI( 20, fli.d, 0x1p+1 ), + RevZfaDInstDefaults().FLI( 21, fli.d, 0x1.4p+1 ), + RevZfaDInstDefaults().FLI( 22, fli.d, 0x1.8p+1 ), + RevZfaDInstDefaults().FLI( 23, fli.d, 0x1p+2 ), + RevZfaDInstDefaults().FLI( 24, fli.d, 0x1p+3 ), + RevZfaDInstDefaults().FLI( 25, fli.d, 0x1p+4 ), + RevZfaDInstDefaults().FLI( 26, fli.d, 0x1p+7 ), + RevZfaDInstDefaults().FLI( 27, fli.d, 0x1p+8 ), + RevZfaDInstDefaults().FLI( 28, fli.d, 0x1p+15 ), + RevZfaDInstDefaults().FLI( 29, fli.d, 0x1p+16 ), + RevZfaDInstDefaults().FLI( 30, fli.d, inf ), + RevZfaDInstDefaults().FLI( 31, fli.d, nan ), + + // FP Minimum and Maximum with NaN returned if any argument is NaN + RevZfaDInstDefaults().SetMnemonic( "fminm.d %rd, %rs1, %rs2" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ).SetRaiseFPE( true ).SetFunct3( 0b010 ).SetFunct2or7( 0b0010101 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fminmd ), + RevZfaDInstDefaults().SetMnemonic( "fmaxm.d %rd, %rs1, %rs2" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ).SetRaiseFPE( true ).SetFunct3( 0b011 ).SetFunct2or7( 0b0010101 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fmaxmd ), + + // FP Round To Integer with and without inexact exception + RevZfaDInstDefaults().SetMnemonic( "fround.d %rd, %rs1" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegUNKNOWN ).SetRaiseFPE( true ).SetFunct2or7( 0b0100001 ).Setrs2fcvtOp( 0b00100 ).SetImplFunc( froundd ), + RevZfaDInstDefaults().SetMnemonic( "froundnx.d %rd, %rs1" ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegUNKNOWN ).SetRaiseFPE( true ).SetFunct2or7( 0b0100001 ).Setrs2fcvtOp( 0b00101 ).SetImplFunc( froundnxd ), + + // Quiet FP ordered comparison without raising exceptions on NaN inputs + RevZfaDInstDefaults().SetMnemonic( "fltq.d %rd, %rs1, %rs2" ).SetFunct3( 0b101 ).SetFunct2or7( 0b1010001 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fltqd ).SetrdClass( RevRegClass::RegGPR ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ), + RevZfaDInstDefaults().SetMnemonic( "fleq.d %rd, %rs1, %rs2" ).SetFunct3( 0b100 ).SetFunct2or7( 0b1010001 ).Setrs2fcvtOp( 0b00000 ).SetImplFunc( fleqd ).SetrdClass( RevRegClass::RegGPR ).Setrs1Class( RevRegClass::RegFLOAT ).Setrs2Class( RevRegClass::RegFLOAT ), + + // Modular conversion to integer + RevZfaDInstDefaults().SetMnemonic( "fcvtmod.w.d %rd, %rs1, rtz" ).SetFunct2or7( 0b1100001 ).SetImplFunc( fcvtmodwd ).SetrdClass( RevRegClass::RegGPR ).Setrs2fcvtOp( 0b01000 ).SetFunct3( 0b001 ).Setrs1Class( RevRegClass::RegFLOAT ).SetRaiseFPE( true ), + + }; } + + // clang-format on + +#undef min +#undef inf +#undef nan + +public: + /// Zfa: standard constructor + Zfa( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zfa", Feature, RevMem, Output ) { + if( Feature->HasD() ) { + if( !Feature->IsRV64() ) { + // clang-format off + ZfaTable.push_back( + RevZfaInstDefaults().SetMnemonic( "fmvh.x.d %rd, %rs1" ).SetFunct2or7( 0b1110001 ).SetImplFunc( fmvhxd ).SetrdClass( RevRegClass::RegGPR ).Setrs1Class( RevRegClass::RegFLOAT ) + ); + ZfaTable.push_back( + RevZfaInstDefaults().SetMnemonic( "fmvp.d.x %rd, %rs1, %rs2" ).SetFunct2or7( 0b1011001 ).SetImplFunc( fmvpdx ).Setrs1Class( RevRegClass::RegGPR ).Setrs2Class( RevRegClass::RegGPR ) + ); + // clang-format on + } + auto TableD{ ZfaTableD() }; + ZfaTable.insert( ZfaTable.end(), std::move_iterator( TableD.begin() ), std::move_iterator( TableD.end() ) ); + } + SetTable( std::move( ZfaTable ) ); + } + +}; // end class Zfa + +} // namespace SST::RevCPU + +#endif diff --git a/include/insns/Zicbom.h b/include/insns/Zicbom.h index ddab571a6..3a4b07033 100644 --- a/include/insns/Zicbom.h +++ b/include/insns/Zicbom.h @@ -11,63 +11,60 @@ #ifndef _SST_REVCPU_ZICBOM_H_ #define _SST_REVCPU_ZICBOM_H_ -#include "../RevInstHelpers.h" #include "../RevExt.h" +#include "../RevInstHelpers.h" -#include #include +#include -namespace SST::RevCPU{ -#define CBO_INVAL_IMM 0b000000000000 -#define CBO_FLUSH_IMM 0b000000000001 -#define CBO_CLEAN_IMM 0b000000000010 -class Zicbom : public RevExt{ +namespace SST::RevCPU { - static bool cmo(RevFeature *F, RevRegFile *R, RevMem *M, const RevInst& Inst) { - switch(Inst.imm){ - case CBO_INVAL_IMM: - // CBO.INVAL - M->InvLine(F->GetHartToExecID(), R->GetX(Inst.rs1)); - break; - case CBO_FLUSH_IMM: - // CBO.FLUSH - M->FlushLine(F->GetHartToExecID(), R->GetX(Inst.rs1)); - break; - case CBO_CLEAN_IMM: - // CBO.CLEAN - M->CleanLine(F->GetHartToExecID(), R->GetX(Inst.rs1)); - break; - default: - return false; - break; +class Zicbom : public RevExt { + enum class CBO : uint16_t { + INVAL = 0b000, + CLEAN = 0b001, + FLUSH = 0b010, + ZERO = 0b100, + }; + + template + static bool cmo( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + switch( cbo ) { + case CBO::INVAL: M->InvLine( F->GetHartToExecID(), R->GetX( Inst.rs1 ) ); break; + case CBO::CLEAN: M->CleanLine( F->GetHartToExecID(), R->GetX( Inst.rs1 ) ); break; + case CBO::FLUSH: M->FlushLine( F->GetHartToExecID(), R->GetX( Inst.rs1 ) ); break; + default: return false; } - R->AdvancePC(Inst); + R->AdvancePC( Inst ); return true; } struct RevZicbomInstDefaults : RevInstDefaults { - static constexpr uint8_t opcode = 0b0001111; - static constexpr uint8_t funct3 = 0b010; - static constexpr RevRegClass rs1Class = RevRegClass::RegGPR; - static constexpr RevRegClass rs2Class = RevRegClass::RegUNKNOWN; - static constexpr RevRegClass rs3Class = RevRegClass::RegUNKNOWN; - static constexpr RevRegClass rdClass = RevRegClass::RegUNKNOWN; + RevZicbomInstDefaults() { + SetFormat( RVTypeI ); + SetOpcode( 0b0001111 ); + SetFunct3( 0b010 ); + Setrs2Class( RevRegClass::RegUNKNOWN ); + SetrdClass( RevRegClass::RegUNKNOWN ); + Setimm( RevImmFunc::FEnc ); + SetPredicate( []( uint32_t Inst ) { return DECODE_RD( Inst ) == 0; } ); + } }; + // clang-format off std::vector ZicbomTable = { - {RevInstEntryBuilder().SetMnemonic("cbo.clean").SetCost(1).Setimm12(0b000000000001).Setimm(FEnc).SetFormat(RVTypeI).SetImplFunc(&cmo).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("cbo.flush").SetCost(1).Setimm12(0b000000000010).Setimm(FEnc).SetFormat(RVTypeI).SetImplFunc(&cmo).InstEntry}, - {RevInstEntryBuilder().SetMnemonic("cbo.inval").SetCost(1).Setimm12(0b000000000000).Setimm(FEnc).SetFormat(RVTypeI).SetImplFunc(&cmo).InstEntry}, + RevZicbomInstDefaults().SetMnemonic( "cbo.inval" ).Setimm12( uint16_t( CBO::INVAL ) ).SetImplFunc( cmo ), + RevZicbomInstDefaults().SetMnemonic( "cbo.clean" ).Setimm12( uint16_t( CBO::CLEAN ) ).SetImplFunc( cmo ), + RevZicbomInstDefaults().SetMnemonic( "cbo.flush" ).Setimm12( uint16_t( CBO::FLUSH ) ).SetImplFunc( cmo ), +// RevZicbomInstDefaults().SetMnemonic( "cbo.zero" ).Setimm12( uint16_t( CBO::ZERO ) ).SetImplFunc( cmo ), }; + // clang-format on public: - Zicbom( RevFeature *Feature, - RevMem *RevMem, - SST::Output *Output ) - : RevExt( "Zicbom", Feature, RevMem, Output){ - SetTable(std::move(ZicbomTable)); + Zicbom( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zicbom", Feature, RevMem, Output ) { + SetTable( std::move( ZicbomTable ) ); } }; // end class Zicbom -} // namespace SST::RevCPU +} // namespace SST::RevCPU #endif diff --git a/include/insns/Zicsr.h b/include/insns/Zicsr.h new file mode 100644 index 000000000..28cf1f963 --- /dev/null +++ b/include/insns/Zicsr.h @@ -0,0 +1,165 @@ +// +// _Zicsr_h_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// A note about the separation of scopes in include/insns/Zicsr.h and include/RevCSR.h: +// +// Zicsr.h: Decode and execute one of only 6 CSR instructions (csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci). Do not enable or +// disable certain CSR registers, or implement the semantics of particular CSR registers here. All CSR instructions with a valid +// encoding are valid as far as Zicsr.h is concerned. The particular CSR register accessed in a CSR instruction is secondary to the +// scope of Zicsr.h. Certain pseudoinstructions like RDTIME or FRFLAGS are listed separately in Zicsr.h only for user-friendly +// disassembly, not for enabling, disabling or implementing them. +// +// RevCSR.h: GetCSR() and SetCSR() are used to get and set specific CSR registers in the register file, regardless of how we arrive +// here. If a particular CSR register is disabled because of CPU extensions present, or if a particular CSR register does not apply +// to it (such as RDTIMEH on RV64), then raise an invalid instruction or other exception here. +// +// DO NOT enable/disable CSR registers in this file, or make them get decoded by a coprocessor instead of by the tables in here. +// These 6 instructions are the same for any RISC-V processor with Zicsr. The semantics of specific CSR registers and whether they +// are supported should not be handled here, but rather in RevCSR.h and its registered SetCSRGetter() and SetCSRSetter(). +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _SST_REVCPU_ZICSR_H_ +#define _SST_REVCPU_ZICSR_H_ + +#include "../RevExt.h" +#include "../RevInstHelpers.h" + +namespace SST::RevCPU { + +class Zicsr : public RevExt { + + enum class CSROp { Write, Set, Clear }; + + /// Modify a CSR Register according to CSRRW, CSRRS, or CSRRC + // Because CSR has a 32/64-bit width depending on XLEN, this function is templatized. + // + // Note: This function and its functionality is the same for ALL CSR registers, and particular CSR registers should not be + // distinguished or enabled/disabled here. That should be done in RevCSR.h. Every CSR register, regardless of its functionality + // in certain extensions, always has 6 atomic instructions which operate on it, which are composed of an optional read, modify, + // and/or write of the CSR register. That sequence of read/modify/write is the same for ALL CSR registers across ALL extensions, + // whether implemented in the processor or in a coprocessor, and it is composed of calls to GetCSR() and/or SetCSR() which are + // implemented here. + template + static bool ModCSRImpl( RevRegFile* R, const RevInst& Inst ) { + static_assert( std::is_unsigned_v, "XLEN must be an unsigned type" ); + + XLEN old = 0; + + // CSRRW with rd == zero definitionally does not read CSR, which might have side effects + if( OP != CSROp::Write || Inst.rd != 0 ) { + old = R->GetCSR( Inst.imm ); + } + + // Operand is an zero-extended 5-bit immediate or register + XLEN val = OPKIND == OpKind::Imm ? ZeroExt( Inst.rs1, 5 ) : R->GetX( Inst.rs1 ); + + // Store the old CSR value in rd + if( Inst.rd != 0 ) + R->SetX( Inst.rd, old ); + + // Handle CSRRS/CSRRC + if( OP != CSROp::Write ) { + if( Inst.rs1 == 0 ) { + goto end; // If CSRRS/CSRRC rs1 == 0, do not modify CSR + } else if( OP == CSROp::Set ) { + val = old | val; + } else { + val = old & ~val; + } + } + + // Write the new CSR value + if( !R->SetCSR( Inst.imm, val ) ) + return false; + + end: + // Advance PC + R->AdvancePC( Inst ); + + return true; + } + + /// Modify a CSR Register according to CSRRW, CSRRS, or CSRRC + // This calls the 32/64-bit ModCSR depending on the current XLEN + template + static bool ModCSR( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + return F->IsRV64() ? ModCSRImpl( R, Inst ) : ModCSRImpl( R, Inst ); + } + + static constexpr auto& csrrw = ModCSR; + static constexpr auto& csrrs = ModCSR; + static constexpr auto& csrrc = ModCSR; + static constexpr auto& csrrwi = ModCSR; + static constexpr auto& csrrsi = ModCSR; + static constexpr auto& csrrci = ModCSR; + + // ---------------------------------------------------------------------- + // + // RISC-V CSR Instructions + // + // ---------------------------------------------------------------------- + struct RevZicsrInstDefaults : RevInstDefaults { + RevZicsrInstDefaults() { + SetOpcode( 0b1110011 ); + SetRaiseFPE( true ); + SetrdClass( RevRegClass::RegGPR ); + Setrs2Class( RevRegClass::RegUNKNOWN ); + Setimm( RevImmFunc::FImm ); + SetFormat( RVTypeI ); + } + }; + + // clang-format off + std::vector ZicsrTable = { + RevZicsrInstDefaults().SetMnemonic( "csrw %csr, %rs1" ).SetFunct3( 0b001 ).SetImplFunc( csrrw ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrrw %csr, %rd, %rs1" ).SetFunct3( 0b001 ).SetImplFunc( csrrw ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0 && DECODE_IMM12( Inst ) != 0x1 && DECODE_IMM12( Inst ) != 0x2; } ), + RevZicsrInstDefaults().SetMnemonic( "fsflags %rs" ).SetFunct3( 0b001 ).SetImplFunc( csrrw ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0 && DECODE_IMM12( Inst ) == 0x1; } ), + RevZicsrInstDefaults().SetMnemonic( "fsrm %rs" ).SetFunct3( 0b001 ).SetImplFunc( csrrw ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0 && DECODE_IMM12( Inst ) == 0x2; } ), + + RevZicsrInstDefaults().SetMnemonic( "csrrs %rd, %csr, %rs1" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != 0 && DECODE_RD( Inst ) != 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrs %csr, %rs1" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) != 0 && DECODE_RD( Inst ) == 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrr %rd, %csr" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) != 0x1 && DECODE_IMM12( Inst ) != 0x2 && [](auto imm){ return imm < 0xc80 || imm > 0xc82; }( DECODE_IMM12( Inst ) | 0x80 ); } ), + RevZicsrInstDefaults().SetMnemonic( "frflags %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0x1; } ), + RevZicsrInstDefaults().SetMnemonic( "frrm %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0x2; } ), + + RevZicsrInstDefaults().SetMnemonic( "csrrc %rd, %csr, %rs1" ).SetFunct3( 0b011 ).SetImplFunc( csrrc ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrc %csr,%rs1" ).SetFunct3( 0b011 ).SetImplFunc( csrrc ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + + RevZicsrInstDefaults().SetMnemonic( "csrrwi %rd, %csr, $imm" ).SetFunct3( 0b101 ).SetImplFunc( csrrwi ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrwi %csr, $imm" ).SetFunct3( 0b101 ).SetImplFunc( csrrwi ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + + RevZicsrInstDefaults().SetMnemonic( "csrrsi %rd, %csr, $imm" ).SetFunct3( 0b110 ).SetImplFunc( csrrsi ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrsi %csr, $imm" ).SetFunct3( 0b110 ).SetImplFunc( csrrsi ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + + RevZicsrInstDefaults().SetMnemonic( "csrrci %rd, %csr, $imm" ).SetFunct3( 0b111 ).SetImplFunc( csrrci ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ), + RevZicsrInstDefaults().SetMnemonic( "csrci %csr, $imm" ).SetFunct3( 0b111 ).SetImplFunc( csrrci ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ), + + RevZicsrInstDefaults().SetMnemonic( "rdcycle %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::cycle; } ), + RevZicsrInstDefaults().SetMnemonic( "rdcycleh %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::cycleh; } ), + RevZicsrInstDefaults().SetMnemonic( "rdtime %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::time; } ), + RevZicsrInstDefaults().SetMnemonic( "rdtimeh %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::timeh; } ), + RevZicsrInstDefaults().SetMnemonic( "rdinstret %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::instret; } ), + RevZicsrInstDefaults().SetMnemonic( "rdinstreth %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == RevCSR::instreth; } ), + }; + // clang-format on + +public: + /// Zicsr: standard constructor + Zicsr( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zicsr", Feature, RevMem, Output ) { + SetTable( std::move( ZicsrTable ) ); + } + +}; // end class Zicsr + +} // namespace SST::RevCPU + +#endif diff --git a/include/insns/Zifencei.h b/include/insns/Zifencei.h new file mode 100644 index 000000000..79b3743e7 --- /dev/null +++ b/include/insns/Zifencei.h @@ -0,0 +1,42 @@ +// +// _Zifencei_h_ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#ifndef _SST_REVCPU_ZIFENCEI_H_ +#define _SST_REVCPU_ZIFENCEI_H_ + +#include "../RevExt.h" +#include "../RevInstHelpers.h" + +namespace SST::RevCPU { + +class Zifencei : public RevExt { + + static bool fencei( const RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { + M->FenceMem( F->GetHartToExecID() ); + R->AdvancePC( Inst ); + return true; + } + + // clang-format off + std::vector ZifenceiTable = { + RevInstDefaults().SetMnemonic("fence.i").SetFormat(RVTypeI).SetOpcode(0b0001111).SetFunct3(0b001).SetrdClass(RevRegClass::RegUNKNOWN).Setrs1Class(RevRegClass::RegUNKNOWN).Setrs2Class(RevRegClass::RegUNKNOWN).SetImplFunc(fencei), + }; + // clang-format on + +public: + Zifencei( const RevFeature* Feature, RevMem* RevMem, SST::Output* Output ) : RevExt( "Zifencei", Feature, RevMem, Output ) { + SetTable( std::move( ZifenceiTable ) ); + } + +}; // end class Zifencei + +} // namespace SST::RevCPU + +#endif diff --git a/scripts/asmCheck.py b/scripts/asmCheck.py old mode 100644 new mode 100755 index 92942291d..d54c53578 --- a/scripts/asmCheck.py +++ b/scripts/asmCheck.py @@ -1,4 +1,3 @@ -import sys import argparse parser = argparse.ArgumentParser(description="Match SST output with asm file - use with __REV_DEEP_TRACE__ define") @@ -7,36 +6,36 @@ args = parser.parse_args() try: - sst_out = open(args.sstOutfile, 'r') -except: - print("Cannot open file " + args.sstOutfile) - exit(1) + sst_out = open(args.sstOutfile, 'r') +except Exception: + print("Cannot open file " + args.sstOutfile) + exit(1) sstLines = sst_out.readlines() - + try: - asm = open(args.asmFilename, 'r') -except: - print("Cannot open file " + args.asmFilename) - exit(1) + asm = open(args.asmFilename, 'r') +except Exception: + print("Cannot open file " + args.asmFilename) + exit(1) asmLines = asm.readlines() asmHash = {} # Strips the newline character for line in asmLines: - splitLine = line.strip().split(":") - PC = splitLine[0] - if "<" in PC: - continue - asmHash[PC] = line.strip() + splitLine = line.strip().split(":") + PC = splitLine[0] + if "<" in PC: + continue + asmHash[PC] = line.strip() for line in sstLines: - if "RDT:" in line: - PC = line.split("PC = ")[1].split(' ')[0] - so = line.split("Inst:")[1].strip() - if PC in asmHash: - o = '{:<60} {:<3} {:<60}'.format(asmHash[PC].strip(),":::", so) - print(o) - else: - print("WARNING: PC " + PC + " not found in asm file, but was executed by Rev") + if "RDT:" in line: + PC = line.split("PC = ")[1].split(' ')[0] + so = line.split("Inst:")[1].strip() + if PC in asmHash: + o = '{:<60} {:<3} {:<60}'.format(asmHash[PC].strip(), ":::", so) + print(o) + else: + print("WARNING: PC " + PC + " not found in asm file, but was executed by Rev") diff --git a/scripts/asmCheck_tracer.py b/scripts/asmCheck_tracer.py new file mode 100755 index 000000000..a01f0ca3f --- /dev/null +++ b/scripts/asmCheck_tracer.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +import argparse + +parser = argparse.ArgumentParser(description="""\ +Match SST output with asm file and/or print call stack at a specified clock +tick - use with TRACER_ON in target program. +Use 'riscv64-unknown-elf-objdump -dC -Mno-aliases ' to create assembly file +""") + +parser.add_argument('-a', '--asmFile', dest='asmFilename', required=True) +parser.add_argument('-s', '--sstOut', dest='sstOutfile', required=True) +parser.add_argument('-c', '--callStk', dest='callStackClk', type=int, required=False) +args = parser.parse_args() + +try: + sst_out = open(args.sstOutfile, 'r') +except Exception: + print("Cannot open file " + args.sstOutfile) + exit(1) + +sstLines = sst_out.readlines() + +try: + asm = open(args.asmFilename, 'r') +except Exception: + print("Cannot open file " + args.asmFilename) + exit(1) + +asmLines = asm.readlines() + +asmHash = {} +asmFunctStartHash = {} +asmFunctRetHash = {} +curFunction = "" +firstInst = False +prevPC = "" +# Strips the newline character +for line in asmLines: + if ">:" in line: + asmFunctRetHash[prevPC] = curFunction + curFunction = line.strip() + firstInst = True + continue + splitLine = line.strip().split(":") + PC = splitLine[0] + prevPC = PC + if "<" in PC: + continue + asmHash[PC] = line.strip() + if firstInst: + asmFunctStartHash[PC] = curFunction + firstInst = False + +printCS = False +if (args.callStackClk): + printCS = True + +callStack = ["main"] + +for line in sstLines: + if "Render:" in line and "Core" in line: + print(line) + clk = line.split("Render:")[1].split(']:')[0].strip() + PC = line.split("*I ")[1].split(':')[0].split('0x')[1] + so = line.split("*I ")[1].split('\t')[0].strip() + if PC in asmHash: + o = '{:<60} {:<3} {:<60}'.format(asmHash[PC].strip(), ":::", so) + if (not args.callStackClk): + print(o) + else: + print("WARNING: PC " + PC + " not found in asm file, but was executed by Rev") + + if int(clk) == args.callStackClk: + print("Call Stack at time: " + clk + " and PC: " + PC) + for f in callStack: + print(f) + + if PC in asmFunctStartHash: + callStack.append(asmFunctStartHash[PC]) + + if PC in asmFunctRetHash: + callStack.pop() diff --git a/scripts/cleanmanpages.sh b/scripts/cleanmanpages.sh new file mode 100755 index 000000000..59d177542 --- /dev/null +++ b/scripts/cleanmanpages.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# -- cleans the unnecessary directory reference manpages _*.3 + +BASE=$1 + +rm -Rf "$BASE"/_*.3 diff --git a/scripts/rev-print.py b/scripts/rev-print.py new file mode 100755 index 000000000..725fe7f7b --- /dev/null +++ b/scripts/rev-print.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-print.py +# +# Intent: Extract and pretty-print rev-fast-printf strings from rev logs +# +# TODO: Consider separate file stream for rev-fast-printf to avoid this +# kind of (slow and inefficient) postprocessing + +import argparse +import re + +parser = argparse.ArgumentParser( + prog="rev-print.py", + description="Extract and render rev-fast-print strings from log file") +parser.add_argument('-l', '--logFile', dest='logFile', required=True, + help="path to REV output log file") +parser.add_argument('-ts', '--timeStamp', dest="timeStamp", required=False, default="False", + help="show timestamp information for rev-fast-print string") +args = parser.parse_args() + +try: + fn = open(args.logFile) +except Exception: + print("Cannot open file " + args.logFile) + exit(1) + +inString = False +reQuick = re.compile("rev-pr") +reTimeStamp = re.compile(r":(\d+)\]: ") +reStart = re.compile("(.*)") +reEnd = re.compile("(.*)") +reBoth = re.compile("(.*)") +for line in fn: + # check for early bail out (most of the time) + q = reQuick.search(line) + if not q and not inString: + continue + b = reBoth.search(line) + if b: + inString = False + print(b.group(1), end="") + continue + e = reEnd.search(line) + if e: + inString = False + print(e.group(1), end="") + continue + s = reStart.search(line) + if s: + inString = True + if args.timeStamp is True: + ts = reTimeStamp.search(line) + if ts: + print(f"#{ts.group(1)}") + print(s.group(1)) + continue + if inString: + print(line) diff --git a/scripts/slurm/build-gcc11-sst13.1.0.sh b/scripts/slurm/build-gcc11-sst13.1.0.sh old mode 100644 new mode 100755 index 895650add..912dfd6ae --- a/scripts/slurm/build-gcc11-sst13.1.0.sh +++ b/scripts/slurm/build-gcc11-sst13.1.0.sh @@ -2,7 +2,7 @@ # # scripts/slurm/build-gcc11-sst13.1.0.sh # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -25,23 +25,23 @@ export CC=gcc-11 export CXX=g++-11 export RVCC=riscv64-unknown-elf-gcc -touch rev.jenkins.${SLURM_JOB_ID}.out -sst --version >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -sst-info revcpu >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu #-- Stage 2: setup the build directories mkdir -p build -cd build +cd build || exit rm -Rf ./* #-- Stage 3: initiate the build -cmake -DBUILD_ASM_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make clean >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make uninstall >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make -j >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -#make install >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install #-- Stage 4: test everything -make test >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +make test #-- EOF diff --git a/scripts/slurm/build-gcc11-sst14.0.0.sh b/scripts/slurm/build-gcc11-sst14.0.0.sh new file mode 100755 index 000000000..d503e7e0e --- /dev/null +++ b/scripts/slurm/build-gcc11-sst14.0.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-gcc11-sst14.0.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/12.2.0 cmake/3.23.0 riscv-linux/gcc/12.2.0 sst/14.0.0 +export CC=gcc-11 +export CXX=g++-11 +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-gcc11-sst14.1.0.sh b/scripts/slurm/build-gcc11-sst14.1.0.sh new file mode 100755 index 000000000..33c3b5fff --- /dev/null +++ b/scripts/slurm/build-gcc11-sst14.1.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-gcc11-sst14.1.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/12.2.0 cmake/3.23.0 riscv-linux/gcc/12.2.0 sst/14.1.0 +export CC=gcc-11 +export CXX=g++-11 +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-gcc11.sh b/scripts/slurm/build-gcc11.sh old mode 100644 new mode 100755 index b0513dc8a..86f80d531 --- a/scripts/slurm/build-gcc11.sh +++ b/scripts/slurm/build-gcc11.sh @@ -2,7 +2,7 @@ # # scripts/slurm/build-gcc11.sh # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -25,23 +25,23 @@ export CC=gcc-11 export CXX=g++-11 export RVCC=riscv64-unknown-elf-gcc -touch rev.jenkins.${SLURM_JOB_ID}.out -sst --version >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -sst-info revcpu >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu #-- Stage 2: setup the build directories mkdir -p build -cd build +cd build || exit rm -Rf ./* #-- Stage 3: initiate the build -cmake -DBUILD_ASM_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make clean >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make uninstall >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make -j >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -#make install >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install #-- Stage 4: test everything -make test >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +make test #-- EOF diff --git a/scripts/slurm/build-gcc13-sst13.1.0.sh b/scripts/slurm/build-gcc13-sst13.1.0.sh new file mode 100755 index 000000000..38c9d04b4 --- /dev/null +++ b/scripts/slurm/build-gcc13-sst13.1.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-gcc11-sst13.1.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/13.2.0 cmake/3.23.0 sst/13.1.0 +export CC=gcc-11 +export CXX=g++-11 +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-gcc13-sst14.0.0.sh b/scripts/slurm/build-gcc13-sst14.0.0.sh new file mode 100755 index 000000000..ad85a331d --- /dev/null +++ b/scripts/slurm/build-gcc13-sst14.0.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-gcc11-sst14.0.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/13.2.0 cmake/3.23.0 sst/14.0.0 +export CC=gcc-11 +export CXX=g++-11 +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-gcc13.sh b/scripts/slurm/build-gcc13.sh new file mode 100755 index 000000000..24ab08bb7 --- /dev/null +++ b/scripts/slurm/build-gcc13.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-gcc13.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/13.2.0 cmake/3.23.0 sst/13.0.0 +export CC=gcc-11 +export CXX=g++-11 +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-llvm12-sst13.1.0.sh b/scripts/slurm/build-llvm12-sst13.1.0.sh old mode 100644 new mode 100755 index 443d8b143..6f0c6994f --- a/scripts/slurm/build-llvm12-sst13.1.0.sh +++ b/scripts/slurm/build-llvm12-sst13.1.0.sh @@ -2,7 +2,7 @@ # # scripts/slurm/build-llvm12-sst13.1.0.sh # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -25,23 +25,23 @@ export CC=clang export CXX=clang++ export RVCC=riscv64-unknown-elf-gcc -touch rev.jenkins.${SLURM_JOB_ID}.out -sst --version >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -sst-info revcpu >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu #-- Stage 2: setup the build directories mkdir -p build -cd build +cd build || exit rm -Rf ./* #-- Stage 3: initiate the build -cmake -DBUILD_ASM_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make clean >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make uninstall >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make -j >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -#make install >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install #-- Stage 4: test everything -make test >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +make test #-- EOF diff --git a/scripts/slurm/build-llvm12-sst14.0.0.sh b/scripts/slurm/build-llvm12-sst14.0.0.sh new file mode 100755 index 000000000..ab335bc4b --- /dev/null +++ b/scripts/slurm/build-llvm12-sst14.0.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-llvm12-sst14.0.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/12.2.0 cmake/3.23.0 riscv-linux/gcc/12.2.0 sst/14.0.0 llvm/12.0.0 +export CC=clang +export CXX=clang++ +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-llvm12-sst14.1.0.sh b/scripts/slurm/build-llvm12-sst14.1.0.sh new file mode 100755 index 000000000..e7f2762ac --- /dev/null +++ b/scripts/slurm/build-llvm12-sst14.1.0.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# scripts/slurm/build-llvm12-sst14.1.0.sh +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# This file is a part of the PAN-RUNTIME package. For license +# information, see the LICENSE file in the top level directory of +# this distribution. +# +# +# Sample SLURM batch script +# +# Usage: sbatch -N1 build.sh +# +# This command requests 1 nodes for execution +# + +#-- Stage 1: load the necessary modules +source /etc/profile.d/modules.sh +module load riscv/gcc/12.2.0 cmake/3.23.0 riscv-linux/gcc/12.2.0 sst/14.1.0 llvm/12.0.0 +export CC=clang +export CXX=clang++ +export RVCC=riscv64-unknown-elf-gcc + +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu + +#-- Stage 2: setup the build directories +mkdir -p build +cd build || exit +rm -Rf ./* + +#-- Stage 3: initiate the build +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install + +#-- Stage 4: test everything +make test + +#-- EOF diff --git a/scripts/slurm/build-llvm12.sh b/scripts/slurm/build-llvm12.sh old mode 100644 new mode 100755 index dd7990f54..e0409a341 --- a/scripts/slurm/build-llvm12.sh +++ b/scripts/slurm/build-llvm12.sh @@ -2,7 +2,7 @@ # # scripts/slurm/build-llvm12.sh # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -25,23 +25,23 @@ export CC=clang export CXX=clang++ export RVCC=riscv64-unknown-elf-gcc -touch rev.jenkins.${SLURM_JOB_ID}.out -sst --version >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -sst-info revcpu >> rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +exec >> "rev.jenkins.${SLURM_JOB_ID}.out" 2>&1 +sst --version +sst-info revcpu #-- Stage 2: setup the build directories mkdir -p build -cd build +cd build || exit rm -Rf ./* #-- Stage 3: initiate the build -cmake -DBUILD_ASM_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make clean >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make uninstall >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -make -j >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 -#make install >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +cmake -DCMAKE_BUILD_TYPE=Debug -DRVCC=${RVCC} ../ +make clean +make uninstall +make -j +#make install #-- Stage 4: test everything -make test >> ../rev.jenkins.${SLURM_JOB_ID}.out 2>&1 +make test #-- EOF diff --git a/scripts/slurm/exec_build.sh b/scripts/slurm/exec_build.sh old mode 100644 new mode 100755 index f392a8c74..35f7f8715 --- a/scripts/slurm/exec_build.sh +++ b/scripts/slurm/exec_build.sh @@ -2,7 +2,7 @@ # # scripts/slurm/exec_build.sh # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -14,33 +14,32 @@ USER=$(id -un) #-- execute the job SCRIPT=$1 -SLURM_ID=`sbatch -N1 --export=ALL $SCRIPT | awk '{print $4}'` +SLURM_ID=$(sbatch -N1 --export=ALL "$SCRIPT" | awk '{print $4}') #-- wait for completion -COMPLETE=`squeue -u $USER | grep ${SLURM_ID}` -while [ -n "$COMPLETE" ]; do +COMPLETE=$(squeue -u "$USER" | grep "${SLURM_ID}") +while [[ -n $COMPLETE ]]; do sleep 1 - COMPLETE=`squeue -u $USER | grep ${SLURM_ID}` + COMPLETE=$(squeue -u "$USER" | grep "${SLURM_ID}") done #-- echo the result to the log -cat rev.jenkins.${SLURM_ID}.out +cat "rev.jenkins.${SLURM_ID}.out" #-- job has completed, test for status -STATE=`cat rev.jenkins.${SLURM_ID}.out | grep "tests failed out of"` -NUM_FAILED=`cat rev.jenkins.${SLURM_ID}.out | grep "tests failed out of" | awk '{print $4}'` +STATE=$(grep "tests failed out of" < "rev.jenkins.${SLURM_ID}.out") +NUM_FAILED=$(grep "tests failed out of" < "rev.jenkins.${SLURM_ID}.out" | awk '{print $4}') -if [ "$NUM_FAILED" -eq "0" ]; +if [[ $NUM_FAILED -eq 0 ]]; then echo "TEST PASSED FOR JOB_ID = ${JOB_ID}; SLURM_JOB=${SLURM_ID}" - echo $STATE + echo "$STATE" exit 0 else echo "TEST FAILED FOR JOB_ID = ${JOB_ID}; SLURM_JOB=${SLURM_ID}" - echo $STATE - exit -1 + echo "$STATE" + exit 1 fi -exit 0 #-- EOF diff --git a/scripts/spikeCheck.py b/scripts/spikeCheck.py old mode 100644 new mode 100755 index a1125a601..764dd4534 --- a/scripts/spikeCheck.py +++ b/scripts/spikeCheck.py @@ -1,4 +1,5 @@ -import sys +#!/usr/bin/env python3 + import argparse parser = argparse.ArgumentParser(description="Match SST output with spkie trace file - use with __REV_DEEP_TRACE__ define") @@ -9,26 +10,26 @@ args = parser.parse_args() try: - sst_out = open(args.sstOutfile, 'r') -except: - print("Cannot open file " + args.sstOutfile) - exit(1) + sst_out = open(args.sstOutfile, 'r') +except Exception: + print("Cannot open file " + args.sstOutfile) + exit(1) sstLines = sst_out.readlines() - + try: - asm = open(args.asmFilename, 'r') -except: - print("Cannot open file " + args.asmFilename) - exit(1) + asm = open(args.asmFilename, 'r') +except Exception: + print("Cannot open file " + args.asmFilename) + exit(1) asmLines = asm.readlines() try: - spike = open(args.spikeOutfile, 'r') -except: - print("Cannot open file " + args.spikeOutfile) - exit(1) + spike = open(args.spikeOutfile, 'r') +except Exception: + print("Cannot open file " + args.spikeOutfile) + exit(1) spikeLines = spike.readlines() @@ -37,32 +38,32 @@ startPC = 0 startPCFound = False for line in asmLines: - splitLine = line.strip().split(":") - PC = splitLine[0] - if "
:" in line: - startPCFound = True - continue - if "<" in PC: - continue - asmHash[PC] = line.strip() - if startPCFound: - print("Found start in asm at: " + PC) - startPC = int(PC,16) - startPCFound = False + splitLine = line.strip().split(":") + PC = splitLine[0] + if "
:" in line: + startPCFound = True + continue + if "<" in PC: + continue + asmHash[PC] = line.strip() + if startPCFound: + print("Found start in asm at: " + PC) + startPC = int(PC, 16) + startPCFound = False startPCInt = startPC foundStart = False for line in spikeLines: - l = line.split() - if len(l) < 5: + ls = line.split() + if len(ls) < 5: continue - if ('exception' in l[2]) and foundStart : + if ('exception' in ls[2]) and foundStart: spikeList.append(line.strip()) continue - if 'exception' in l[2]: + if 'exception' in ls[2]: continue - PCint = int(l[2],16) + PCint = int(ls[2], 16) if PCint == startPCInt: foundStart = True print("Found start in spike at: " + hex(PCint)) @@ -74,27 +75,26 @@ match = '-' -o = '{:<9} {:<70} {:<3} {:<70} {:<3} {:<60}'.format("PC Match", "ASM Instruction" ,":::", "Rev Instruction", ":::", "Spike Instruction") +o = '{:<9} {:<70} {:<3} {:<70} {:<3} {:<60}'.format("PC Match", "ASM Instruction", + ":::", "Rev Instruction", ":::", "Spike Instruction") print(o) for line in sstLines: - if "RDT: Executed" in line: - PC = line.split("PC = ")[1].split(' ')[0] - so = line.split("Inst:")[1].strip() - if "page_fault" in spikeList[0]: - print("found exception") - spikeList.pop(0) - spikeList.pop(0) - while int(PC,16) != int(spikeList[0].split()[2],16): + if "RDT: Executed" in line: + PC = line.split("PC = ")[1].split(' ')[0] + so = line.split("Inst:")[1].strip() + if "page_fault" in spikeList[0]: + print("found exception") spikeList.pop(0) - - if PC in asmHash: - if int(PC,16) == int(spikeList[0].split()[2],16): - match = '+' - else: - match = '-' - o = '{:<3} {:<70} {:<3} {:<70} {:<3} {:<60}'.format(match, asmHash[PC].strip(),":::", so, ":::", spikeList.pop(0)) - print(o) - else: - print("WARNING: PC " + PC + " not found in asm file, but was executed by Rev") - + spikeList.pop(0) + while int(PC, 16) != int(spikeList[0].split()[2], 16): + spikeList.pop(0) + if PC in asmHash: + if int(PC, 16) == int(spikeList[0].split()[2], 16): + match = '+' + else: + match = '-' + o = '{:<3} {:<70} {:<3} {:<70} {:<3} {:<60}'.format(match, asmHash[PC].strip(), ":::", so, ":::", spikeList.pop(0)) + print(o) + else: + print("WARNING: PC " + PC + " not found in asm file, but was executed by Rev") diff --git a/scripts/test_git_hooks.sh b/scripts/test_git_hooks.sh new file mode 100755 index 000000000..6d6beec50 --- /dev/null +++ b/scripts/test_git_hooks.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +exec >&2 + +if [ -z ${NO_COLOR+x} ] && tty -s <&2; then + RED="\033[91m" + END="\033[0m" +else + RED= + END= +fi + +if [ "$(id -nu)" = builduser ]; then + exit 0 +fi + +hooks=$(git config core.hooksPath) +if [ "${hooks}" != .githooks ]; then + printf "${RED}\n" + cat < +#include #include -namespace SST::RevCPU{ +namespace SST::RevCPU { -using MemSegment = RevMem::MemSegment; +using MemSegment = RevMem::MemSegment; -const char splash_msg[] = "\ -\n\ -******* \n\ -/**////** \n\ -/** /** ***** ** **\n\ -/******* **///**/** /**\n\ -/**///** /*******//** /** \n\ -/** //** /**//// //**** \n\ -/** //**//****** //** \n\ -// // ////// // \n\ -\n\ -"; +const char splash_msg[] = R"( +******* +/**////** +/** /** ***** ** ** +/******* **///**/** /** +/**///** /*******//** /** +/** //** /**//// //**** +/** //**//****** //** +// // ////// // +)"; -RevCPU::RevCPU( SST::ComponentId_t id, const SST::Params& params ) - : SST::Component(id), testStage(0), PrivTag(0), address(-1), EnableMemH(false), - DisableCoprocClock(false), Nic(nullptr), Ctrl(nullptr), ClockHandler(nullptr) { +RevCPU::RevCPU( SST::ComponentId_t id, const SST::Params& params ) : SST::Component( id ) { - const int Verbosity = params.find("verbose", 0); + auto Verbosity = params.find( "verbose", 0 ); // Initialize the output handler - output.init("RevCPU[" + getName() + ":@p:@t]: ", Verbosity, 0, SST::Output::STDOUT); + output.init( "RevCPU[" + getName() + ":@p:@t]: ", Verbosity, 0, SST::Output::STDOUT ); // Register a new clock handler - const std::string cpuClock = params.find("clock", "1GHz"); - ClockHandler = new SST::Clock::Handler(this, &RevCPU::clockTick); - timeConverter = registerClock(cpuClock, ClockHandler); + const std::string cpuClock = params.find( "clock", "1GHz" ); + ClockHandler = new SST::Clock::Handler( this, &RevCPU::clockTick ); + timeConverter = registerClock( cpuClock, ClockHandler ); // Inform SST to wait until we authorize it to exit registerAsPrimaryComponent(); @@ -51,613 +48,588 @@ RevCPU::RevCPU( SST::ComponentId_t id, const SST::Params& params ) // Derive the simulation parameters // We must always derive the number of cores before initializing the options - numCores = params.find("numCores", "1"); - numHarts = params.find("numHarts", "1"); + numCores = params.find( "numCores", "1" ); + numHarts = params.find( "numHarts", "1" ); - // Make sure someone isn't trying to have more than 65536 harts per core - if( numHarts > _MAX_HARTS_ ){ - output.fatal(CALL_INFO, -1, "Error: number of harts must be <= %" PRIu32 "\n", _MAX_HARTS_); + // Make sure someone isn't trying to have more than _MAX_HARTS_ harts per core + if( numHarts > _MAX_HARTS_ ) { + output.fatal( CALL_INFO, -1, "Error: number of harts must be <= %" PRIu32 "\n", uint32_t{ _MAX_HARTS_ } ); } - output.verbose(CALL_INFO, 1, 0, - "Building Rev with %" PRIu32 " cores and %" PRIu32 " hart(s) on each core \n", - numCores, numHarts); + output.verbose( + CALL_INFO, 1, 0, "Building Rev with %" PRIu32 " cores and %" PRIu32 " hart(s) on each core \n", numCores, numHarts + ); // read the binary executable name - Exe = params.find("program", "a.out"); - - // read the program arguments - Args = params.find("args", ""); + auto Exe = params.find( "program", "a.out" ); // Create the options object - // TODO: Use std::nothrow to return null instead of throwing std::bad_alloc - Opts = new RevOpts(numCores, numHarts, Verbosity); - if( !Opts ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the RevOpts object\n" ); + Opts = std::make_unique( numCores, numHarts, Verbosity ); + + // Program arguments + Opts->SetArgs( params ); // Initialize the remaining options - { - std::vector startAddrs; - params.find_array("startAddr", startAddrs); - if( !Opts->InitStartAddrs( startAddrs ) ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the starting addresses\n" ); - - std::vector startSyms; - params.find_array("startSymbol", startSyms); - if( !Opts->InitStartSymbols( startSyms ) ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the starting symbols\n" ); - - std::vector machModels; - params.find_array("machine", machModels); - if( !Opts->InitMachineModels( machModels ) ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the machine models\n" ); - - std::vector instTables; - params.find_array("table", instTables); - if( !Opts->InitInstTables( instTables ) ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the instruction tables\n" ); - - std::vector memCosts; - params.find_array("memCost", memCosts); - if( !Opts->InitMemCosts( memCosts ) ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the memory latency range\n" ); - - std::vector prefetchDepths; - params.find_array("prefetchDepth", prefetchDepths); - if( !Opts->InitPrefetchDepth( prefetchDepths) ) - output.fatal(CALL_INFO, -1, "Error: failed to initalize the prefetch depth\n" ); + for( auto [ParamName, InitFunc] : { + std::pair( "startAddr", &RevOpts::InitStartAddrs ), + std::pair( "startSymbol", &RevOpts::InitStartSymbols ), + std::pair( "machine", &RevOpts::InitMachineModels ), + std::pair( "table", &RevOpts::InitInstTables ), + std::pair( "memCost", &RevOpts::InitMemCosts ), + std::pair( "prefetchDepth", &RevOpts::InitPrefetchDepth ), + } ) { + std::vector optList; + params.find_array( ParamName, optList ); + if( !( Opts.get()->*InitFunc )( optList ) ) + output.fatal( CALL_INFO, -1, "Error: failed to initialize %s\n", ParamName ); } // See if we should load the network interface controller - EnableNIC = params.find("enable_nic", 0); + EnableNIC = params.find( "enable_nic", 0 ); - if( EnableNIC ){ + if( EnableNIC ) { // Look up the network component - Nic = loadUserSubComponent("nic"); + Nic = loadUserSubComponent( "nic" ); // check to see if the nic was loaded. if not, DO NOT load an anonymous endpoint - if(!Nic) - output.fatal(CALL_INFO, -1, "Error: no NIC object loaded into RevCPU\n"); + if( !Nic ) + output.fatal( CALL_INFO, -1, "Error: no NIC object loaded into RevCPU\n" ); - Nic->setMsgHandler(new Event::Handler(this, &RevCPU::handleMessage)); + Nic->setMsgHandler( new Event::Handler( this, &RevCPU::handleMessage ) ); // record the number of injected messages per cycle - msgPerCycle = params.find("msgPerCycle", 1); + msgPerCycle = params.find( "msgPerCycle", 1 ); } // Look for the fault injection logic - EnableFaults = params.find("enable_faults", 0); - if( EnableFaults ){ + EnableFaults = params.find( "enable_faults", 0 ); + if( EnableFaults ) { std::vector faults; - params.find_array("faults", faults); - DecodeFaultCodes(faults); + params.find_array( "faults", faults ); + DecodeFaultCodes( faults ); - std::string width = params.find("fault_width", "1"); - DecodeFaultWidth(width); + std::string width = params.find( "fault_width", "1" ); + DecodeFaultWidth( width ); - fault_width = params.find("fault_range", "65536"); - FaultCntr = fault_width; + fault_width = params.find( "fault_range", "65536" ); + FaultCntr = fault_width; } // Create the memory object - const uint64_t memSize = params.find("memSize", 1073741824); - EnableMemH = params.find("enable_memH", 0); - if( !EnableMemH ){ - // TODO: Use std::nothrow to return null instead of throwing std::bad_alloc - Mem = new RevMem( memSize, Opts, &output ); - if( !Mem ) - output.fatal(CALL_INFO, -1, "Error: failed to initialize the memory object\n" ); - }else{ - Ctrl = loadUserSubComponent("memory"); + const uint64_t memSize = params.find( "memSize", 1073741824 ); + EnableMemH = params.find( "enableMemH", 0 ); + if( !EnableMemH ) { + Mem = std::make_unique( memSize, Opts.get(), &output ); + } else { + Ctrl = std::unique_ptr( loadUserSubComponent( "memory" ) ); if( !Ctrl ) - output.fatal(CALL_INFO, -1, "Error : failed to inintialize the memory controller subcomponent\n"); - - // TODO: Use std::nothrow to return null instead of throwing std::bad_alloc - Mem = new RevMem( memSize, Opts, Ctrl, &output ); - if( !Mem ) - output.fatal(CALL_INFO, -1, "Error : failed to initialize the memory object\n" ); + output.fatal( CALL_INFO, -1, "Error : failed to inintialize the memory controller subcomponent\n" ); + Mem = std::make_unique( memSize, Opts.get(), Ctrl.get(), &output ); if( EnableFaults ) - output.verbose(CALL_INFO, 1, 0, "Warning: memory faults cannot be enabled with memHierarchy support\n"); + output.verbose( CALL_INFO, 1, 0, "Warning: memory faults cannot be enabled with memHierarchy support\n" ); } // Set TLB Size - const uint64_t tlbSize = params.find("tlbSize", 512); - Mem->SetTLBSize(tlbSize); + auto tlbSize = params.find( "tlbSize", 512 ); + Mem->SetTLBSize( tlbSize ); // Set max heap size - const uint64_t maxHeapSize = params.find("maxHeapSize", memSize/4); - Mem->SetMaxHeapSize(maxHeapSize); + const uint64_t maxHeapSize = params.find( "maxHeapSize", memSize / 4 ); + Mem->SetMaxHeapSize( maxHeapSize ); // Load the binary into memory - // TODO: Use std::nothrow to return null instead of throwing std::bad_alloc - Loader = new RevLoader( Exe, Args, Mem, &output ); - if( !Loader ){ - output.fatal(CALL_INFO, -1, "Error: failed to initialize the RISC-V loader\n" ); - } + Loader = std::make_unique( Exe, Opts->GetArgv(), Mem.get(), &output ); - Opts->SetArgs(Loader->GetArgv()); - - EnableCoProc = params.find("enableCoProc", 0); - if(EnableCoProc){ + // Create the processor objects + Procs.reserve( Procs.size() + numCores ); + for( uint32_t i = 0; i < numCores; i++ ) { + Procs.push_back( std::make_unique( i, Opts.get(), numHarts, Mem.get(), Loader.get(), this->GetNewTID(), &output ) ); + } - // Create the processor objects - Procs.reserve(Procs.size() + numCores); - for( unsigned i=0; iGetNewTID(), &output ) ); - } + EnableCoProc = params.find( "enableCoProc", 0 ); + if( EnableCoProc ) { // Create the co-processor objects - for( unsigned i=0; i("co_proc", SST::ComponentInfo::SHARE_NONE, Procs[i]); - if (!CoProc) { - output.fatal(CALL_INFO, -1, "Error : failed to inintialize the co-processor subcomponent\n"); + for( uint32_t i = 0; i < numCores; i++ ) { + RevCoProc* CoProc = loadUserSubComponent( "co_proc", SST::ComponentInfo::SHARE_NONE, Procs[i].get() ); + if( !CoProc ) { + output.fatal( CALL_INFO, -1, "Error : failed to inintialize the co-processor subcomponent\n" ); } - CoProcs.push_back(CoProc); - Procs[i]->SetCoProc(CoProc); + Procs[i]->SetCoProc( CoProc ); + CoProcs.push_back( std::unique_ptr( CoProc ) ); } - }else{ - // Create the processor objects - Procs.reserve(Procs.size() + numCores); - for( unsigned i=0; iGetNewTID(), &output ) ); + } + + // Memory dumping option(s) + std::vector memDumpRanges; + params.find_array( "memDumpRanges", memDumpRanges ); + if( !memDumpRanges.empty() ) { + for( auto& segName : memDumpRanges ) { + // FIXME: Figure out how to parse units (GB, MB, KB, etc.) + // segName is a string... Look for scoped params for this segment + const auto& scopedParams = params.get_scoped_params( segName ); + // Check scopedParams for the following: + // - startAddr (hex) + // - size (bytes) + if( !scopedParams.contains( "startAddr" ) ) { + output.fatal( + CALL_INFO, + -1, + "Error: memDumpRanges requires startAddr. Please specify this scoped " + "param as %s.startAddr in the configuration file\n", + segName.c_str() + ); + } else if( !scopedParams.contains( "size" ) ) { + output.fatal( + CALL_INFO, + -1, + "Error: memDumpRanges requires size. Please specify this " + "scoped param as %s.size in the configuration file\n", + segName.c_str() + ); + } + const uint64_t startAddr = scopedParams.find( "startAddr" ); + const uint64_t size = scopedParams.find( "size" ); + Mem->AddDumpRange( segName, startAddr, size ); } } - #ifndef NO_REV_TRACER +#ifndef NO_REV_TRACER // Configure tracer and assign to each core - if (output.getVerboseLevel()>=5) { - for( unsigned i=0; i= 5 ) { + for( uint32_t i = 0; i < numCores; i++ ) { // Each core gets its very own tracer - RevTracer* trc = new RevTracer(getName(), &output); + RevTracer* trc = new RevTracer( getName(), &output ); std::string diasmType; - Opts->GetMachineModel(0,diasmType); // TODO first param is core - if (trc->SetDisassembler(diasmType)) - output.verbose(CALL_INFO, 1, 0, "Warning: tracer could not find disassembler. Using REV default\n"); + Opts->GetMachineModel( 0, diasmType ); // TODO first param is core + if( trc->SetDisassembler( diasmType ) ) + output.verbose( CALL_INFO, 1, 0, "Warning: tracer could not find disassembler. Using REV default\n" ); - trc->SetTraceSymbols(Loader->GetTraceSymbols()); + trc->SetTraceSymbols( Loader->GetTraceSymbols() ); // tracer user controls - cycle on and off. Ignored unless > 0 - trc->SetStartCycle(params.find("trcStartCycle",0)); - trc->SetCycleLimit(params.find("trcLimit",0)); - trc->SetCmdTemplate(params.find("trcOp", TRC_OP_DEFAULT).c_str()); + trc->SetStartCycle( params.find( "trcStartCycle", 0 ) ); + trc->SetCycleLimit( params.find( "trcLimit", 0 ) ); + trc->SetCmdTemplate( params.find( "trcOp", TRC_OP_DEFAULT ).c_str() ); // clear trace states trc->Reset(); // Assign to components - Procs[i]->SetTracer(trc); - if (Ctrl) - Ctrl->setTracer(trc); + Procs[i]->SetTracer( trc ); + if( Ctrl ) + Ctrl->setTracer( trc ); } } - #endif +#endif // Setup timeConverter - for( size_t i=0; iSetTimeConverter(timeConverter); + for( size_t i = 0; i < Procs.size(); i++ ) { + Procs[i]->SetTimeConverter( timeConverter ); } // Initial thread setup - uint32_t MainThreadID = id+1; // Prevents having MainThreadID == 0 which is reserved for INVALID + uint32_t MainThreadID = uint32_t( id ) + 1; // Prevents having MainThreadID == 0 which is reserved for INVALID - uint64_t StartAddr = 0x00ull; + uint64_t StartAddr = 0; std::string StartSymbol; - bool IsStartSymbolProvided = Opts->GetStartSymbol( id, StartSymbol ); - bool IsStartAddrProvided = Opts->GetStartAddr( id, StartAddr ) && StartAddr != 0x00ull; - uint64_t ResolvedStartSymbolAddr = (IsStartSymbolProvided) ? Loader->GetSymbolAddr(StartSymbol) : 0x00ull; + bool IsStartSymbolProvided = Opts->GetStartSymbol( uint32_t( id ), StartSymbol ); + bool IsStartAddrProvided = Opts->GetStartAddr( uint32_t( id ), StartAddr ) && StartAddr != 0; + uint64_t ResolvedStartSymbolAddr = IsStartSymbolProvided ? Loader->GetSymbolAddr( StartSymbol ) : 0; // If no start address has been provided ... - if (!IsStartAddrProvided) { + if( !IsStartAddrProvided ) { // ... check if symbol was provided ... - if (!IsStartSymbolProvided) { - // ... no, try to default to 'main' ... - StartAddr = Loader->GetSymbolAddr("main"); - if( StartAddr == 0x00ull ){ - // ... no hope left! - output.fatal(CALL_INFO, -1, - "Error: failed to auto discover address for
for main thread\n"); - } + if( !IsStartSymbolProvided ) { + // ... no, try to default to 'main' ... + StartAddr = Loader->GetSymbolAddr( "main" ); + if( StartAddr == 0 ) { + // ... no hope left! + output.fatal( + CALL_INFO, + -1, + "Error: failed to auto discover address for
for " + "main thread\n" + ); + } } else { // ... if symbol was provided, check whether it is valid or not ... - if (!ResolvedStartSymbolAddr) { + if( !ResolvedStartSymbolAddr ) { // ... not valid, error out - output.fatal(CALL_INFO, -1, - "Error: failed to resolve address for symbol <%s>\n", StartSymbol.c_str()); + output.fatal( CALL_INFO, -1, "Error: failed to resolve address for symbol <%s>\n", StartSymbol.c_str() ); } // ... valid use the resolved symbol StartAddr = ResolvedStartSymbolAddr; } - } else { // A start address was provided ... + } else { // A start address was provided ... // ... check if a symbol was provided and is compatible with the start address ... - if ((IsStartSymbolProvided) && (ResolvedStartSymbolAddr != StartAddr)) { + if( ( IsStartSymbolProvided ) && ( ResolvedStartSymbolAddr != StartAddr ) ) { // ... they are different, don't know the user intent so error out now - output.fatal(CALL_INFO, -1, - "Error: start address and start symbol differ startAddr=0x%" PRIx64 " StartSymbol=%s ResolvedStartSymbolAddr=0x%" PRIx64 "\n", - StartAddr, StartSymbol.c_str(), ResolvedStartSymbolAddr); - } // ... else no symbol provided, continue on with StartAddr as the target + output.fatal( + CALL_INFO, + -1, + "Error: start address and start symbol differ startAddr=0x%" PRIx64 " StartSymbol=%s ResolvedStartSymbolAddr=0x%" PRIx64 + "\n", + StartAddr, + StartSymbol.c_str(), + ResolvedStartSymbolAddr + ); + } // ... else no symbol provided, continue on with StartAddr as the target } - output.verbose(CALL_INFO, 11, 0, "Start address is 0x%" PRIx64 "\n", StartAddr); + output.verbose( CALL_INFO, 11, 0, "Start address is 0x%" PRIx64 "\n", StartAddr ); - InitMainThread(MainThreadID, StartAddr); + InitMainThread( MainThreadID, StartAddr ); // setup the per-proc statistics - TotalCycles.reserve(numCores); - CyclesWithIssue.reserve(numCores); - FloatsRead.reserve(numCores); - FloatsWritten.reserve(numCores); - DoublesRead.reserve(numCores); - DoublesWritten.reserve(numCores); - BytesRead.reserve(numCores); - BytesWritten.reserve(numCores); - FloatsExec.reserve(numCores); - TLBHitsPerCore.reserve(numCores); - TLBMissesPerCore.reserve(numCores); - - for(unsigned s = 0; s < numCores; s++){ - auto core = "core_" + std::to_string(s); - TotalCycles.push_back(registerStatistic("TotalCycles", core)); - CyclesWithIssue.push_back(registerStatistic("CyclesWithIssue", core)); - FloatsRead.push_back( registerStatistic("FloatsRead", core)); - FloatsWritten.push_back( registerStatistic("FloatsWritten", core)); - DoublesRead.push_back( registerStatistic("DoublesRead", core)); - DoublesWritten.push_back( registerStatistic("DoublesWritten", core)); - BytesRead.push_back( registerStatistic("BytesRead", core)); - BytesWritten.push_back( registerStatistic("BytesWritten", core)); - FloatsExec.push_back( registerStatistic("FloatsExec", core)); - TLBHitsPerCore.push_back( registerStatistic("TLBHitsPerCore", core)); - TLBMissesPerCore.push_back( registerStatistic("TLBMissesPerCore", core)); + TotalCycles.reserve( numCores ); + CyclesWithIssue.reserve( numCores ); + FloatsRead.reserve( numCores ); + FloatsWritten.reserve( numCores ); + DoublesRead.reserve( numCores ); + DoublesWritten.reserve( numCores ); + BytesRead.reserve( numCores ); + BytesWritten.reserve( numCores ); + FloatsExec.reserve( numCores ); + TLBHitsPerCore.reserve( numCores ); + TLBMissesPerCore.reserve( numCores ); + + for( uint32_t s = 0; s < numCores; s++ ) { + auto core = "core_" + std::to_string( s ); + TotalCycles.push_back( registerStatistic( "TotalCycles", core ) ); + CyclesWithIssue.push_back( registerStatistic( "CyclesWithIssue", core ) ); + FloatsRead.push_back( registerStatistic( "FloatsRead", core ) ); + FloatsWritten.push_back( registerStatistic( "FloatsWritten", core ) ); + DoublesRead.push_back( registerStatistic( "DoublesRead", core ) ); + DoublesWritten.push_back( registerStatistic( "DoublesWritten", core ) ); + BytesRead.push_back( registerStatistic( "BytesRead", core ) ); + BytesWritten.push_back( registerStatistic( "BytesWritten", core ) ); + FloatsExec.push_back( registerStatistic( "FloatsExec", core ) ); + TLBHitsPerCore.push_back( registerStatistic( "TLBHitsPerCore", core ) ); + TLBMissesPerCore.push_back( registerStatistic( "TLBMissesPerCore", core ) ); } // determine whether we need to enable/disable manual coproc clocking - DisableCoprocClock = params.find("independentCoprocClock", 0); + DisableCoprocClock = params.find( "independentCoprocClock", 0 ); // Create the completion array - Enabled = new bool [numCores]{false}; + Enabled = std::vector( numCores ); - const unsigned Splash = params.find("splash", 0); + const uint32_t Splash = params.find( "splash", 0 ); if( Splash > 0 ) - output.verbose(CALL_INFO, 1, 0, splash_msg); + output.verbose( CALL_INFO, 1, 0, splash_msg ); // Done with initialization - output.verbose(CALL_INFO, 1, 0, "Initialization of RevCPUs complete.\n"); -} - -RevCPU::~RevCPU(){ - // delete the competion array - delete[] Enabled; + output.verbose( CALL_INFO, 1, 0, "Initialization of RevCPUs complete.\n" ); - // delete the processors objects - for( size_t i = 0; i < Procs.size(); i++ ){ - delete Procs[i]; + for( const auto& [Name, Seg] : Mem->GetDumpRanges() ) { + // Open a file called '{Name}.init.dump' + std::ofstream dumpFile( Name + ".dump.init", std::ios::binary ); + Mem->DumpMemSeg( Seg, 16, dumpFile ); } - - for (size_t i = 0; i < CoProcs.size(); i++){ - delete CoProcs[i]; - } - - // delete the memory controller if present - delete Ctrl; - - // delete the memory object - delete Mem; - - // delete the loader object - delete Loader; - - // delete the options object - delete Opts; } -void RevCPU::DecodeFaultWidth(const std::string& width){ +void RevCPU::DecodeFaultWidth( const std::string& width ) { fault_width = 1; // default to single bit failures - if( width == "single" ){ + if( width == "single" ) { fault_width = 1; - }else if( width == "word" ){ + } else if( width == "word" ) { fault_width = 8; - }else{ - fault_width = std::stoi(width); + } else { + fault_width = uint32_t( std::stoul( width ) ); } - if( fault_width > 64 ){ - output.fatal(CALL_INFO, -1, "Fault width must be <= 64 bits"); + if( fault_width > 64 ) { + output.fatal( CALL_INFO, -1, "Fault width must be <= 64 bits" ); } } -void RevCPU::DecodeFaultCodes(const std::vector& faults){ - if( faults.empty() ){ - output.fatal(CALL_INFO, -1, "No fault codes defined"); +void RevCPU::DecodeFaultCodes( const std::vector& faults ) { + if( faults.empty() ) { + output.fatal( CALL_INFO, -1, "No fault codes defined" ); } EnableCrackFaults = EnableMemFaults = EnableRegFaults = EnableALUFaults = false; - for(auto& fault : faults){ - if( fault == "decode"){ + for( auto& fault : faults ) { + if( fault == "decode" ) { EnableCrackFaults = true; - }else if( fault == "mem"){ + } else if( fault == "mem" ) { EnableMemFaults = true; - }else if( fault == "reg"){ + } else if( fault == "reg" ) { EnableRegFaults = true; - }else if( fault == "alu"){ + } else if( fault == "alu" ) { EnableALUFaults = true; - }else if( fault == "all" ){ - EnableCrackFaults = EnableMemFaults = EnableRegFaults = EnableALUFaults = true; - }else{ + } else if( fault == "all" ) { + EnableCrackFaults = EnableMemFaults = EnableRegFaults = EnableALUFaults = true; + } else { output.fatal( CALL_INFO, -1, "Undefined fault code: %s", fault.c_str() ); } } } -void RevCPU::registerStatistics(){ - SyncGetSend = registerStatistic("SyncGetSend"); - SyncPutSend = registerStatistic("SyncPutSend"); - AsyncGetSend = registerStatistic("AsyncGetSend"); - AsyncPutSend = registerStatistic("AsyncPutSend"); - SyncStreamGetSend = registerStatistic("SyncStreamGetSend"); - SyncStreamPutSend = registerStatistic("SyncStreamPutSend"); - AsyncStreamGetSend = registerStatistic("AsyncStreamGetSend"); - AsyncStreamPutSend = registerStatistic("AsyncStreamPutSend"); - ExecSend = registerStatistic("ExecSend"); - StatusSend = registerStatistic("StatusSend"); - CancelSend = registerStatistic("CancelSend"); - ReserveSend = registerStatistic("ReserveSend"); - RevokeSend = registerStatistic("RevokeSend"); - HaltSend = registerStatistic("HaltSend"); - ResumeSend = registerStatistic("ResumeSend"); - ReadRegSend = registerStatistic("ReadRegSend"); - WriteRegSend = registerStatistic("WriteRegSend"); - SingleStepSend = registerStatistic("SingleStepSend"); - SetFutureSend = registerStatistic("SetFutureSend"); - RevokeFutureSend = registerStatistic("RevokeFutureSend"); - StatusFutureSend = registerStatistic("StatusFutureSend"); - SuccessSend = registerStatistic("SuccessSend"); - FailedSend = registerStatistic("FailedSend"); - BOTWSend = registerStatistic("BOTWSend"); - SyncGetRecv = registerStatistic("SyncGetRecv"); - SyncPutRecv = registerStatistic("SyncPutRecv"); - AsyncGetRecv = registerStatistic("AsyncGetRecv"); - AsyncPutRecv = registerStatistic("AsyncPutRecv"); - SyncStreamGetRecv = registerStatistic("SyncStreamGetRecv"); - SyncStreamPutRecv = registerStatistic("SyncStreamPutRecv"); - AsyncStreamGetRecv = registerStatistic("AsyncStreamGetRecv"); - AsyncStreamPutRecv = registerStatistic("AsyncStreamPutRecv"); - ExecRecv = registerStatistic("ExecRecv"); - StatusRecv = registerStatistic("StatusRecv"); - CancelRecv = registerStatistic("CancelRecv"); - ReserveRecv = registerStatistic("ReserveRecv"); - RevokeRecv = registerStatistic("RevokeRecv"); - HaltRecv = registerStatistic("HaltRecv"); - ResumeRecv = registerStatistic("ResumeRecv"); - ReadRegRecv = registerStatistic("ReadRegRecv"); - WriteRegRecv = registerStatistic("WriteRegRecv"); - SingleStepRecv = registerStatistic("SingleStepRecv"); - SetFutureRecv = registerStatistic("SetFutureRecv"); - RevokeFutureRecv = registerStatistic("RevokeFutureRecv"); - StatusFutureRecv = registerStatistic("StatusFutureRecv"); - SuccessRecv = registerStatistic("SuccessRecv"); - FailedRecv = registerStatistic("FailedRecv"); - BOTWRecv = registerStatistic("BOTWRecv"); +void RevCPU::registerStatistics() { + SyncGetSend = registerStatistic( "SyncGetSend" ); + SyncPutSend = registerStatistic( "SyncPutSend" ); + AsyncGetSend = registerStatistic( "AsyncGetSend" ); + AsyncPutSend = registerStatistic( "AsyncPutSend" ); + SyncStreamGetSend = registerStatistic( "SyncStreamGetSend" ); + SyncStreamPutSend = registerStatistic( "SyncStreamPutSend" ); + AsyncStreamGetSend = registerStatistic( "AsyncStreamGetSend" ); + AsyncStreamPutSend = registerStatistic( "AsyncStreamPutSend" ); + ExecSend = registerStatistic( "ExecSend" ); + StatusSend = registerStatistic( "StatusSend" ); + CancelSend = registerStatistic( "CancelSend" ); + ReserveSend = registerStatistic( "ReserveSend" ); + RevokeSend = registerStatistic( "RevokeSend" ); + HaltSend = registerStatistic( "HaltSend" ); + ResumeSend = registerStatistic( "ResumeSend" ); + ReadRegSend = registerStatistic( "ReadRegSend" ); + WriteRegSend = registerStatistic( "WriteRegSend" ); + SingleStepSend = registerStatistic( "SingleStepSend" ); + SetFutureSend = registerStatistic( "SetFutureSend" ); + RevokeFutureSend = registerStatistic( "RevokeFutureSend" ); + StatusFutureSend = registerStatistic( "StatusFutureSend" ); + SuccessSend = registerStatistic( "SuccessSend" ); + FailedSend = registerStatistic( "FailedSend" ); + BOTWSend = registerStatistic( "BOTWSend" ); + SyncGetRecv = registerStatistic( "SyncGetRecv" ); + SyncPutRecv = registerStatistic( "SyncPutRecv" ); + AsyncGetRecv = registerStatistic( "AsyncGetRecv" ); + AsyncPutRecv = registerStatistic( "AsyncPutRecv" ); + SyncStreamGetRecv = registerStatistic( "SyncStreamGetRecv" ); + SyncStreamPutRecv = registerStatistic( "SyncStreamPutRecv" ); + AsyncStreamGetRecv = registerStatistic( "AsyncStreamGetRecv" ); + AsyncStreamPutRecv = registerStatistic( "AsyncStreamPutRecv" ); + ExecRecv = registerStatistic( "ExecRecv" ); + StatusRecv = registerStatistic( "StatusRecv" ); + CancelRecv = registerStatistic( "CancelRecv" ); + ReserveRecv = registerStatistic( "ReserveRecv" ); + RevokeRecv = registerStatistic( "RevokeRecv" ); + HaltRecv = registerStatistic( "HaltRecv" ); + ResumeRecv = registerStatistic( "ResumeRecv" ); + ReadRegRecv = registerStatistic( "ReadRegRecv" ); + WriteRegRecv = registerStatistic( "WriteRegRecv" ); + SingleStepRecv = registerStatistic( "SingleStepRecv" ); + SetFutureRecv = registerStatistic( "SetFutureRecv" ); + RevokeFutureRecv = registerStatistic( "RevokeFutureRecv" ); + StatusFutureRecv = registerStatistic( "StatusFutureRecv" ); + SuccessRecv = registerStatistic( "SuccessRecv" ); + FailedRecv = registerStatistic( "FailedRecv" ); + BOTWRecv = registerStatistic( "BOTWRecv" ); } -void RevCPU::setup(){ - if( EnableNIC ){ +void RevCPU::setup() { + if( EnableNIC ) { Nic->setup(); address = Nic->getAddress(); } - if( EnableMemH ){ + if( EnableMemH ) { Ctrl->setup(); } } -void RevCPU::finish(){ -} +void RevCPU::finish() {} -void RevCPU::init( unsigned int phase ){ +void RevCPU::init( uint32_t phase ) { if( EnableNIC ) - Nic->init(phase); + Nic->init( phase ); if( EnableMemH ) - Ctrl->init(phase); + Ctrl->init( phase ); } -void RevCPU::handleMessage(Event *ev){ - nicEvent *event = static_cast(ev); +void RevCPU::handleMessage( Event* ev ) { + nicEvent* event = static_cast( ev ); // -- RevNIC: This is where you can unpack and handle the data payload delete event; } -uint8_t RevCPU::createTag(){ +uint8_t RevCPU::createTag() { uint8_t rtn = 0; - if( PrivTag == 0b11111111 ){ - rtn = 0b00000000; + if( PrivTag == 0b11111111 ) { PrivTag = 0b00000001; - return 0b00000000; - }else{ - rtn = PrivTag; - PrivTag +=1; + } else { + rtn = PrivTag++; } return rtn; } -void RevCPU::HandleCrackFault(SST::Cycle_t currentCycle){ - output.verbose(CALL_INFO, 4, 0, "FAULT: Crack fault injected at cycle: %" PRIu64 "\n", - currentCycle); +void RevCPU::HandleCrackFault( SST::Cycle_t currentCycle ) { + output.verbose( CALL_INFO, 4, 0, "FAULT: Crack fault injected at cycle: %" PRIu64 "\n", currentCycle ); // select a random processor core - unsigned Core = 0; - if( numCores > 1 ){ - Core = RevRand(0, numCores-1); + uint32_t Core = 0; + if( numCores > 1 ) { + Core = RevRand( 0, numCores - 1 ); } - Procs[Core]->HandleCrackFault(fault_width); + Procs[Core]->HandleCrackFault( fault_width ); } -void RevCPU::HandleMemFault(SST::Cycle_t currentCycle){ - output.verbose(CALL_INFO, 4, 0, "FAULT: Memory fault injected at cycle: %" PRIu64 "\n", - currentCycle); - Mem->HandleMemFault(fault_width); +void RevCPU::HandleMemFault( SST::Cycle_t currentCycle ) { + output.verbose( CALL_INFO, 4, 0, "FAULT: Memory fault injected at cycle: %" PRIu64 "\n", currentCycle ); + Mem->HandleMemFault( fault_width ); } -void RevCPU::HandleRegFault(SST::Cycle_t currentCycle){ - output.verbose(CALL_INFO, 4, 0, "FAULT: Register fault injected at cycle: %" PRIu64 "\n", - currentCycle); +void RevCPU::HandleRegFault( SST::Cycle_t currentCycle ) { + output.verbose( CALL_INFO, 4, 0, "FAULT: Register fault injected at cycle: %" PRIu64 "\n", currentCycle ); // select a random processor core - unsigned Core = 0; - if( numCores > 1 ){ - Core = RevRand(0, numCores-1); + uint32_t Core = 0; + if( numCores > 1 ) { + Core = RevRand( 0, numCores - 1 ); } - Procs[Core]->HandleRegFault(fault_width); + Procs[Core]->HandleRegFault( fault_width ); } -void RevCPU::HandleALUFault(SST::Cycle_t currentCycle){ - output.verbose(CALL_INFO, 4, 0, "FAULT: ALU fault injected at cycle: %" PRIu64 "\n", - currentCycle); +void RevCPU::HandleALUFault( SST::Cycle_t currentCycle ) { + output.verbose( CALL_INFO, 4, 0, "FAULT: ALU fault injected at cycle: %" PRIu64 "\n", currentCycle ); // select a random processor core - unsigned Core = 0; - if( numCores > 1 ){ - Core = RevRand(0, numCores-1); + uint32_t Core = 0; + if( numCores > 1 ) { + Core = RevRand( 0, numCores - 1 ); } - Procs[Core]->HandleALUFault(fault_width); + Procs[Core]->HandleALUFault( fault_width ); } -void RevCPU::HandleFaultInjection(SST::Cycle_t currentCycle){ +void RevCPU::HandleFaultInjection( SST::Cycle_t currentCycle ) { // build up a vector of faults // then randomly determine which one to inject std::vector myfaults; - if( EnableCrackFaults ){ - myfaults.push_back("crack"); + if( EnableCrackFaults ) { + myfaults.push_back( "crack" ); } - if( EnableMemFaults ){ - myfaults.push_back("mem"); + if( EnableMemFaults ) { + myfaults.push_back( "mem" ); } - if( EnableRegFaults ){ - myfaults.push_back("reg"); + if( EnableRegFaults ) { + myfaults.push_back( "reg" ); } - if( EnableALUFaults ){ - myfaults.push_back("alu"); + if( EnableALUFaults ) { + myfaults.push_back( "alu" ); } - if( myfaults.size() == 0 ){ - output.fatal(CALL_INFO, -1, - "Error: no faults enabled; add a fault vector in the 'faults' param\n" ); + if( myfaults.size() == 0 ) { + output.fatal( CALL_INFO, -1, "Error: no faults enabled; add a fault vector in the 'faults' param\n" ); } - unsigned selector = 0; - if( myfaults.size() != 1 ){ - selector = RevRand(0, int(myfaults.size())-1); + uint32_t selector = 0; + if( myfaults.size() != 1 ) { + selector = RevRand( 0u, int( myfaults.size() ) - 1 ); } // handle the selected fault - if( myfaults[selector] == "crack" ){ - HandleCrackFault(currentCycle); - }else if( myfaults[selector] == "mem" ){ - HandleMemFault(currentCycle); - }else if( myfaults[selector] == "reg" ){ - HandleRegFault(currentCycle); - }else if( myfaults[selector] == "alu" ){ - HandleALUFault(currentCycle); - }else{ - output.fatal(CALL_INFO, -1, "Error: erroneous fault selection\n" ); + if( myfaults[selector] == "crack" ) { + HandleCrackFault( currentCycle ); + } else if( myfaults[selector] == "mem" ) { + HandleMemFault( currentCycle ); + } else if( myfaults[selector] == "reg" ) { + HandleRegFault( currentCycle ); + } else if( myfaults[selector] == "alu" ) { + HandleALUFault( currentCycle ); + } else { + output.fatal( CALL_INFO, -1, "Error: erroneous fault selection\n" ); } } -void RevCPU::UpdateCoreStatistics(unsigned coreNum){ - auto [ stats, memStats ] = Procs[coreNum]->GetAndClearStats(); - TotalCycles[coreNum]->addData(stats.totalCycles); - CyclesWithIssue[coreNum]->addData(stats.cyclesBusy); - FloatsRead[coreNum]->addData(memStats.floatsRead); - FloatsWritten[coreNum]->addData(memStats.floatsWritten); - DoublesRead[coreNum]->addData(memStats.doublesRead); - DoublesWritten[coreNum]->addData(memStats.doublesWritten); - BytesRead[coreNum]->addData(memStats.bytesRead); - BytesWritten[coreNum]->addData(memStats.bytesWritten); - FloatsExec[coreNum]->addData(stats.floatsExec); - TLBHitsPerCore[coreNum]->addData(memStats.TLBHits); - TLBMissesPerCore[coreNum]->addData(memStats.TLBMisses); +void RevCPU::UpdateCoreStatistics( uint32_t coreNum ) { + auto [stats, memStats] = Procs[coreNum]->GetAndClearStats(); + TotalCycles[coreNum]->addData( stats.totalCycles ); + CyclesWithIssue[coreNum]->addData( stats.cyclesBusy ); + FloatsRead[coreNum]->addData( memStats.floatsRead ); + FloatsWritten[coreNum]->addData( memStats.floatsWritten ); + DoublesRead[coreNum]->addData( memStats.doublesRead ); + DoublesWritten[coreNum]->addData( memStats.doublesWritten ); + BytesRead[coreNum]->addData( memStats.bytesRead ); + BytesWritten[coreNum]->addData( memStats.bytesWritten ); + FloatsExec[coreNum]->addData( stats.floatsExec ); + TLBHitsPerCore[coreNum]->addData( memStats.TLBHits ); + TLBMissesPerCore[coreNum]->addData( memStats.TLBMisses ); } -bool RevCPU::clockTick( SST::Cycle_t currentCycle ){ +bool RevCPU::clockTick( SST::Cycle_t currentCycle ) { bool rtn = true; - output.verbose(CALL_INFO, 8, 0, "Cycle: %" PRIu64 "\n", currentCycle); + output.verbose( CALL_INFO, 8, 0, "Cycle: %" PRIu64 "\n", currentCycle ); // Execute each enabled core - for( size_t i=0; iClockTick(currentCycle) ){ - if(EnableCoProc && !CoProcs.empty()){ + UpdateThreadAssignments( i ); + if( Enabled[i] ) { + if( !Procs[i]->ClockTick( currentCycle ) ) { + if( EnableCoProc && !CoProcs.empty() ) { CoProcs[i]->Teardown(); } - UpdateCoreStatistics(i); + UpdateCoreStatistics( i ); Enabled[i] = false; - output.verbose(CALL_INFO, 5, 0, "Closing Processor %zu at Cycle: %" PRIu64 "\n", - i, currentCycle); + output.verbose( CALL_INFO, 5, 0, "Closing Processor %" PRIu32 " at Cycle: %" PRIu64 "\n", i, currentCycle ); } - if(EnableCoProc && - !CoProcs[i]->ClockTick(currentCycle) && - !DisableCoprocClock){ - output.verbose(CALL_INFO, 5, 0, "Closing Co-Processor %zu at Cycle: %" PRIu64 "\n", - i, currentCycle); - + if( EnableCoProc && !CoProcs[i]->ClockTick( currentCycle ) && !DisableCoprocClock ) { + output.verbose( CALL_INFO, 5, 0, "Closing Co-Processor %" PRIu32 " at Cycle: %" PRIu64 "\n", i, currentCycle ); } } // See if any of the threads on this proc changes state - HandleThreadStateChangesForProc(i); + HandleThreadStateChangesForProc( i ); - if( Procs[i]->HasNoBusyHarts() ){ + if( Procs[i]->HasNoBusyHarts() ) { Enabled[i] = false; } } // check to see if we need to inject a fault - if( EnableFaults ){ - if( FaultCntr == 0 ){ + if( EnableFaults ) { + if( FaultCntr == 0 ) { // inject a fault - HandleFaultInjection(currentCycle); + HandleFaultInjection( currentCycle ); // reset the fault counter FaultCntr = fault_width; - }else{ + } else { FaultCntr--; } } // check to see if all the processors are completed - for( size_t i=0; iPrintStatSummary(); } + + for( const auto& [Name, Seg] : Mem->GetDumpRanges() ) { + // Open a file called '{Name}.init.dump' + std::ofstream dumpFile( Name + ".dump.final", std::ios::binary ); + Mem->DumpMemSeg( Seg, 16, dumpFile ); + } primaryComponentOKToEndSim(); - output.verbose(CALL_INFO, 5, 0, "OK to end sim at cycle: %" PRIu64 "\n", static_cast(currentCycle)); + output.verbose( CALL_INFO, 5, 0, "OK to end sim at cycle: %" PRIu64 "\n", static_cast( currentCycle ) ); } else { rtn = false; } @@ -665,47 +637,48 @@ bool RevCPU::clockTick( SST::Cycle_t currentCycle ){ return rtn; } - // Initializes a RevThread object. // - Moves it to the 'Threads' map // - Adds it's ThreadID to the ReadyThreads to be scheduled -void RevCPU::InitThread(std::unique_ptr&& ThreadToInit){ +void RevCPU::InitThread( std::unique_ptr&& ThreadToInit ) { // Get a pointer to the register state for this thread std::unique_ptr RegState = ThreadToInit->TransferVirtRegState(); + // Set the global pointer register and the frame pointer register - auto gp = Loader->GetSymbolAddr("__global_pointer$"); - RegState->SetX(RevReg::gp, gp); - RegState->SetX(RevReg::s0, gp); // s0 = x8 = frame pointer register + auto gp = Loader->GetSymbolAddr( "__global_pointer$" ); + RegState->SetX( RevReg::gp, gp ); + RegState->SetX( RevReg::fp, gp ); + // Set state to Ready - ThreadToInit->SetState(ThreadState::READY); - output.verbose(CALL_INFO, 4, 0, "Initializing Thread %" PRIu32 "\n", ThreadToInit->GetID()); - output.verbose(CALL_INFO, 11, 0, "Thread Information: %s", ThreadToInit->to_string().c_str()); - ReadyThreads.emplace_back(std::move(ThreadToInit)); + ThreadToInit->SetState( ThreadState::READY ); + output.verbose( CALL_INFO, 4, 0, "Initializing Thread %" PRIu32 "\n", ThreadToInit->GetID() ); + output.verbose( CALL_INFO, 11, 0, "Thread Information: %s", ThreadToInit->to_string().c_str() ); + ReadyThreads.emplace_back( std::move( ThreadToInit ) ); } // Assigns a RevThred to a specific Proc which then loads it into a RevHart // This should not be called without first checking if the Proc has an IdleHart -void RevCPU::AssignThread(std::unique_ptr&& ThreadToAssign, unsigned ProcID){ - output.verbose(CALL_INFO, 4, 0, "Assigning Thread %" PRIu32 " to Processor %" PRIu32 "\n", ThreadToAssign->GetID(), ProcID); - Procs[ProcID]->AssignThread(std::move(ThreadToAssign)); +void RevCPU::AssignThread( std::unique_ptr&& ThreadToAssign, uint32_t ProcID ) { + output.verbose( CALL_INFO, 4, 0, "Assigning Thread %" PRIu32 " to Processor %" PRIu32 "\n", ThreadToAssign->GetID(), ProcID ); + Procs[ProcID]->AssignThread( std::move( ThreadToAssign ) ); return; } // Checks if a thread with a given Thread ID can proceed (used for pthread_join). // it does this by seeing if a given thread's WaitingOnTID has completed -bool RevCPU::ThreadCanProceed(const std::unique_ptr& Thread){ - bool rtn = false; +bool RevCPU::ThreadCanProceed( const std::unique_ptr& Thread ) { + bool rtn = false; // Get the thread's waiting to join TID uint32_t WaitingOnTID = Thread->GetWaitingToJoinTID(); // If the thread is waiting on another thread, check if that thread has completed - if( WaitingOnTID != _INVALID_TID_ ){ + if( WaitingOnTID != _INVALID_TID_ ) { // Check if WaitingOnTID has completed... if so, return = true, else return false - output.verbose(CALL_INFO, 6, 0, "Thread %" PRIu32 " is waiting on Thread %u\n", Thread->GetID(), WaitingOnTID); + output.verbose( CALL_INFO, 6, 0, "Thread %" PRIu32 " is waiting on Thread %" PRIu32 "\n", Thread->GetID(), WaitingOnTID ); // Check if the WaitingOnTID has completed, if not, thread cannot proceed - rtn = ( CompletedThreads.find(WaitingOnTID) != CompletedThreads.end() ) ? true : false; + rtn = ( CompletedThreads.find( WaitingOnTID ) != CompletedThreads.end() ) ? true : false; } // If the thread is not waiting on another thread, it can proceed else { @@ -719,136 +692,156 @@ bool RevCPU::ThreadCanProceed(const std::unique_ptr& Thread){ // Checks if any of the blocked threads can proceed based on if the thread // they were waiting on has completed -void RevCPU::CheckBlockedThreads(){ +void RevCPU::CheckBlockedThreads() { // Iterate over all block threads for( auto it = BlockedThreads.begin(); it != BlockedThreads.end(); ) { - if( ThreadCanProceed(*it) ){ - ReadyThreads.emplace_back(std::move(*it)); - it = BlockedThreads.erase(it); - }else{ + if( ThreadCanProceed( *it ) ) { + ReadyThreads.emplace_back( std::move( *it ) ); + it = BlockedThreads.erase( it ); + } else { ++it; } } return; } -// ---------------------------------- -// We need to initialize the x10 register to include the value of ARGC -// This is >= 1 (the executable name is always included) -// We also need to initialize the ARGV pointer to the value -// of the ARGV base pointer in memory which is currently set to the -// program header region. When we come out of reset, this is StackTop+60 bytes -// ---------------------------------- -void RevCPU::SetupArgs(const std::unique_ptr& RegFile){ - auto Argv = Opts->GetArgv(); - // setup argc - RegFile->SetX(RevReg::a0, Argv.size()); - RegFile->SetX(RevReg::a1, Mem->GetStackTop() + 60); - return; -} - // Checks core 'i' to see if it has any available harts to assign work to // if it does and there is work to assign (ie. ReadyThreads is not empty) // assign it and enable the processor if not already enabled. -void RevCPU::UpdateThreadAssignments(uint32_t ProcID){ +void RevCPU::UpdateThreadAssignments( uint32_t ProcID ) { // Check if we have anything to assign - if( ReadyThreads.empty() ){ + if( ReadyThreads.empty() ) { return; } // There is work to assign, check if this proc has room - if( Procs[ProcID]->HasIdleHart() ){ + if( Procs[ProcID]->HasIdleHart() ) { // There is room, assign a thread // Get the next thread to assign - Procs[ProcID]->AssignThread(std::move(ReadyThreads.front())); + Procs[ProcID]->AssignThread( std::move( ReadyThreads.front() ) ); // Remove thread from ready threads vector - ReadyThreads.erase(ReadyThreads.begin()); + ReadyThreads.erase( ReadyThreads.begin() ); // Proc has a thread assigned to it, enable it - Enabled[ProcID] = true; + Enabled[ProcID] = true; } return; } // Checks for state changes in the threads of a given processor index 'i' // and handle appropriately -void RevCPU::HandleThreadStateChangesForProc(uint32_t ProcID){ +void RevCPU::HandleThreadStateChangesForProc( uint32_t ProcID ) { // Handle any thread state changes for this core // NOTE: At this point we handle EVERY thread that changed state every cycle - for( auto& Thread : Procs[ProcID]->TransferThreadsThatChangedState()){ + for( auto& Thread : Procs[ProcID]->TransferThreadsThatChangedState() ) { uint32_t ThreadID = Thread->GetID(); // Handle the thread that changed state based on the new state - switch ( Thread->GetState() ) { + switch( Thread->GetState() ) { case ThreadState::DONE: // This thread has completed execution - output.verbose(CALL_INFO, 8, 0, "Thread %" PRIu32 " on Core %" PRIu32 " is DONE\n", ThreadID, ProcID); - CompletedThreads.emplace(ThreadID, std::move(Thread)); + output.verbose( CALL_INFO, 8, 0, "Thread %" PRIu32 " on Core %" PRIu32 " is DONE\n", ThreadID, ProcID ); + CompletedThreads.emplace( ThreadID, std::move( Thread ) ); break; case ThreadState::BLOCKED: // This thread is blocked (currently only caused by a rev_pthread_join) - output.verbose(CALL_INFO, 8, 0, "Thread %" PRIu32 "on Core %" PRIu32 " is BLOCKED\n", ThreadID, ProcID); + output.verbose( CALL_INFO, 8, 0, "Thread %" PRIu32 "on Core %" PRIu32 " is BLOCKED\n", ThreadID, ProcID ); // Set its state to BLOCKED - Thread->SetState(ThreadState::BLOCKED); + Thread->SetState( ThreadState::BLOCKED ); // Add it to BlockedThreads - BlockedThreads.emplace_back(std::move(Thread)); + BlockedThreads.emplace_back( std::move( Thread ) ); break; case ThreadState::START: // A new thread was created - output.verbose(CALL_INFO, 99, 1, "A new thread with ID = %" PRIu32 " was found on Core %" PRIu32, Thread->GetID(), ProcID); + output.verbose( CALL_INFO, 99, 1, "A new thread with ID = %" PRIu32 " was found on Core %" PRIu32, Thread->GetID(), ProcID ); // Mark it ready for execution - Thread->SetState(ThreadState::READY); + Thread->SetState( ThreadState::READY ); // Add it to the ReadyThreads so it is scheduled - ReadyThreads.emplace_back(std::move(Thread)); + ReadyThreads.emplace_back( std::move( Thread ) ); break; case ThreadState::RUNNING: - output.verbose(CALL_INFO, 11, 0, "Thread %" PRIu32 " on Core %" PRIu32 " is RUNNING\n", ThreadID, ProcID); + output.verbose( CALL_INFO, 11, 0, "Thread %" PRIu32 " on Core %" PRIu32 " is RUNNING\n", ThreadID, ProcID ); break; case ThreadState::READY: // If this happens we are not setting state when assigning thread somewhere - output.fatal(CALL_INFO, 99, "Error: Thread %" PRIu32 " on Core %" PRIu32 " is assigned but is in READY state... This is a bug\n", - ThreadID, ProcID); + output.fatal( + CALL_INFO, + 99, + "Error: Thread %" PRIu32 " on Core %" PRIu32 " is assigned but is in READY state... This is a bug\n", + ThreadID, + ProcID + ); break; - default: // Should DEFINITELY never happen - output.fatal(CALL_INFO, 99, "Error: Thread %" PRIu32 " on Core %" PRIu32 " is in an unknown state... This is a bug.\n%s\n", - ThreadID, ProcID, Thread->to_string().c_str()); + default: // Should DEFINITELY never happen + output.fatal( + CALL_INFO, + 99, + "Error: Thread %" PRIu32 " on Core %" PRIu32 " is in an unknown state... This is a bug.\n%s\n", + ThreadID, + ProcID, + Thread->to_string().c_str() + ); break; } // If the Proc does not have any threads assigned to it, there is no work to do, it is disabled - if( Procs[ProcID]->HasNoWork() ){ + if( Procs[ProcID]->HasNoWork() ) { Enabled[ProcID] = false; } } } -void RevCPU::InitMainThread(uint32_t MainThreadID, const uint64_t StartAddr){ - // @Lee: Is there a better way to get the feature info? - std::unique_ptr MainThreadRegState = std::make_unique(Procs[0]->GetRevFeature()); - MainThreadRegState->SetPC(StartAddr); - MainThreadRegState->SetX(RevReg::tp,Mem->GetThreadMemSegs().front()->getTopAddr()); - MainThreadRegState->SetX(RevReg::sp,Mem->GetThreadMemSegs().front()->getTopAddr()-Mem->GetTLSSize()); - MainThreadRegState->SetX(RevReg::gp, Loader->GetSymbolAddr("__global_pointer$")); - MainThreadRegState->SetX(8, Loader->GetSymbolAddr("__global_pointer$")); - SetupArgs(MainThreadRegState); - std::unique_ptr MainThread = std::make_unique(MainThreadID, - _INVALID_TID_, // No Parent Thread ID - Mem->GetThreadMemSegs().front(), - std::move(MainThreadRegState)); - MainThread->SetState(ThreadState::READY); - - output.verbose(CALL_INFO, 11, 0, "Main thread initialized %s\n", MainThread->to_string().c_str()); +void RevCPU::InitMainThread( uint32_t MainThreadID, const uint64_t StartAddr ) { + auto MainThreadRegState = std::make_unique( Procs[0].get() ); + + // The Program Counter gets set to the start address + MainThreadRegState->SetPC( StartAddr ); + + // We need to initialize the a0 register to the value of ARGC. + // This is >= 1 (the executable name is always included). + // We also need to initialize the a1 register to the ARGV pointer + // of the ARGV base pointer in memory which is currently set to + // the top of stack. + uint64_t stackTop = Mem->GetStackTop(); + MainThreadRegState->SetX( RevReg::a0, Opts->GetArgv().size() + 1 ); + MainThreadRegState->SetX( RevReg::a1, stackTop ); + + // We subtract Mem->GetTLSSize() bytes from the current stack top, and + // round down to a multiple of 16 bytes. We set it as the new top of stack. + stackTop = ( stackTop - Mem->GetTLSSize() ) & ~uint64_t{ 15 }; + Mem->SetStackTop( stackTop ); + + // We set the stack pointer and the thread pointer to the new stack top + // The thread local storage is accessed with a nonnegative offset from tp, + // and the stack grows down with sp being subtracted from before storing. + MainThreadRegState->SetX( RevReg::sp, stackTop ); + MainThreadRegState->SetX( RevReg::tp, stackTop ); + + auto gp = Loader->GetSymbolAddr( "__global_pointer$" ); + MainThreadRegState->SetX( RevReg::gp, gp ); + MainThreadRegState->SetX( RevReg::fp, gp ); + + std::unique_ptr MainThread = std::make_unique( + MainThreadID, + _INVALID_TID_, // No Parent Thread ID + Mem->GetThreadMemSegs().front(), + std::move( MainThreadRegState ) + ); + MainThread->SetState( ThreadState::READY ); + + output.verbose( CALL_INFO, 11, 0, "Main thread initialized %s\n", MainThread->to_string().c_str() ); // Add to ReadyThreads so it gets scheduled - ReadyThreads.emplace_back(std::move(MainThread)); + ReadyThreads.emplace_back( std::move( MainThread ) ); } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevCoProc.cc b/src/RevCoProc.cc index 61cdf9f7f..d5c9917ae 100644 --- a/src/RevCoProc.cc +++ b/src/RevCoProc.cc @@ -10,32 +10,30 @@ #include "RevCoProc.h" -using namespace SST; -using namespace RevCPU; - +namespace SST::RevCPU { // --------------------------------------------------------------- // RevCoProc // --------------------------------------------------------------- -RevCoProc::RevCoProc(ComponentId_t id, Params& params, RevProc* parent) - : SubComponent(id), output(nullptr), parent(parent) { +RevCoProc::RevCoProc( ComponentId_t id, Params& params, RevCore* parent ) + : SubComponent( id ), output( nullptr ), parent( parent ) { - uint32_t verbosity = params.find("verbose"); - output = new SST::Output("[RevCoProc @t]: ", verbosity, 0, SST::Output::STDOUT); + uint32_t verbosity = params.find( "verbose" ); + output = new SST::Output( "[RevCoProc @t]: ", verbosity, 0, SST::Output::STDOUT ); } -RevCoProc::~RevCoProc(){ +RevCoProc::~RevCoProc() { delete output; } // --------------------------------------------------------------- // RevSimpleCoProc // --------------------------------------------------------------- -RevSimpleCoProc::RevSimpleCoProc(ComponentId_t id, Params& params, RevProc* parent) - : RevCoProc(id, params, parent), num_instRetired(0) { +RevSimpleCoProc::RevSimpleCoProc( ComponentId_t id, Params& params, RevCore* parent ) + : RevCoProc( id, params, parent ), num_instRetired( 0 ) { - std::string ClockFreq = params.find("clock", "1Ghz"); - cycleCount = 0; + std::string ClockFreq = params.find( "clock", "1Ghz" ); + cycleCount = 0; registerStats(); @@ -45,39 +43,37 @@ RevSimpleCoProc::RevSimpleCoProc(ComponentId_t id, Params& params, RevProc* pare output->output("Registering subcomponent RevSimpleCoProc with frequency=%s\n", ClockFreq.c_str());*/ } -RevSimpleCoProc::~RevSimpleCoProc(){ - -}; - -bool RevSimpleCoProc::IssueInst(RevFeature *F, RevRegFile *R, RevMem *M, uint32_t Inst){ - RevCoProcInst inst = RevCoProcInst(Inst, F, R, M); +bool RevSimpleCoProc::IssueInst( const RevFeature* F, RevRegFile* R, RevMem* M, uint32_t Inst ) { + RevCoProcInst inst = RevCoProcInst( Inst, F, R, M ); std::cout << "CoProc instruction issued: " << std::hex << Inst << std::dec << std::endl; //parent->ExternalDepSet(CreatePasskey(), F->GetHartToExecID(), 7, false); - InstQ.push(inst); + InstQ.push( inst ); return true; } -void RevSimpleCoProc::registerStats(){ - num_instRetired = registerStatistic("InstRetired"); +void RevSimpleCoProc::registerStats() { + num_instRetired = registerStatistic( "InstRetired" ); } -bool RevSimpleCoProc::Reset(){ +bool RevSimpleCoProc::Reset() { InstQ = {}; return true; } -bool RevSimpleCoProc::ClockTick(SST::Cycle_t cycle){ - if(!InstQ.empty()){ +bool RevSimpleCoProc::ClockTick( SST::Cycle_t cycle ) { + if( !InstQ.empty() ) { uint32_t inst = InstQ.front().Inst; //parent->ExternalDepClear(CreatePasskey(), InstQ.front().Feature->GetHartToExecID(), 7, false); - num_instRetired->addData(1); - parent->ExternalStallHart(CreatePasskey(), 0); + num_instRetired->addData( 1 ); + parent->ExternalStallHart( CreatePasskey(), 0 ); InstQ.pop(); std::cout << "CoProcessor to execute instruction: " << std::hex << inst << std::endl; cycleCount = cycle; } - if((cycle - cycleCount) > 500){ - parent->ExternalReleaseHart(CreatePasskey(), 0); - } + if( ( cycle - cycleCount ) > 500 ) { + parent->ExternalReleaseHart( CreatePasskey(), 0 ); + } return true; } + +} // namespace SST::RevCPU diff --git a/src/RevCore.cc b/src/RevCore.cc new file mode 100644 index 000000000..ae02c9d41 --- /dev/null +++ b/src/RevCore.cc @@ -0,0 +1,2077 @@ +// +// _RevCore_cc_ +// +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "RevCore.h" +#include "RevSysCalls.cc" +#include "sst/core/output.h" + +namespace SST::RevCPU { + +using MemSegment = RevMem::MemSegment; + +std::unique_ptr RevCore::CreateFeature() { + // initialize the machine model for the target core + std::string Machine; + if( !opts->GetMachineModel( id, Machine ) ) + output->fatal( CALL_INFO, -1, "Error: failed to retrieve the machine model for core=%" PRIu32 "\n", id ); + + uint32_t MinCost = 0; + uint32_t MaxCost = 0; + + opts->GetMemCost( id, MinCost, MaxCost ); + + return std::make_unique( std::move( Machine ), output, MinCost, MaxCost, id ); +} + +RevCore::RevCore( + uint32_t id, + RevOpts* opts, + uint32_t numHarts, + RevMem* mem, + RevLoader* loader, + std::function GetNewTID, + SST::Output* output +) + : id( id ), numHarts( numHarts ), opts( opts ), mem( mem ), loader( loader ), GetNewThreadID( std::move( GetNewTID ) ), + output( output ), featureUP( CreateFeature() ) { + + LSQueue = std::make_shared>(); + LSQueue->clear(); + + // Create the Hart Objects + for( uint32_t i = 0; i < numHarts; i++ ) { + Harts.emplace_back( new RevHart( i, LSQueue, [=]( const MemReq& req ) { this->MarkLoadComplete( req ); } ) ); + ValidHarts.set( i, true ); + } + + uint32_t Depth = 0; + opts->GetPrefetchDepth( id, Depth ); + if( Depth == 0 ) { + Depth = 16; + } + + sfetch = + std::make_unique( mem, feature, Depth, LSQueue, [=]( const MemReq& req ) { this->MarkLoadComplete( req ); } ); + if( !sfetch ) + output->fatal( CALL_INFO, -1, "Error: failed to create the RevPrefetcher object for core=%" PRIu32 "\n", id ); + + // load the instruction tables + if( !LoadInstructionTable() ) + output->fatal( CALL_INFO, -1, "Error : failed to load instruction table for core=%" PRIu32 "\n", id ); + + // reset the core + if( !Reset() ) + output->fatal( CALL_INFO, -1, "Error: failed to reset the core resources for core=%" PRIu32 "\n", id ); +} + +bool RevCore::Halt() { + if( Halted ) + return false; + Halted = true; + SingleStep = false; + return true; +} + +bool RevCore::Resume() { + if( Halted ) { + Halted = false; + SingleStep = false; + return true; + } + return false; +} + +bool RevCore::SingleStepHart() { + if( SingleStep ) + return true; + if( Halted ) { + Halted = false; + SingleStep = true; + return true; + } else { + // must be halted to single step + return false; + } +} + +void RevCore::SetCoProc( RevCoProc* coproc ) { + if( coProc == nullptr ) { + coProc = coproc; + } else { + output->fatal( + CALL_INFO, + -1, + "CONFIG ERROR: Core %" PRIu32 " : Attempting to assign a " + "co-processor when one is already present\n", + id + ); + } +} + +bool RevCore::EnableExt( RevExt* Ext ) { + if( !Ext ) + output->fatal( CALL_INFO, -1, "Error: failed to initialize RISC-V extensions\n" ); + + output->verbose( CALL_INFO, 6, 0, "Core %" PRIu32 " ; Enabling extension=%s\n", id, Ext->GetName().data() ); + + // add the extension to our vector of enabled objects + Extensions.push_back( std::unique_ptr( Ext ) ); + + // setup the mapping of InstTable to Ext objects + auto load = [&]( const std::vector& Table ) { + InstTable.reserve( InstTable.size() + Table.size() ); + for( uint32_t i = 0; i < Table.size(); i++ ) { + InstTable.push_back( Table[i] ); + if( !EntryToExt.insert( std::pair( uint32_t( InstTable.size() - 1 ), std::pair( uint32_t( Extensions.size() - 1 ), i ) ) ) + .second ) + output->fatal( CALL_INFO, -1, "Error: EntryToExt entry already exists for index %zu\n", InstTable.size() - 1 ); + } + }; + + // retrieve all the target instructions + load( Ext->GetTable() ); + + // load the compressed instructions + if( feature->IsModeEnabled( RV_C ) ) { + output->verbose( CALL_INFO, 6, 0, "Core %" PRIu32 " ; Enabling compressed extension=%s\n", id, Ext->GetName().data() ); + load( Ext->GetCTable() ); + } + + return true; +} + +bool RevCore::SeedInstTable() try { + output->verbose( + CALL_INFO, 6, 0, "Core %" PRIu32 " ; Seeding instruction table for machine model=%s\n", id, feature->GetMachineModel().data() + ); + + // I Extension + if( feature->IsModeEnabled( RV_I ) ) { + EnableExt( new RV32I( feature, mem, output ) ); + if( feature->IsRV64() ) { + EnableExt( new RV64I( feature, mem, output ) ); + } + } + + // M Extension + if( feature->IsModeEnabled( RV_ZMMUL ) ) { + EnableExt( new RV32M( feature, mem, output ) ); + if( feature->IsRV64() ) { + EnableExt( new RV64M( feature, mem, output ) ); + } + } + + // Zaamo Extension + if( feature->IsModeEnabled( RV_ZAAMO ) ) { + EnableExt( new Zaamo( feature, mem, output ) ); + } + + // Zalrsc Extension + if( feature->IsModeEnabled( RV_ZALRSC ) ) { + EnableExt( new Zalrsc( feature, mem, output ) ); + } + + // F Extension + if( feature->IsModeEnabled( RV_F ) ) { + EnableExt( new RV32F( feature, mem, output ) ); + if( feature->IsRV64() ) { + EnableExt( new RV64F( feature, mem, output ) ); + } + } + + // D Extension + if( feature->IsModeEnabled( RV_D ) ) { + EnableExt( new RV32D( feature, mem, output ) ); + if( feature->IsRV64() ) { + EnableExt( new RV64D( feature, mem, output ) ); + } + } + + // Zicbom Extension + if( feature->IsModeEnabled( RV_ZICBOM ) ) { + EnableExt( new Zicbom( feature, mem, output ) ); + } + + // Zicsr Extension + if( feature->IsModeEnabled( RV_ZICSR ) ) { + EnableExt( new Zicsr( feature, mem, output ) ); + } + + // Zifencei Extension + if( feature->IsModeEnabled( RV_ZIFENCEI ) ) { + EnableExt( new Zifencei( feature, mem, output ) ); + } + + // Zfa Extension + if( feature->IsModeEnabled( RV_ZFA ) ) { + EnableExt( new Zfa( feature, mem, output ) ); + } + + return true; +} catch( ... ) { + + return false; +} + +uint32_t RevCore::CompressCEncoding( const RevInstEntry& Entry ) { + uint32_t Value = 0x00; + + Value |= Entry.opcode; + Value |= uint32_t( Entry.funct2 ) << 2; + Value |= uint32_t( Entry.funct3 ) << 4; + Value |= uint32_t( Entry.funct4 ) << 8; + Value |= uint32_t( Entry.funct6 ) << 12; + + return Value; +} + +uint64_t RevCore::CompressEncoding( const RevInstEntry& Entry ) { + uint64_t Value = 0x00; + + Value |= Entry.opcode; + Value |= uint64_t( Entry.funct3 ) << 8; + Value |= uint64_t( Entry.funct2or7 ) << 11; + Value |= uint64_t( Entry.imm12 ) << 18; + Value |= uint64_t( Entry.rs2fcvtOp ) << 30; + + return Value; +} + +std::string RevCore::ExtractMnemonic( const RevInstEntry& Entry ) { + std::string Tmp = Entry.mnemonic; + std::vector vstr; + RevOpts::splitStr( Tmp, " ", vstr ); + return std::move( vstr[0] ); +} + +bool RevCore::InitTableMapping() { + output->verbose( + CALL_INFO, 6, 0, "Core %" PRIu32 " ; Initializing table mapping for machine model=%s\n", id, feature->GetMachineModel().data() + ); + + for( uint32_t i = 0; i < InstTable.size(); i++ ) { + NameToEntry.insert( std::pair( ExtractMnemonic( InstTable[i] ), i ) ); + if( !InstTable[i].compressed ) { + // map normal instruction + EncToEntry.insert( std::pair( CompressEncoding( InstTable[i] ), i ) ); + output->verbose( + CALL_INFO, + 6, + 0, + "Core %" PRIu32 " ; Table Entry %" PRIu64 " = %s\n", + id, + CompressEncoding( InstTable[i] ), + ExtractMnemonic( InstTable[i] ).data() + ); + } else { + // map compressed instruction + CEncToEntry.insert( std::pair( CompressCEncoding( InstTable[i] ), i ) ); + output->verbose( + CALL_INFO, + 6, + 0, + "Core %" PRIu32 " ; Compressed Table Entry %" PRIu32 " = %s\n", + id, + CompressCEncoding( InstTable[i] ), + ExtractMnemonic( InstTable[i] ).data() + ); + } + } + return true; +} + +bool RevCore::ReadOverrideTables() { + output->verbose( + CALL_INFO, 6, 0, "Core %" PRIu32 " ; Reading override tables for machine model=%s\n", id, feature->GetMachineModel().data() + ); + + std::string Table; + if( !opts->GetInstTable( id, Table ) ) + return false; + + // if the length of the file name is 0, just return + if( Table == "_REV_INTERNAL_" ) + return true; + + // open the file + std::ifstream infile( Table ); + if( !infile.is_open() ) + output->fatal( CALL_INFO, -1, "Error: failed to read instruction table for core=%" PRIu32 "\n", id ); + + // read all the values + std::string Inst; + std::string Cost; + uint32_t Entry; + while( infile >> Inst >> Cost ) { + auto it = NameToEntry.find( Inst ); + if( it == NameToEntry.end() ) + output->fatal( CALL_INFO, -1, "Error: could not find instruction in table for map value=%s\n", Inst.data() ); + + Entry = it->second; + InstTable[Entry].cost = (uint32_t) ( std::stoi( Cost, nullptr, 0 ) ); + } + + // close the file + infile.close(); + + return true; +} + +bool RevCore::LoadInstructionTable() { + // Stage 1: load the instruction table for each enable feature + if( !SeedInstTable() ) + return false; + + // Stage 2: setup the internal mapping tables for performance + if( !InitTableMapping() ) + return false; + + // Stage 3: examine the user-defined cost tables to see if we need to override the defaults + if( !ReadOverrideTables() ) + return false; + + return true; +} + +bool RevCore::Reset() { + + IdleHarts.reset(); + + // All harts are idle to start + for( uint32_t i = 0; i < numHarts; i++ ) { + IdleHarts[i] = true; + ValidHarts[i] = true; + } + // Other state bitsets are the unset + + Pipeline.clear(); + CoProcStallReq.reset(); + + return true; +} + +RevInst RevCore::DecodeCRInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct4 = InstTable[Entry].funct4; + + // registers + CompInst.rd = CompInst.rs1 = DECODE_RD( Inst ); + CompInst.rs2 = DECODE_LOWER_CRS2( Inst ); + CompInst.imm = 0x00; + + if( 0b10 == CompInst.opcode ) { + if( 0b1000 == CompInst.funct4 ) { + if( 0 != CompInst.rs2 ) { + // if c.mv force rs1 to x0 + CompInst.rs1 = 0; + } else { + // if c.jr force rd to x0 + CompInst.rd = 0; + } + } else if( 0b1001 == CompInst.funct4 ) { + if( 0 != CompInst.rs2 ) { + // if c.add + } else if( 0 != CompInst.rs1 ) { + // if c.jalr force rd to x1 + CompInst.rd = 1; + } else { + // if c.ebreak + } + } + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCIInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rd = CompInst.rs1 = DECODE_RD( Inst ); + CompInst.imm = DECODE_LOWER_CRS2( Inst ); + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; + + if( ( CompInst.opcode == 0b10 ) && ( CompInst.funct3 == 0b001 ) ) { + // c.fldsp + CompInst.imm = 0; + CompInst.imm = ( Inst & 0b1100000 ) >> 2; // [4:3] + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; // [5] + CompInst.imm |= ( Inst & 0b11100 ) << 4; // [8:6] + CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) + } else if( ( CompInst.opcode == 0b10 ) && ( CompInst.funct3 == 0b010 ) ) { + // c.lwsp + CompInst.imm = 0; + CompInst.imm = ( Inst & 0b1110000 ) >> 2; // [4:2] + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; // [5] + CompInst.imm |= ( Inst & 0b1100 ) << 4; // [7:6] + CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) + } else if( CompInst.opcode == 0b10 && CompInst.funct3 == 0b011 ) { + CompInst.imm = 0; + if( feature->IsRV64() ) { + // c.ldsp + CompInst.imm = ( Inst & 0b1100000 ) >> 2; // [4:3] + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; // [5] + CompInst.imm |= ( Inst & 0b11100 ) << 4; // [8:6] + CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) + } else { + // c.flwsp + CompInst.imm = ( Inst & 0b1110000 ) >> 2; // [4:2] + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; // [5] + CompInst.imm |= ( Inst & 0b1100 ) << 4; // [7:6] + CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) + } + } else if( ( CompInst.opcode == 0b01 ) && ( CompInst.funct3 == 0b011 ) && ( CompInst.rd == 2 ) ) { + // c.addi16sp + // swizzle: nzimm[4|6|8:7|5] nzimm[9] + CompInst.imm = ( Inst & 0b1000000 ) >> 2; // bit 4 + CompInst.imm |= ( Inst & 0b100 ) << 3; // bit 5 + CompInst.imm |= ( Inst & 0b100000 ) << 1; // bit 6 + CompInst.imm |= ( Inst & 0b11000 ) << 4; // bit 8:7 + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 3; // bit 9 + CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) + // sign extend + CompInst.imm = uint32_t( CompInst.ImmSignExt( 10 ) ); + } else if( ( CompInst.opcode == 0b01 ) && ( CompInst.funct3 == 0b011 ) && ( CompInst.rd != 0 ) && ( CompInst.rd != 2 ) ) { + // c.lui + CompInst.imm = ( Inst & 0b1111100 ) << 10; // [16:12] + CompInst.imm |= ( Inst & 0b1000000000000 ) << 5; // [17] + // sign extend + CompInst.imm = uint32_t( CompInst.ImmSignExt( 18 ) ); + CompInst.imm >>= 12; //immd value will be re-aligned on execution + } else if( CompInst.opcode == 0b01 && CompInst.funct3 == 0b010 && CompInst.rd != 0 ) { + // c.li + CompInst.imm = ( Inst & 0b1111100 ) >> 2; // [4:0] + CompInst.imm |= ( Inst & 0b1000000000000 ) >> 7; // [5] + CompInst.rs1 = 0; // Force rs1 to be x0, expands to add rd, x0, imm + // sign extend + CompInst.imm = uint32_t( CompInst.ImmSignExt( 6 ) ); + } else { + // sign extend + CompInst.imm = uint32_t( CompInst.ImmSignExt( 6 ) ); + } + + //if c.addi, expands to addi %rd, %rd, $imm so set rs1 to rd -or- + // c.slli, expands to slli %rd %rd $imm -or - + // c.addiw. expands to addiw %rd %rd $imm + if( ( 0b01 == CompInst.opcode && 0b000 == CompInst.funct3 ) || + ( 0b10 == CompInst.opcode && 0b000 == CompInst.funct3 ) || + ( 0b01 == CompInst.opcode && 0b001 == CompInst.funct3 ) ) { + CompInst.rs1 = CompInst.rd; + } + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCSSInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rs2 = DECODE_LOWER_CRS2( Inst ); + CompInst.imm = ( Inst & 0b1111110000000 ) >> 7; + + if( CompInst.funct3 == 0b101 ) { + // c.fsdsp + CompInst.imm = ( Inst & 0b1110000000000 ) >> 7; // [5:3] + CompInst.imm |= ( Inst & 0b1110000000 ) >> 1; // [8:6] + CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) + } else if( CompInst.funct3 == 0b110 ) { + // c.swsp + CompInst.imm = 0; + CompInst.imm = ( Inst & 0b1111000000000 ) >> 7; // [5:2] + CompInst.imm |= ( Inst & 0b110000000 ) >> 1; // [7:6] + CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) + } else if( CompInst.funct3 == 0b111 ) { + CompInst.imm = 0; + if( feature->IsRV64() ) { + // c.sdsp + CompInst.imm = ( Inst & 0b1110000000000 ) >> 7; // [5:3] + CompInst.imm |= ( Inst & 0b1110000000 ) >> 1; // [8:6] + CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) + } else { + // c.fswsp + CompInst.imm = ( Inst & 0b1111000000000 ) >> 7; // [5:2] + CompInst.imm |= ( Inst & 0b110000000 ) >> 1; // [7:6] + CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) + } + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCIWInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rd = BitExtract<2, 3>( Inst ); + CompInst.imm = BitExtract<5, 8>( Inst ); + + // Apply compressed offset + CompInst.rd = CRegIdx( CompInst.rd ); + + //swizzle: nzuimm[5:4|9:6|2|3] + std::bitset<32> imm( CompInst.imm ), tmp; + tmp[0] = imm[1]; + tmp[1] = imm[0]; + tmp[2] = imm[6]; + tmp[3] = imm[7]; + tmp[4] = imm[2]; + tmp[5] = imm[3]; + tmp[6] = imm[4]; + tmp[7] = imm[5]; + + CompInst.imm = uint32_t( tmp.to_ulong() ); + + // Set rs1 to x2 and scale offset by 4 if this is an addi4spn + if( 0x00 == CompInst.opcode && 0x00 == CompInst.funct3 ) { + CompInst.imm = CompInst.imm << 2 & 0b1111111100; + CompInst.rs1 = 2; + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCLInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rd = BitExtract<2, 3>( Inst ); + CompInst.rs1 = BitExtract<7, 3>( Inst ); + + //Apply compressed offset + CompInst.rd = CRegIdx( CompInst.rd ); + CompInst.rs1 = CRegIdx( CompInst.rs1 ); + + if( CompInst.funct3 == 0b001 ) { + // c.fld + CompInst.imm = ( Inst & 0b1100000 ) << 1; // [7:6] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } else if( CompInst.funct3 == 0b010 ) { + // c.lw + CompInst.imm = ( Inst & 0b100000 ) << 1; // [6] + CompInst.imm |= ( Inst & 0b1000000 ) >> 4; // [2] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } else if( CompInst.funct3 == 0b011 ) { + if( feature->IsRV64() ) { + // c.ld + CompInst.imm = ( ( Inst & 0b1100000 ) << 1 ); // [7:6] + CompInst.imm |= ( ( Inst & 0b1110000000000 ) >> 7 ); // [5:3] + } else { + // c.flw + CompInst.imm = ( Inst & 0b100000 ) << 1; // [6] + CompInst.imm |= ( Inst & 0b1000000 ) >> 4; // [2] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } + } else if( CompInst.funct3 == 0b101 ) { + // c.fsd + CompInst.imm = ( Inst & 0b1100000 ) << 1; // [7:6] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } else if( CompInst.funct3 == 0b110 ) { + // c.sw + CompInst.imm = ( Inst & 0b100000 ) << 1; // [6] + CompInst.imm |= ( Inst & 0b1000000 ) >> 4; // [2] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } else if( CompInst.funct3 == 0b111 ) { + if( feature->IsRV64() ) { + // c.sd + CompInst.imm = ( Inst & 0b1100000 ) << 1; // [7:6] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } else { + // c.fsw + CompInst.imm = ( Inst & 0b100000 ) << 1; // [6] + CompInst.imm |= ( Inst & 0b1000000 ) >> 4; // [2] + CompInst.imm |= ( Inst & 0b1110000000000 ) >> 7; // [5:3] + } + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCSInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rs2 = BitExtract<2, 3>( Inst ); + CompInst.rs1 = BitExtract<7, 3>( Inst ); + + //Apply Compressed offset + CompInst.rs2 = CRegIdx( CompInst.rs2 ); + CompInst.rs1 = CRegIdx( CompInst.rs1 ); + + // The immd is pre-scaled in this instruction format + if( CompInst.funct3 == 0b110 ) { + //c.sw + CompInst.imm = ( Inst & 0b0100000 ) << 1; //offset[6] + CompInst.imm |= ( Inst & 0b01110000000000 ) >> 6; //offset[5:3] + CompInst.imm |= ( Inst & 0b01000000 ) >> 4; //offset[2] + } else { + if( feature->IsRV64() ) { + //c.sd + CompInst.imm = ( Inst & 0b01100000 ) << 1; //imm[7:6] + CompInst.imm |= ( Inst & 0b01110000000000 ) >> 7; //imm[5:3] + } else { + //c.fsw + CompInst.imm = ( Inst & 0b00100000 ) << 1; //imm[6] + CompInst.imm = ( Inst & 0b01000000 ) << 4; //imm[2] + CompInst.imm |= ( Inst & 0b01110000000000 ) >> 7; //imm[5:3] + } + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCAInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct2 = InstTable[Entry].funct2; + CompInst.funct6 = InstTable[Entry].funct6; + + // registers + CompInst.rs2 = BitExtract<2, 3>( Inst ); + CompInst.rd = CompInst.rs1 = BitExtract<7, 3>( Inst ); + + //Adjust registers for compressed offset + CompInst.rs2 = CRegIdx( CompInst.rs2 ); + CompInst.rs1 = CRegIdx( CompInst.rs1 ); + CompInst.rd = CRegIdx( CompInst.rd ); + + //All instructions of this format expand to rd rd rs2, so set rs1 to rd + CompInst.rs1 = CompInst.rd; + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCBInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + CompInst.rd = CompInst.rs1 = BitExtract<7, 3>( Inst ); + CompInst.offset = uint16_t( BitExtract<2, 5>( Inst ) ); + CompInst.offset |= ( Inst & 0b1110000000000 ) >> 5; + + //Apply compressed offset + CompInst.rs1 = CRegIdx( CompInst.rs1 ); + + //If c.srli, c.srai or c.andi set rd to rs1 + if( 0b01 == CompInst.opcode && 0b100 == CompInst.funct3 ) { + CompInst.rd = CompInst.rs1; + } + + //swizzle: offset[8|4:3] offset[7:6|2:1|5] + std::bitset<16> tmp; + // handle c.beqz/c.bnez offset + if( CompInst.opcode == 0b01 && CompInst.funct3 >= 0b110 ) { + std::bitset<16> o( CompInst.offset ); + tmp[0] = o[1]; + tmp[1] = o[2]; + tmp[2] = o[5]; + tmp[3] = o[6]; + tmp[4] = o[0]; + tmp[5] = o[3]; + tmp[6] = o[4]; + tmp[7] = o[7]; + } + + CompInst.offset = uint16_t( tmp.to_ulong() << 1 ); // scale to corrrect position to be consistent with other compressed ops + + if( 0b01 == CompInst.opcode && CompInst.funct3 >= 0b110 ) { + //Set rs2 to x0 if c.beqz or c.bnez + CompInst.rs2 = 0; + CompInst.imm = CompInst.offset; + CompInst.imm = uint32_t( CompInst.ImmSignExt( 9 ) ); + } else { + CompInst.imm = ( Inst & 0b01111100 ) >> 2; + CompInst.imm |= ( Inst & 0b01000000000000 ) >> 7; + CompInst.imm = uint32_t( CompInst.ImmSignExt( 6 ) ); + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +RevInst RevCore::DecodeCJInst( uint32_t Inst, uint32_t Entry ) const { + RevInst CompInst; + + // cost + CompInst.cost = InstTable[Entry].cost; + + // encodings + CompInst.opcode = InstTable[Entry].opcode; + CompInst.funct3 = InstTable[Entry].funct3; + + // registers + uint16_t offset = uint16_t( BitExtract<2, 11>( Inst ) ); + + //swizzle bits offset[11|4|9:8|10|6|7|3:1|5] + std::bitset<16> offsetBits( offset ), target; + target[0] = offsetBits[1]; + target[1] = offsetBits[2]; + target[2] = offsetBits[3]; + target[3] = offsetBits[9]; + target[4] = offsetBits[0]; + target[5] = offsetBits[5]; + target[6] = offsetBits[4]; + target[7] = offsetBits[7]; + target[8] = offsetBits[8]; + target[9] = offsetBits[6]; + target[10] = offsetBits[10]; + CompInst.jumpTarget = uint16_t( target.to_ulong() << 1 ); + + if( 0b01 == CompInst.opcode && ( 0b001 == CompInst.funct3 || 0b101 == CompInst.funct3 ) ) { + //Set rd to x1 if this is a c.jal, x0 if this is a c.j + CompInst.rd = 0b001 == CompInst.funct3; + CompInst.imm = CompInst.jumpTarget; + CompInst.imm = uint32_t( CompInst.ImmSignExt( 12 ) ); + } + + CompInst.instSize = 2; + CompInst.compressed = true; + + return CompInst; +} + +// Find the first matching encoding which satisfies a predicate, if any +auto RevCore::matchInst( + const std::unordered_multimap& map, + uint64_t encoding, + const std::vector& InstTable, + uint32_t Inst +) const { + // Iterate through all entries which match the encoding + auto match = map.end(); // No match + for( auto [it, end] = map.equal_range( encoding ); it != end; ++it ) { + uint32_t Entry = it->second; + // If an entry is valid and has a satisfied predicate + if( Entry < InstTable.size() && InstTable[Entry].predicate( Inst ) ) { + // Only one instruction entry with a satisfied predicate should match + if( match != map.end() ) + output->fatal( + CALL_INFO, -1, "Error: Multiple decodings for instruction 0x%08" PRIx32 " at PC=0x%" PRIx64 "\n", Inst, GetPC() + ); + match = it; + } + } + return match; +} + +RevInst RevCore::DecodeCompressed( uint32_t Inst ) const { + uint8_t opc = 0; + uint8_t funct2 = 0; + uint8_t funct3 = 0; + uint8_t funct4 = 0; + uint8_t funct6 = 0; + uint8_t l3 = 0; + uint32_t Enc = 0; + + if( !feature->HasCompressed() ) { + output->fatal( + CALL_INFO, -1, "Error: failed to decode instruction at PC=0x%" PRIx64 "; Compressed instructions not enabled!\n", GetPC() + ); + } + + // Truncate instruction to the first 16 bits + Inst = static_cast( Inst ); + + // decode the opcode + opc = Inst & 0b11; + l3 = ( Inst & 0b1110000000000000 ) >> 13; + if( opc == 0b00 ) { + // quadrant 0 + funct3 = l3; + } else if( opc == 0b01 ) { + // quadrant 1 + if( l3 <= 0b011 ) { + // upper portion: misc + funct3 = l3; + } else if( l3 > 0b011 && l3 < 0b101 ) { + // middle portion: arithmetics + uint8_t opSelect = ( Inst & 0b110000000000 ) >> 10; + if( opSelect == 0b11 ) { + funct6 = ( Inst & 0b1111110000000000 ) >> 10; + funct2 = ( Inst & 0b01100000 ) >> 5; + } else { + funct3 = l3; + funct2 = opSelect; + } + } else { + // lower power: jumps/branches + funct3 = l3; + } + } else if( opc == 0b10 ) { + // quadrant 2 + if( l3 == 0b000 ) { + // slli{64} + funct3 = l3; + } else if( l3 < 0b100 ) { + // float/double/quad load + funct3 = l3; + } else if( l3 == 0b100 ) { + // jump, mv, break, add + funct4 = ( Inst & 0b1111000000000000 ) >> 12; + } else { + // float/double/quad store + funct3 = l3; + } + } + + Enc |= uint32_t( opc ); + Enc |= uint32_t( funct2 << 2 ); + Enc |= uint32_t( funct3 << 4 ); + Enc |= uint32_t( funct4 << 8 ); + Enc |= uint32_t( funct6 << 12 ); + + bool isCoProcInst = false; + auto it = matchInst( CEncToEntry, Enc, InstTable, Inst ); + if( it == CEncToEntry.end() ) { + if( coProc && coProc->IssueInst( feature, RegFile, mem, Inst ) ) { + isCoProcInst = true; + //Create NOP - ADDI x0, x0, 0 + uint8_t caddi_op = 0b01; + Inst = 0; + Enc = caddi_op; + it = matchInst( CEncToEntry, Enc, InstTable, Inst ); + } + } + + if( it == CEncToEntry.end() ) { + output->fatal( + CALL_INFO, + -1, + "Error: failed to decode instruction at PC=0x%" PRIx64 "; Enc=%" PRIx32 "\n opc=%" PRIx8 "; funct2=%" PRIx8 ", funct3=%" PRIx8 + ", funct4=%" PRIx8 ", funct6=%" PRIx8 "\n", + GetPC(), + Enc, + opc, + funct2, + funct3, + funct4, + funct6 + ); + } + + auto Entry = it->second; + if( Entry >= InstTable.size() ) { + output->fatal( + CALL_INFO, + -1, + "Error: no entry in table for instruction at PC=0x%" PRIx64 " Opcode = %" PRIx8 " Funct2 = %" PRIx8 " Funct3 = %" PRIx8 + " Funct4 = %" PRIx8 " Funct6 = %" PRIx8 " Enc = %" PRIx32 "\n", + GetPC(), + opc, + funct2, + funct3, + funct4, + funct6, + Enc + ); + } + + RevInst ret{}; + + switch( InstTable[Entry].format ) { + case RVCTypeCR: ret = DecodeCRInst( Inst, Entry ); break; + case RVCTypeCI: ret = DecodeCIInst( Inst, Entry ); break; + case RVCTypeCSS: ret = DecodeCSSInst( Inst, Entry ); break; + case RVCTypeCIW: ret = DecodeCIWInst( Inst, Entry ); break; + case RVCTypeCL: ret = DecodeCLInst( Inst, Entry ); break; + case RVCTypeCS: ret = DecodeCSInst( Inst, Entry ); break; + case RVCTypeCA: ret = DecodeCAInst( Inst, Entry ); break; + case RVCTypeCB: ret = DecodeCBInst( Inst, Entry ); break; + case RVCTypeCJ: ret = DecodeCJInst( Inst, Entry ); break; + default: output->fatal( CALL_INFO, -1, "Error: failed to decode instruction format at PC=%" PRIx64 ".", GetPC() ); + } + + ret.entry = Entry; + ret.isCoProcInst = isCoProcInst; + return ret; +} + +RevInst RevCore::DecodeRInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = InstTable[Entry].funct3; + DInst.funct2or7 = InstTable[Entry].funct2or7; + + // Whether the instruction raises floating-point exceptions + DInst.raisefpe = InstTable[Entry].raisefpe; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ) { + DInst.rd = DECODE_RD( Inst ); + } + if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ) { + DInst.rs1 = DECODE_RS1( Inst ); + } + if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ) { + DInst.rs2 = DECODE_RS2( Inst ); + } + + // imm + if( InstTable[Entry].imm == RevImmFunc::FImm && InstTable[Entry].rs2Class == RevRegClass::RegUNKNOWN ) { + DInst.imm = DECODE_IMM12( Inst ) & 0b011111; + } else { + DInst.imm = 0x0; + } + + // Size + DInst.instSize = 4; + + // Decode the atomic RL/AQ fields + if( DInst.opcode == 0b0101111 ) { + DInst.rl = DECODE_RL( Inst ); + DInst.aq = DECODE_AQ( Inst ); + } + + // Decode any ancillary SP/DP float options + if( DInst.opcode == 0b1010011 ) { + DInst.rm = DECODE_RM( Inst ); + } + + DInst.compressed = false; + + return DInst; +} + +RevInst RevCore::DecodeIInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = InstTable[Entry].funct3; + DInst.funct2or7 = 0x0; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ) { + DInst.rd = DECODE_RD( Inst ); + } + if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ) { + DInst.rs1 = DECODE_RS1( Inst ); + } + + // imm + DInst.imm = DECODE_IMM12( Inst ); + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + + return DInst; +} + +RevInst RevCore::DecodeSInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = InstTable[Entry].funct3; + DInst.funct2or7 = 0x0; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ) { + DInst.rs1 = DECODE_RS1( Inst ); + } + if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ) { + DInst.rs2 = DECODE_RS2( Inst ); + } + + // imm + DInst.imm = DECODE_RD( Inst ) | DECODE_FUNCT7( Inst ) << 5; + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + return DInst; +} + +RevInst RevCore::DecodeUInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = 0x0; + DInst.funct2or7 = 0x0; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ) { + DInst.rd = DECODE_RD( Inst ); + } + + // imm + DInst.imm = DECODE_IMM20( Inst ); + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + return DInst; +} + +RevInst RevCore::DecodeBInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = InstTable[Entry].funct3; + DInst.funct2or7 = 0x0; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ) { + DInst.rs1 = DECODE_RS1( Inst ); + } + if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ) { + DInst.rs2 = DECODE_RS2( Inst ); + } + + // imm + DInst.imm = ( Inst >> 19 & 0b1000000000000 ) | // [12] + ( Inst << 4 & 0b100000000000 ) | // [11] + ( Inst >> 20 & 0b11111100000 ) | // [10:5] + ( Inst >> 7 & 0b11110 ); // [4:1] + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + return DInst; +} + +RevInst RevCore::DecodeJInst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = InstTable[Entry].funct3; + DInst.funct2or7 = 0x0; + + // registers + DInst.rd = 0x0; + DInst.rs1 = 0x0; + DInst.rs2 = 0x0; + DInst.rs3 = 0x0; + + if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ) { + DInst.rd = DECODE_RD( Inst ); + } + + // immA + DInst.imm = ( Inst >> 11 & 0b100000000000000000000 ) | // imm[20] + ( Inst & 0b11111111000000000000 ) | // imm[19:12] + ( Inst >> 9 & 0b100000000000 ) | // imm[11] + ( Inst >> 20 & 0b11111111110 ); // imm[10:1] + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + return DInst; +} + +RevInst RevCore::DecodeR4Inst( uint32_t Inst, uint32_t Entry ) const { + RevInst DInst; + + // cost + DInst.cost = InstTable[Entry].cost; + + // encodings + DInst.opcode = InstTable[Entry].opcode; + DInst.funct3 = 0x0; + DInst.funct2or7 = uint8_t( DECODE_FUNCT2( Inst ) ); + DInst.rm = DECODE_RM( Inst ); + + // Whether the instruction raises floating-point exceptions + DInst.raisefpe = InstTable[Entry].raisefpe; + + // registers + DInst.rd = DECODE_RD( Inst ); + DInst.rs1 = DECODE_RS1( Inst ); + DInst.rs2 = DECODE_RS2( Inst ); + DInst.rs3 = DECODE_RS3( Inst ); + + // imm + DInst.imm = 0x0; + + // Size + DInst.instSize = 4; + + DInst.compressed = false; + return DInst; +} + +bool RevCore::DebugReadReg( uint32_t Idx, uint64_t* Value ) const { + if( !Halted ) + return false; + if( Idx >= _REV_NUM_REGS_ ) { + return false; + } + RevRegFile* regFile = GetRegFile( HartToExecID ); + *Value = regFile->GetX( Idx ); + return true; +} + +bool RevCore::DebugWriteReg( uint32_t Idx, uint64_t Value ) const { + RevRegFile* regFile = GetRegFile( HartToExecID ); + if( !Halted ) + return false; + if( Idx >= _REV_NUM_REGS_ ) { + return false; + } + regFile->SetX( Idx, Value ); + return true; +} + +bool RevCore::PrefetchInst() { + uint64_t PC = Harts[HartToDecodeID]->RegFile->GetPC(); + + // These are addresses that we can't decode + // Return false back to the main program loop + if( PC == 0 ) { + return false; + } + + return sfetch->IsAvail( PC ); +} + +RevInst RevCore::FetchAndDecodeInst() { + uint32_t Inst = 0; + uint64_t PC = GetPC(); + bool Fetched = false; + + // Stage 1: Retrieve the instruction + if( !sfetch->InstFetch( PC, Fetched, Inst ) ) { + output->fatal( CALL_INFO, -1, "Error: failed to retrieve prefetched instruction at PC=0x%" PRIx64 "\n", PC ); + } + + if( 0 != Inst ) { + output->verbose( + CALL_INFO, + 6, + 0, + ~Inst & 3 ? "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; PC:InstPayload = 0x%" PRIx64 ":0x%04" PRIx32 "\n" : + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; PC:InstPayload = 0x%" PRIx64 ":0x%08" PRIx32 "\n", + id, + HartToDecodeID, + ActiveThreadID, + PC, + ~Inst & 3 ? Inst & 0xffff : Inst + ); + } else { + output->fatal( + CALL_INFO, -1, "Error: Core %" PRIu32 " failed to decode instruction at PC=0x%" PRIx64 "; Inst=%" PRIu32 "\n", id, PC, Inst + ); + } + + // Trace capture fetched instruction + if( Tracer ) + Tracer->SetFetchedInsn( PC, Inst ); + + // Stage 1a: handle the crack fault injection + if( CrackFault ) { + auto rval = RevRand( 0, ( uint32_t{ 1 } << fault_width ) - 1 ); + Inst |= rval; + + // clear the fault + CrackFault = false; + } + + // Decode the instruction + RevInst DInst = DecodeInst( Inst ); + + // Set RegFile Entry and cost, and clear trigger + RegFile->SetEntry( DInst.entry ); + RegFile->SetCost( DInst.cost ); + RegFile->SetTrigger( false ); + + // Return decoded instruction + return DInst; +} + +// Decode the instruction +// This function is pure, with no side effects or dependencies +// on non-constant outside variables. This make it memoizable, +// but right now, there isn't enough benefit for memoization. +RevInst RevCore::DecodeInst( uint32_t Inst ) const { + if( ~Inst & 0b11 ) { + // this is a compressed instruction + return DecodeCompressed( Inst ); + } + + // Stage 2: Retrieve the opcode + const uint32_t Opcode = Inst & 0b1111111; + + // Stage 3: Determine if we have a funct3 field + uint32_t Funct3 = 0; + const uint32_t inst42 = Opcode >> 2 & 0b111; + const uint32_t inst65 = Opcode >> 5 & 0b11; + + if( ( inst42 == 0b011 ) && ( inst65 == 0b11 ) ) { + // JAL + Funct3 = 0; + } else if( inst42 == 0b101 && inst65 == 0b00 ) { + // AUIPC + Funct3 = 0; + } else if( inst42 == 0b101 && inst65 == 0b01 ) { + // LUI + Funct3 = 0; + } else { + // Retrieve the field + Funct3 = DECODE_FUNCT3( Inst ); + } + + // Stage 4: Determine if we have a funct7 field (R-Type and some specific I-Type) + uint32_t Funct2or7 = 0; + if( inst65 == 0b01 ) { + if( inst42 == 0b011 || inst42 == 0b100 || inst42 == 0b110 ) { + // R-Type encodings + Funct2or7 = DECODE_FUNCT7( Inst ); + //Atomics have a smaller funct7 field - trim out the aq and rl fields + if( Opcode == 0b0101111 ) { + Funct2or7 = BitExtract<2, 5>( Funct2or7 ); + } + } + } else if( inst65 == 0b10 && inst42 < 0b100 ) { + // R4-Type encodings -- we store the Funct2 precision field in Funct2or7 + Funct2or7 = DECODE_FUNCT2( Inst ); + } else if( inst65 == 0b10 && inst42 == 0b100 ) { + // R-Type encodings + Funct2or7 = DECODE_FUNCT7( Inst ); + } else if( inst65 == 0b00 && inst42 == 0b110 && Funct3 != 0 ) { + // R-Type encodings + Funct2or7 = DECODE_FUNCT7( Inst ); + } else if( inst65 == 0b00 && inst42 == 0b100 && Funct3 == 0b101 ) { + // Special I-Type encoding for SRAI - also, Funct7 is only 6 bits in this case + Funct2or7 = BitExtract<26, 7>( Inst ); + } + + uint64_t rs2fcvtOp = 0; + //Special encodings for FCVT and Zfa instructions + if( Opcode == 0b1010011 ) { + // clang-format off + switch( Funct2or7 ) { + case 0b0100000: // for FCVT.S.D, FCVT.S.Q, FCVT.S.H, FROUNDNX.S, FROUND.S + case 0b0100001: // for FCVT.D.S, FCVT.D.Q, FCVT.D.H, FROUNDNX.D, FROUND.D + case 0b0100010: // for FCVT.H.S, FCVT.H.D, FCVT.H.Q, FROUNDNX.H, FROUND.H + case 0b0100011: // for FCVT.Q.S, FCVT.Q.D, FCVT.Q.H, FROUNDNX.Q, FROUND.Q + case 0b1100000: // for FCVT.W.S, FCVT.WU.S, FCVT.L.S, FCVT.LU.S + case 0b1100001: // for FCVT.W.D, FCVT.WU.D, FCVT.L.D, FCVT.LU.D, FCVTMOD.W.D + case 0b1100010: // for FCVT.W.H, FCVT.WU.H, FCVT.L.H, FCVT.LU.H + case 0b1100011: // for FCVT.W.Q, FCVT.WU.Q, FCVT.L.Q, FCVT.LU.Q + case 0b1101000: // for FCVT.S.W, FCVT.S.WU, FCVT.S.L, FCVT.S.LU + case 0b1101001: // for FCVT.D.W, FCVT.D.WU, FCVT.D.L, FCVT.D.LU + case 0b1101010: // for FCVT.H.W, FCVT.H.WU, FCVT.H.L, FCVT.H.LU + case 0b1101011: // for FCVT.Q.W, FCVT.Q.WU, FCVT.Q.L, FCVT.Q.LU + case 0b1111000: // for Zfa FLI.S + case 0b1111001: // for Zfa FLI.D + case 0b1111010: // for Zfa FLI.H + case 0b1111011: // for Zfa FLI.Q + rs2fcvtOp = DECODE_RS2( Inst ); + } + // clang-format on + } + + // Stage 5: Determine if we have an imm12 field (ECALL and EBREAK, CBO) + uint32_t Imm12 = 0; + if( ( inst42 == 0b100 && inst65 == 0b11 && Funct3 == 0b000 ) || ( inst42 == 0b011 && inst65 == 0b00 && Funct3 == 0b010 ) ) { + Imm12 = DECODE_IMM12( Inst ); + } + + // Stage 6: Compress the encoding + uint64_t Enc = Opcode; + Enc |= Funct3 << 8; + Enc |= Funct2or7 << 11; + Enc |= Imm12 << 18; + Enc |= rs2fcvtOp << 30; + + // Stage 7: Look up the value in the table + auto it = matchInst( EncToEntry, Enc, InstTable, Inst ); + + // This is kind of a hack, but we may not have found the instruction because + // Funct3 is overloaded with rounding mode, so if this is a RV32F or RV64F + // set Funct3 to zero and check again. We exclude if Funct3 == 0b101 || + // Funct3 == 0b110 because those are invalid FP rounding mode (rm) values. + if( inst65 == 0b10 && Funct3 != 0b101 && Funct3 != 0b110 && it == EncToEntry.end() ) { + Enc = ~( ~Enc | 0x700 ); + it = matchInst( EncToEntry, Enc, InstTable, Inst ); + } + + bool isCoProcInst = false; + + // If we did not find a valid instruction, look for a coprocessor instruction + if( it == EncToEntry.end() && coProc && coProc->IssueInst( feature, RegFile, mem, Inst ) ) { + //Create NOP - ADDI x0, x0, 0 + isCoProcInst = true; + Enc = 0b0010011; + Inst = 0; + it = matchInst( EncToEntry, Enc, InstTable, Inst ); + } + + if( it == EncToEntry.end() ) { + // failed to decode the instruction + output->fatal( CALL_INFO, -1, "Error: failed to decode instruction at PC=0x%" PRIx64 "; Enc=%" PRIu64 "\n", GetPC(), Enc ); + } + + uint32_t Entry = it->second; + if( Entry >= InstTable.size() ) { + if( coProc && coProc->IssueInst( feature, RegFile, mem, Inst ) ) { + //Create NOP - ADDI x0, x0, 0 + isCoProcInst = true; + Enc = 0b0010011; + Inst = 0; + it = matchInst( EncToEntry, Enc, InstTable, Inst ); + Entry = it->second; + } + } + + if( Entry >= InstTable.size() ) { + output->fatal( + CALL_INFO, + -1, + "Error: no entry in table for instruction at PC=0x%" PRIx64 " Opcode = 0x%" PRIx32 " Funct3 = %" PRIx32 + " Funct2or7 = %" PRIx32 " Imm12 = %" PRIx32 " Enc = %" PRIx64 "\n", + GetPC(), + Opcode, + Funct3, + Funct2or7, + Imm12, + Enc + ); + } + + // Stage 8: Do a full deocode using the target format + RevInst ret{}; + switch( InstTable[Entry].format ) { + case RVTypeR: ret = DecodeRInst( Inst, Entry ); break; + case RVTypeI: ret = DecodeIInst( Inst, Entry ); break; + case RVTypeS: ret = DecodeSInst( Inst, Entry ); break; + case RVTypeU: ret = DecodeUInst( Inst, Entry ); break; + case RVTypeB: ret = DecodeBInst( Inst, Entry ); break; + case RVTypeJ: ret = DecodeJInst( Inst, Entry ); break; + case RVTypeR4: ret = DecodeR4Inst( Inst, Entry ); break; + default: output->fatal( CALL_INFO, -1, "Error: failed to decode instruction format at PC=%" PRIx64 ".", GetPC() ); + } + + ret.entry = Entry; + ret.isCoProcInst = isCoProcInst; + return ret; +} + +void RevCore::HandleRegFault( uint32_t width ) { + const char* RegPrefix; + RevRegFile* regFile = GetRegFile( HartToExecID ); + + // select a register + uint32_t RegIdx = RevRand( 0u, _REV_NUM_REGS_ - 1 ); + + if( !feature->HasF() || RevRand( 0, 1 ) ) { + // X registers + if( regFile->IsRV64() ) { + regFile->RV64[RegIdx] |= RevRand( 0, ~( ~uint64_t{ 0 } << width ) ); + } else { + regFile->RV32[RegIdx] |= RevRand( 0, ~( ~uint32_t{ 0 } << width ) ); + } + RegPrefix = "x"; + } else { + // F registers + if( feature->HasD() ) { + uint64_t tmp; + memcpy( &tmp, ®File->DPF[RegIdx], sizeof( tmp ) ); + tmp |= RevRand( 0, ~( ~uint64_t{ 0 } << width ) ); + memcpy( ®File->DPF[RegIdx], &tmp, sizeof( tmp ) ); + } else { + uint32_t tmp; + memcpy( &tmp, ®File->SPF[RegIdx], sizeof( tmp ) ); + tmp |= RevRand( 0, ~( ~uint32_t{ 0 } << width ) ); + memcpy( ®File->SPF[RegIdx], &tmp, sizeof( tmp ) ); + } + RegPrefix = "f"; + } + + output->verbose( + CALL_INFO, 5, 0, "FAULT:REG: Register fault of %" PRIu32 " bits into register %s%" PRIu32 "\n", width, RegPrefix, RegIdx + ); +} + +void RevCore::HandleCrackFault( uint32_t width ) { + CrackFault = true; + fault_width = width; + output->verbose( CALL_INFO, 5, 0, "FAULT:CRACK: Crack+Decode fault injected into next decode cycle\n" ); +} + +void RevCore::HandleALUFault( uint32_t width ) { + ALUFault = true; + fault_width = true; + output->verbose( CALL_INFO, 5, 0, "FAULT:ALU: ALU fault injected into next retire cycle\n" ); +} + +bool RevCore::DependencyCheck( uint32_t HartID, const RevInst* I ) const { + const RevRegFile* regFile = GetRegFile( HartID ); + const RevInstEntry* E = &InstTable[I->entry]; + + // For ECALL, check for any outstanding dependencies on a0-a7 + if( I->opcode == 0b1110011 && I->imm == 0 && I->funct3 == 0 && I->rd == 0 && I->rs1 == 0 ) { + for( RevReg reg : { RevReg::a7, RevReg::a0, RevReg::a1, RevReg::a2, RevReg::a3, RevReg::a4, RevReg::a5, RevReg::a6 } ) { + if( LSQCheck( HartToDecodeID, RegFile, safe_static_cast( reg ), RevRegClass::RegGPR ) || ScoreboardCheck( RegFile, uint16_t( reg ), RevRegClass::RegGPR ) ) { + return true; + } + } + return false; + } + + return + // check LS queue for outstanding load + LSQCheck( HartID, regFile, I->rs1, E->rs1Class ) || LSQCheck( HartID, regFile, I->rs2, E->rs2Class ) || + LSQCheck( HartID, regFile, I->rs3, E->rs3Class ) || LSQCheck( HartID, regFile, I->rd, E->rdClass ) || + + // Iterate through the source registers rs1, rs2, rs3 and find any dependency + // based on the class of the source register and the associated scoreboard + ScoreboardCheck( regFile, I->rs1, E->rs1Class ) || ScoreboardCheck( regFile, I->rs2, E->rs2Class ) || + ScoreboardCheck( regFile, I->rs3, E->rs3Class ); +} + +void RevCore::ExternalStallHart( RevCorePasskey, uint16_t HartID ) { + if( HartID < Harts.size() ) { + CoProcStallReq.set( HartID ); + } else { + output->fatal( + CALL_INFO, -1, "Core %" PRIu32 " ; CoProc Request: Cannot stall Hart %" PRIu32 " as the ID is invalid\n", id, HartID + ); + } +} + +void RevCore::ExternalReleaseHart( RevCorePasskey, uint16_t HartID ) { + if( HartID < Harts.size() ) { + CoProcStallReq.reset( HartID ); + } else { + output->fatal( + CALL_INFO, -1, "Core %" PRIu32 " ; CoProc Request: Cannot release Hart %" PRIu32 " as the ID is invalid\n", id, HartID + ); + } +} + +uint32_t RevCore::GetNextHartToDecodeID() const { + if( HartsClearToDecode.none() ) { + return HartToDecodeID; + }; + + uint32_t nextID = HartToDecodeID; + if( HartsClearToDecode[HartToDecodeID] ) { + nextID = HartToDecodeID; + } else { + for( size_t tID = 0; tID < Harts.size(); tID++ ) { + nextID++; + if( nextID >= Harts.size() ) { + nextID = 0; + } + if( HartsClearToDecode[nextID] ) { + break; + }; + } + output->verbose( + CALL_INFO, 6, 0, "Core %" PRIu32 "; Hart switch from %" PRIu32 " to %" PRIu32 "\n", id, HartToDecodeID, nextID + ); + } + return nextID; +} + +void RevCore::MarkLoadComplete( const MemReq& req ) { + // Iterate over all outstanding loads for this reg (if any) + for( auto [i, end] = LSQueue->equal_range( req.LSQHash() ); i != end; ++i ) { + if( i->second.Addr == req.Addr ) { + // Only clear the dependency if this is the + // LAST outstanding load for this register + if( LSQueue->count( req.LSQHash() ) == 1 ) { + DependencyClear( req.Hart, req.DestReg, req.RegType ); + } + sfetch->MarkInstructionLoadComplete( req ); + // Remove this load from the queue + LSQueue->erase( i ); + return; + } + } + + // Instruction prefetch fills target x0; we can ignore these + if( req.DestReg == 0 && req.RegType == RevRegClass::RegGPR ) + return; + output->fatal( + CALL_INFO, + -1, + "Core %" PRIu32 "; Hart %" PRIu32 "; " + "Cannot find matching address for outstanding " + "load for reg %" PRIu32 " from address %" PRIx64 "\n", + id, + req.Hart, + req.DestReg, + req.Addr + ); +} + +bool RevCore::ClockTick( SST::Cycle_t currentCycle ) { + RevInst Inst; + bool rtn = false; + ++Stats.totalCycles; + ++cycles; + currentSimCycle = currentCycle; + + // -- MAIN PROGRAM LOOP -- + // + // If the clock is down to zero, then fetch the next instruction + // else if the the instruction has not yet been triggered, execute it + // else, wait until the counter is decremented to zero to retire the instruction + + // This function updates the bitset of Harts that are + // ready to decode + UpdateStatusOfHarts(); + + if( HartsClearToDecode.any() && ( !Halted ) ) { + // Determine what hart is ready to decode + HartToDecodeID = GetNextHartToDecodeID(); + ActiveThreadID = Harts.at( HartToDecodeID )->GetAssignedThreadID(); + RegFile = Harts[HartToDecodeID]->RegFile.get(); + + feature->SetHartToExecID( HartToDecodeID ); + + // fetch the next instruction + if( !PrefetchInst() ) { + Stalled = true; + Stats.cyclesStalled++; + } else { + Stalled = false; + } + + if( !Stalled && !CoProcStallReq[HartToDecodeID] ) { + Inst = FetchAndDecodeInst(); + Inst.entry = RegFile->GetEntry(); + } + + // Now that we have decoded the instruction, check for pipeline hazards + if( ExecEcall() || Stalled || DependencyCheck( HartToDecodeID, &Inst ) || CoProcStallReq[HartToDecodeID] ) { + RegFile->SetCost( 0 ); // We failed dependency check, so set cost to 0 - this will + Stats.cyclesIdle_Pipeline++; // prevent the instruction from advancing to the next stage + HartsClearToExecute[HartToDecodeID] = false; + HartToExecID = _REV_INVALID_HART_ID_; + } else { + Stats.cyclesBusy++; + HartsClearToExecute[HartToDecodeID] = true; + HartToExecID = HartToDecodeID; + } + Inst.cost = RegFile->GetCost(); + Inst.entry = RegFile->GetEntry(); + rtn = true; + ExecPC = RegFile->GetPC(); + } + + if( ( ( HartToExecID != _REV_INVALID_HART_ID_ ) && !RegFile->GetTrigger() ) && !Halted && HartsClearToExecute[HartToExecID] ) { + // trigger the next instruction + // HartToExecID = HartToDecodeID; + RegFile->SetTrigger( true ); + +#ifdef NO_REV_TRACER + // pull the PC + output->verbose( + CALL_INFO, + 6, + 0, + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; Executing PC= 0x%" PRIx64 "\n", + id, + HartToExecID, + ActiveThreadID, + ExecPC + ); +#endif + + // Find the instruction extension + auto it = EntryToExt.find( RegFile->GetEntry() ); + if( it == EntryToExt.end() ) { + // failed to find the extension + output->fatal( CALL_INFO, -1, "Error: failed to find the instruction extension at PC=%" PRIx64 ".", ExecPC ); + } + + // found the instruction extension + std::pair EToE = it->second; + RevExt* Ext = Extensions[EToE.first].get(); + + // -- BEGIN new pipelining implementation + Pipeline.emplace_back( HartToExecID, Inst ); + + if( Ext->GetName() == "RV32F" || Ext->GetName() == "RV32D" || Ext->GetName() == "RV64F" || Ext->GetName() == "RV64D" ) { + Stats.floatsExec++; + } + + // set the hazarding + DependencySet( HartToExecID, &( Pipeline.back().second ) ); + // -- END new pipelining implementation + +#ifndef NO_REV_TRACER + // Tracer context + mem->SetTracer( Tracer ); + RegFile->SetTracer( Tracer ); +#endif + + // execute the instruction + if( !Ext->Execute( EToE.second, Pipeline.back().second, HartToExecID, RegFile ) ) { + output->fatal( CALL_INFO, -1, "Error: failed to execute instruction at PC=%" PRIx64 ".", ExecPC ); + } + +#ifndef NO_REV_TRACER + // Clear memory tracer so we don't pick up instruction fetches and other access. + // TODO: method to determine origin of memory access (core, cache, pan, host debugger, ... ) + mem->SetTracer( nullptr ); + // Conditionally trace after execution + if( Tracer ) + Tracer->Exec( currentCycle, id, HartToExecID, ActiveThreadID, InstTable[Inst.entry].mnemonic ); +#endif + +#ifdef __REV_DEEP_TRACE__ + if( feature->IsRV64() ) { + std::cout << "RDT: Executed PC = " << std::hex << ExecPC << " Inst: " << std::setw( 23 ) << InstTable[Inst.entry].mnemonic + << " r" << std::dec << (uint32_t) Inst.rd << "= " << std::hex << RegFile->RV64[Inst.rd] << " r" << std::dec + << (uint32_t) Inst.rs1 << "= " << std::hex << RegFile->RV64[Inst.rs1] << " r" << std::dec << (uint32_t) Inst.rs2 + << "= " << std::hex << RegFile->RV64[Inst.rs2] << " imm = " << std::hex << Inst.imm << std::endl; + std::cout << "RDT: Address of RD = 0x" << std::hex << (uint64_t*) ( &RegFile->RV64[Inst.rd] ) << std::dec << std::endl; + } else { + std::cout << "RDT: Executed PC = " << std::hex << ExecPC << " Inst: " << std::setw( 23 ) << InstTable[Inst.entry].mnemonic + << " r" << std::dec << (uint32_t) Inst.rd << "= " << std::hex << RegFile->RV32[Inst.rd] << " r" << std::dec + << (uint32_t) Inst.rs1 << "= " << std::hex << RegFile->RV32[Inst.rs1] << " r" << std::dec << (uint32_t) Inst.rs2 + << "= " << std::hex << RegFile->RV32[Inst.rs2] << " imm = " << std::hex << Inst.imm << std::endl; + } +#endif + + // inject the ALU fault + if( ALUFault ) { + InjectALUFault( EToE, Inst ); + } + + // if this is a singlestep, clear the singlestep and halt + if( SingleStep ) { + SingleStep = false; + Halted = true; + } + + rtn = true; + } else { + // wait until the counter has been decremented + // note that this will continue to occur until the counter is drained + // and the HART is halted + output->verbose( CALL_INFO, 9, 0, "Core %" PRIu32 " ; No available thread to exec PC= 0x%" PRIx64 "\n", id, ExecPC ); + rtn = true; + Stats.cyclesIdle_Total++; + if( HartsClearToExecute.any() ) { + Stats.cyclesIdle_MemoryFetch++; + } + } + + // Check for pipeline hazards + if( !Pipeline.empty() && ( Pipeline.front().second.cost > 0 ) ) { + Pipeline.front().second.cost--; + if( Pipeline.front().second.cost == 0 ) { // && + // Ready to retire this instruction + uint16_t HartID = Pipeline.front().first; +#ifdef NO_REV_TRACER + output->verbose( + CALL_INFO, + 6, + 0, + "Core %" PRIu32 "; Hart %" PRIu32 "; ThreadID %" PRIu32 "; Retiring PC= 0x%" PRIx64 "\n", + id, + HartID, + ActiveThreadID, + ExecPC + ); +#endif + ++Stats.retired; + RegFile->IncrementInstRet(); + + // Only clear the dependency if there is no outstanding load + if( ( RegFile->GetLSQueue()->count( LSQHash( Pipeline.front().second.rd, InstTable[Pipeline.front().second.entry].rdClass, HartID ) ) ) == 0 ) { + DependencyClear( HartID, &( Pipeline.front().second ) ); + } + Pipeline.pop_front(); + RegFile->SetCost( 0 ); + } else { + // could not retire the instruction, bump the cost + Pipeline.front().second.cost++; + } + } + // Check for completion states and new tasks + if( RegFile->GetPC() == 0 ) { + // look for more work on the execution queue + // if no work is found, don't update the PC + // just wait and spin + if( HartHasNoDependencies( HartToDecodeID ) ) { + std::unique_ptr ActiveThread = PopThreadFromHart( HartToDecodeID ); + ActiveThread->SetState( ThreadState::DONE ); + HartsClearToExecute[HartToDecodeID] = false; + HartsClearToDecode[HartToDecodeID] = false; + IdleHarts.set( HartToDecodeID ); + AddThreadsThatChangedState( std::move( ActiveThread ) ); + } + + if( HartToExecID != _REV_INVALID_HART_ID_ && !IdleHarts[HartToExecID] && HartHasNoDependencies( HartToExecID ) ) { + std::unique_ptr ActiveThread = PopThreadFromHart( HartToDecodeID ); + ActiveThread->SetState( ThreadState::DONE ); + HartsClearToExecute[HartToExecID] = false; + HartsClearToDecode[HartToExecID] = false; + IdleHarts[HartToExecID] = true; + AddThreadsThatChangedState( std::move( ActiveThread ) ); + } + } + +#ifndef NO_REV_TRACER + // Dump trace state + if( Tracer ) + Tracer->Render( currentCycle ); +#endif + + return rtn; +} + +std::unique_ptr RevCore::PopThreadFromHart( uint32_t HartID ) { + if( HartID >= numHarts ) { + output->fatal( + CALL_INFO, -1, "Error: tried to pop thread from hart %" PRIu32 " but there are only %" PRIu32 " hart(s)\n", HartID, numHarts + ); + } + IdleHarts[HartID] = true; + return Harts.at( HartID )->PopThread(); +} + +void RevCore::PrintStatSummary() { + auto memStatsTotal = mem->GetMemStatsTotal(); + + double eff = StatsTotal.totalCycles ? double( StatsTotal.cyclesBusy ) / double( StatsTotal.totalCycles ) : 0; + output->verbose( + CALL_INFO, + 2, + 0, + "Program execution complete\n" + "Core %" PRIu32 " Program Stats: Total Cycles: %" PRIu64 " Busy Cycles: %" PRIu64 " Idle Cycles: %" PRIu64 " Eff: %f\n", + id, + StatsTotal.totalCycles, + StatsTotal.cyclesBusy, + StatsTotal.cyclesIdle_Total, + eff + ); + + output->verbose( + CALL_INFO, + 3, + 0, + "\t Bytes Read: %" PRIu64 " Bytes Written: %" PRIu64 " Floats Read: %" PRIu64 " Doubles Read %" PRIu64 " Floats Exec: %" PRIu64 + " TLB Hits: %" PRIu64 " TLB Misses: %" PRIu64 " Inst Retired: %" PRIu64 "\n\n", + memStatsTotal.bytesRead, + memStatsTotal.bytesWritten, + memStatsTotal.floatsRead, + memStatsTotal.doublesRead, + StatsTotal.floatsExec, + memStatsTotal.TLBHits, + memStatsTotal.TLBMisses, + StatsTotal.retired + ); +} + +RevRegFile* RevCore::GetRegFile( uint32_t HartID ) const { + if( HartID >= Harts.size() ) { + output->fatal( + CALL_INFO, -1, "Error: tried to get RegFile for Hart %" PRIu32 " but there are only %" PRIu32 " hart(s)\n", HartID, numHarts + ); + } + return Harts.at( HartID )->RegFile.get(); +} + +void RevCore::CreateThread( uint32_t NewTID, uint64_t firstPC, void* arg ) { + // tidAddr is the address we have to write the new thread's id to + output->verbose( CALL_INFO, 2, 0, "Creating new thread with PC = 0x%" PRIx64 "\n", firstPC ); + uint32_t ParentThreadID = Harts.at( HartToExecID )->GetAssignedThreadID(); + + // Create the new thread's memory + std::shared_ptr NewThreadMem = mem->AddThreadMem(); + + // TODO: Copy TLS into new memory + + // Create new register file + auto NewThreadRegFile = std::make_unique( this ); + + // Copy the arg to the new threads a0 register + NewThreadRegFile->SetX( RevReg::a0, reinterpret_cast( arg ) ); + + // Set the stack and thread pointer + // The thread local storage is accessed with a nonnegative offset from tp, + // and the stack grows down with sp being subtracted from before storing. + uint64_t sp = ( NewThreadMem->getTopAddr() - mem->GetTLSSize() ) & ~uint64_t{ 15 }; + NewThreadRegFile->SetX( RevReg::tp, sp ); + NewThreadRegFile->SetX( RevReg::sp, sp ); + + // Set the global pointer + auto gp = loader->GetSymbolAddr( "__global_pointer$" ); + NewThreadRegFile->SetX( RevReg::gp, gp ); + NewThreadRegFile->SetX( RevReg::fp, gp ); // frame pointer register + NewThreadRegFile->SetPC( firstPC ); + + // Create a new RevThread Object + std::unique_ptr NewThread = + std::make_unique( NewTID, ParentThreadID, NewThreadMem, std::move( NewThreadRegFile ) ); + + // Add new thread to this vector so the RevCPU will add and schedule it + AddThreadsThatChangedState( std::move( NewThread ) ); +} + +// +// This is the function that is called when an ECALL exception is detected inside ClockTick +// - Currently the only way to set this exception is by Ext->Execute(....) an ECALL instruction +// +// Eventually this will be integrated into a TrapHandler however since ECALLs are the only +// supported exceptions at this point there is no need just yet. +// +// Returns true if an ECALL is in progress +bool RevCore::ExecEcall() { + if( RegFile->GetSCAUSE() != RevExceptionCause::ECALL_USER_MODE ) + return false; + + // ECALL in progress + uint32_t EcallCode = RegFile->GetX( RevReg::a7 ); + output->verbose( + CALL_INFO, + 6, + 0, + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 " - Exception Raised: ECALL with code = %" PRIu32 "\n", + id, + HartToExecID, + ActiveThreadID, + EcallCode + ); + + // TODO: Cache handler function during ECALL instruction execution + auto it = Ecalls.find( EcallCode ); + if( it == Ecalls.end() ) { + output->fatal( CALL_INFO, -1, "Ecall Code = %" PRIu32 " not found", EcallCode ); + } + + // Execute the Ecall handler + HartToExecID = HartToDecodeID; + bool completed = ( this->*it->second )() != EcallStatus::CONTINUE; + + // If we have completed, reset the EcallState and SCAUSE + if( completed ) { + Harts[HartToDecodeID]->GetEcallState().clear(); + RegFile->SetSCAUSE( RevExceptionCause::NONE ); + } + + return true; +} + +// Looks for a hart without a thread assigned to it and then assigns it. +// This function should never be called if there are no available harts +// so if for some reason we can't find a hart without a thread assigned +// to it then we have a bug. +void RevCore::AssignThread( std::unique_ptr Thread ) { + uint32_t HartToAssign = FindIdleHartID(); + + if( HartToAssign == _REV_INVALID_HART_ID_ ) { + output->fatal( + CALL_INFO, + 1, + "Attempted to assign a thread to a hart but no available harts were " + "found.\n" + "We should never have tried to assign a thread to this Core if it had no " + "harts available (ie. Core->NumIdleHarts() == 0 ).\n" + "This is a bug\n" + ); + } + + // Assign the thread to the hart + Harts.at( HartToAssign )->AssignThread( std::move( Thread ) ); + + IdleHarts[HartToAssign] = false; + + return; +} + +uint32_t RevCore::FindIdleHartID() const { + uint32_t IdleHartID = _REV_INVALID_HART_ID_; + // Iterate over IdleHarts to find the first idle hart + for( uint32_t i = 0; i < Harts.size(); i++ ) { + if( IdleHarts[i] ) { + IdleHartID = i; + break; + } + } + if( IdleHartID == _REV_INVALID_HART_ID_ ) { + output->fatal( CALL_INFO, -1, "Attempted to find an idle hart but none were found. This is a bug\n" ); + } + + return IdleHartID; +} + +void RevCore::InjectALUFault( std::pair EToE, RevInst& Inst ) { + // inject ALU fault + RevExt* Ext = Extensions[EToE.first].get(); + if( ( Ext->GetName() == "RV64F" ) || ( Ext->GetName() == "RV64D" ) ) { + // write an rv64 float rd + uint64_t tmp; + static_assert( sizeof( tmp ) == sizeof( RegFile->DPF[Inst.rd] ) ); + memcpy( &tmp, &RegFile->DPF[Inst.rd], sizeof( tmp ) ); + tmp |= RevRand( 0, ~( ~uint64_t{ 0 } << fault_width ) ); + memcpy( &RegFile->DPF[Inst.rd], &tmp, sizeof( tmp ) ); + } else if( ( Ext->GetName() == "RV32F" ) || ( Ext->GetName() == "RV32D" ) ) { + // write an rv32 float rd + uint32_t tmp; + static_assert( sizeof( tmp ) == sizeof( RegFile->SPF[Inst.rd] ) ); + memcpy( &tmp, &RegFile->SPF[Inst.rd], sizeof( tmp ) ); + tmp |= RevRand( 0, ~( uint32_t{ 0 } << fault_width ) ); + memcpy( &RegFile->SPF[Inst.rd], &tmp, sizeof( tmp ) ); + } else { + // write an X register + uint64_t rval = RevRand( 0, ~( ~uint64_t{ 0 } << fault_width ) ); + RegFile->SetX( Inst.rd, rval | RegFile->GetX( Inst.rd ) ); + } + + // clear the fault + ALUFault = false; +} + +///< RevCore: Used by RevCPU to determine if it can disable this proc +/// based on the criteria there are no threads assigned to it and the +/// CoProc is done +bool RevCore::HasNoWork() const { + return HasNoBusyHarts() && ( !coProc || coProc->IsDone() ); +} + +void RevCore::UpdateStatusOfHarts() { + // A Hart is ClearToDecode if: + // 1. It has a thread assigned to it (ie. NOT Idle) + // 2. It's last instruction is done executing (ie. cost is set to 0) + for( size_t i = 0; i < Harts.size(); i++ ) { + HartsClearToDecode[i] = !IdleHarts[i] && Harts[i]->RegFile->cost == 0; + } + return; +} + +} // namespace SST::RevCPU + +// EOF diff --git a/src/RevExt.cc b/src/RevExt.cc index ca5244e16..965896799 100644 --- a/src/RevExt.cc +++ b/src/RevExt.cc @@ -1,7 +1,7 @@ // // _RevExt_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -9,78 +9,52 @@ // #include "RevExt.h" -namespace SST::RevCPU{ -/// Change the FP environment -auto RevExt::SetFPEnv(unsigned Inst, const RevInst& payload, uint16_t HartID, RevRegFile* regFile){ - // Save a copy of the current FP environment - RevFenv saved_fenv; +namespace SST::RevCPU { - switch(payload.rm == FRMode::DYN ? regFile->GetFPRound() : payload.rm){ - case FRMode::RNE: // Round to Nearest, ties to Even - RevFenv::SetRound(FE_TONEAREST); - break; - case FRMode::RTZ: // Round towards Zero - RevFenv::SetRound(FE_TOWARDZERO); - break; - case FRMode::RDN: // Round Down (towards -Inf) - RevFenv::SetRound(FE_DOWNWARD); - break; - case FRMode::RUP: // Round Up (towards +Inf) - RevFenv::SetRound(FE_UPWARD); - break; - case FRMode::RMM: // Round to Nearest, ties to Max Magnitude - output->fatal(CALL_INFO, -1, - "Error: Round to nearest Max Magnitude not implemented at PC = 0x%" PRIx64 "\n", - regFile->GetPC()); - break; - default: - output->fatal(CALL_INFO, -1, "Illegal instruction: Bad FP rounding mode at PC = 0x%" PRIx64 "\n", - regFile->GetPC()); - break; - } - - return saved_fenv; // Return saved FP environment state -} +/// Execute an instruction +bool RevExt::Execute( uint32_t Inst, const RevInst& payload, uint32_t HartID, RevRegFile* regFile ) const { + bool ( *func )( const RevFeature*, RevRegFile*, RevMem*, const RevInst& ); -bool RevExt::Execute(unsigned Inst, const RevInst& payload, uint16_t HartID, RevRegFile* regFile){ - bool (*func)(RevFeature *, - RevRegFile *, - RevMem *, - const RevInst&); - - if( payload.compressed ){ + if( payload.compressed ) { // this is a compressed instruction, grab the compressed trampoline function func = Inst < ctable.size() ? ctable[Inst].func : nullptr; - }else{ + } else { // retrieve the function pointer for this instruction func = Inst < table.size() ? table[Inst].func : nullptr; } - if( !func ){ - output->fatal(CALL_INFO, -1, - "Error: instruction at index=%u does not exist in extension=%s", - Inst, - name.data()); + if( !func ) { + output->fatal( CALL_INFO, -1, "Error: instruction at index=%" PRIu32 " does not exist in extension=%s", Inst, name.data() ); return false; } - // execute the instruction bool ret = false; - - if(payload.rm == FRMode::None){ - // If the instruction has no FRMode, we do not need to save and restore it - ret = func(feature, regFile, mem, payload); - }else{ - // saved_fenv represents a saved FP environment, which, when destroyed, - // restores the original FP environment. We execute the function in the - // modified FP environment on the host, then restore the FP environment. - auto saved_fenv = SetFPEnv(Inst, payload, HartID, regFile); - ret = func(feature, regFile, mem, payload); + if( !payload.raisefpe ) { + // If the instruction cannot raise FP exceptions, don't mess with the FP + // environment. No RISC-V FP instructions which cannot raise FP exceptions + // depend on the FP rounding mode, i.e. depending on rounding mode implies + // that the instruction can raise FP exceptions. + ret = func( feature, regFile, mem, payload ); + } else { + // saved_fenv represents a saved FP environment on the host, which, when + // destroyed, restores the original FP host environment. We execute the + // instruction in a default FP environment on the host with all FP + // exceptions cleared and the rounding mode set according to the encoding + // and frm register. The FP exceptions which occur on the host are stored + // in FCSR when saved_fenv is destroyed. + RevFenv saved_fenv( regFile, payload.rm, output ); + + // Execute the instruction + ret = func( feature, regFile, mem, payload ); + + // Fall-through destroys saved_fenv, setting the FCSR's fflags and + // restoring the host's FP environment } return ret; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevFeature.cc b/src/RevFeature.cc index 01ccfe50c..694fc05b3 100644 --- a/src/RevFeature.cc +++ b/src/RevFeature.cc @@ -1,7 +1,7 @@ // // _RevFeature_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -9,98 +9,135 @@ // #include "RevFeature.h" -#include -#include +#include #include +#include +#include -namespace SST::RevCPU{ - -RevFeature::RevFeature( std::string Machine, - SST::Output *Output, - unsigned Min, - unsigned Max, - unsigned Id ) - : machine(std::move(Machine)), output(Output), MinCost(Min), MaxCost(Max), - ProcID(Id), HartToExecID(0), features(RV_UNKNOWN), xlen(0) { - output->verbose(CALL_INFO, 6, 0, - "Core %u ; Initializing feature set from machine string=%s\n", - ProcID, - machine.c_str()); +namespace SST::RevCPU { + +RevFeature::RevFeature( std::string Machine, SST::Output* Output, uint32_t Min, uint32_t Max, uint32_t Id ) + : machine( std::move( Machine ) ), output( Output ), MinCost( Min ), MaxCost( Max ), ProcID( Id ) { + output->verbose( + CALL_INFO, 6, 0, "Core %" PRIu32 " ; Initializing feature set from machine string=%s\n", ProcID, machine.c_str() + ); if( !ParseMachineModel() ) - output->fatal(CALL_INFO, -1, - "Error: failed to parse the machine model: %s\n", machine.c_str()); + output->fatal( CALL_INFO, -1, "Error: failed to parse the machine model: %s\n", machine.c_str() ); } -bool RevFeature::ParseMachineModel(){ +bool RevFeature::ParseMachineModel() { // walk the feature string const char* mac = machine.c_str(); // -- step 1: parse the memory model - if(!strncasecmp(mac, "RV32", 4)) + if( !strncasecmp( mac, "RV32", 4 ) ) xlen = 32; - else if(!strncasecmp(mac, "RV64", 4)) + else if( !strncasecmp( mac, "RV64", 4 ) ) xlen = 64; else return false; mac += 4; - output->verbose(CALL_INFO, 6, 0, "Core %u ; Setting XLEN to %u\n", ProcID, xlen); - output->verbose(CALL_INFO, 6, 0, "Core %u ; Architecture string=%s\n", ProcID, mac); + output->verbose( CALL_INFO, 6, 0, "Core %" PRIu32 " ; Setting XLEN to %" PRIu32 "\n", ProcID, xlen ); + output->verbose( CALL_INFO, 6, 0, "Core %" PRIu32 " ; Architecture string=%s\n", ProcID, mac ); + // clang-format off ///< List of architecture extensions. These must listed in canonical order - ///< as shown in Table 27.11, Chapter 27, of the RiSC-V Unpriviledged Spec. + ///< as shown in Table 27.11, Chapter 27, of the RISC-V Unprivileged Spec + ///< (Table 74 of Chapter 36 in the 2024 version). + ///< ///< By using a canonical ordering, the extensions' presence can be tested ///< in linear time complexity of the table and the string. Some of the ///< extensions imply other extensions, so the extension flags are ORed. - static constexpr std::pair table[] = { - { "E", RV_E }, - { "I", RV_I }, - { "M", RV_M }, - { "A", RV_A }, - { "F", RV_F | RV_ZICSR }, - { "D", RV_D | RV_F | RV_ZICSR }, - { "G", RV_I | RV_M | RV_A | RV_F | RV_D | RV_ZICSR | RV_ZIFENCEI }, - { "Q", RV_Q | RV_D | RV_F | RV_ZICSR }, - { "L", RV_L }, - { "C", RV_C }, - { "B", RV_B }, - { "J", RV_J }, - { "T", RV_T }, - { "P", RV_P }, - { "V", RV_V | RV_D | RV_F | RV_ZICSR }, - { "N", RV_N }, - { "Zicsr", RV_ZICSR }, - { "Zifencei", RV_ZIFENCEI }, - { "Zam", RV_ZAM | RV_A }, - { "Ztso", RV_ZTSO }, - { "Zfa", RV_ZFA | RV_F | RV_ZICSR }, - { "Zicbom", RV_ZICBOM }, + ///< + ///< The second and third values are the major and minor default version. + ///< The fourth and fifth values are the major version range that Rev supports. + ///< Values of -1, 0 for the fourth and fifth values indicates no Rev support yet. + ///< + ///< ExtensionName DefaultMajor DefaultMinor MinSupportedVersion MaxSupportedVersion Flags + static constexpr std::tuple table[] = { + { "I", 2, 1, 2, 2, RV_I }, + { "E", 2, 0, -1, 0, RV_E }, // Unsupported + { "M", 2, 0, 2, 2, RV_M | RV_ZMMUL }, + { "A", 2, 1, 2, 2, RV_ZAAMO | RV_ZALRSC }, + { "F", 2, 2, 2, 2, RV_F | RV_ZICSR }, + { "D", 2, 2, 2, 2, RV_D | RV_F | RV_ZICSR }, + { "G", 2, 0, 2, 2, RV_I | RV_M | RV_ZMMUL | RV_ZAAMO | RV_ZALRSC | + RV_F | RV_D | RV_ZICSR | RV_ZIFENCEI }, + { "Q", 2, 2, -1, 0, RV_Q | RV_D | RV_F | RV_ZICSR }, // Unsupported + { "C", 2, 0, 2, 2, RV_C }, + { "B", 1, 0, -1, 0, RV_B }, // Unsupported + { "P", 0, 2, -1, 0, RV_P }, // Unsupported + { "V", 1, 0, -1, 0, RV_V | RV_D | RV_F | RV_ZICSR }, + { "H", 1, 0, -1, 0, RV_H }, // Unsupported + { "Zicbom", 1, 0, 1, 1, RV_ZICBOM }, + { "Zicntr", 2, 0, 2, 2, RV_ZICNTR | RV_ZICSR }, + { "Zicsr", 2, 0, 2, 2, RV_ZICSR }, + { "Zifencei", 2, 0, 2, 2, RV_ZIFENCEI }, + { "Zmmul", 1, 0, 1, 1, RV_ZMMUL }, + { "Zaamo", 2, 1, 2, 2, RV_ZAAMO }, + { "Zalrsc", 2, 1, 2, 2, RV_ZALRSC }, + { "Zfa", 1, 0, 1, 1, RV_ZFA | RV_F | RV_ZICSR }, + { "Zfh", 1, 0, -1, 0, RV_ZFH | RV_ZFHMIN | RV_F | RV_ZICSR }, // Unsupported + { "Zfhmin", 1, 0, -1, 0, RV_ZFHMIN | RV_F | RV_ZICSR }, // Unsupported + { "Ztso", 1, 0, -1, 0, RV_ZTSO }, // Unsupported }; + // clang-format on // -- step 2: parse all the features // Note: Extension strings, if present, must appear in the order listed in the table above. - if (*mac){ - for (const auto& tab : table) { + if( *mac ) { + char unsupported_version[128]; + *unsupported_version = 0; + + for( auto [ext, majorVersion, minorVersion, minimumVersion, maximumVersion, flags] : table ) { // Look for an architecture string matching the current extension - if(!strncasecmp(mac, tab.first.data(), tab.first.size())){ + if( !strncasecmp( mac, ext.data(), ext.size() ) ) { // Set the machine entries for the matching extension - SetMachineEntry(RevFeatureType{tab.second}); + SetMachineEntry( RevFeatureType{ flags } ); // Move past the currently matching extension - mac += tab.first.size(); + mac += ext.size(); + + // Optional version string follows extension + if( isdigit( *mac ) ) { + majorVersion = strtoul( mac, const_cast( &mac ), 10 ); + if( tolower( *mac ) == 'p' && isdigit( *++mac ) ) + minorVersion = strtoul( mac, const_cast( &mac ), 10 ); + } + + // Record first unsupported extension version + // Error is delayed so that parse errors in the architecture string take priority + if( ( majorVersion < minimumVersion || majorVersion > maximumVersion ) && !*unsupported_version ) { + snprintf( + unsupported_version, + sizeof( unsupported_version ), + "Error: Version %" PRIu64 ".%" PRIu64 " of %s extension is not supported\n", + majorVersion, + minorVersion, + ext.data() + ); + } // Skip underscore separators - while (*mac == '_') ++mac; + while( *mac == '_' ) + ++mac; // Success if end of string is reached - if (!*mac) + if( !*mac ) { + // Report error on first unsupported extension version + if( *unsupported_version ) { + output->fatal( CALL_INFO, -1, "%s", unsupported_version ); + } return true; + } } } } return false; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevLoader.cc b/src/RevLoader.cc index ebffb0981..f45c4d1cd 100644 --- a/src/RevLoader.cc +++ b/src/RevLoader.cc @@ -1,7 +1,7 @@ // // _RevLoader_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -11,65 +11,51 @@ #include "RevLoader.h" #include "RevMem.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { using MemSegment = RevMem::MemSegment; -RevLoader::RevLoader( std::string Exe, std::string Args, - RevMem *Mem, SST::Output *Output ) - : exe(Exe), args(Args), mem(Mem), output(Output), - RV32Entry(0x00l), RV64Entry(0x00ull) { - if( !LoadElf() ) - output->fatal(CALL_INFO, -1, "Error: failed to load executable into memory\n"); -} - -RevLoader::~RevLoader(){ -} - -bool RevLoader::IsElf( const Elf64_Ehdr eh64 ){ - if( (eh64).e_ident[0] == 0x7f && - (eh64).e_ident[1] == 'E' && - (eh64).e_ident[2] == 'L' && - (eh64).e_ident[3] == 'F' ) +bool RevLoader::IsElf( const Elf64_Ehdr eh64 ) { + if( ( eh64 ).e_ident[0] == 0x7f && ( eh64 ).e_ident[1] == 'E' && ( eh64 ).e_ident[2] == 'L' && ( eh64 ).e_ident[3] == 'F' ) return true; return false; } -bool RevLoader::IsRVElf32( const Elf64_Ehdr eh64 ){ - if( IsElf(eh64) && (eh64).e_ident[4] == 1 ) +bool RevLoader::IsRVElf32( const Elf64_Ehdr eh64 ) { + if( IsElf( eh64 ) && ( eh64 ).e_ident[4] == 1 ) return true; return false; } -bool RevLoader::IsRVElf64( const Elf64_Ehdr eh64 ){ - if( IsElf(eh64) && (eh64).e_ident[4] == 2 ) +bool RevLoader::IsRVElf64( const Elf64_Ehdr eh64 ) { + if( IsElf( eh64 ) && ( eh64 ).e_ident[4] == 2 ) return true; return false; } -bool RevLoader::IsRVLittle( const Elf64_Ehdr eh64 ){ - if( IsElf(eh64) && (eh64).e_ident[5] == 1 ) +bool RevLoader::IsRVLittle( const Elf64_Ehdr eh64 ) { + if( IsElf( eh64 ) && ( eh64 ).e_ident[5] == 1 ) return true; return false; } -bool RevLoader::IsRVBig( const Elf64_Ehdr eh64 ){ - if( IsElf(eh64) && (eh64).e_ident[5] == 2 ) +bool RevLoader::IsRVBig( const Elf64_Ehdr eh64 ) { + if( IsElf( eh64 ) && ( eh64 ).e_ident[5] == 2 ) return true; return false; } // breaks the write into cache line chunks -bool RevLoader::WriteCacheLine(uint64_t Addr, size_t Len, void *Data){ - if( Len == 0 ){ +bool RevLoader::WriteCacheLine( uint64_t Addr, uint32_t Len, const void* Data ) { + if( Len == 0 ) { // nothing to do here, move along return true; } // calculate the cache line size - unsigned lineSize = mem->getLineSize(); - if( lineSize == 0 ){ + uint32_t lineSize = mem->getLineSize(); + if( lineSize == 0 ) { // default to 64byte cache lines lineSize = 64; } @@ -78,29 +64,29 @@ bool RevLoader::WriteCacheLine(uint64_t Addr, size_t Len, void *Data){ // then dispatch the write as normal. Otherwise, // block the writes as cache lines // #131 added case for when Len==lineSize - if( Len <= lineSize ){ + if( Len <= lineSize ) { // one cache line to write, dispatch it - return mem->WriteMem(0, Addr, Len, Data); + return mem->WriteMem( 0, Addr, Len, Data ); } // calculate the base address of the first cache line - size_t Total = 0; - bool done = false; + size_t Total = 0; + bool done = false; uint64_t BaseCacheAddr = Addr; - while( !done ){ - if( BaseCacheAddr % lineSize == 0 ){ + while( !done ) { + if( BaseCacheAddr % lineSize == 0 ) { done = true; - }else{ + } else { BaseCacheAddr--; } } // write the first cache line - size_t TmpSize = BaseCacheAddr + lineSize - Addr; - uint64_t TmpData = uint64_t(Data); + uint32_t TmpSize = uint32_t( BaseCacheAddr + lineSize - Addr ); + uint64_t TmpData = uint64_t( Data ); uint64_t TmpAddr = Addr; - if( !mem->WriteMem(0, TmpAddr, TmpSize, reinterpret_cast(TmpData)) ){ - output->fatal(CALL_INFO, -1, "Error: Failed to perform cache line write\n" ); + if( !mem->WriteMem( 0, TmpAddr, TmpSize, reinterpret_cast( TmpData ) ) ) { + output->fatal( CALL_INFO, -1, "Error: Failed to perform cache line write\n" ); } TmpAddr += TmpSize; @@ -108,17 +94,17 @@ bool RevLoader::WriteCacheLine(uint64_t Addr, size_t Len, void *Data){ Total += TmpSize; // now perform the remainder of the writes - do{ - if( (Len-Total) > lineSize ){ + do { + if( ( Len - Total ) > lineSize ) { // setup another full cache line write TmpSize = lineSize; - }else{ + } else { // this is probably the final write operation - TmpSize = (Len-Total); + TmpSize = uint32_t( Len - Total ); } - if( !mem->WriteMem(0, TmpAddr, TmpSize, reinterpret_cast(TmpData)) ){ - output->fatal(CALL_INFO, -1, "Error: Failed to perform cache line write\n" ); + if( !mem->WriteMem( 0, TmpAddr, TmpSize, reinterpret_cast( TmpData ) ) ) { + output->fatal( CALL_INFO, -1, "Error: Failed to perform cache line write\n" ); } // incrememnt the temp counters @@ -126,489 +112,467 @@ bool RevLoader::WriteCacheLine(uint64_t Addr, size_t Len, void *Data){ TmpData += TmpSize; Total += TmpSize; - }while( Total < Len ); + } while( Total < Len ); return true; } // Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_le -bool RevLoader::LoadElf32(char *membuf, size_t sz){ +bool RevLoader::LoadElf32( char* membuf, size_t sz ) { // Parse the ELF header - Elf32_Ehdr *eh = (Elf32_Ehdr *)(membuf); + Elf32_Ehdr* eh = (Elf32_Ehdr*) ( membuf ); // Parse the program headers - Elf32_Phdr *ph = (Elf32_Phdr *)(membuf + eh->e_phoff); + Elf32_Phdr* ph = (Elf32_Phdr*) ( membuf + eh->e_phoff ); // Parse the section headers - Elf32_Shdr* sh = (Elf32_Shdr*)(membuf + eh->e_shoff); - char *shstrtab = membuf + sh[eh->e_shstrndx].sh_offset; + Elf32_Shdr* sh = (Elf32_Shdr*) ( membuf + eh->e_shoff ); + char* shstrtab = membuf + sh[eh->e_shstrndx].sh_offset; // Store the entry point of the program - RV32Entry = eh->e_entry; + RV32Entry = eh->e_entry; // Add memory segments for each program header - for (unsigned i = 0; i < eh->e_phnum; i++) { - if( sz < ph[i].p_offset + ph[i].p_filesz ){ - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + for( size_t i = 0; i < eh->e_phnum; i++ ) { + if( sz < ph[i].p_offset + ph[i].p_filesz ) { + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); } // Check if the program header is PT_TLS // - If so, save the addr & size of the TLS segment - if( ph[i].p_type == PT_TLS ){ + if( ph[i].p_type == PT_TLS ) { TLSBaseAddr = ph[i].p_paddr; - TLSSize = ph[i].p_memsz; - mem->SetTLSInfo(ph[i].p_paddr, ph[i].p_memsz); + TLSSize = ph[i].p_memsz; + mem->SetTLSInfo( ph[i].p_paddr, ph[i].p_memsz ); } // Add a memory segment for the program header - if( ph[i].p_memsz ){ - mem->AddRoundedMemSeg(ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__); + if( ph[i].p_memsz ) { + mem->AddRoundedMemSeg( ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__ ); } } - mem->AddThreadMem(); + (void) mem->AddThreadMem(); // Add memory segments for each program header - for (unsigned i = 0; i < eh->e_phnum; i++) { - if( sz < ph[i].p_offset + ph[i].p_filesz ){ - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + for( size_t i = 0; i < eh->e_phnum; i++ ) { + if( sz < ph[i].p_offset + ph[i].p_filesz ) { + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); } // Add a memory segment for the program header - if( ph[i].p_memsz ){ - mem->AddRoundedMemSeg(ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__); + if( ph[i].p_memsz ) { + mem->AddRoundedMemSeg( ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__ ); } } uint64_t StaticDataEnd = 0; - uint64_t BSSEnd = 0; - uint64_t DataEnd = 0; - uint64_t TextEnd = 0; - for (unsigned i = 0; i < eh->e_shnum; i++) { + uint64_t BSSEnd = 0; + uint64_t DataEnd = 0; + uint64_t TextEnd = 0; + for( size_t i = 0; i < eh->e_shnum; i++ ) { // check if the section header name is bss - if( strcmp(shstrtab + sh[i].sh_name, ".bss") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".bss" ) == 0 ) { BSSEnd = sh[i].sh_addr + sh[i].sh_size; } - if( strcmp(shstrtab + sh[i].sh_name, ".text") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".text" ) == 0 ) { TextEnd = sh[i].sh_addr + sh[i].sh_size; } - if( strcmp(shstrtab + sh[i].sh_name, ".data") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".data" ) == 0 ) { DataEnd = sh[i].sh_addr + sh[i].sh_size; } } // If BSS exists, static data ends after it - if( BSSEnd > 0 ){ + if( BSSEnd > 0 ) { StaticDataEnd = BSSEnd; - } else if ( DataEnd > 0 ){ + } else if( DataEnd > 0 ) { // BSS Doesn't exist, but data does StaticDataEnd = DataEnd; - } else if ( TextEnd > 0 ){ + } else if( TextEnd > 0 ) { // Text is last resort StaticDataEnd = TextEnd; } else { // Can't find any (Text, BSS, or Data) sections - output->fatal(CALL_INFO, -1, "Error: No text, data, or bss sections --- RV64 Elf is unrecognizable\n" ); + output->fatal( + CALL_INFO, + -1, + "Error: No text, data, or bss sections --- RV64 Elf is " + "unrecognizable\n" + ); } // Check that the ELF file is valid - if( sz < eh->e_phoff + eh->e_phnum * sizeof(*ph) ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + if( sz < eh->e_phoff + eh->e_phnum * sizeof( *ph ) ) + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); // Write the program headers to memory - elfinfo.phnum = eh->e_phnum; - elfinfo.phent = sizeof(Elf32_Phdr); - elfinfo.phdr = eh->e_phoff; - elfinfo.phdr_size = eh->e_phnum * sizeof(Elf32_Phdr); + elfinfo.phnum = eh->e_phnum; + elfinfo.phent = sizeof( Elf32_Phdr ); + elfinfo.phdr = eh->e_phoff; + elfinfo.phdr_size = eh->e_phnum * sizeof( Elf32_Phdr ); // set the first stack pointer - uint32_t sp = mem->GetStackTop() - (uint32_t)(elfinfo.phdr_size); - WriteCacheLine(sp, elfinfo.phdr_size, ph); - mem->SetStackTop(sp); + uint64_t sp = mem->GetStackTop() - elfinfo.phdr_size; + WriteCacheLine( sp, uint32_t( elfinfo.phdr_size ), ph ); + mem->SetStackTop( sp ); // iterate over the program headers - for( unsigned i=0; ie_phnum; i++ ){ + for( size_t i = 0; i < eh->e_phnum; i++ ) { // Look for the loadable program headers - if( ph[i].p_type == PT_LOAD && ph[i].p_memsz ){ - if( ph[i].p_filesz ){ - if( sz < ph[i].p_offset + ph[i].p_filesz ){ - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + if( ph[i].p_type == PT_LOAD && ph[i].p_memsz ) { + if( ph[i].p_filesz ) { + if( sz < ph[i].p_offset + ph[i].p_filesz ) { + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); } - WriteCacheLine(ph[i].p_paddr, - ph[i].p_filesz, - (uint8_t*)(membuf+ph[i].p_offset)); + WriteCacheLine( ph[i].p_paddr, ph[i].p_filesz, (uint8_t*) ( membuf + ph[i].p_offset ) ); } - std::vector zeros(ph[i].p_memsz - ph[i].p_filesz); - WriteCacheLine(ph[i].p_paddr + ph[i].p_filesz, - ph[i].p_memsz - ph[i].p_filesz, - &zeros[0]); + std::vector zeros( ph[i].p_memsz - ph[i].p_filesz ); + WriteCacheLine( ph[i].p_paddr + ph[i].p_filesz, ph[i].p_memsz - ph[i].p_filesz, &zeros[0] ); } } // Check that the ELF file is valid - if( sz < eh->e_shoff + eh->e_shnum * sizeof(*sh) ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + if( sz < eh->e_shoff + eh->e_shnum * sizeof( *sh ) ) + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); if( eh->e_shstrndx >= eh->e_shnum ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); if( sz < sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); - unsigned strtabidx = 0; - unsigned symtabidx = 0; + uint64_t strtabidx = 0; + uint64_t symtabidx = 0; // Iterate over every section header - for( unsigned i=0; ie_shnum; i++ ){ + for( size_t i = 0; i < eh->e_shnum; i++ ) { // If the section header is empty, skip it if( sh[i].sh_type & SHT_NOBITS ) continue; if( sz < sh[i].sh_offset + sh[i].sh_size ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); // Find the string table index - if( strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0 ) + if( strcmp( shstrtab + sh[i].sh_name, ".strtab" ) == 0 ) strtabidx = i; // Find the symbol table index - if( strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0 ) + if( strcmp( shstrtab + sh[i].sh_name, ".symtab" ) == 0 ) symtabidx = i; } // If the string table index and symbol table index are valid (NonZero) - if( strtabidx && symtabidx ){ + if( strtabidx && symtabidx ) { // If there is a string table and symbol table, add them as valid memory // Parse the string table - char *strtab = membuf + sh[strtabidx].sh_offset; - Elf32_Sym* sym = (Elf32_Sym*)(membuf + sh[symtabidx].sh_offset); + char* strtab = membuf + sh[strtabidx].sh_offset; + Elf32_Sym* sym = (Elf32_Sym*) ( membuf + sh[symtabidx].sh_offset ); // Iterate over every symbol in the symbol table - for( unsigned i=0; i= sh[strtabidx].sh_size ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); - if( strnlen(strtab + sym[i].st_name, maxlen) >= maxlen ) - output->fatal(CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); + if( strnlen( strtab + sym[i].st_name, maxlen ) >= maxlen ) + output->fatal( CALL_INFO, -1, "Error: RV32 Elf is unrecognizable\n" ); // Add the symbol to the symbol table - symtable[strtab+sym[i].st_name] = sym[i].st_value; + symtable[strtab + sym[i].st_name] = sym[i].st_value; } } // Initialize the heap - mem->InitHeap(StaticDataEnd); + mem->InitHeap( StaticDataEnd ); return true; } -bool RevLoader::LoadElf64(char *membuf, size_t sz){ +bool RevLoader::LoadElf64( char* membuf, size_t sz ) { // Parse the ELF header - Elf64_Ehdr *eh = (Elf64_Ehdr *)(membuf); + Elf64_Ehdr* eh = (Elf64_Ehdr*) ( membuf ); // Parse the program headers - Elf64_Phdr *ph = (Elf64_Phdr *)(membuf + eh->e_phoff); + Elf64_Phdr* ph = (Elf64_Phdr*) ( membuf + eh->e_phoff ); // Parse the section headers - Elf64_Shdr* sh = (Elf64_Shdr*)(membuf + eh->e_shoff); - char *shstrtab = membuf + sh[eh->e_shstrndx].sh_offset; + Elf64_Shdr* sh = (Elf64_Shdr*) ( membuf + eh->e_shoff ); + char* shstrtab = membuf + sh[eh->e_shstrndx].sh_offset; // Store the entry point of the program - RV64Entry = eh->e_entry; + RV64Entry = eh->e_entry; // Add memory segments for each program header - for (unsigned i = 0; i < eh->e_phnum; i++) { - if( sz < ph[i].p_offset + ph[i].p_filesz ){ - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + for( size_t i = 0; i < eh->e_phnum; i++ ) { + if( sz < ph[i].p_offset + ph[i].p_filesz ) { + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); } // Check if the program header is PT_TLS // - If so, save the addr & size of the TLS segment - if( ph[i].p_type == PT_TLS ){ + if( ph[i].p_type == PT_TLS ) { TLSBaseAddr = ph[i].p_paddr; - TLSSize = ph[i].p_memsz; - mem->SetTLSInfo(ph[i].p_paddr, ph[i].p_memsz); + TLSSize = ph[i].p_memsz; + mem->SetTLSInfo( ph[i].p_paddr, ph[i].p_memsz ); } // Add a memory segment for the program header - if( ph[i].p_memsz ){ - mem->AddRoundedMemSeg(ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__); + if( ph[i].p_memsz ) { + mem->AddRoundedMemSeg( ph[i].p_paddr, ph[i].p_memsz, __PAGE_SIZE__ ); } } // Add the first thread's memory - mem->AddThreadMem(); + (void) mem->AddThreadMem(); uint64_t StaticDataEnd = 0; - uint64_t BSSEnd = 0; - uint64_t DataEnd = 0; - uint64_t TextEnd = 0; - for (unsigned i = 0; i < eh->e_shnum; i++) { + uint64_t BSSEnd = 0; + uint64_t DataEnd = 0; + uint64_t TextEnd = 0; + for( size_t i = 0; i < eh->e_shnum; i++ ) { // check if the section header name is bss - if( strcmp(shstrtab + sh[i].sh_name, ".bss") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".bss" ) == 0 ) { BSSEnd = sh[i].sh_addr + sh[i].sh_size; } - if( strcmp(shstrtab + sh[i].sh_name, ".text") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".text" ) == 0 ) { TextEnd = sh[i].sh_addr + sh[i].sh_size; } - if( strcmp(shstrtab + sh[i].sh_name, ".data") == 0 ){ + if( strcmp( shstrtab + sh[i].sh_name, ".data" ) == 0 ) { DataEnd = sh[i].sh_addr + sh[i].sh_size; } } // If BSS exists, static data ends after it - if( BSSEnd > 0 ){ + if( BSSEnd > 0 ) { StaticDataEnd = BSSEnd; - } else if ( DataEnd > 0 ){ + } else if( DataEnd > 0 ) { // BSS Doesn't exist, but data does StaticDataEnd = DataEnd; - } else if ( TextEnd > 0 ){ + } else if( TextEnd > 0 ) { // Text is last resort StaticDataEnd = TextEnd; } else { // Can't find any (Text, BSS, or Data) sections - output->fatal(CALL_INFO, -1, "Error: No text, data, or bss sections --- RV64 Elf is unrecognizable\n" ); + output->fatal( + CALL_INFO, + -1, + "Error: No text, data, or bss sections --- RV64 Elf is " + "unrecognizable\n" + ); } // Check that the ELF file is valid - if( sz < eh->e_phoff + eh->e_phnum * sizeof(*ph) ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + if( sz < eh->e_phoff + eh->e_phnum * sizeof( *ph ) ) + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); // Write the program headers to memory - elfinfo.phnum = eh->e_phnum; - elfinfo.phent = sizeof(Elf64_Phdr); - elfinfo.phdr = eh->e_phoff; - elfinfo.phdr_size = eh->e_phnum * sizeof(Elf64_Phdr); + elfinfo.phnum = eh->e_phnum; + elfinfo.phent = sizeof( Elf64_Phdr ); + elfinfo.phdr = eh->e_phoff; + elfinfo.phdr_size = eh->e_phnum * sizeof( Elf64_Phdr ); // set the first stack pointer - uint64_t sp = mem->GetStackTop() - elfinfo.phdr_size; - WriteCacheLine(sp, elfinfo.phdr_size, ph); - mem->SetStackTop(sp); + uint64_t sp = mem->GetStackTop() - elfinfo.phdr_size; + WriteCacheLine( sp, uint32_t( elfinfo.phdr_size ), ph ); + mem->SetStackTop( sp ); // iterate over the program headers - for( unsigned i=0; ie_phnum; i++ ){ + for( size_t i = 0; i < eh->e_phnum; i++ ) { // Look for the loadable headers - if( ph[i].p_type == PT_LOAD && ph[i].p_memsz ){ - if( ph[i].p_filesz ){ - if( sz < ph[i].p_offset + ph[i].p_filesz ){ - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + if( ph[i].p_type == PT_LOAD && ph[i].p_memsz ) { + if( ph[i].p_filesz ) { + if( sz < ph[i].p_offset + ph[i].p_filesz ) { + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); } - WriteCacheLine(ph[i].p_paddr, - ph[i].p_filesz, - (uint8_t*)(membuf+ph[i].p_offset)); + WriteCacheLine( ph[i].p_paddr, uint32_t( ph[i].p_filesz ), (uint8_t*) ( membuf + ph[i].p_offset ) ); } - std::vector zeros(ph[i].p_memsz - ph[i].p_filesz); - WriteCacheLine(ph[i].p_paddr + ph[i].p_filesz, - ph[i].p_memsz - ph[i].p_filesz, - &zeros[0]); + std::vector zeros( ph[i].p_memsz - ph[i].p_filesz ); + WriteCacheLine( ph[i].p_paddr + ph[i].p_filesz, uint32_t( ph[i].p_memsz - ph[i].p_filesz ), &zeros[0] ); } } // Check that the ELF file is valid - if( sz < eh->e_shoff + eh->e_shnum * sizeof(*sh) ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + if( sz < eh->e_shoff + eh->e_shnum * sizeof( *sh ) ) + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); if( eh->e_shstrndx >= eh->e_shnum ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); if( sz < sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); - unsigned strtabidx = 0; - unsigned symtabidx = 0; + uint64_t strtabidx = 0; + uint64_t symtabidx = 0; // Iterate over every section header - for( unsigned i=0; ie_shnum; i++ ){ + for( size_t i = 0; i < eh->e_shnum; i++ ) { // If the section header is empty, skip it - if( sh[i].sh_type & SHT_NOBITS ){ + if( sh[i].sh_type & SHT_NOBITS ) { continue; } - if( sz < sh[i].sh_offset + sh[i].sh_size ){ - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + if( sz < sh[i].sh_offset + sh[i].sh_size ) { + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); } // Find the string table index - if( strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0 ) + if( strcmp( shstrtab + sh[i].sh_name, ".strtab" ) == 0 ) strtabidx = i; // Find the symbol table index - if( strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0 ) + if( strcmp( shstrtab + sh[i].sh_name, ".symtab" ) == 0 ) symtabidx = i; } // If the string table index and symbol table index are valid (NonZero) - if( strtabidx && symtabidx ){ + if( strtabidx && symtabidx ) { // Parse the string table - char *strtab = membuf + sh[strtabidx].sh_offset; - Elf64_Sym* sym = (Elf64_Sym*)(membuf + sh[symtabidx].sh_offset); + char* strtab = membuf + sh[strtabidx].sh_offset; + Elf64_Sym* sym = (Elf64_Sym*) ( membuf + sh[symtabidx].sh_offset ); // Iterate over every symbol in the symbol table - for( unsigned i=0; i= sh[strtabidx].sh_size ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); - if( strnlen(strtab + sym[i].st_name, maxlen) >= maxlen ) - output->fatal(CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); + if( strnlen( strtab + sym[i].st_name, maxlen ) >= maxlen ) + output->fatal( CALL_INFO, -1, "Error: RV64 Elf is unrecognizable\n" ); // Add the symbol to the symbol table - symtable[strtab+sym[i].st_name] = sym[i].st_value; + symtable[strtab + sym[i].st_name] = sym[i].st_value; } } // Initialize the heap - mem->InitHeap(StaticDataEnd); + mem->InitHeap( StaticDataEnd ); return true; } -std::string RevLoader::GetArgv(unsigned entry){ - if( entry > (argv.size()-1) ) - return ""; - - return argv[entry]; -} - -bool RevLoader::LoadProgramArgs(){ +template +bool RevLoader::LoadProgramArgs( const std::string& exe, const std::vector& args ) { // -------------- BEGIN MEMORY LAYOUT NOTES - // At this point in the code, the loader has initialized .text, .bss, .sbss, etc - // We seek to utilize the argument array information that is passed in - // from the user (see parameter="args") in order to initialize the arguments to 'main' + // At this point in the code, the loader has initialized .text, .bss, .sbss, etc. + // + // We seek to utilize the argument array information that is passed in from the + // user (see parameter="args") in order to initialize the arguments to main(). + // // For example, people often implement: // int main( int argc, char **argv) // - // This function builds the necessary information for the input arguments - // and writes this information to memory + // This function builds the necessary information for the input arguments and + // writes this information to memory. // - // There are two things we know: - // 1) StackTop is the current top of the stack initialized by the loader (not RevMem) - // 2) MemTop is the theoretical "top" of memory (eg, the highest possible virtual address) set by RevMem + // StackTop is the current top of the stack initialized by the loader (not RevMem). // - // These data elements are written to the highest 1024 bytes of memory, or: - // [MemTop] --> [Memtop-1024] + // These data elements are pushed onto the stack, and the new StackTop is used as + // the argv pointer passed to main(). // - // This is addressable memory, but exists BEYOND the top of the standard stack - // The data is written in two parts. First, we write the ARGV strings (null terminated) - // in reverse order into the most significant addresses as follows: + // [Old StackTop] + // Pointee of argv[argc-1] + // ... + // Pointee of argv[2] + // Pointee of argv[1] + // Pointee of argv[0] (also known as the executable name) // - // [MemTop] - // ARGV[ARGC-1] - // ARGV[ARGC-2] - // .... - // ARGV[0] (also known as the executable name) + // argv[argc-1] pointer + // ... + // argv[2] pointer + // argv[1] pointer + // argv[0] pointer + // [New StackTop] // - // Note that the addresses are written contiguously + // Note that the argv[i] addresses are written contiguously. // - // Next, we setup the prologue header just above the base stack pointer - // that contains the layout of this array. This includes our ARGC value - // We start this block of memory at SP+48 bytes as follows: + // The size of each argv[i] pointer is equal to XLEN. + // It is necessary that argv[i] be contiguous in memory across i + // and that sizeof(argv[i]) == sizeof(char*) == XLEN. // - // [SP+48] : ARGC - // [SP+52] : POINTER TO A MEMORY LOCATION THAT CONTAINS THE BASE ADDRESS OF *ARGV[0] - // [SP+60] : POINTER TO ARGV[0] - // [SP+68] : POINTER TO ARGV[1] - // [SP+72] : ... + // Each string that argv[i] points to starts at an address which is a multiple of XLEN. // - // Finally, when the processor comes out of Reset() (see RevProc.cc), we initialize - // the x10 register to the value of ARGC and the x11 register to the base pointer to ARGV + // Finally, in RevCPU::InitMainThread(), we initialize the a0 register to the value of + // argc and the a1 register to the base pointer to argv. // -------------- END MEMORY LAYOUT NOTES + // Allocate sizeof(XLEN) bytes for each of the argv[] pointers + // ArgvBase + ArgvOffset is the address where each of the argv strings will start + XLEN ArgvOffset = XLEN( sizeof( XLEN ) * ( args.size() + 1 ) ); - // argv[0] = program name - argv.push_back(exe); + // Compute the total size, rounding each string up to a multiple of sizeof( XLEN ) + // The terminating 0 byte is included, so arg.size() is rounded up to next multiple + XLEN ArgArraySize = ArgvOffset; + for( auto& arg : args ) + ArgArraySize += XLEN( arg.size() | ( sizeof( XLEN ) - 1 ) ) + 1; - // split the rest of the arguments into tokens - splitStr(args, ' ', argv); + // Round ArgArraySize up to a multiple of 16 bytes + ArgArraySize = ( ( ArgArraySize - 1 ) | XLEN{ 15 } ) + 1; - if( argv.size() == 0 ){ - output->fatal(CALL_INFO, -1, "Error: failed to initialize the program arguments\n"); - return false; - } + // OldStackTop is the current StackTop rounded down to a multiple of 16 bytes + const XLEN OldStackTop = mem->GetStackTop() & ~XLEN{ 15 }; - uint64_t OldStackTop = mem->GetMemTop(); - uint64_t ArgArray = mem->GetStackTop()+48; + // Allocate ArgArraySize elements at ArgArrayBase + // Set the new StackTop to ArgArraySize bytes below OldStackTop + const XLEN ArgArrayBase = OldStackTop - ArgArraySize; + mem->SetStackTop( ArgArrayBase ); - // setup the argc argument values - uint32_t Argc = (uint32_t)(argv.size()); - WriteCacheLine(ArgArray, 4, &Argc); - ArgArray += 4; + // Start argv[] at ArgArrayBase + XLEN ArgArray = ArgArrayBase; - // write the argument values - for( int i=(argv.size()-1); i >= 0; i-- ){ - output->verbose(CALL_INFO, 6, 0, - "Loading program argv[%d] = %s\n", i, argv[i].c_str() ); + // Add a new element to argv + auto add_argv = [&]( const std::string& arg ) { + // Length of argv[i] string + size_t Len = arg.size() + 1; - // retrieve the current stack pointer - std::vector tmpc(argv[i].size() + 1); - argv[i].copy(&tmpc[0], argv[i].size()+1); - tmpc[argv[i].size()] = '\0'; - size_t len = argv[i].size() + 1; + // Address of argv[i][0] + XLEN Target = ArgArrayBase + ArgvOffset; - OldStackTop -= len; + // Write the address &argv[i][0] into argv[i] + WriteCacheLine( ArgArray, sizeof( XLEN ), &Target ); - WriteCacheLine(OldStackTop, len, &tmpc[0]); - } + // Advance ArgArray sizeof(XLEN) to the next argv[i] + ArgArray += sizeof( XLEN ); - // now reverse engineer the address alignments - // -- this is the address of the argv pointers (address + 8) in the stack - // -- Note: this is NOT the actual addresses of the argv[n]'s - uint64_t ArgBase = ArgArray+8; - WriteCacheLine(ArgArray, 8, &ArgBase); - ArgArray += 8; - - // -- these are the addresses of each argv entry - for( size_t i=0; iSetNextThreadMemAddr(OldStackTop - _STACK_SIZE_ - mem->GetTLSSize() - __PAGE_SIZE__); - return true; -} - -void RevLoader::splitStr(const std::string& s, - char c, - std::vector& v){ - std::string::size_type i = 0; - std::string::size_type j = s.find(c); + // Advance ArgvOffset the string length rounded up to a multiple of sizeof( XLEN ) + ArgvOffset += XLEN( ( Len - 1 ) | ( sizeof( XLEN ) - 1 ) ) + 1; + }; - if( (j==std::string::npos) && (s.length() > 0) ){ - v.push_back(s); - return ; - } + // argv[0] == name of executable + add_argv( exe ); - while (j != std::string::npos) { - v.push_back(s.substr(i, j-i)); - i = ++j; - j = s.find(c, j); - if (j == std::string::npos) - v.push_back(s.substr(i, s.length())); - } + // Program arguments + for( auto& arg : args ) + add_argv( arg ); + return true; } -bool RevLoader::LoadElf(){ +bool RevLoader::LoadElf( const std::string& exe, const std::vector& args ) { // open the target file - int fd = open(exe.c_str(), O_RDONLY); + int fd = open( exe.c_str(), O_RDONLY ); struct stat FileStats; - if( fstat(fd, &FileStats) < 0 ) - output->fatal(CALL_INFO, -1, "Error: failed to stat executable file: %s\n", exe.c_str() ); + if( fstat( fd, &FileStats ) < 0 ) + output->fatal( CALL_INFO, -1, "Error: failed to stat executable file: %s\n", exe.c_str() ); - size_t FileSize = FileStats.st_size; + size_t FileSize = static_cast( FileStats.st_size ); // map the executable into memory - char *membuf = (char *)(mmap(NULL, FileSize, PROT_READ, MAP_PRIVATE, fd, 0)); + char* membuf = static_cast( mmap( NULL, FileSize, PROT_READ, MAP_PRIVATE, fd, 0 ) ); if( membuf == MAP_FAILED ) - output->fatal(CALL_INFO, -1, "Error: failed to map executable file: %s\n", exe.c_str() ); + output->fatal( CALL_INFO, -1, "Error: failed to map executable file: %s\n", exe.c_str() ); // close the target file - close(fd); + close( fd ); // check the size of the elf header - if( FileSize < sizeof(Elf64_Ehdr) ) - output->fatal(CALL_INFO, -1, "Error: Elf header is unrecognizable\n" ); - - const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)(membuf); - if( !IsRVElf32(*eh64) && !IsRVElf64(*eh64) ) - output->fatal(CALL_INFO, -1, "Error: Cannot determine Elf32 or Elf64 from header\n" ); - - if( !IsRVLittle(*eh64) ) - output->fatal(CALL_INFO, -1, "Error: Not in little endian format\n" ); - - if( IsRVElf32(*eh64) ){ - if( !LoadElf32(membuf, FileSize) ) - output->fatal(CALL_INFO, -1, "Error: could not load Elf32 binary\n" ); - }else{ - if( !LoadElf64(membuf, FileSize) ) - output->fatal(CALL_INFO, -1, "Error: could not load Elf64 binary\n" ); + if( FileSize < sizeof( Elf64_Ehdr ) ) + output->fatal( CALL_INFO, -1, "Error: Elf header is unrecognizable\n" ); + + Elf64_Ehdr eh64; + memcpy( &eh64, membuf, sizeof( eh64 ) ); + + if( !IsRVElf32( eh64 ) && !IsRVElf64( eh64 ) ) + output->fatal( CALL_INFO, -1, "Error: Cannot determine Elf32 or Elf64 from header\n" ); + + if( !IsRVLittle( eh64 ) ) + output->fatal( CALL_INFO, -1, "Error: Not in little endian format\n" ); + + if( IsRVElf32( eh64 ) ) { + if( !LoadElf32( membuf, FileSize ) ) + output->fatal( CALL_INFO, -1, "Error: could not load Elf32 binary\n" ); + } else { + if( !LoadElf64( membuf, FileSize ) ) + output->fatal( CALL_INFO, -1, "Error: could not load Elf64 binary\n" ); } // unmap the file @@ -616,38 +580,36 @@ bool RevLoader::LoadElf(){ // print the symbol table entries std::map::iterator it = symtable.begin(); - while( it != symtable.end() ){ + while( it != symtable.end() ) { // create inverse map to allow tracer to lookup symbols - tracer_symbols.emplace(it->second, it->first); - output->verbose(CALL_INFO, 6, 0, - "Symbol Table Entry [%s:0x%" PRIx64 "]\n", - it->first.c_str(), it->second ); + tracer_symbols.emplace( it->second, it->first ); + output->verbose( CALL_INFO, 6, 0, "Symbol Table Entry [%s:0x%" PRIx64 "]\n", it->first.c_str(), it->second ); it++; } /// load the program arguments - if( !LoadProgramArgs() ) + if( IsRVElf64( eh64 ) ? !LoadProgramArgs( exe, args ) : !LoadProgramArgs( exe, args ) ) return false; // Initiate a memory fence in order to ensure that the entire ELF // infrastructure is loaded - mem->FenceMem(0); + mem->FenceMem( 0 ); return true; } -uint64_t RevLoader::GetSymbolAddr(std::string Symbol){ - uint64_t tmp = 0x00ull; - if( symtable.find(Symbol) != symtable.end() ){ +uint64_t RevLoader::GetSymbolAddr( std::string Symbol ) { + uint64_t tmp = 0; + if( symtable.find( Symbol ) != symtable.end() ) { tmp = symtable[Symbol]; } return tmp; } -std::map *SST::RevCPU::RevLoader::GetTraceSymbols() -{ - return &tracer_symbols; +std::map* SST::RevCPU::RevLoader::GetTraceSymbols() { + return &tracer_symbols; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevMem.cc b/src/RevMem.cc index 14dd9ebff..170944977 100644 --- a/src/RevMem.cc +++ b/src/RevMem.cc @@ -1,7 +1,7 @@ // // _RevMem_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -11,54 +11,37 @@ #include "RevMem.h" #include "RevRand.h" #include -#include -#include +#include #include -#include -#include +#include +#include -namespace SST::RevCPU{ +namespace SST::RevCPU { using MemSegment = RevMem::MemSegment; -RevMem::RevMem( uint64_t MemSize, RevOpts *Opts, RevMemCtrl *Ctrl, SST::Output *Output ) - : memSize(MemSize), opts(Opts), ctrl(Ctrl), output(Output) { - // Note: this constructor assumes the use of the memHierarchy backend - pageSize = 262144; //Page Size (in Bytes) - addrShift = lg(pageSize); - nextPage = 0; - - // We initialize StackTop to the size of memory minus 1024 bytes - // This allocates 1024 bytes for program header information to contain - // the ARGC and ARGV information - stacktop = (_REVMEM_BASE_ + memSize) - 1024; - - // Add the 1024 bytes for the program header information - AddMemSegAt(stacktop, 1024); +// We initialize StackTop to the size of memory minus 1024 bytes +// This allocates 1024 bytes for program header information to contain +// the ARGC and ARGV information +// Note: this constructor assumes the use of the memHierarchy backend +RevMem::RevMem( uint64_t memSize, RevOpts* opts, RevMemCtrl* ctrl, SST::Output* output ) + : memSize( memSize ), opts( opts ), ctrl( ctrl ), output( output ), pageSize( 262144 ), addrShift( uint32_t( lg( pageSize ) ) ), + stacktop( _REVMEM_BASE_ + memSize - 1024 ) { + AddMemSegAt( stacktop, 1024 ); // Add the 1024 bytes for the program header information } -RevMem::RevMem( uint64_t MemSize, RevOpts *Opts, SST::Output *Output ) - : memSize(MemSize), opts(Opts), ctrl(nullptr), output(Output) { - - // allocate the backing memory, zeroing it - physMem = new char [memSize]{}; - pageSize = 262144; //Page Size (in Bytes) - addrShift = lg(pageSize); - nextPage = 0; - +// allocate the backing memory, zeroing it +RevMem::RevMem( uint64_t memSize, RevOpts* opts, SST::Output* output ) + : physMem( new( std::nothrow ) unsigned char[memSize]{} ), memSize( memSize ), opts( opts ), output( output ), pageSize( 262144 ), + addrShift( uint32_t( lg( pageSize ) ) ), stacktop( _REVMEM_BASE_ + memSize - 1024 ) { if( !physMem ) - output->fatal(CALL_INFO, -1, "Error: could not allocate backing memory\n"); - - // We initialize StackTop to the size of memory minus 1024 bytes - // This allocates 1024 bytes for program header information to contain - // the ARGC and ARGV information - stacktop = (_REVMEM_BASE_ + memSize) - 1024; - AddMemSegAt(stacktop, 1024); + output->fatal( CALL_INFO, -1, "Error: could not allocate backing memory\n" ); + AddMemSegAt( stacktop, 1024 ); // Add the 1024 bytes for the program header information } -bool RevMem::outstandingRqsts(){ - if( ctrl ){ +bool RevMem::outstandingRqsts() { + if( ctrl ) { return ctrl->outstandingRqsts(); } @@ -66,32 +49,30 @@ bool RevMem::outstandingRqsts(){ return false; } -void RevMem::HandleMemFault(unsigned width){ +void RevMem::HandleMemFault( uint32_t width ) { // build up the fault payload - uint64_t rval = RevRand(0, (uint32_t{1} << width) - 1); + uint64_t rval = RevRand( 0, ( uint32_t{ 1 } << width ) - 1 ); // find an address to fault - unsigned NBytes = RevRand(0, memSize-8); - uint64_t *Addr = (uint64_t *)(&physMem[0] + NBytes); + uint64_t NBytes = RevRand( 0, memSize - 8 ); + uint64_t* Addr = (uint64_t*) ( &physMem[0] + NBytes ); // write the fault (read-modify-write) *Addr |= rval; - output->verbose(CALL_INFO, 5, 0, - "FAULT:MEM: Memory fault %u bits at address : 0x%" PRIxPTR "\n", - width, reinterpret_cast(Addr)); + output->verbose( CALL_INFO, 5, 0, "FAULT:MEM: Memory fault %" PRIu32 " bits at address : 0x%p\n", width, Addr ); } -bool RevMem::SetFuture(uint64_t Addr){ - FutureRes.push_back(Addr); +bool RevMem::SetFuture( uint64_t Addr ) { + FutureRes.push_back( Addr ); std::sort( FutureRes.begin(), FutureRes.end() ); FutureRes.erase( std::unique( FutureRes.begin(), FutureRes.end() ), FutureRes.end() ); return true; } -bool RevMem::RevokeFuture(uint64_t Addr){ - for( unsigned i=0; i(*it)) && - (Addr == std::get(*it)) ){ - // existing reservation; return w/ error - uint32_t *Tmp = reinterpret_cast(Target); - Tmp[0] = 0x01ul; - return false; - }else if( (Hart != std::get(*it)) && - (Addr == std::get(*it)) ){ - // existing reservation; return w/ error - uint32_t *Tmp = reinterpret_cast(Target); - Tmp[0] = 0x01ul; - return false; - } - } - - // didn't find a colliding object; add it - LRSC.push_back(std::tuple(Hart, Addr, (unsigned)(aq|(rl<<1)), - reinterpret_cast(Target))); +void RevMem::LR( uint32_t hart, uint64_t addr, size_t len, void* target, const MemReq& req, RevFlag flags ) { + // Create a reservation for this hart, overwriting one if it already exists + // A reservation maps a hart to an (addr, len) range and is invalidated if any other hart writes to this range + LRSC.insert_or_assign( hart, std::pair( addr, len ) ); // now handle the memory operation - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - //check to see if we're about to walk off the page.... - // uint32_t adjPageNum = 0; - // uint64_t adjPhysAddr = 0; - // uint64_t endOfPage = (pageMap[pageNum].first << addrShift) + pageSize; - char *BaseMem = &physMem[physAddr]; - char *DataMem = (char *)(Target); - - if( ctrl ){ - ctrl->sendREADLOCKRequest(Hart, Addr, (uint64_t)(BaseMem), - Len, Target, req, flags); - }else{ - memcpy(DataMem, BaseMem, Len); + uint64_t pageNum = addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, addr ); + unsigned char* BaseMem = &physMem[physAddr]; + + if( ctrl ) { + ctrl->sendREADLOCKRequest( hart, addr, uint64_t( BaseMem ), uint32_t( len ), target, req, flags ); + } else { + memcpy( target, BaseMem, len ); + RevHandleFlagResp( target, len, flags ); // clear the hazard req.MarkLoadComplete(); } +} - return true; +bool RevMem::InvalidateLRReservations( uint32_t hart, uint64_t addr, size_t len ) { + bool ret = false; + // Loop over all active reservations + for( auto it = LRSC.cbegin(); it != LRSC.cend(); ) { + // Invalidate reservations on a different hart which contain any bytes in common with [addr, addr+len) + auto& [Addr, Len] = it->second; + if( hart != it->first && addr < Addr + Len && addr + len > Addr ) { + it = LRSC.erase( it ); + ret = true; + } else { + ++it; + } + } + return ret; } -bool RevMem::SCBase(unsigned Hart, uint64_t Addr, size_t Len, - void *Data, void *Target, uint8_t aq, uint8_t rl, - RevFlag flags){ - std::vector>::iterator it; - - for( it = LRSC.begin(); it != LRSC.end(); ++it ){ - if( (Hart == std::get(*it)) && - (Addr == std::get(*it)) ){ - // existing reservation; test to see if the value matches - uint64_t *TmpTarget = std::get(*it); - uint64_t *TmpData = static_cast(Data); - - if( Len == 32 ){ - uint32_t A = 0; - uint32_t B = 0; - for( size_t i = 0; i < Len; i++ ){ - A |= uint32_t(TmpTarget[i]) << i; - B |= uint32_t(TmpData[i]) << i; - } - if( (A & B) == 0 ){ - static_cast(Target)[0] = 1; - return false; - } - }else{ - uint64_t A = 0; - uint64_t B = 0; - for( size_t i = 0; i < Len; i++ ){ - A |= TmpTarget[i] << i; - B |= TmpData[i] << i; - } - if( (A & B) == 0 ){ - static_cast(Target)[0] = 1; - return false; - } - } +bool RevMem::SC( uint32_t hart, uint64_t addr, uint32_t len, void* data, RevFlag flags ) { + // Find the reservation for this hart (there can only be one active reservation per hart) + auto it = LRSC.find( hart ); + if( it != LRSC.end() ) { + // Get the address and length of the reservation + auto [Addr, Len] = it->second; - // everything has passed so far, - // write the value back to memory - WriteMem(Hart, Addr, Len, Data, flags); + // Invalidate the reservation for this hart unconditionally + LRSC.erase( it ); - // write zeros to target - for( unsigned i=0; i(Target); - Tmp[i] = 0x0; - } + // SC succeeds only if the store's address range lies totally within the reservation + if( addr >= Addr && addr + len <= Addr + Len ) { + // Write the value back to memory + WriteMem( hart, addr, len, data, flags ); - // erase the entry - LRSC.erase(it); + // SC succeeded return true; } } - - // failed, write a nonzero value to target - uint32_t *Tmp = reinterpret_cast(Target); - Tmp[0] = 0x1; - + // SC failed return false; } -void RevMem::FlushTLB(){ +void RevMem::FlushTLB() { TLB.clear(); LRUQueue.clear(); return; } -uint64_t RevMem::SearchTLB(uint64_t vAddr){ - auto it = TLB.find(vAddr); - if (it == TLB.end()) { +uint64_t RevMem::SearchTLB( uint64_t vAddr ) { + auto it = TLB.find( vAddr ); + if( it == TLB.end() ) { // TLB Miss :( memStats.TLBMisses++; return _INVALID_ADDR_; } else { memStats.TLBHits++; // Move the accessed vAddr to the front of the LRU list - LRUQueue.erase(it->second.second); - LRUQueue.push_front(vAddr); + LRUQueue.erase( it->second.second ); + LRUQueue.push_front( vAddr ); // Update the second of the pair in the tlbMap to point to the new location in LRU list it->second.second = LRUQueue.begin(); // Return the physAddr @@ -237,98 +171,103 @@ uint64_t RevMem::SearchTLB(uint64_t vAddr){ } } -void RevMem::AddToTLB(uint64_t vAddr, uint64_t physAddr){ - auto it = TLB.find(vAddr); - if (it != TLB.end()) { +void RevMem::AddToTLB( uint64_t vAddr, uint64_t physAddr ) { + auto it = TLB.find( vAddr ); + if( it != TLB.end() ) { // If the vAddr is already present in the TLB, // then this is a page update, not a miss // Move the vAddr to the front of LRU list - LRUQueue.erase(it->second.second); - LRUQueue.push_front(vAddr); + LRUQueue.erase( it->second.second ); + LRUQueue.push_front( vAddr ); // Update the pair in the TLB - it->second.first = physAddr; + it->second.first = physAddr; it->second.second = LRUQueue.begin(); } else { // If cache is full, remove the least recently used // vAddr from both cache and LRU list - if (LRUQueue.size() == tlbSize) { + if( LRUQueue.size() == tlbSize ) { uint64_t LRUvAddr = LRUQueue.back(); LRUQueue.pop_back(); - TLB.erase(LRUvAddr); + TLB.erase( LRUvAddr ); } // Insert the vAddr and physAddr into the TLB and LRU list - LRUQueue.push_front(vAddr); - TLB.insert({vAddr, {physAddr, LRUQueue.begin()}}); + LRUQueue.push_front( vAddr ); + TLB.insert( { + vAddr, {physAddr, LRUQueue.begin()} + } ); } } -uint64_t RevMem::CalcPhysAddr(uint64_t pageNum, uint64_t vAddr){ +uint64_t RevMem::CalcPhysAddr( uint64_t pageNum, uint64_t vAddr ) { /* Check if vAddr is in the TLB */ - uint64_t physAddr = SearchTLB(vAddr); + uint64_t physAddr = SearchTLB( vAddr ); /* If not in TLB, physAddr will equal _INVALID_ADDR_ */ - if( physAddr == _INVALID_ADDR_ ){ + if( physAddr == _INVALID_ADDR_ ) { /* Check if vAddr is a valid address before translating to physAddr */ - if( isValidVirtAddr(vAddr) ){ - if(pageMap.count(pageNum) == 0){ + if( isValidVirtAddr( vAddr ) ) { + if( pageMap.count( pageNum ) == 0 ) { // First touch of this page, mark it as in use - pageMap[pageNum] = std::pair(nextPage, true); - physAddr = (nextPage << addrShift) + ((pageSize - 1) & vAddr); + pageMap[pageNum] = std::pair( nextPage, true ); + physAddr = ( nextPage << addrShift ) + ( ( pageSize - 1 ) & vAddr ); #ifdef _REV_DEBUG_ - std::cout << "First Touch for page:" << pageNum << " addrShift:" << addrShift << " vAddr: 0x" << std::hex << vAddr << " PhsyAddr: 0x" << physAddr << std::dec << " Next Page: " << nextPage << std::endl; + std::cout << "First Touch for page:" << pageNum << " addrShift:" << addrShift << " vAddr: 0x" << std::hex << vAddr + << " PhsyAddr: 0x" << physAddr << std::dec << " Next Page: " << nextPage << std::endl; #endif nextPage++; - }else if(pageMap.count(pageNum) == 1){ + } else if( pageMap.count( pageNum ) == 1 ) { //We've accessed this page before, just get the physical address - physAddr = (pageMap[pageNum].first << addrShift) + ((pageSize - 1) & vAddr); + physAddr = ( pageMap[pageNum].first << addrShift ) + ( ( pageSize - 1 ) & vAddr ); #ifdef _REV_DEBUG_ - std::cout << "Access for page:" << pageNum << " addrShift:" << addrShift << " vAddr: 0x" << std::hex << vAddr << " PhsyAddr: 0x" << physAddr << std::dec << " Next Page: " << nextPage << std::endl; + std::cout << "Access for page:" << pageNum << " addrShift:" << addrShift << " vAddr: 0x" << std::hex << vAddr + << " PhsyAddr: 0x" << physAddr << std::dec << " Next Page: " << nextPage << std::endl; #endif - }else{ - output->fatal(CALL_INFO, -1, "Error: Page allocated multiple times\n"); + } else { + output->fatal( CALL_INFO, -1, "Error: Page allocated multiple times\n" ); } - AddToTLB(vAddr, physAddr); - } - else { + AddToTLB( vAddr, physAddr ); + } else { /* vAddr not a valid address */ - // #ifdef _REV_DEBUG_ - for( auto Seg : MemSegs ){ + for( auto Seg : MemSegs ) { std::cout << *Seg << std::endl; } - for( auto Seg : ThreadMemSegs ){ + for( auto Seg : ThreadMemSegs ) { std::cout << *Seg << std::endl; } - output->fatal(CALL_INFO, 11, - "Segmentation Fault: Virtual address 0x%" PRIx64 " (PhysAddr = 0x%" PRIx64 ") was not found in any mem segments\n", - vAddr, physAddr); + output->fatal( + CALL_INFO, + 11, + "Segmentation Fault: Virtual address 0x%" PRIx64 " (PhysAddr = 0x%" PRIx64 ") was not found in any mem segments\n", + vAddr, + physAddr + ); } } return physAddr; } // This function will change a decent amount in an upcoming PR -bool RevMem::isValidVirtAddr(const uint64_t vAddr){ - for(const auto& Seg : MemSegs ){ - if( Seg->contains(vAddr) ){ +bool RevMem::isValidVirtAddr( const uint64_t vAddr ) { + for( const auto& Seg : MemSegs ) { + if( Seg->contains( vAddr ) ) { return true; } } - for( const auto& Seg : ThreadMemSegs ){ - if( Seg->contains(vAddr) ){ + for( const auto& Seg : ThreadMemSegs ) { + if( Seg->contains( vAddr ) ) { return true; } } return false; } - -uint64_t RevMem::AddMemSegAt(const uint64_t& BaseAddr, const uint64_t& SegSize){ - MemSegs.emplace_back(std::make_shared(BaseAddr, SegSize)); +uint64_t RevMem::AddMemSegAt( const uint64_t& BaseAddr, const uint64_t& SegSize ) { + MemSegs.emplace_back( new MemSegment( BaseAddr, SegSize ) ); return BaseAddr; } @@ -337,108 +276,113 @@ uint64_t RevMem::AddMemSegAt(const uint64_t& BaseAddr, const uint64_t& SegSize){ // vector because there will be no FreeMemSegs that contain addresses in the static segments) // // AllocMem is the only way that a user can allocate & deallocate memory -uint64_t RevMem::AddRoundedMemSeg(uint64_t BaseAddr, const uint64_t& SegSize, size_t RoundUpSize){ +uint64_t RevMem::AddRoundedMemSeg( uint64_t BaseAddr, const uint64_t& SegSize, size_t RoundUpSize ) { size_t RoundedSegSize = 0; // Make sure we're not dividing by zero - if( RoundUpSize == 0 ){ - output->fatal(CALL_INFO, -1, "Error: RoundUpSize must be greater than 0\n"); + if( RoundUpSize == 0 ) { + output->fatal( CALL_INFO, -1, "Error: RoundUpSize must be greater than 0\n" ); } uint64_t Remainder = SegSize % RoundUpSize; // See if we need to round up at all - if( Remainder == 0 ){ + if( Remainder == 0 ) { RoundedSegSize = SegSize; } else { RoundedSegSize = SegSize + RoundUpSize - Remainder; } uint64_t NewSegTopAddr = BaseAddr + RoundedSegSize; - bool Added = false; + bool Added = false; // Check if memory segment is already allocated - for( auto Seg : MemSegs ){ + for( auto Seg : MemSegs ) { // If it contains the base address - if( Seg->contains(BaseAddr) ){ + if( Seg->contains( BaseAddr ) ) { // If it doesn't contain the top address, we need to expand it - if( !Seg->contains(NewSegTopAddr) ){ + if( !Seg->contains( NewSegTopAddr ) ) { size_t BytesToExpandBy = NewSegTopAddr - Seg->getTopAddr(); - Seg->setSize(Seg->getSize() + BytesToExpandBy); + Seg->setSize( Seg->getSize() + BytesToExpandBy ); } else { // If it contains the top address, we don't need to do anything - output->verbose(CALL_INFO, 10, 99, - "Warning: Memory segment already allocated that contains the requested rounded allocation at %" PRIx64 "of size %" PRIu64 " Bytes\n", BaseAddr, SegSize); + output->verbose( + CALL_INFO, + 10, + 99, + "Warning: Memory segment already allocated that " + "contains the requested rounded allocation at %" PRIx64 "of size %" PRIu64 " Bytes\n", + BaseAddr, + SegSize + ); } // Return the containing segments Base Address BaseAddr = Seg->getBaseAddr(); - Added = true; + Added = true; break; - } // --- End (if contains BaseAddr) + } // --- End (if contains BaseAddr) - else if ( !Seg->contains(BaseAddr) && Seg->contains(NewSegTopAddr) ){ + else if( !Seg->contains( BaseAddr ) && Seg->contains( NewSegTopAddr ) ) { // Existing segment only contains the top part of the new segment, expand downwards - Seg->setBaseAddr(BaseAddr); + Seg->setBaseAddr( BaseAddr ); size_t BytesToExpandBy = Seg->getBaseAddr() - BaseAddr; - Seg->setSize(Seg->getSize() + BytesToExpandBy); + Seg->setSize( Seg->getSize() + BytesToExpandBy ); Added = true; break; } - } - if( !Added ){ + if( !Added ) { // BaseAddr & RoundedTopAddr not a part of a segment // Add rounded segment - MemSegs.emplace_back(std::make_shared(BaseAddr, RoundedSegSize)); + MemSegs.emplace_back( new MemSegment( BaseAddr, RoundedSegSize ) ); } return BaseAddr; } -std::shared_ptr RevMem::AddThreadMem(){ +std::shared_ptr RevMem::AddThreadMem() { // Calculate the BaseAddr of the segment uint64_t BaseAddr = NextThreadMemAddr - ThreadMemSize; - ThreadMemSegs.emplace_back(std::make_shared(BaseAddr, ThreadMemSize)); + ThreadMemSegs.emplace_back( new MemSegment( BaseAddr, ThreadMemSize ) ); // Page boundary between NextThreadMemAddr = BaseAddr - pageSize - 1; return ThreadMemSegs.back(); } -void RevMem::SetTLSInfo(const uint64_t& BaseAddr, const uint64_t& Size){ +void RevMem::SetTLSInfo( const uint64_t& BaseAddr, const uint64_t& Size ) { TLSBaseAddr = BaseAddr; TLSSize += Size; ThreadMemSize = _STACK_SIZE_ + TLSSize; return; } - // AllocMem differs from AddMemSeg because it first searches the FreeMemSegs // vector to see if there is a free segment that will fit the new data // If there is not a free segment, it will allocate a new segment at the end of the heap -uint64_t RevMem::AllocMem(const uint64_t& SegSize){ - output->verbose(CALL_INFO, 10, 99, "Attempting to allocate %" PRIu64 " bytes on the heap\n", SegSize); +uint64_t RevMem::AllocMem( const uint64_t& SegSize ) { + output->verbose( CALL_INFO, 10, 99, "Attempting to allocate %" PRIu64 " bytes on the heap\n", SegSize ); uint64_t NewSegBaseAddr = 0; // Check if there is a free segment that can fit the new data - for( size_t i=0; i < FreeMemSegs.size(); i++ ){ - auto FreeSeg = FreeMemSegs[i]; + for( size_t i = 0; i < FreeMemSegs.size(); i++ ) { + auto FreeSeg = FreeMemSegs[i]; // if the FreeSeg is bigger than the new data, we can shrink it so it starts // after the new segment (SegSize) uint64_t oldFreeSegSize = FreeSeg->getSize(); - if( oldFreeSegSize > SegSize ){ + if( oldFreeSegSize > SegSize ) { // New data will start where the free segment started NewSegBaseAddr = FreeSeg->getBaseAddr(); - MemSegs.emplace_back(std::make_shared(NewSegBaseAddr, SegSize)); - FreeSeg->setBaseAddr(FreeSeg->getBaseAddr() + SegSize); - FreeSeg->setSize(oldFreeSegSize - SegSize); + MemSegs.emplace_back( new MemSegment( NewSegBaseAddr, SegSize ) ); + FreeSeg->setBaseAddr( FreeSeg->getBaseAddr() + SegSize ); + FreeSeg->setSize( oldFreeSegSize - SegSize ); return NewSegBaseAddr; } // New data will fit exactly in the free segment // ie. remove from FreeMemSegs & add to MemSegs - else if (oldFreeSegSize == SegSize ){ + else if( oldFreeSegSize == SegSize ) { // New data will start where the free segment started NewSegBaseAddr = FreeSeg->getBaseAddr(); - MemSegs.emplace_back(std::make_shared(NewSegBaseAddr, SegSize)); - FreeMemSegs.erase(FreeMemSegs.begin()+i); + MemSegs.emplace_back( new MemSegment( NewSegBaseAddr, SegSize ) ); + FreeMemSegs.erase( FreeMemSegs.begin() + ptrdiff_t( i ) ); return NewSegBaseAddr; } // FreeSeg not big enough to fit the new data @@ -448,12 +392,12 @@ uint64_t RevMem::AllocMem(const uint64_t& SegSize){ } // If we still haven't allocated, expand the heap - if( !NewSegBaseAddr ){ + if( !NewSegBaseAddr ) { NewSegBaseAddr = heapend; } - MemSegs.emplace_back(std::make_shared(NewSegBaseAddr, SegSize)); + MemSegs.emplace_back( new MemSegment( NewSegBaseAddr, SegSize ) ); - ExpandHeap(SegSize); + ExpandHeap( SegSize ); return NewSegBaseAddr; } @@ -461,52 +405,52 @@ uint64_t RevMem::AllocMem(const uint64_t& SegSize){ // AllocMemAt differs from AddMemSegAt because it first searches the FreeMemSegs // vector to see if there is a free segment that will fit the new data // If its unable to allocate at the location requested it will error. This may change in the future. -uint64_t RevMem::AllocMemAt(const uint64_t& BaseAddr, const uint64_t& SegSize){ - int ret = 0; - output->verbose(CALL_INFO, 10, 99, "Attempting to allocate %" PRIu64 " bytes on the heap", SegSize); +uint64_t RevMem::AllocMemAt( const uint64_t& BaseAddr, const uint64_t& SegSize ) { + uint64_t ret = 0; + output->verbose( CALL_INFO, 10, 99, "Attempting to allocate %" PRIu64 " bytes on the heap", SegSize ); // Check if this range exists in the FreeMemSegs vector - for( unsigned i=0; i < FreeMemSegs.size(); i++ ){ + for( uint32_t i = 0; i < FreeMemSegs.size(); i++ ) { auto FreeSeg = FreeMemSegs[i]; - if( FreeSeg->contains(BaseAddr, SegSize) ){ + if( FreeSeg->contains( BaseAddr, SegSize ) ) { // Check if were allocating on a boundary of FreeSeg // if not, were allocating in the middle - if( FreeSeg->getBaseAddr() != BaseAddr && FreeSeg->getTopAddr() != (BaseAddr + SegSize) ){ + if( FreeSeg->getBaseAddr() != BaseAddr && FreeSeg->getTopAddr() != ( BaseAddr + SegSize ) ) { // Before: |-------------------- FreeSeg --------------------| // After: |--- FreeSeg ---|- AllocedSeg -|--- NewFreeSeg ---| size_t OldFreeSegTop = FreeSeg->getTopAddr(); // Shrink FreeSeg so it's size goes up to the new AllocedSeg's BaseAddr - FreeSeg->setSize(BaseAddr - FreeSeg->getBaseAddr()); + FreeSeg->setSize( BaseAddr - FreeSeg->getBaseAddr() ); // Create New AllocedSeg; this is done later on before returning // Create New FreeSeg that fills the upper part of the old FreeSeg uint64_t NewFreeSegBaseAddr = BaseAddr + SegSize; - size_t NewFreeSegSize = OldFreeSegTop - NewFreeSegBaseAddr; - FreeMemSegs.emplace_back(std::make_shared(NewFreeSegBaseAddr, NewFreeSegSize)); + size_t NewFreeSegSize = OldFreeSegTop - NewFreeSegBaseAddr; + FreeMemSegs.emplace_back( new MemSegment( NewFreeSegBaseAddr, NewFreeSegSize ) ); } // If were allocating at the beginning of a FreeSeg (That doesn't take up the whole segment) - else if( FreeSeg->getBaseAddr() == BaseAddr && FreeSeg->getTopAddr() != (BaseAddr + SegSize) ){ + else if( FreeSeg->getBaseAddr() == BaseAddr && FreeSeg->getTopAddr() != ( BaseAddr + SegSize ) ) { // - Before: |--------------- FreeSeg --------------| // - After: |---- AllocedSeg ----|---- FreeSeg ----| - FreeSeg->setBaseAddr(BaseAddr + SegSize); + FreeSeg->setBaseAddr( BaseAddr + SegSize ); } // If were allocating at the end of a FreeSeg (ie. TopAddr is last allocated address) - else if( FreeSeg->getBaseAddr() != BaseAddr && FreeSeg->getTopAddr() == (BaseAddr + SegSize) ) { + else if( FreeSeg->getBaseAddr() != BaseAddr && FreeSeg->getTopAddr() == ( BaseAddr + SegSize ) ) { // - Before: |--------------- FreeSeg --------------| // - After: |---- FreeSeg ----|---- AllocedSeg ----| - FreeSeg->setSize(FreeSeg->getSize() - SegSize); + FreeSeg->setSize( FreeSeg->getSize() - SegSize ); } // Entire segment is being occupied else { // - Before: |-------- FreeSeg -------| // - After: |------ AllocedSeg ------| - FreeMemSegs.erase(FreeMemSegs.begin()+i); + FreeMemSegs.erase( FreeMemSegs.begin() + i ); } // Segment was allocated so return the BaseAddr ret = BaseAddr; @@ -514,384 +458,203 @@ uint64_t RevMem::AllocMemAt(const uint64_t& BaseAddr, const uint64_t& SegSize){ } } - if (ret) { // Found a place + if( ret ) { // Found a place // Check if any addresses in the segment are already - for( auto Seg : MemSegs ){ + for( auto Seg : MemSegs ) { // Check if either the baseAddr or topAddr of the potential new segment exists inside of an already allocated segment - if( Seg->contains(BaseAddr) || Seg->contains(BaseAddr + SegSize) ){ - output->fatal(CALL_INFO, 11, - "Error: Attempting to allocate memory at address 0x%lx of size 0x%lx which contains memory that is" - "already allocated in the segment with BaseAddr = 0x%lx and Size 0x%lx\n", - BaseAddr, SegSize, Seg->getBaseAddr(), Seg->getSize()); + if( Seg->contains( BaseAddr ) || Seg->contains( BaseAddr + SegSize ) ) { + output->fatal( + CALL_INFO, + 11, + "Error: Attempting to allocate memory at address 0x%" PRIx64 " of size 0x%" PRIx64 " which contains memory that is" + "already allocated in the segment with BaseAddr = 0x%" PRIx64 " and Size 0x%" PRIx64 "\n", + BaseAddr, + SegSize, + Seg->getBaseAddr(), + Seg->getSize() + ); } else { continue; } } - MemSegs.emplace_back(std::make_shared(BaseAddr, SegSize)); + MemSegs.emplace_back( new MemSegment( BaseAddr, SegSize ) ); } return ret; } - -bool RevMem::FenceMem(unsigned Hart){ - if( ctrl ){ - return ctrl->sendFENCE(Hart); +bool RevMem::FenceMem( uint32_t Hart ) { + if( ctrl ) { + return ctrl->sendFENCE( Hart ); } return true; // base RevMem support does nothing here } -bool RevMem::AMOMem(unsigned Hart, uint64_t Addr, size_t Len, - void *Data, void *Target, - const MemReq& req, - RevFlag flags){ +bool RevMem::AMOMem( uint32_t Hart, uint64_t Addr, uint32_t Len, void* Data, void* Target, const MemReq& req, RevFlag flags ) { #ifdef _REV_DEBUG_ std::cout << "AMO of " << Len << " Bytes Starting at 0x" << std::hex << Addr << std::dec << std::endl; #endif - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - char *BaseMem = &physMem[physAddr]; - - if( ctrl ){ + if( ctrl ) { // sending to the RevMemCtrl - ctrl->sendAMORequest(Hart, Addr, (uint64_t)(BaseMem), Len, - static_cast(Data), Target, req, flags); - }else{ + uint64_t pageNum = Addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, Addr ); + unsigned char* BaseMem = &physMem[physAddr]; + + ctrl->sendAMORequest( Hart, Addr, uint64_t( BaseMem ), Len, static_cast( Data ), Target, req, flags ); + } else { // process the request locally - char *TmpD = new char [8]{}; - char *TmpT = new char [8]{}; - std::memset(TmpD, 0, 8); - std::memcpy(TmpD, static_cast(Data), Len); - std::memset(TmpT, 0, 8); - - ReadMem(Hart, Addr, Len, Target, req, flags); - - std::memcpy(TmpT, static_cast(Target), Len); - if( Len == 4 ){ - ApplyAMO(flags, Target, *(uint32_t *)(TmpD)); - }else{ - ApplyAMO(flags, Target, *(uint64_t *)(TmpD)); - } + union { + uint32_t TmpD4; + uint64_t TmpD8; + }; + + // Get a copy of the data operand + memcpy( &TmpD8, Data, Len ); + + // Read Target from memory + ReadMem( Hart, Addr, Len, Target, req, flags ); - WriteMem(Hart, Addr, Len, Target, flags); + union { + uint32_t TmpT4; + uint64_t TmpT8; + }; - if( Len == 4 ){ - std::memcpy((uint32_t *)(Target), (uint32_t *)(TmpT), Len); - }else{ - std::memcpy((uint64_t *)(Target), (uint64_t *)(TmpT), Len); + // Make a copy of Target for atomic operation + memcpy( &TmpT8, Target, Len ); + + // Perform atomic operation + if( Len == 4 ) { + ApplyAMO( flags, &TmpT4, TmpD4 ); + } else { + ApplyAMO( flags, &TmpT8, TmpD8 ); } + // Write new value to memory + WriteMem( Hart, Addr, Len, &TmpT8, flags ); + // clear the hazard req.MarkLoadComplete(); - delete[] TmpD; - delete[] TmpT; } return true; } -bool RevMem::WriteMem( unsigned Hart, uint64_t Addr, size_t Len, const void *Data, - RevFlag flags){ +bool RevMem::WriteMem( uint32_t Hart, uint64_t Addr, uint32_t Len, const void* Data, RevFlag flags ) { #ifdef _REV_DEBUG_ std::cout << "Writing " << Len << " Bytes Starting at 0x" << std::hex << Addr << std::dec << std::endl; #endif - if(Addr == 0xDEADBEEF){ - std::cout << "Found special write. Val = " << std::hex << *(int*)(Data) << std::dec << std::endl; - } - RevokeFuture(Addr); // revoke the future if it is present; ignore the return - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - - //check to see if we're about to walk off the page.... - uint32_t adjPageNum = 0; - uint64_t adjPhysAddr = 0; - uint64_t endOfPage = (pageMap[pageNum].first << addrShift) + pageSize; - char *BaseMem = &physMem[physAddr]; - char *DataMem = (char *)(Data); - if((physAddr + Len) > endOfPage){ - uint32_t span = (physAddr + Len) - endOfPage; - adjPageNum = ((Addr+Len)-span) >> addrShift; - adjPhysAddr = CalcPhysAddr(adjPageNum, ((Addr+Len)-span)); -#ifdef _REV_DEBUG_ - std::cout << "Warning: Writing off end of page... " << std::endl; -#endif - if( ctrl ){ - ctrl->sendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - DataMem, - flags); - }else{ - for( unsigned i=0; i< (Len-span); i++ ){ - BaseMem[i] = DataMem[i]; - } - } - BaseMem = &physMem[adjPhysAddr]; - if( ctrl ){ - // write the memory using RevMemCtrl - unsigned Cur = (Len-span); - ctrl->sendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - &(DataMem[Cur]), - flags); - }else{ - // write the memory using the internal RevMem model - unsigned Cur = (Len-span); - for( unsigned i=0; i< span; i++ ){ - BaseMem[i] = DataMem[Cur]; - Cur++; - } - } - }else{ - if( ctrl ){ - // write the memory using RevMemCtrl - ctrl->sendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - DataMem, - flags); - }else{ - // write the memory using the internal RevMem model - for( unsigned i=0; isendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - DataMem, - RevFlag::F_NONE); - }else{ - for( unsigned i=0; i< (Len-span); i++ ){ - BaseMem[i] = DataMem[i]; - } - } - BaseMem = &physMem[adjPhysAddr]; - if( ctrl ){ - // write the memory using RevMemCtrl - unsigned Cur = (Len-span); - ctrl->sendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - &(DataMem[Cur]), - RevFlag::F_NONE); - }else{ - // write the memory using the internal RevMem model - unsigned Cur = (Len-span); - for( unsigned i=0; i< span; i++ ){ - BaseMem[i] = DataMem[Cur]; -#ifdef _REV_DEBUG_ - std::cout << "ADJ WRITE TO: " << std::hex << (uint64_t)(&BaseMem[i]) << std::dec - << "; FROM LOGICAL PHYS=" << std::hex << adjPhysAddr + i << std::dec - << "; DATA=" << std::hex << (uint8_t)(BaseMem[i]) << std::dec - << "; VIRTUAL ADDR=" << std::hex << Addr+Cur << std::dec << std::endl; -#endif - Cur++; - } - } - }else{ - if( ctrl ){ - // write the memory using RevMemCtrl - ctrl->sendWRITERequest(Hart, Addr, - (uint64_t)(BaseMem), - Len, - DataMem, - RevFlag::F_NONE); - }else{ - // write the memory using the internal RevMem model - for( unsigned i=0; i> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - - //check to see if we're about to walk off the page.... - uint32_t adjPageNum = 0; - uint64_t adjPhysAddr = 0; - uint64_t endOfPage = (pageMap[pageNum].first << addrShift) + pageSize; - char *BaseMem = &physMem[physAddr]; - char *DataMem = (char *)(Data); - if((physAddr + Len) > endOfPage){ - uint32_t span = (physAddr + Len) - endOfPage; - adjPageNum = ((Addr+Len)-span) >> addrShift; - adjPhysAddr = CalcPhysAddr(adjPageNum, ((Addr+Len)-span)); - for( unsigned i=0; i< (Len-span); i++ ){ - DataMem[i] = BaseMem[i]; - } - BaseMem = &physMem[adjPhysAddr]; - unsigned Cur = (Len-span); - for( unsigned i=0; i< span; i++ ){ - DataMem[Cur] = BaseMem[i]; - } -#ifdef _REV_DEBUG_ - std::cout << "Warning: Reading off end of page... " << std::endl; -#endif - }else{ - for( unsigned i=0; i RevMem::AdjPageAddr( uint64_t Addr, uint64_t Len ) { + if( Len > pageSize ) { + output->fatal( + CALL_INFO, 7, "Error: Attempting to read/write %" PRIu64 " bytes > pageSize (= %" PRIu32 " bytes)\n", Len, pageSize + ); } - memStats.bytesRead += Len; - return true; + uint64_t pageNum = Addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, Addr ); + uint64_t endOfPage = ( pageMap[pageNum].first << addrShift ) + pageSize; + uint64_t remainder = 0; + uint64_t adjPhysAddr = physAddr; + + if( physAddr + Len > endOfPage ) { + remainder = endOfPage - physAddr; + uint64_t adjAddr = Addr + remainder; + uint64_t adjPageNum = adjAddr >> addrShift; + adjPhysAddr = CalcPhysAddr( adjPageNum, adjAddr ); + } + return { remainder, physAddr, adjPhysAddr }; } -bool RevMem::ReadMem(unsigned Hart, uint64_t Addr, size_t Len, void *Target, - const MemReq& req, RevFlag flags){ +bool RevMem::ReadMem( uint32_t Hart, uint64_t Addr, uint32_t Len, void* Target, const MemReq& req, RevFlag flags ) { #ifdef _REV_DEBUG_ std::cout << "NEW READMEM: Reading " << Len << " Bytes Starting at 0x" << std::hex << Addr << std::dec << std::endl; #endif - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - //check to see if we're about to walk off the page.... - uint32_t adjPageNum = 0; - uint64_t adjPhysAddr = 0; - uint64_t endOfPage = (pageMap[pageNum].first << addrShift) + pageSize; - char *BaseMem = &physMem[physAddr]; - char *DataMem = static_cast(Target); - - if((physAddr + Len) > endOfPage){ - uint32_t span = (physAddr + Len) - endOfPage; - adjPageNum = ((Addr+Len)-span) >> addrShift; - adjPhysAddr = CalcPhysAddr(adjPageNum, ((Addr+Len)-span)); - if( ctrl ){ - ctrl->sendREADRequest(Hart, Addr, (uint64_t)(BaseMem), Len, Target, req, flags); - }else{ - for( unsigned i=0; i< (Len-span); i++ ){ - DataMem[i] = BaseMem[i]; - } - } - BaseMem = &physMem[adjPhysAddr]; - //If we are using memH, this paging scheme is not relevant, we already issued the ReadReq above - //ctrl->sendREADRequest(Hart, Addr, (uint64_t)(BaseMem), Len, ((char*)Target)+Cur, req, flags); - unsigned Cur = (Len-span); - for( unsigned i=0; i< span; i++ ){ - DataMem[Cur] = BaseMem[i]; - Cur++; - } + + auto* DataMem = static_cast( Target ); + + if( ctrl ) { + // read the memory using RevMemCtrl + TRACE_MEMH_SENDREAD( req.Addr, Len, req.DestReg ); + ctrl->sendREADRequest( Hart, Addr, 0, Len, DataMem, req, flags ); + } else { + // read the memory using the internal RevMem model + TRACE_MEM_READ( Addr, Len, DataMem ); + + //check to see if we're about to walk off the page.... + auto [remainder, physAddr, adjPhysAddr] = AdjPageAddr( Addr, Len ); + memcpy( DataMem, &physMem[physAddr], remainder ); + memcpy( DataMem + remainder, &physMem[adjPhysAddr], Len - remainder ); + + // Handle flag response + RevHandleFlagResp( Target, Len, flags ); + // clear the hazard - if this was an AMO operation then we will clear outside of this function in AMOMem() - if(MemOp::MemOpAMO != req.ReqType){ + if( MemOp::MemOpAMO != req.ReqType ) req.MarkLoadComplete(); - } -#ifdef _REV_DEBUG_ - std::cout << "Warning: Reading off end of page... " << std::endl; -#endif - }else{ - if( ctrl ){ - TRACE_MEMH_SENDREAD(req.Addr, Len, req.DestReg); - ctrl->sendREADRequest(Hart, Addr, (uint64_t)(BaseMem), Len, Target, req, flags); - }else{ - for( unsigned i=0; i> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - if( ctrl ){ - ctrl->sendFLUSHRequest(Hart, Addr, physAddr, getLineSize(), - false, RevFlag::F_NONE); +bool RevMem::FlushLine( uint32_t Hart, uint64_t Addr ) { + uint64_t pageNum = Addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, Addr ); + if( ctrl ) { + ctrl->sendFLUSHRequest( Hart, Addr, physAddr, getLineSize(), false, RevFlag::F_NONE ); } // else, this is effectively a nop return true; } -bool RevMem::InvLine( unsigned Hart, uint64_t Addr ){ - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - if( ctrl ){ - ctrl->sendFLUSHRequest(Hart, Addr, physAddr, getLineSize(), - true, RevFlag::F_NONE); +bool RevMem::InvLine( uint32_t Hart, uint64_t Addr ) { + uint64_t pageNum = Addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, Addr ); + if( ctrl ) { + ctrl->sendFLUSHRequest( Hart, Addr, physAddr, getLineSize(), true, RevFlag::F_NONE ); } // else, this is effectively a nop return true; } -bool RevMem::CleanLine( unsigned Hart, uint64_t Addr ){ - uint64_t pageNum = Addr >> addrShift; - uint64_t physAddr = CalcPhysAddr(pageNum, Addr); - if( ctrl ){ - ctrl->sendFENCE(Hart); - ctrl->sendFLUSHRequest(Hart, Addr, physAddr, getLineSize(), - false, RevFlag::F_NONE); +bool RevMem::CleanLine( uint32_t Hart, uint64_t Addr ) { + uint64_t pageNum = Addr >> addrShift; + uint64_t physAddr = CalcPhysAddr( pageNum, Addr ); + if( ctrl ) { + ctrl->sendFENCE( Hart ); + ctrl->sendFLUSHRequest( Hart, Addr, physAddr, getLineSize(), false, RevFlag::F_NONE ); } // else, this is effectively a nop return true; } - // This function is used to remove/shrink a memory segment // You *must* deallocate a chunk of memory that STARTS on a previously // allocated baseAddr @@ -917,45 +680,52 @@ bool RevMem::CleanLine( unsigned Hart, uint64_t Addr ){ // // 3. Deallocating memory that hasn't been allocated // - |---- FreeSeg ----| ==> SegFault :/ -uint64_t RevMem::DeallocMem(uint64_t BaseAddr, uint64_t Size){ - output->verbose(CALL_INFO, 10, 99, - "Attempting to deallocate %lul bytes starting at BaseAddr = 0x%lx\n", - Size, BaseAddr); +uint64_t RevMem::DeallocMem( uint64_t BaseAddr, uint64_t Size ) { + output->verbose( + CALL_INFO, 10, 99, "Attempting to deallocate %" PRIu64 " bytes starting at BaseAddr = 0x%" PRIx64 "\n", Size, BaseAddr + ); - int ret = -1; + uint64_t ret = -uint64_t{ 1 }; // Search through allocated segments for the segment that begins on the baseAddr - for( unsigned i=0; igetBaseAddr() != BaseAddr ){ + if( AllocedSeg->getBaseAddr() != BaseAddr ) { continue; } else { // Found the segment we're deallocating... // Make sure we're not trying to free beyond the segment boundaries - if( Size > AllocedSeg->getSize() ){ - output->fatal(CALL_INFO, 11, "Dealloc Error: Cannot free beyond the segment bounds. Attempted to" - "free from 0x%lx to 0x%lx however the highest address in the segment is 0x%lx", - BaseAddr, BaseAddr+Size, AllocedSeg->getTopAddr()); + if( Size > AllocedSeg->getSize() ) { + output->fatal( + CALL_INFO, + 11, + "Dealloc Error: Cannot free beyond the segment bounds. Attempted to" + "free from 0x%" PRIx64 " to 0x%" PRIx64 " however the highest address in the segment " + "is 0x%" PRIx64, + BaseAddr, + BaseAddr + Size, + AllocedSeg->getTopAddr() + ); } // (2.) Check if we're only deallocating a part of a segment - else if( Size < AllocedSeg->getSize() ){ - output->verbose(CALL_INFO, 10, 99, " => partial deallocation detected\n"); + else if( Size < AllocedSeg->getSize() ) { + output->verbose( CALL_INFO, 10, 99, " => partial deallocation detected\n" ); uint64_t oldAllocedSize = AllocedSeg->getSize(); // Free data starts where alloced data used to // Before: |------------------- AllocedSeg ------------------------| // After: |--- FreeSeg ---|------------- AllocedSeg --------------| // Alloced data now starts after the dealloced data - AllocedSeg->setBaseAddr(BaseAddr + Size); - AllocedSeg->setSize(oldAllocedSize - Size); + AllocedSeg->setBaseAddr( BaseAddr + Size ); + AllocedSeg->setSize( oldAllocedSize - Size ); ret = 0; break; - } // --- End Partial Deallocation + } // --- End Partial Deallocation // We are deallocating the entire segment (1.) else { - output->verbose(CALL_INFO, 10, 99, " => entire deallocation\n"); + output->verbose( CALL_INFO, 10, 99, " => entire deallocation\n" ); // Delete it from MemSegs - MemSegs.erase(MemSegs.begin() + i); + MemSegs.erase( MemSegs.begin() + i ); ret = 0; break; } @@ -963,33 +733,33 @@ uint64_t RevMem::DeallocMem(uint64_t BaseAddr, uint64_t Size){ } // We found a matching segment to deallocate - if (ret == 0) { + if( ret == 0 ) { // Check if the address before the baseAddr is also free // If so, we can merge the two segments // - Before: |--- FreeSeg ---|---- NewFreeSeg ----|--- AllocedSeg ---| // - After: |--- FreeSeg ------------------------|--- AllocedSeg ---| bool hasMerged = false; - for( auto FreeSeg : FreeMemSegs ){ + for( auto FreeSeg : FreeMemSegs ) { // Check if the address that precedes the baseAddr is free - if( FreeSeg->contains(BaseAddr-1) ){ + if( FreeSeg->contains( BaseAddr - 1 ) ) { // We can merge the two segments // by setting the Size of the FreeSeg to be the sum of the two // and NOT creating a new FreeMemSeg - output->verbose(CALL_INFO, 10, 99, " => merging with previous free segment\n"); - FreeSeg->setSize(FreeSeg->getSize() + Size); + output->verbose( CALL_INFO, 10, 99, " => merging with previous free segment\n" ); + FreeSeg->setSize( FreeSeg->getSize() + Size ); // Dealloc success, return 0 hasMerged = true; break; } } - if (!hasMerged) { - output->verbose(CALL_INFO, 10, 99, " => allocating new free segment\n"); + if( !hasMerged ) { + output->verbose( CALL_INFO, 10, 99, " => allocating new free segment\n" ); // If we get here, the address that precedes the newly freed data is not free // We need to create a new FreeMemSeg that starts at the baseAddr of the previously // allocated data and is `Size` bytes long // - Before: |--------------------|--- AllocedSeg ---| // - After: |---- NewFreeSeg ----|--- AllocedSeg ---| - FreeMemSegs.emplace_back(std::make_shared(BaseAddr, Size)); + FreeMemSegs.emplace_back( new MemSegment( BaseAddr, Size ) ); } } @@ -997,37 +767,40 @@ uint64_t RevMem::DeallocMem(uint64_t BaseAddr, uint64_t Size){ return ret; } - /// @brief This function is called from the loader to initialize the heap /// @param EndOfStaticData: The address of the end of the static data section (ie. end of .bss section) -void RevMem::InitHeap(const uint64_t& EndOfStaticData){ - if( EndOfStaticData == 0x00ull ){ +void RevMem::InitHeap( const uint64_t& EndOfStaticData ) { + if( EndOfStaticData == 0 ) { // Program didn't contain .text, .data, or .bss sections - output->fatal(CALL_INFO, 7, - "The loader was unable" - "to find a .text section in your executable. This is a bug." - "EndOfStaticData = 0x%lx which is less than or equal to 0", - EndOfStaticData); + output->fatal( + CALL_INFO, 7, "The loader was unable to find a .text section in your executable. This is a bug. EndOfStaticData = 0." + ); } else { // Mark heap as free - FreeMemSegs.emplace_back(std::make_shared(EndOfStaticData+1, maxHeapSize)); + FreeMemSegs.emplace_back( new MemSegment( EndOfStaticData + 1, maxHeapSize ) ); - heapend = EndOfStaticData + 1; + heapend = EndOfStaticData + 1; heapstart = EndOfStaticData + 1; } return; } -uint64_t RevMem::ExpandHeap(uint64_t Size){ +uint64_t RevMem::ExpandHeap( uint64_t Size ) { // We don't want multiple concurrent processes changing the heapend // at the same time (ie. two ThreadCtx calling brk) uint64_t NewHeapEnd = heapend + Size; // Check if we are out of heap space (ie. heapend >= bottom of stack) - if( NewHeapEnd > maxHeapSize ){ - output->fatal(CALL_INFO, 7, "Out Of Memory --- Attempted to expand heap to 0x%" PRIx64 - " which goes beyond the maxHeapSize = 0x%x set in the python configuration. " - "If unset, this value will be equal to 1/4 of memSize.\n", NewHeapEnd, maxHeapSize); + if( NewHeapEnd > maxHeapSize ) { + output->fatal( + CALL_INFO, + 7, + "Out Of Memory --- Attempted to expand heap to 0x%" PRIx64 " which goes beyond the maxHeapSize = 0x%" PRIx64 " set in the " + "python configuration. " + "If unset, this value will be equal to 1/4 of memSize.\n", + NewHeapEnd, + maxHeapSize + ); } // update the heapend heapend = NewHeapEnd; @@ -1035,5 +808,76 @@ uint64_t RevMem::ExpandHeap(uint64_t Size){ return heapend; } -} // namespace SST::RevCPU +void RevMem::DumpMem( const uint64_t startAddr, const uint64_t numBytes, const uint64_t bytesPerRow, std::ostream& outputStream ) { + uint64_t translatedStartAddr = startAddr; //CalcPhysAddr( 0, startAddr ); + const uint64_t endAddr = startAddr + numBytes; //translatedStartAddr + numBytes; + + for( uint64_t addr = translatedStartAddr; addr < endAddr; addr += bytesPerRow ) { + outputStream << "0x" << std::setw( 16 ) << std::setfill( '0' ) << std::hex << addr << ": "; + + for( uint64_t i = 0; i < bytesPerRow; ++i ) { + if( addr + i < endAddr ) { + uint8_t byte = physMem[addr + i]; + outputStream << std::setw( 2 ) << std::setfill( '0' ) << std::hex << uint32_t{ byte } << " "; + } else { + outputStream << " "; + } + } + + outputStream << " "; + + for( uint64_t i = 0; i < bytesPerRow; ++i ) { + if( addr + i < endAddr ) { + uint8_t byte = physMem[addr + i]; + if( std::isprint( byte ) ) { + outputStream << static_cast( byte ); + } else { + outputStream << "."; + } + } + } + outputStream << std::endl; + } +} + +void RevMem::DumpMemSeg( const std::shared_ptr& MemSeg, const uint64_t bytesPerRow, std::ostream& outputStream ) { + + outputStream << "// " << *MemSeg << std::endl; + DumpMem( MemSeg->getBaseAddr(), MemSeg->getSize(), bytesPerRow, outputStream ); +} + +void RevMem::DumpValidMem( const uint64_t bytesPerRow, std::ostream& outputStream ) { + + std::sort( MemSegs.begin(), MemSegs.end() ); + outputStream << "Memory Segments:" << std::endl; + for( uint32_t i = 0; i < MemSegs.size(); i++ ) { + outputStream << "// SEGMENT #" << i << *MemSegs[i] << std::endl; + DumpMemSeg( MemSegs[i], bytesPerRow, outputStream ); + } + for( const auto& MemSeg : MemSegs ) { + DumpMem( MemSeg->getBaseAddr(), MemSeg->getSize(), bytesPerRow, outputStream ); + } + + std::sort( ThreadMemSegs.begin(), ThreadMemSegs.end() ); + for( const auto& MemSeg : ThreadMemSegs ) { + outputStream << "// " << *MemSeg << std::endl; + DumpMem( MemSeg->getBaseAddr(), MemSeg->getSize(), bytesPerRow, outputStream ); + } +} + +void RevMem::DumpThreadMem( const uint64_t bytesPerRow, std::ostream& outputStream ) { + + outputStream << "Thread Memory Segments:" << std::endl; + std::sort( ThreadMemSegs.begin(), ThreadMemSegs.end() ); + for( const auto& MemSeg : ThreadMemSegs ) { + outputStream << "// " << *MemSeg << std::endl; + DumpMem( MemSeg->getBaseAddr(), MemSeg->getSize(), bytesPerRow, outputStream ); + } +} + +void RevMem::AddDumpRange( const std::string& Name, const uint64_t BaseAddr, const uint64_t Size ) { + DumpRanges[Name] = std::make_shared( BaseAddr, Size ); +} +} // namespace SST::RevCPU + // EOF diff --git a/src/RevMemCtrl.cc b/src/RevMemCtrl.cc index 3af9ad121..6b9d2d889 100644 --- a/src/RevMemCtrl.cc +++ b/src/RevMemCtrl.cc @@ -1,7 +1,7 @@ // -// _RevMemCtrl_h_ +// _RevMemCtrl_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -9,12 +9,13 @@ // #include "RevMemCtrl.h" -#include "RevInstTable.h" +#include "RevRegFile.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { /// MemOp: Formatted Output -std::ostream& operator<<(std::ostream& os, MemOp op){ +std::ostream& operator<<( std::ostream& os, MemOp op ) { + // clang-format off switch(op){ case MemOp::MemOpREAD: return os << "MemOpREAD"; case MemOp::MemOpWRITE: return os << "MemOpWRITE"; @@ -27,266 +28,192 @@ std::ostream& operator<<(std::ostream& os, MemOp op){ case MemOp::MemOpFENCE: return os << "MemOpFENCE"; case MemOp::MemOpAMO: return os << "MemOpAMO"; } + // clang-format on return os; } // --------------------------------------------------------------- // RevMemOp // --------------------------------------------------------------- -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - MemOp Op, RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), Inv(false), - Op(Op), CustomOpc(0), - SplitRqst(1), flags(flags), target(nullptr), procReq(){ -} - -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, void *target, - MemOp Op, RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), Inv(false), - Op(Op), CustomOpc(0), - SplitRqst(1), flags(flags), target(target), procReq(){ -} - -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - char *buffer, MemOp Op, - RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), - Inv(false), Op(Op), CustomOpc(0), - SplitRqst(1), flags(flags), target(nullptr), procReq(){ - for(uint32_t i = 0; i < Size; i++){ - membuf.push_back(buffer[i]); +RevMemOp::RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, MemOp Op, RevFlag flags ) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( 0 ), SplitRqst( 1 ), + flags( flags ), target( nullptr ), procReq() {} + +RevMemOp::RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, MemOp Op, RevFlag flags ) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( 0 ), SplitRqst( 1 ), + flags( flags ), target( target ), procReq() {} + +RevMemOp::RevMemOp( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, MemOp Op, RevFlag flags ) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( 0 ), SplitRqst( 1 ), + flags( flags ), target( nullptr ), procReq() { + for( uint32_t i = 0; i < Size; i++ ) { + membuf.push_back( buffer[i] ); } } -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - char *buffer, void *target, MemOp Op, - RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), - Inv(false), Op(Op), CustomOpc(0), - SplitRqst(1), flags(flags), target(target), procReq(){ - for(uint32_t i = 0; i < Size; i++){ - membuf.push_back(buffer[i]); +RevMemOp::RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, void* target, MemOp Op, RevFlag flags +) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( 0 ), SplitRqst( 1 ), + flags( flags ), target( target ), procReq() { + for( uint32_t i = 0; i < Size; i++ ) { + membuf.push_back( buffer[i] ); } } -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - std::vector buffer, MemOp Op, - RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), - Inv(false), Op(Op), CustomOpc(0), - SplitRqst(1), membuf(buffer), flags(flags), target(nullptr), procReq(){ -} - -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, - void *target, unsigned CustomOpc, MemOp Op, - RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), Inv(false), Op(Op), - CustomOpc(CustomOpc), SplitRqst(1), flags(flags), - target(target), procReq(){ -} - -RevMemOp::RevMemOp(unsigned Hart, uint64_t Addr, uint64_t PAddr, - uint32_t Size, char *buffer, - unsigned CustomOpc, MemOp Op, - RevFlag flags ) - : Hart(Hart), Addr(Addr), PAddr(PAddr), Size(Size), Inv(false), Op(Op), - CustomOpc(CustomOpc), SplitRqst(1), flags(flags), target(nullptr), procReq(){ - for(uint32_t i = 0; i< Size; i++){ - membuf.push_back((uint8_t)(buffer[i])); +RevMemOp::RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, std::vector buffer, MemOp Op, RevFlag flags +) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( 0 ), SplitRqst( 1 ), + membuf( buffer ), flags( flags ), target( nullptr ), procReq() {} + +RevMemOp::RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, uint32_t CustomOpc, MemOp Op, RevFlag flags +) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( CustomOpc ), SplitRqst( 1 ), + flags( flags ), target( target ), procReq() {} + +RevMemOp::RevMemOp( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, uint32_t CustomOpc, MemOp Op, RevFlag flags +) + : Hart( Hart ), Addr( Addr ), PAddr( PAddr ), Size( Size ), Inv( false ), Op( Op ), CustomOpc( CustomOpc ), SplitRqst( 1 ), + flags( flags ), target( nullptr ), procReq() { + for( uint32_t i = 0; i < Size; i++ ) { + membuf.push_back( (uint8_t) ( buffer[i] ) ); } } -void RevMemOp::setTempT(std::vector T){ - for( auto i : T ){ - tempT.push_back(i); +void RevMemOp::setTempT( std::vector T ) { + for( auto i : T ) { + tempT.push_back( i ); } } // --------------------------------------------------------------- // RevMemCtrl // --------------------------------------------------------------- -RevMemCtrl::RevMemCtrl(ComponentId_t id, const Params& params) - : SubComponent(id), output(nullptr) { - - uint32_t verbosity = params.find("verbose"); - output = new SST::Output("[RevMemCtrl @t]: ", verbosity, 0, SST::Output::STDOUT); +RevMemCtrl::RevMemCtrl( ComponentId_t id, const Params& params ) : SubComponent( id ), output( nullptr ) { + uint32_t verbosity = params.find( "verbose" ); + output = new SST::Output( "[RevMemCtrl @t]: ", verbosity, 0, SST::Output::STDOUT ); } -RevMemCtrl::~RevMemCtrl(){ +RevMemCtrl::~RevMemCtrl() { delete output; } // --------------------------------------------------------------- // RevBasicMemCtrl // --------------------------------------------------------------- -RevBasicMemCtrl::RevBasicMemCtrl(ComponentId_t id, const Params& params) - : RevMemCtrl(id, params), memIface(nullptr), stdMemHandlers(nullptr), - hasCache(false), lineSize(0), - max_loads(64), max_stores(64), max_flush(64), max_llsc(64), - max_readlock(64), max_writeunlock(64), max_custom(64), max_ops(2), - num_read(0x00ull), num_write(0x00ull), num_flush(0x00ull), num_llsc(0x00ull), - num_readlock(0x00ull), num_writeunlock(0x00ull), num_custom(0x00ull), - num_fence(0x00ull) { - - stdMemHandlers = new RevBasicMemCtrl::RevStdMemHandlers(this, output); - - std::string ClockFreq = params.find("clock", "1Ghz"); - - max_loads = params.find("max_loads", 64); - max_stores = params.find("max_stores", 64); - max_flush = params.find("max_flush", 64); - max_llsc = params.find("max_llsc", 64); - max_readlock = params.find("max_readlock", 64); - max_writeunlock = params.find("max_writeunlock", 64); - max_custom = params.find("max_custom", 64); - max_ops = params.find("ops_per_cycle", 2); - - rqstQ.reserve(max_ops); +RevBasicMemCtrl::RevBasicMemCtrl( ComponentId_t id, const Params& params ) + : RevMemCtrl( id, params ), memIface( nullptr ), stdMemHandlers( nullptr ), hasCache( false ), lineSize( 0 ), max_loads( 64 ), + max_stores( 64 ), max_flush( 64 ), max_llsc( 64 ), max_readlock( 64 ), max_writeunlock( 64 ), max_custom( 64 ), max_ops( 2 ), + num_read( 0 ), num_write( 0 ), num_flush( 0 ), num_llsc( 0 ), num_readlock( 0 ), num_writeunlock( 0 ), num_custom( 0 ), + num_fence( 0 ) { - memIface = loadUserSubComponent( - "memIface", ComponentInfo::SHARE_NONE, //*/ComponentInfo::SHARE_PORTS | ComponentInfo::INSERT_STATS, - getTimeConverter(ClockFreq), new StandardMem::Handler( - this, &RevBasicMemCtrl::processMemEvent)); + stdMemHandlers = new RevBasicMemCtrl::RevStdMemHandlers( this, output ); - if( !memIface ){ - output->fatal(CALL_INFO, -1, "Error : memory interface is null\n"); + std::string ClockFreq = params.find( "clock", "1Ghz" ); + + max_loads = params.find( "max_loads", 64 ); + max_stores = params.find( "max_stores", 64 ); + max_flush = params.find( "max_flush", 64 ); + max_llsc = params.find( "max_llsc", 64 ); + max_readlock = params.find( "max_readlock", 64 ); + max_writeunlock = params.find( "max_writeunlock", 64 ); + max_custom = params.find( "max_custom", 64 ); + max_ops = params.find( "ops_per_cycle", 2 ); + + rqstQ.reserve( max_ops ); + + memIface = loadUserSubComponent( + "memIface", + ComponentInfo::SHARE_NONE, //*/ComponentInfo::SHARE_PORTS | ComponentInfo::INSERT_STATS, + getTimeConverter( ClockFreq ), + new StandardMem::Handler( this, &RevBasicMemCtrl::processMemEvent ) + ); + + if( !memIface ) { + output->fatal( CALL_INFO, -1, "Error : memory interface is null\n" ); } registerStats(); - registerClock( ClockFreq, - new Clock::Handler(this, &RevBasicMemCtrl::clockTick)); + registerClock( ClockFreq, new Clock::Handler( this, &RevBasicMemCtrl::clockTick ) ); } -RevBasicMemCtrl::~RevBasicMemCtrl(){ +RevBasicMemCtrl::~RevBasicMemCtrl() { for( auto* p : rqstQ ) delete p; rqstQ.clear(); delete stdMemHandlers; } -void RevBasicMemCtrl::registerStats(){ +void RevBasicMemCtrl::registerStats() { for( auto* stat : { - "ReadInFlight", - "ReadPending", - "ReadBytes", - "WriteInFlight", - "WritePending", - "WriteBytes", - "FlushInFlight", - "FlushPending", - "ReadLockInFlight", - "ReadLockPending", - "ReadLockBytes", - "WriteUnlockInFlight", - "WriteUnlockPending", - "WriteUnlockBytes", - "LoadLinkInFlight", - "LoadLinkPending", - "StoreCondInFlight", - "StoreCondPending", - "CustomInFlight", - "CustomPending", - "CustomBytes", - "FencePending", - "AMOAddBytes", - "AMOAddPending", - "AMOXorBytes", - "AMOXorPending", - "AMOAndBytes", - "AMOAndPending", - "AMOOrBytes", - "AMOOrPending", - "AMOMinBytes", - "AMOMinPending", - "AMOMaxBytes", - "AMOMaxPending", - "AMOMinuBytes", - "AMOMinuPending", - "AMOMaxuBytes", - "AMOMaxuPending", - "AMOSwapBytes", - "AMOSwapPending", - }){ - stats.push_back(registerStatistic(stat)); + "ReadInFlight", "ReadPending", "ReadBytes", "WriteInFlight", "WritePending", + "WriteBytes", "FlushInFlight", "FlushPending", "ReadLockInFlight", "ReadLockPending", + "ReadLockBytes", "WriteUnlockInFlight", "WriteUnlockPending", "WriteUnlockBytes", "LoadLinkInFlight", + "LoadLinkPending", "StoreCondInFlight", "StoreCondPending", "CustomInFlight", "CustomPending", + "CustomBytes", "FencePending", "AMOAddBytes", "AMOAddPending", "AMOXorBytes", + "AMOXorPending", "AMOAndBytes", "AMOAndPending", "AMOOrBytes", "AMOOrPending", + "AMOMinBytes", "AMOMinPending", "AMOMaxBytes", "AMOMaxPending", "AMOMinuBytes", + "AMOMinuPending", "AMOMaxuBytes", "AMOMaxuPending", "AMOSwapBytes", "AMOSwapPending", + } ) { + stats.push_back( registerStatistic( stat ) ); } } -void RevBasicMemCtrl::recordStat(RevBasicMemCtrl::MemCtrlStats Stat, - uint64_t Data){ - if( Stat > RevBasicMemCtrl::MemCtrlStats::AMOSwapPending){ +void RevBasicMemCtrl::recordStat( RevBasicMemCtrl::MemCtrlStats Stat, uint64_t Data ) { + if( Stat > RevBasicMemCtrl::MemCtrlStats::AMOSwapPending ) { // do nothing return; } - stats[Stat]->addData(Data); + stats[Stat]->addData( Data ); } -bool RevBasicMemCtrl::sendFLUSHRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - bool Inv, - RevFlag flags){ +bool RevBasicMemCtrl::sendFLUSHRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, bool Inv, RevFlag flags ) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, - MemOp::MemOpFLUSH, flags); - Op->setInv(Inv); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::FlushPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, MemOp::MemOpFLUSH, flags ); + Op->setInv( Inv ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::FlushPending, 1 ); return true; } -bool RevBasicMemCtrl::sendREADRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - void *target, - const MemReq& req, - RevFlag flags){ +bool RevBasicMemCtrl::sendREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, target, - MemOp::MemOpREAD, flags); - Op->setMemReq(req); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::ReadPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, target, MemOp::MemOpREAD, flags ); + Op->setMemReq( req ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::ReadPending, 1 ); return true; } -bool RevBasicMemCtrl::sendWRITERequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - char *buffer, - RevFlag flags){ +bool RevBasicMemCtrl::sendWRITERequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, buffer, - MemOp::MemOpWRITE, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::WritePending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, buffer, MemOp::MemOpWRITE, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::WritePending, 1 ); return true; } -bool RevBasicMemCtrl::sendAMORequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - char *buffer, - void *target, - const MemReq& req, - RevFlag flags){ +bool RevBasicMemCtrl::sendAMORequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, void* target, const MemReq& req, RevFlag flags +) { if( Size == 0 ) return true; // Check to see if our flags contain an atomic request - // The flag hex value is a bitwise OR of all the RevFlag - // AMO enums - if( !RevFlagHas(flags, RevFlag::F_ATOMIC) ){ + if( !RevFlagAtomic( flags ) ) { // not an atomic request return true; } @@ -294,261 +221,231 @@ bool RevBasicMemCtrl::sendAMORequest(unsigned Hart, // Create a memory operation for the AMO // Since this is a read-modify-write operation, the first RevMemOp // is a MemOp::MemOpREAD. - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, buffer, target, - MemOp::MemOpREAD, flags); - Op->setMemReq(req); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, buffer, target, MemOp::MemOpREAD, flags ); + Op->setMemReq( req ); // Store the first operation in the AMOTable. When the read // response comes back, we will catch the response, perform // the MODIFY (using the operation in flags), then dispatch // a WRITE operation. - auto tmp = std::make_tuple(Hart, buffer, target, flags, Op, false); - AMOTable.insert({Addr, tmp}); + auto tmp = std::make_tuple( Hart, buffer, target, flags, Op, false ); + AMOTable.insert( { Addr, tmp } ); // We have the request created and recorded in the AMOTable // Push it onto the request queue - rqstQ.push_back(Op); + rqstQ.push_back( Op ); // now we record the stat for the particular AMO static constexpr std::pair table[] = { - { RevFlag::F_AMOADD, RevBasicMemCtrl::MemCtrlStats::AMOAddPending }, - { RevFlag::F_AMOXOR, RevBasicMemCtrl::MemCtrlStats::AMOXorPending }, - { RevFlag::F_AMOAND, RevBasicMemCtrl::MemCtrlStats::AMOAndPending }, - { RevFlag::F_AMOOR, RevBasicMemCtrl::MemCtrlStats::AMOOrPending }, - { RevFlag::F_AMOMIN, RevBasicMemCtrl::MemCtrlStats::AMOMinPending }, - { RevFlag::F_AMOMAX, RevBasicMemCtrl::MemCtrlStats::AMOMaxPending }, - { RevFlag::F_AMOMIN, RevBasicMemCtrl::MemCtrlStats::AMOMinuPending }, - { RevFlag::F_AMOMAXU, RevBasicMemCtrl::MemCtrlStats::AMOMaxuPending }, - { RevFlag::F_AMOSWAP, RevBasicMemCtrl::MemCtrlStats::AMOSwapPending }, + { RevFlag::F_AMOADD, RevBasicMemCtrl::MemCtrlStats::AMOAddPending}, + { RevFlag::F_AMOXOR, RevBasicMemCtrl::MemCtrlStats::AMOXorPending}, + { RevFlag::F_AMOAND, RevBasicMemCtrl::MemCtrlStats::AMOAndPending}, + { RevFlag::F_AMOOR, RevBasicMemCtrl::MemCtrlStats::AMOOrPending}, + { RevFlag::F_AMOMIN, RevBasicMemCtrl::MemCtrlStats::AMOMinPending}, + { RevFlag::F_AMOMAX, RevBasicMemCtrl::MemCtrlStats::AMOMaxPending}, + { RevFlag::F_AMOMIN, RevBasicMemCtrl::MemCtrlStats::AMOMinuPending}, + {RevFlag::F_AMOMAXU, RevBasicMemCtrl::MemCtrlStats::AMOMaxuPending}, + {RevFlag::F_AMOSWAP, RevBasicMemCtrl::MemCtrlStats::AMOSwapPending}, }; - for(auto& [flag, stat] : table){ - if( RevFlagHas(flags, flag) ){ - recordStat(stat, 1); + RevFlag amo{ RevFlagAtomic( flags ) }; + for( const auto& [flag, stat] : table ) { + if( amo == flag ) { + recordStat( stat, 1 ); break; } } return true; } -bool RevBasicMemCtrl::sendREADLOCKRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - void *target, - const MemReq& req, - RevFlag flags){ +bool RevBasicMemCtrl::sendREADLOCKRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, const MemReq& req, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, target, - MemOp::MemOpREADLOCK, flags); - Op->setMemReq(req); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::ReadLockPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, target, MemOp::MemOpREADLOCK, flags ); + Op->setMemReq( req ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::ReadLockPending, 1 ); return true; } -bool RevBasicMemCtrl::sendWRITELOCKRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - char *buffer, - RevFlag flags){ +bool RevBasicMemCtrl::sendWRITELOCKRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, buffer, - MemOp::MemOpWRITEUNLOCK, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::WriteUnlockPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, buffer, MemOp::MemOpWRITEUNLOCK, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::WriteUnlockPending, 1 ); return true; } -bool RevBasicMemCtrl::sendLOADLINKRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - RevFlag flags){ +bool RevBasicMemCtrl::sendLOADLINKRequest( uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, RevFlag flags ) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, - MemOp::MemOpLOADLINK, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::LoadLinkPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, MemOp::MemOpLOADLINK, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::LoadLinkPending, 1 ); return true; } -bool RevBasicMemCtrl::sendSTORECONDRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - char *buffer, - RevFlag flags){ +bool RevBasicMemCtrl::sendSTORECONDRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, buffer, - MemOp::MemOpSTORECOND, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::StoreCondPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, buffer, MemOp::MemOpSTORECOND, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::StoreCondPending, 1 ); return true; } -bool RevBasicMemCtrl::sendCUSTOMREADRequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - void *target, - unsigned Opc, - RevFlag flags){ +bool RevBasicMemCtrl::sendCUSTOMREADRequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, void* target, uint32_t Opc, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, target, Opc, - MemOp::MemOpCUSTOM, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::CustomPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, target, Opc, MemOp::MemOpCUSTOM, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::CustomPending, 1 ); return true; } -bool RevBasicMemCtrl::sendCUSTOMWRITERequest(unsigned Hart, - uint64_t Addr, - uint64_t PAddr, - uint32_t Size, - char *buffer, - unsigned Opc, - RevFlag flags){ +bool RevBasicMemCtrl::sendCUSTOMWRITERequest( + uint32_t Hart, uint64_t Addr, uint64_t PAddr, uint32_t Size, unsigned char* buffer, uint32_t Opc, RevFlag flags +) { if( Size == 0 ) return true; - RevMemOp *Op = new RevMemOp(Hart, Addr, PAddr, Size, buffer, Opc, - MemOp::MemOpCUSTOM, flags); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::CustomPending, 1); + RevMemOp* Op = new RevMemOp( Hart, Addr, PAddr, Size, buffer, Opc, MemOp::MemOpCUSTOM, flags ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::CustomPending, 1 ); return true; } -bool RevBasicMemCtrl::sendFENCE(unsigned Hart){ - RevMemOp *Op = new RevMemOp(Hart, 0x00ull, 0x00ull, 0x00, - MemOp::MemOpFENCE, RevFlag::F_NONE); - rqstQ.push_back(Op); - recordStat(RevBasicMemCtrl::MemCtrlStats::FencePending, 1); +bool RevBasicMemCtrl::sendFENCE( uint32_t Hart ) { + RevMemOp* Op = new RevMemOp( Hart, 0, 0, 0, MemOp::MemOpFENCE, RevFlag::F_NONE ); + rqstQ.push_back( Op ); + recordStat( RevBasicMemCtrl::MemCtrlStats::FencePending, 1 ); return true; } -void RevBasicMemCtrl::processMemEvent(StandardMem::Request* ev){ - output->verbose(CALL_INFO, 15, 0, "Received memory request event\n"); - if( ev == nullptr ){ - output->fatal(CALL_INFO, -1, "Error : Received null memory event\n"); +void RevBasicMemCtrl::processMemEvent( StandardMem::Request* ev ) { + output->verbose( CALL_INFO, 15, 0, "Received memory request event\n" ); + if( ev == nullptr ) { + output->fatal( CALL_INFO, -1, "Error : Received null memory event\n" ); } - ev->handle(stdMemHandlers); + ev->handle( stdMemHandlers ); } -void RevBasicMemCtrl::init(unsigned int phase){ - memIface->init(phase); +void RevBasicMemCtrl::init( uint32_t phase ) { + memIface->init( phase ); // query the caching infrastructure - if( phase == 1 ){ - lineSize = memIface->getLineSize(); - if( lineSize > 0 ){ - output->verbose(CALL_INFO, 5, 0, "Detected cache layers; default line size=%u\n", lineSize); + if( phase == 1 ) { + lineSize = uint32_t( memIface->getLineSize() ); + if( lineSize > 0 ) { + output->verbose( CALL_INFO, 5, 0, "Detected cache layers; default line size=%" PRIu32 "\n", lineSize ); hasCache = true; - }else{ - output->verbose(CALL_INFO, 5, 0, "No cache detected; disabling caching\n"); + } else { + output->verbose( CALL_INFO, 5, 0, "No cache detected; disabling caching\n" ); hasCache = false; } } } -void RevBasicMemCtrl::setup(){ +void RevBasicMemCtrl::setup() { memIface->setup(); } -void RevBasicMemCtrl::finish(){ -} +void RevBasicMemCtrl::finish() {} -bool RevBasicMemCtrl::isMemOpAvail(RevMemOp *Op, - unsigned &t_max_loads, - unsigned &t_max_stores, - unsigned &t_max_flush, - unsigned &t_max_llsc, - unsigned &t_max_readlock, - unsigned &t_max_writeunlock, - unsigned &t_max_custom){ +bool RevBasicMemCtrl::isMemOpAvail( + RevMemOp* Op, + uint32_t& t_max_loads, + uint32_t& t_max_stores, + uint32_t& t_max_flush, + uint32_t& t_max_llsc, + uint32_t& t_max_readlock, + uint32_t& t_max_writeunlock, + uint32_t& t_max_custom +) { - switch(Op->getOp()){ + switch( Op->getOp() ) { case MemOp::MemOpREAD: - if( t_max_loads < max_loads ){ + if( t_max_loads < max_loads ) { t_max_loads++; return true; } return false; break; case MemOp::MemOpWRITE: - if( t_max_stores < max_stores ){ + if( t_max_stores < max_stores ) { t_max_stores++; return true; } return false; break; case MemOp::MemOpFLUSH: - if( t_max_flush < max_flush ){ + if( t_max_flush < max_flush ) { t_max_flush++; return true; } return false; break; case MemOp::MemOpREADLOCK: - if( t_max_readlock < max_readlock ){ + if( t_max_readlock < max_readlock ) { t_max_readlock++; return true; } return false; break; case MemOp::MemOpWRITEUNLOCK: - if( t_max_writeunlock < max_writeunlock ){ + if( t_max_writeunlock < max_writeunlock ) { t_max_writeunlock++; return true; } return false; break; case MemOp::MemOpLOADLINK: - if( t_max_llsc < max_llsc ){ + if( t_max_llsc < max_llsc ) { t_max_llsc++; return true; } return false; break; case MemOp::MemOpSTORECOND: - if( t_max_llsc < max_llsc ){ + if( t_max_llsc < max_llsc ) { t_max_llsc++; return true; } return false; break; case MemOp::MemOpCUSTOM: - if( t_max_custom < max_custom ){ + if( t_max_custom < max_custom ) { t_max_custom++; return true; } return false; break; - case MemOp::MemOpFENCE: - return true; - break; + case MemOp::MemOpFENCE: return true; break; default: - output->fatal(CALL_INFO, -1, "Error : unknown memory operation type\n"); + output->fatal( CALL_INFO, -1, "Error : unknown memory operation type\n" ); return false; break; } return false; } -unsigned RevBasicMemCtrl::getBaseCacheLineSize(uint64_t Addr, uint32_t Size){ +uint32_t RevBasicMemCtrl::getBaseCacheLineSize( uint64_t Addr, uint32_t Size ) { - bool done = false; + bool done = false; uint64_t BaseCacheAddr = Addr; - while( !done ){ - if( (BaseCacheAddr%(uint64_t)(lineSize)) == 0 ){ + while( !done ) { + if( BaseCacheAddr % lineSize == 0 ) { done = true; - }else{ - BaseCacheAddr-=1; + } else { + BaseCacheAddr -= 1; } } @@ -556,117 +453,111 @@ unsigned RevBasicMemCtrl::getBaseCacheLineSize(uint64_t Addr, uint32_t Size){ std::cout << "not aligned to a base cache line" << std::endl; std::cout << "BaseCacheAddr = 0x" << std::hex << BaseCacheAddr << std::dec << std::endl; std::cout << "Addr = 0x" << std::hex << Addr << std::dec << std::endl; - std::cout << "lineSize = " << (uint64_t)(lineSize) << std::endl; + std::cout << "lineSize = " << (uint64_t) ( lineSize ) << std::endl; #endif - if( Addr == BaseCacheAddr ){ - if( Size < lineSize ){ + if( Addr == BaseCacheAddr ) { + if( Size < lineSize ) { return Size; - }else{ + } else { return lineSize; } - }else if( (Addr+(uint64_t)(Size)) <= (BaseCacheAddr+(uint64_t)(lineSize)) ){ + } else if( Addr + Size <= BaseCacheAddr + lineSize ) { // we stay within a single cache line return Size; - }else{ - return ((BaseCacheAddr+lineSize)-Addr); + } else { + return uint32_t( BaseCacheAddr + lineSize - Addr ); } } -unsigned RevBasicMemCtrl::getNumCacheLines(uint64_t Addr, uint32_t Size){ +uint32_t RevBasicMemCtrl::getNumCacheLines( uint64_t Addr, uint32_t Size ) { // if the cache is disabled, then return 1 // eg, there is a 1-to-1 mapping of CPU memops to memory requests if( !hasCache ) return 1; - if( Addr%lineSize ){ - if( (uint64_t)(Size) <= (lineSize-(Addr%lineSize)) ){ + if( Addr % lineSize ) { + if( (uint64_t) ( Size ) <= ( lineSize - ( Addr % lineSize ) ) ) { return 1; - }else if( Size < lineSize ){ + } else if( Size < lineSize ) { // this request is less than a cache line but // due to the offset, it spans two cache lines return 2; - }else{ - return ((Size/lineSize)+(Addr%lineSize > 1)); + } else { + return ( ( Size / lineSize ) + ( Addr % lineSize > 1 ) ); } - }else{ + } else { // address is aligned already - if( Size <= lineSize ){ + if( Size <= lineSize ) { return 1; - }else{ - return (Size/lineSize)+1; + } else { + return ( Size / lineSize ) + 1; } } } -bool RevBasicMemCtrl::buildCacheMemRqst(RevMemOp *op, - bool &Success){ - Interfaces::StandardMem::Request *rqst = nullptr; - unsigned NumLines = getNumCacheLines(op->getAddr(), - op->getSize()); - RevFlag TmpFlags = op->getStdFlags(); +bool RevBasicMemCtrl::buildCacheMemRqst( RevMemOp* op, bool& Success ) { + Interfaces::StandardMem::Request* rqst = nullptr; + uint32_t NumLines = getNumCacheLines( op->getAddr(), op->getSize() ); + RevFlag TmpFlags = op->getStdFlags(); #ifdef _REV_DEBUG_ - std::cout << "building caching mem request for addr=0x" - << std::hex << op->getAddr() << std::dec - << "; NumLines = " << NumLines + std::cout << "building caching mem request for addr=0x" << std::hex << op->getAddr() << std::dec << "; NumLines = " << NumLines << "; Size = " << op->getSize() << std::endl; #endif // first determine if we have enough request slots to service all the cache lines // if we don't have enough request slots, then requeue the entire RevMemOp - switch(op->getOp()){ + switch( op->getOp() ) { case MemOp::MemOpREAD: - if( (max_loads-num_read) < NumLines ){ + if( ( max_loads - num_read ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpWRITE: - if( (max_stores-num_write) < NumLines ){ + if( ( max_stores - num_write ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpFLUSH: - if( (max_flush-num_flush) < NumLines ){ + if( ( max_flush - num_flush ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpREADLOCK: - if( (max_readlock-num_readlock) < NumLines ){ + if( ( max_readlock - num_readlock ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpWRITEUNLOCK: - if( (max_writeunlock-num_writeunlock) < NumLines ){ + if( ( max_writeunlock - num_writeunlock ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpLOADLINK: - if( (max_llsc-num_llsc) < NumLines ){ + if( ( max_llsc - num_llsc ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpSTORECOND: - if( (max_llsc-num_llsc) < NumLines ){ + if( ( max_llsc - num_llsc ) < NumLines ) { Success = false; return true; } break; case MemOp::MemOpCUSTOM: - if( (max_custom-num_custom) < NumLines ){ + if( ( max_custom - num_custom ) < NumLines ) { Success = false; return true; } break; - default: - return false; - break; + default: return false; break; } Success = true; @@ -679,379 +570,335 @@ bool RevBasicMemCtrl::buildCacheMemRqst(RevMemOp *op, // this the base address to the end of the first cache line // this prevents us from sending requests that span multiple cache lines - op->setSplitRqst(NumLines); + op->setSplitRqst( NumLines ); std::vector tmpBuf = op->getBuf(); std::vector newBuf; - unsigned BaseCacheLineSize = 0; - if( NumLines > 1 ){ - BaseCacheLineSize = getBaseCacheLineSize(op->getAddr(), op->getSize()); - }else{ + uint32_t BaseCacheLineSize = 0; + if( NumLines > 1 ) { + BaseCacheLineSize = getBaseCacheLineSize( op->getAddr(), op->getSize() ); + } else { BaseCacheLineSize = op->getSize(); } #ifdef _REV_DEBUG_ - std::cout << "base cache line request size = " - << BaseCacheLineSize - << std::endl; + std::cout << "base cache line request size = " << BaseCacheLineSize << std::endl; #endif - unsigned curByte = 0; + uint64_t curByte = 0; - switch(op->getOp()){ + switch( op->getOp() ) { case MemOp::MemOpREAD: #ifdef _REV_DEBUG_ std::cout << "<<<< READ REQUEST >>>>" << std::endl; #endif - rqst = new Interfaces::StandardMem::Read(op->getAddr(), - (uint64_t)(BaseCacheLineSize), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::Read( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadInFlight, 1); + memIface->send( rqst ); + recordStat( ReadInFlight, 1 ); num_read++; break; case MemOp::MemOpWRITE: #ifdef _REV_DEBUG_ std::cout << "<<<< WRITE REQUEST >>>>" << std::endl; #endif - for( unsigned i=0; igetAddr(), - (uint64_t)(BaseCacheLineSize), - newBuf, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::Write( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), newBuf, (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteInFlight, 1); + memIface->send( rqst ); + recordStat( WriteInFlight, 1 ); num_write++; break; case MemOp::MemOpFLUSH: - rqst = new Interfaces::StandardMem::FlushAddr(op->getAddr(), - (uint64_t)(BaseCacheLineSize), - op->getInv(), - (uint64_t)(BaseCacheLineSize), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::FlushAddr( + op->getAddr(), BaseCacheLineSize, op->getInv(), BaseCacheLineSize, (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(FlushInFlight, 1); + memIface->send( rqst ); + recordStat( FlushInFlight, 1 ); num_flush++; break; case MemOp::MemOpREADLOCK: - rqst = new Interfaces::StandardMem::ReadLock(op->getAddr(), - (uint64_t)(BaseCacheLineSize), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::ReadLock( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadLockInFlight, 1); + memIface->send( rqst ); + recordStat( ReadLockInFlight, 1 ); num_readlock++; break; case MemOp::MemOpWRITEUNLOCK: - for( unsigned i=0; igetAddr(), - (uint64_t)(BaseCacheLineSize), - newBuf, - false, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::WriteUnlock( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), newBuf, false, (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteUnlockInFlight, 1); + memIface->send( rqst ); + recordStat( WriteUnlockInFlight, 1 ); num_writeunlock++; break; case MemOp::MemOpLOADLINK: - rqst = new Interfaces::StandardMem::LoadLink(op->getAddr(), - (uint64_t)(BaseCacheLineSize), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::LoadLink( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(LoadLinkInFlight, 1); + memIface->send( rqst ); + recordStat( LoadLinkInFlight, 1 ); num_llsc++; break; case MemOp::MemOpSTORECOND: - for( unsigned i=0; igetAddr(), - (uint64_t)(BaseCacheLineSize), - newBuf, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::StoreConditional( + op->getAddr(), (uint64_t) ( BaseCacheLineSize ), newBuf, (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(StoreCondInFlight, 1); + memIface->send( rqst ); + recordStat( StoreCondInFlight, 1 ); num_llsc++; break; case MemOp::MemOpCUSTOM: // TODO: need more support for custom memory ops - rqst = new Interfaces::StandardMem::CustomReq(nullptr, (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::CustomReq( nullptr, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(CustomInFlight, 1); + memIface->send( rqst ); + recordStat( CustomInFlight, 1 ); num_custom++; break; case MemOp::MemOpFENCE: // we should never get here with a FENCE operation // the FENCE is handled locally and never dispatch on the memIface - default: - return false; - break; + default: return false; break; } // dispatch a request for each subsequent cache line newBuf.clear(); - uint64_t newBase = op->getAddr() + BaseCacheLineSize; - uint64_t bytesLeft = (uint64_t)(op->getSize()) - BaseCacheLineSize; - uint64_t newSize = 0x00ull; + uint64_t newBase = op->getAddr() + BaseCacheLineSize; + uint64_t bytesLeft = (uint64_t) ( op->getSize() ) - BaseCacheLineSize; + uint32_t newSize = 0; - for( unsigned i=1; igetOp()){ + switch( op->getOp() ) { case MemOp::MemOpREAD: - rqst = new Interfaces::StandardMem::Read(newBase, - newSize, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::Read( newBase, newSize, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadInFlight, 1); + memIface->send( rqst ); + recordStat( ReadInFlight, 1 ); num_read++; break; case MemOp::MemOpWRITE: - for( unsigned j=curByte; j<(curByte+newSize); j++ ){ - newBuf.push_back(tmpBuf[j]); + for( auto j = curByte; j < curByte + newSize; j++ ) { + newBuf.push_back( tmpBuf[j] ); } curByte += newSize; - rqst = new Interfaces::StandardMem::Write(newBase, - newSize, - newBuf, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::Write( newBase, newSize, newBuf, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteInFlight, 1); + memIface->send( rqst ); + recordStat( WriteInFlight, 1 ); num_write++; break; case MemOp::MemOpFLUSH: - rqst = new Interfaces::StandardMem::FlushAddr(newBase, - newSize, - op->getInv(), - newSize, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = + new Interfaces::StandardMem::FlushAddr( newBase, newSize, op->getInv(), newSize, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(FlushInFlight, 1); + memIface->send( rqst ); + recordStat( FlushInFlight, 1 ); num_flush++; break; case MemOp::MemOpREADLOCK: - rqst = new Interfaces::StandardMem::ReadLock(newBase, - newSize, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::ReadLock( newBase, newSize, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadLockInFlight, 1); + memIface->send( rqst ); + recordStat( ReadLockInFlight, 1 ); num_readlock++; break; case MemOp::MemOpWRITEUNLOCK: - for( unsigned j=curByte; j<(curByte+newSize); j++ ){ - newBuf.push_back(tmpBuf[j]); + for( auto j = curByte; j < curByte + newSize; j++ ) { + newBuf.push_back( tmpBuf[j] ); } curByte += newSize; - rqst = new Interfaces::StandardMem::WriteUnlock(newBase, - newSize, - newBuf, - false, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::WriteUnlock( newBase, newSize, newBuf, false, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteUnlockInFlight, 1); + memIface->send( rqst ); + recordStat( WriteUnlockInFlight, 1 ); num_writeunlock++; break; case MemOp::MemOpLOADLINK: - rqst = new Interfaces::StandardMem::LoadLink(newBase, - newSize, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::LoadLink( newBase, newSize, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(LoadLinkInFlight, 1); + memIface->send( rqst ); + recordStat( LoadLinkInFlight, 1 ); num_llsc++; break; case MemOp::MemOpSTORECOND: - for( unsigned j=curByte; j<(curByte+newSize); j++ ){ - newBuf.push_back(tmpBuf[j]); + for( auto j = curByte; j < curByte + newSize; j++ ) { + newBuf.push_back( tmpBuf[j] ); } curByte += newSize; - rqst = new Interfaces::StandardMem::StoreConditional(newBase, - newSize, - newBuf, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::StoreConditional( newBase, newSize, newBuf, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(StoreCondInFlight, 1); + memIface->send( rqst ); + recordStat( StoreCondInFlight, 1 ); num_llsc++; break; case MemOp::MemOpCUSTOM: // TODO: need more support for custom memory ops - rqst = new Interfaces::StandardMem::CustomReq(nullptr, (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::CustomReq( nullptr, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(CustomInFlight, 1); + memIface->send( rqst ); + recordStat( CustomInFlight, 1 ); num_custom++; break; case MemOp::MemOpFENCE: // we should never get here with a FENCE operation // the FENCE is handled locally and never dispatch on the memIface - default: - return false; - break; - } // end case + default: return false; break; + } // end case bytesLeft -= newSize; newBase += newSize; - } // end for + } // end for return true; } -bool RevBasicMemCtrl::buildRawMemRqst(RevMemOp *op, - RevFlag TmpFlags){ - Interfaces::StandardMem::Request *rqst = nullptr; +bool RevBasicMemCtrl::buildRawMemRqst( RevMemOp* op, RevFlag TmpFlags ) { + Interfaces::StandardMem::Request* rqst = nullptr; #ifdef _REV_DEBUG_ - std::cout << "building raw mem request for addr=0x" - << std::hex << op->getAddr() << std::dec - << "; Flags = 0x" << std::hex << (StandardMem::Request::flags_t)TmpFlags << std::dec << std::endl; + std::cout << "building raw mem request for addr=0x" << std::hex << op->getAddr() << std::dec << "; Flags = 0x" << std::hex + << (StandardMem::Request::flags_t) TmpFlags << std::dec << std::endl; #endif - switch(op->getOp()){ + switch( op->getOp() ) { case MemOp::MemOpREAD: - rqst = new Interfaces::StandardMem::Read(op->getAddr(), - (uint64_t)(op->getSize()), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = + new Interfaces::StandardMem::Read( op->getAddr(), (uint64_t) ( op->getSize() ), (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadInFlight, 1); + memIface->send( rqst ); + recordStat( ReadInFlight, 1 ); num_read++; break; case MemOp::MemOpWRITE: - rqst = new Interfaces::StandardMem::Write(op->getAddr(), - (uint64_t)(op->getSize()), - op->getBuf(), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::Write( + op->getAddr(), (uint64_t) ( op->getSize() ), op->getBuf(), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteInFlight, 1); + memIface->send( rqst ); + recordStat( WriteInFlight, 1 ); num_write++; break; case MemOp::MemOpFLUSH: - rqst = new Interfaces::StandardMem::FlushAddr(op->getAddr(), - (uint64_t)(op->getSize()), - op->getInv(), - (uint64_t)(op->getSize()), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::FlushAddr( + op->getAddr(), op->getSize(), op->getInv(), op->getSize(), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(FlushInFlight, 1); + memIface->send( rqst ); + recordStat( FlushInFlight, 1 ); num_flush++; break; case MemOp::MemOpREADLOCK: - rqst = new Interfaces::StandardMem::ReadLock(op->getAddr(), - (uint64_t)(op->getSize()), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::ReadLock( + op->getAddr(), (uint64_t) ( op->getSize() ), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(ReadLockInFlight, 1); + memIface->send( rqst ); + recordStat( ReadLockInFlight, 1 ); num_readlock++; break; case MemOp::MemOpWRITEUNLOCK: - rqst = new Interfaces::StandardMem::WriteUnlock(op->getAddr(), - (uint64_t)(op->getSize()), - op->getBuf(), - false, - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::WriteUnlock( + op->getAddr(), (uint64_t) ( op->getSize() ), op->getBuf(), false, (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(WriteUnlockInFlight, 1); + memIface->send( rqst ); + recordStat( WriteUnlockInFlight, 1 ); num_writeunlock++; break; case MemOp::MemOpLOADLINK: - rqst = new Interfaces::StandardMem::LoadLink(op->getAddr(), - (uint64_t)(op->getSize()), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::LoadLink( + op->getAddr(), (uint64_t) ( op->getSize() ), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(LoadLinkInFlight, 1); + memIface->send( rqst ); + recordStat( LoadLinkInFlight, 1 ); num_llsc++; break; case MemOp::MemOpSTORECOND: - rqst = new Interfaces::StandardMem::StoreConditional(op->getAddr(), - (uint64_t)(op->getSize()), - op->getBuf(), - (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::StoreConditional( + op->getAddr(), (uint64_t) ( op->getSize() ), op->getBuf(), (StandardMem::Request::flags_t) TmpFlags + ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(StoreCondInFlight, 1); + memIface->send( rqst ); + recordStat( StoreCondInFlight, 1 ); num_llsc++; break; case MemOp::MemOpCUSTOM: // TODO: need more support for custom memory ops - rqst = new Interfaces::StandardMem::CustomReq(nullptr, (StandardMem::Request::flags_t)TmpFlags); - requests.push_back(rqst->getID()); + rqst = new Interfaces::StandardMem::CustomReq( nullptr, (StandardMem::Request::flags_t) TmpFlags ); + requests.push_back( rqst->getID() ); outstanding[rqst->getID()] = op; - memIface->send(rqst); - recordStat(CustomInFlight, 1); + memIface->send( rqst ); + recordStat( CustomInFlight, 1 ); num_custom++; break; case MemOp::MemOpFENCE: // we should never get here with a FENCE operation // the FENCE is handled locally and never dispatch on the memIface - default: - return false; - break; + default: return false; break; } return true; } -bool RevBasicMemCtrl::buildStandardMemRqst(RevMemOp *op, - bool &Success){ - if( !op ){ +bool RevBasicMemCtrl::buildStandardMemRqst( RevMemOp* op, bool& Success ) { + if( !op ) { return false; } #ifdef _REV_DEBUG_ - std::cout << "building mem request for addr=0x" - << std::hex << op->getAddr() << std::dec - << "; flags = 0x" << std::hex << (StandardMem::Request::flags_t)op->getFlags() << std::dec << std::endl; + std::cout << "building mem request for addr=0x" << std::hex << op->getAddr() << std::dec << "; flags = 0x" << std::hex + << (StandardMem::Request::flags_t) op->getFlags() << std::dec << std::endl; if( !lineSize ) std::cout << "WARNING: lineSize == 0!" << std::endl; else if( op->getAddr() % lineSize ) @@ -1079,35 +926,33 @@ bool RevBasicMemCtrl::buildStandardMemRqst(RevMemOp *op, // RevMemOp // --------------------------------------------------------- RevFlag TmpFlags; - if( (hasCache) && - (op->isCacheable()) ){ + if( ( hasCache ) && ( op->isCacheable() ) ) { // cache is enabled and we want to cache the request - return buildCacheMemRqst(op, Success); - }else if( (hasCache) && (!op->isCacheable()) ){ + return buildCacheMemRqst( op, Success ); + } else if( ( hasCache ) && ( !op->isCacheable() ) ) { // cache is enabled but the request says not to cache the data - Success = true; + Success = true; TmpFlags = op->getStdFlags(); - return buildRawMemRqst(op, TmpFlags); - }else{ + return buildRawMemRqst( op, TmpFlags ); + } else { // no cache enabled - Success = true; + Success = true; TmpFlags = op->getNonCacheFlags(); - return buildRawMemRqst(op, TmpFlags); + return buildRawMemRqst( op, TmpFlags ); } } -bool RevBasicMemCtrl::isAQ(unsigned Slot, unsigned Hart){ - if( AMOTable.size() == 0 ){ +bool RevBasicMemCtrl::isAQ( uint32_t Slot, uint32_t Hart ) { + if( AMOTable.size() == 0 ) { return false; - }else if( Slot == 0 ){ + } else if( Slot == 0 ) { return false; } // search all preceding slots for an AMO from the same Hart - for( unsigned i = 0; i < Slot; i++ ){ - if( RevFlagHas(rqstQ[i]->getFlags(), RevFlag::F_ATOMIC) && - rqstQ[i]->getHart() == rqstQ[Slot]->getHart() ){ - if( RevFlagHas(rqstQ[i]->getFlags(), RevFlag::F_AQ) ){ + for( uint32_t i = 0; i < Slot; i++ ) { + if( RevFlagAtomic( rqstQ[i]->getFlags() ) && rqstQ[i]->getHart() == rqstQ[Slot]->getHart() ) { + if( RevFlagHas( rqstQ[i]->getFlags(), RevFlag::F_AQ ) ) { // this implies that we found a preceding request in the request queue // that was 1) an AMO and 2) came from the same HART as 'slot' // and 3) had the AQ flag set; @@ -1120,19 +965,18 @@ bool RevBasicMemCtrl::isAQ(unsigned Slot, unsigned Hart){ return false; } -bool RevBasicMemCtrl::isRL(unsigned Slot, unsigned Hart){ - if( AMOTable.size() == 0 ){ +bool RevBasicMemCtrl::isRL( uint32_t Slot, uint32_t Hart ) { + if( AMOTable.size() == 0 ) { return false; - }else if( Slot == 0 ){ + } else if( Slot == 0 ) { return false; } - if( RevFlagHas(rqstQ[Slot]->getFlags(), RevFlag::F_ATOMIC) && - RevFlagHas(rqstQ[Slot]->getFlags(), RevFlag::F_RL) ){ + if( RevFlagAtomic( rqstQ[Slot]->getFlags() ) && RevFlagHas( rqstQ[Slot]->getFlags(), RevFlag::F_RL ) ) { // this is an AMO, check to see if there are other ops from the same // HART in flight - for( unsigned i = 0; i < Slot; i++ ){ - if( rqstQ[i]->getHart() == rqstQ[Slot]->getHart() ){ + for( uint32_t i = 0; i < Slot; i++ ) { + if( rqstQ[i]->getHart() == rqstQ[Slot]->getHart() ) { // this implies that the same Hart has preceding memory ops // in which case, we can't dispatch this AMO until they clear return true; @@ -1142,20 +986,21 @@ bool RevBasicMemCtrl::isRL(unsigned Slot, unsigned Hart){ return false; } -bool RevBasicMemCtrl::isPendingAMO(unsigned Slot){ - return (isAQ(Slot, rqstQ[Slot]->getHart()) || - isRL(Slot, rqstQ[Slot]->getHart())); +bool RevBasicMemCtrl::isPendingAMO( uint32_t Slot ) { + return ( isAQ( Slot, rqstQ[Slot]->getHart() ) || isRL( Slot, rqstQ[Slot]->getHart() ) ); } -bool RevBasicMemCtrl::processNextRqst(unsigned &t_max_loads, - unsigned &t_max_stores, - unsigned &t_max_flush, - unsigned &t_max_llsc, - unsigned &t_max_readlock, - unsigned &t_max_writeunlock, - unsigned &t_max_custom, - unsigned &t_max_ops){ - if( rqstQ.size() == 0 ){ +bool RevBasicMemCtrl::processNextRqst( + uint32_t& t_max_loads, + uint32_t& t_max_stores, + uint32_t& t_max_flush, + uint32_t& t_max_llsc, + uint32_t& t_max_readlock, + uint32_t& t_max_writeunlock, + uint32_t& t_max_custom, + uint32_t& t_max_ops +) { + if( rqstQ.size() == 0 ) { // nothing to do, saturate and exit this cycle t_max_ops = max_ops; return true; @@ -1164,27 +1009,20 @@ bool RevBasicMemCtrl::processNextRqst(unsigned &t_max_loads, bool success = false; // retrieve the next candidate memory operation - for( unsigned i=0; igetOp() == MemOp::MemOpFENCE ){ + if( op->getOp() == MemOp::MemOpFENCE ) { // time to fence! // saturate and exit this cycle // no need to build a StandardMem request t_max_ops = max_ops; - rqstQ.erase(rqstQ.begin()+i); - num_fence+=1; + rqstQ.erase( rqstQ.begin() + i ); + num_fence += 1; delete op; return true; } @@ -1193,21 +1031,21 @@ bool RevBasicMemCtrl::processNextRqst(unsigned &t_max_loads, // from dispatching this request. if this returns 'true' // then we can't dispatch the request. note that // we do this after processing FENCE requests - if( isPendingAMO(i) ){ + if( isPendingAMO( i ) ) { t_max_ops = max_ops; return true; } // build a StandardMem request - if( !buildStandardMemRqst(op, success) ){ - output->fatal(CALL_INFO, -1, "Error : failed to build memory request"); + if( !buildStandardMemRqst( op, success ) ) { + output->fatal( CALL_INFO, -1, "Error : failed to build memory request" ); return false; } // sent the request, remove it - if( success ){ - rqstQ.erase(rqstQ.begin()+i); - }else{ + if( success ) { + rqstQ.erase( rqstQ.begin() + i ); + } else { // go ahead and max out our current request window // otherwise, this request for induce an infinite loop // we also leave the current (failed) request in the queue @@ -1224,184 +1062,197 @@ bool RevBasicMemCtrl::processNextRqst(unsigned &t_max_loads, t_max_ops = max_ops; #ifdef _REV_DEBUG_ - for( unsigned i=0; igetAddr() << std::dec - << "; physAddr = 0x" << std::hex << rqstQ[i]->getPhysAddr() - << std::dec << std::endl; + for( uint32_t i = 0; i < rqstQ.size(); i++ ) { + std::cout << "rqstQ[" << i << "] = " << rqstQ[i]->getOp() << " @ 0x" << std::hex << rqstQ[i]->getAddr() << std::dec + << "; physAddr = 0x" << std::hex << rqstQ[i]->getPhysAddr() << std::dec << std::endl; } #endif return true; } -void RevBasicMemCtrl::handleFlagResp(RevMemOp *op){ - RevFlag flags = op->getFlags(); - unsigned bits = 8 * op->getSize(); - - if( RevFlagHas(flags, RevFlag::F_SEXT32) ){ - uint32_t *target = static_cast(op->getTarget()); - *target = SignExt(*target, bits); - }else if( RevFlagHas(flags, RevFlag::F_SEXT64) ){ - uint64_t *target = static_cast(op->getTarget()); - *target = SignExt(*target, bits); - }else if( RevFlagHas(flags, RevFlag::F_ZEXT32) ){ - uint32_t *target = static_cast(op->getTarget()); - *target = ZeroExt(*target, bits); - }else if( RevFlagHas(flags, RevFlag::F_ZEXT64) ){ - uint64_t *target = static_cast(op->getTarget()); - *target = ZeroExt(*target, bits); - }else if( RevFlagHas(flags, RevFlag::F_BOXNAN) ){ - double *target = static_cast(op->getTarget()); - BoxNaN(target, target); +/// RevFlag: Perform an integer conversion +template +static inline void convert( void* target ) { + SRC src; + memcpy( &src, target, sizeof( src ) ); + DEST dest{ src }; + memcpy( target, &dest, sizeof( dest ) ); +} + +/// RevFlag: Handle flag response +void RevHandleFlagResp( void* target, size_t size, RevFlag flags ) { + if( RevFlagHas( flags, RevFlag::F_BOXNAN ) && size < sizeof( double ) ) { + BoxNaN( static_cast( target ), static_cast( target ) ); + } else { + switch( size ) { + case 1: + if( RevFlagHas( flags, RevFlag::F_SEXT32 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_ZEXT32 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_SEXT64 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_ZEXT64 ) ) { + convert( target ); + } + break; + case 2: + if( RevFlagHas( flags, RevFlag::F_SEXT32 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_ZEXT32 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_SEXT64 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_ZEXT64 ) ) { + convert( target ); + } + break; + case 4: + if( RevFlagHas( flags, RevFlag::F_SEXT64 ) ) { + convert( target ); + } else if( RevFlagHas( flags, RevFlag::F_ZEXT64 ) ) { + convert( target ); + } + } } } -unsigned RevBasicMemCtrl::getNumSplitRqsts(RevMemOp *op){ - unsigned count = 0; - for (const auto& n : outstanding ){ - if( n.second == op ){ +uint32_t RevBasicMemCtrl::getNumSplitRqsts( RevMemOp* op ) { + uint32_t count = 0; + for( const auto& n : outstanding ) { + if( n.second == op ) { count++; } } return count; } -void RevBasicMemCtrl::handleReadResp(StandardMem::ReadResp* ev){ - if( std::find(requests.begin(), requests.end(), ev->getID()) != requests.end() ){ - requests.erase(std::find(requests.begin(), requests.end(), ev->getID())); - RevMemOp *op = outstanding[ev->getID()]; +void RevBasicMemCtrl::handleReadResp( StandardMem::ReadResp* ev ) { + if( std::find( requests.begin(), requests.end(), ev->getID() ) != requests.end() ) { + requests.erase( std::find( requests.begin(), requests.end(), ev->getID() ) ); + RevMemOp* op = outstanding[ev->getID()]; if( !op ) - output->fatal(CALL_INFO, -1, "RevMemOp is null in handleReadResp\n" ); + output->fatal( CALL_INFO, -1, "RevMemOp is null in handleReadResp\n" ); #ifdef _REV_DEBUG_ - std::cout << "handleReadResp : id=" << ev->getID() << " @Addr= 0x" - << std::hex << op->getAddr() << std::dec << std::endl; - for( unsigned i=0; i < op->getSize(); i++ ){ - std::cout << " : data[" << i << "] = " << (unsigned)(ev->data[i]) << std::endl; + std::cout << "handleReadResp : id=" << ev->getID() << " @Addr= 0x" << std::hex << op->getAddr() << std::dec << std::endl; + for( uint32_t i = 0; i < op->getSize(); i++ ) { + std::cout << " : data[" << i << "] = " << (uint32_t) ( ev->data[i] ) << std::endl; } std::cout << "isOutstanding val = 0x" << std::hex << op->getMemReq().isOutstanding << std::dec << std::endl; - std::cout << "Address of the target register = 0x" << std::hex - << (uint64_t *)(op->getTarget()) << std::dec << std::endl; + std::cout << "Address of the target register = 0x" << std::hex << (uint64_t*) ( op->getTarget() ) << std::dec << std::endl; #endif - auto range = AMOTable.equal_range(op->getAddr()); + auto range = AMOTable.equal_range( op->getAddr() ); bool isAMO = false; - for( auto i = range.first; i != range.second; ++i ){ + for( auto i = range.first; i != range.second; ++i ) { auto Entry = i->second; // determine if we have an atomic request associated // with this read operation - if( std::get(Entry) == op ){ + if( std::get( Entry ) == op ) { isAMO = true; } } // determine if we have a split request - if( op->getSplitRqst() > 1 ){ + if( op->getSplitRqst() > 1 ) { // split request exists, determine how to handle it - uint8_t *target = static_cast(op->getTarget()); - unsigned startByte = (unsigned)(ev->pAddr - op->getAddr()); - target += uint8_t(startByte); - for( unsigned i=0; i<(unsigned)(ev->size); i++ ){ + uint8_t* target = static_cast( op->getTarget() ); + uint32_t startByte = (uint32_t) ( ev->pAddr - op->getAddr() ); + target += uint8_t( startByte ); + for( uint32_t i = 0; i < (uint32_t) ( ev->size ); i++ ) { *target = ev->data[i]; target++; } - if( getNumSplitRqsts(op) == 1 ){ + if( getNumSplitRqsts( op ) == 1 ) { // this was the last request to service, delete the op - handleFlagResp(op); - if( isAMO ){ - handleAMO(op); + handleFlagResp( op ); + if( isAMO ) { + handleAMO( op ); } const MemReq& r = op->getMemReq(); - if( !isAMO ){ + if( !isAMO ) { r.MarkLoadComplete(); } delete op; } - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; num_read--; - return ; + return; } // no split request exists; handle as normal - uint8_t *target = (uint8_t *)(op->getTarget()); - for( unsigned i = 0; i < op->getSize(); i++ ){ + uint8_t* target = (uint8_t*) ( op->getTarget() ); + for( uint32_t i = 0; i < op->getSize(); i++ ) { *target = ev->data[i]; target++; } // determine if we need to sign/zero extend - handleFlagResp(op); - if( isAMO ){ - handleAMO(op); + handleFlagResp( op ); + if( isAMO ) { + handleAMO( op ); } const MemReq& r = op->getMemReq(); - if( !isAMO ){ - TRACE_MEM_READ_RESPONSE(op->getSize(), op->getTarget(), &r); + if( !isAMO ) { + TRACE_MEM_READ_RESPONSE( op->getSize(), op->getTarget(), &r ); r.MarkLoadComplete(); } delete op; - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - }else{ - output->fatal(CALL_INFO, -1, "Error : found unknown ReadResp\n"); + } else { + output->fatal( CALL_INFO, -1, "Error : found unknown ReadResp\n" ); } num_read--; } -void RevBasicMemCtrl::performAMO(std::tuple Entry){ - RevMemOp *Tmp = std::get(Entry); - if( Tmp == nullptr ){ - output->fatal(CALL_INFO, -1, "Error : AMOTable entry is null\n" ); +void RevBasicMemCtrl::performAMO( std::tuple Entry ) { + RevMemOp* Tmp = std::get( Entry ); + if( Tmp == nullptr ) { + output->fatal( CALL_INFO, -1, "Error : AMOTable entry is null\n" ); } - void *Target = Tmp->getTarget(); + void* Target = Tmp->getTarget(); - RevFlag flags = Tmp->getFlags(); + RevFlag flags = Tmp->getFlags(); std::vector buffer = Tmp->getBuf(); std::vector tempT; tempT.clear(); - uint8_t *TmpBuf8 = static_cast(Target); - for( size_t i = 0; i < Tmp->getSize(); i++ ){ - tempT.push_back(TmpBuf8[i]); + uint8_t* TmpBuf8 = static_cast( Target ); + for( size_t i = 0; i < Tmp->getSize(); i++ ) { + tempT.push_back( TmpBuf8[i] ); } - if( Tmp->getSize() == 4 ){ + if( Tmp->getSize() == 4 ) { // 32-bit (W) AMOs uint32_t TmpBuf = 0; - for( size_t i = 0; i < buffer.size(); i++ ){ - TmpBuf |= uint32_t{buffer[i]} << i*8; + for( size_t i = 0; i < buffer.size(); i++ ) { + TmpBuf |= uint32_t{ buffer[i] } << i * 8; } - ApplyAMO(flags, Target, TmpBuf); - }else{ + ApplyAMO( flags, Target, TmpBuf ); + } else { // 64-bit (D) AMOs uint64_t TmpBuf = 0; - for( size_t i = 0; i < buffer.size(); i++ ){ - TmpBuf |= uint64_t{buffer[i]} << i*8; + for( size_t i = 0; i < buffer.size(); i++ ) { + TmpBuf |= uint64_t{ buffer[i] } << i * 8; } - ApplyAMO(flags, Target, TmpBuf); + ApplyAMO( flags, Target, TmpBuf ); } // copy the target data over to the buffer and build the memory request buffer.clear(); - for( size_t i = 0; i < Tmp->getSize(); i++ ){ - buffer.push_back(TmpBuf8[i]); + for( size_t i = 0; i < Tmp->getSize(); i++ ) { + buffer.push_back( TmpBuf8[i] ); } - RevMemOp *Op = new RevMemOp(Tmp->getHart(), Tmp->getAddr(), - Tmp->getPhysAddr(), Tmp->getSize(), - buffer, - MemOp::MemOpWRITE, - Tmp->getFlags()); - Op->setTempT(tempT); - for( unsigned i = 0; i < Op->getSize(); i++ ){ + RevMemOp* Op = + new RevMemOp( Tmp->getHart(), Tmp->getAddr(), Tmp->getPhysAddr(), Tmp->getSize(), buffer, MemOp::MemOpWRITE, Tmp->getFlags() ); + Op->setTempT( tempT ); + for( uint32_t i = 0; i < Op->getSize(); i++ ) { TmpBuf8[i] = tempT[i]; } @@ -1410,226 +1261,224 @@ void RevBasicMemCtrl::performAMO(std::tuplegetMemReq(); - Op->setMemReq(r); + Op->setMemReq( r ); // insert a new entry into the AMO Table - auto NewEntry = std::make_tuple(Op->getHart(), - nullptr, // this can be null here since we don't need to modify the response - Op->getTarget(), - Op->getFlags(), - Op, - true); - AMOTable.insert({Op->getAddr(), NewEntry}); - rqstQ.push_back(Op); + auto NewEntry = std::make_tuple( + Op->getHart(), + nullptr, // this can be null here since we don't need to modify the response + Op->getTarget(), + Op->getFlags(), + Op, + true + ); + AMOTable.insert( { Op->getAddr(), NewEntry } ); + rqstQ.push_back( Op ); } -void RevBasicMemCtrl::handleAMO(RevMemOp *op){ - auto range = AMOTable.equal_range(op->getAddr()); - for( auto i = range.first; i != range.second; ++i ){ +void RevBasicMemCtrl::handleAMO( RevMemOp* op ) { + auto range = AMOTable.equal_range( op->getAddr() ); + for( auto i = range.first; i != range.second; ++i ) { auto Entry = i->second; // perform the arithmetic operation and generate a WRITE request - if( std::get(Entry) == op ){ - performAMO(Entry); - AMOTable.erase(i); // erase the current entry so we can add a new one - return ; + if( std::get( Entry ) == op ) { + performAMO( Entry ); + AMOTable.erase( i ); // erase the current entry so we can add a new one + return; } } } -void RevBasicMemCtrl::handleWriteResp(StandardMem::WriteResp* ev){ - if( std::find(requests.begin(), requests.end(), ev->getID()) != requests.end() ){ - requests.erase(std::find(requests.begin(), requests.end(), ev->getID())); - RevMemOp *op = outstanding[ev->getID()]; +void RevBasicMemCtrl::handleWriteResp( StandardMem::WriteResp* ev ) { + if( std::find( requests.begin(), requests.end(), ev->getID() ) != requests.end() ) { + requests.erase( std::find( requests.begin(), requests.end(), ev->getID() ) ); + RevMemOp* op = outstanding[ev->getID()]; if( !op ) - output->fatal(CALL_INFO, -1, "RevMemOp is null in handleWriteResp\n" ); + output->fatal( CALL_INFO, -1, "RevMemOp is null in handleWriteResp\n" ); #ifdef _REV_DEBUG_ - std::cout << "handleWriteResp : id=" << ev->getID() << " @Addr= 0x" - << std::hex << op->getAddr() << std::dec << std::endl; + std::cout << "handleWriteResp : id=" << ev->getID() << " @Addr= 0x" << std::hex << op->getAddr() << std::dec << std::endl; #endif // walk the AMOTable and clear any matching AMO ops // note that we must match on both the target address and the RevMemOp pointer bool isAMO = false; - auto range = AMOTable.equal_range(op->getAddr()); - for( auto i = range.first; i != range.second; ){ + auto range = AMOTable.equal_range( op->getAddr() ); + for( auto i = range.first; i != range.second; ) { auto Entry = i->second; // if the request matches the target, // then delete it - if( std::get(Entry) == op ){ - AMOTable.erase(i++); + if( std::get( Entry ) == op ) { + AMOTable.erase( i++ ); isAMO = true; - }else{ + } else { ++i; } } // determine if we have a split request - if( op->getSplitRqst() > 1 ){ + if( op->getSplitRqst() > 1 ) { // split request exists, determine how to handle it - if( getNumSplitRqsts(op) == 1 ){ + if( getNumSplitRqsts( op ) == 1 ) { // this was the last request to service, delete the op const MemReq& r = op->getMemReq(); - if( isAMO ){ + if( isAMO ) { r.MarkLoadComplete(); } delete op; } - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; num_write--; - return ; + return; } // no split request exists; handle as normal // this was a write request for an AMO, clear the hazard const MemReq& r = op->getMemReq(); - if( isAMO ){ + if( isAMO ) { // write the target std::vector tempT = op->getTempT(); r.MarkLoadComplete(); } delete op; - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - }else{ - output->fatal(CALL_INFO, -1, "Error : found unknown WriteResp\n"); + } else { + output->fatal( CALL_INFO, -1, "Error : found unknown WriteResp\n" ); } num_write--; } -void RevBasicMemCtrl::handleFlushResp(StandardMem::FlushResp* ev){ - if( std::find(requests.begin(), requests.end(), ev->getID()) != requests.end() ){ - requests.erase(std::find(requests.begin(), requests.end(), ev->getID())); - RevMemOp *op = outstanding[ev->getID()]; +void RevBasicMemCtrl::handleFlushResp( StandardMem::FlushResp* ev ) { + if( std::find( requests.begin(), requests.end(), ev->getID() ) != requests.end() ) { + requests.erase( std::find( requests.begin(), requests.end(), ev->getID() ) ); + RevMemOp* op = outstanding[ev->getID()]; if( !op ) - output->fatal(CALL_INFO, -1, "RevMemOp is null in handleFlushResp\n" ); + output->fatal( CALL_INFO, -1, "RevMemOp is null in handleFlushResp\n" ); // determine if we have a split request - if( op->getSplitRqst() > 1 ){ + if( op->getSplitRqst() > 1 ) { // split request exists, determine how to handle it - if( getNumSplitRqsts(op) == 1 ){ + if( getNumSplitRqsts( op ) == 1 ) { // this was the last request to service, delete the op delete op; } - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; num_flush--; - return ; + return; } // no split request exists; handle as normal delete op; - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - }else{ - output->fatal(CALL_INFO, -1, "Error : found unknown FlushResp\n"); + } else { + output->fatal( CALL_INFO, -1, "Error : found unknown FlushResp\n" ); } num_flush--; } -void RevBasicMemCtrl::handleCustomResp(StandardMem::CustomResp* ev){ - if( std::find(requests.begin(), requests.end(), ev->getID()) != requests.end() ){ - requests.erase(std::find(requests.begin(), requests.end(), ev->getID())); - RevMemOp *op = outstanding[ev->getID()]; +void RevBasicMemCtrl::handleCustomResp( StandardMem::CustomResp* ev ) { + if( std::find( requests.begin(), requests.end(), ev->getID() ) != requests.end() ) { + requests.erase( std::find( requests.begin(), requests.end(), ev->getID() ) ); + RevMemOp* op = outstanding[ev->getID()]; if( !op ) - output->fatal(CALL_INFO, -1, "RevMemOp is null in handleCustomResp\n" ); + output->fatal( CALL_INFO, -1, "RevMemOp is null in handleCustomResp\n" ); // determine if we have a split request - if( op->getSplitRqst() > 1 ){ + if( op->getSplitRqst() > 1 ) { // split request exists, determine how to handle it - if( getNumSplitRqsts(op) == 1 ){ + if( getNumSplitRqsts( op ) == 1 ) { // this was the last request to service, delete the op delete op; } - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; num_custom--; - return ; + return; } // no split request exists; handle as normal delete op; - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - }else{ - output->fatal(CALL_INFO, -1, "Error : found unknown CustomResp\n"); + } else { + output->fatal( CALL_INFO, -1, "Error : found unknown CustomResp\n" ); } num_custom--; } -void RevBasicMemCtrl::handleInvResp(StandardMem::InvNotify* ev){ - if( std::find(requests.begin(), requests.end(), ev->getID()) != requests.end() ){ - requests.erase(std::find(requests.begin(), requests.end(), ev->getID())); - RevMemOp *op = outstanding[ev->getID()]; +void RevBasicMemCtrl::handleInvResp( StandardMem::InvNotify* ev ) { + if( std::find( requests.begin(), requests.end(), ev->getID() ) != requests.end() ) { + requests.erase( std::find( requests.begin(), requests.end(), ev->getID() ) ); + RevMemOp* op = outstanding[ev->getID()]; if( !op ) - output->fatal(CALL_INFO, -1, "RevMemOp is null in handleInvResp\n" ); + output->fatal( CALL_INFO, -1, "RevMemOp is null in handleInvResp\n" ); // determine if we have a split request - if( op->getSplitRqst() > 1 ){ + if( op->getSplitRqst() > 1 ) { // split request exists, determine how to handle it - if( getNumSplitRqsts(op) == 1 ){ + if( getNumSplitRqsts( op ) == 1 ) { // this was the last request to service, delete the op delete op; } - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - return ; + return; } // no split request exists; handle as normal delete op; - outstanding.erase(ev->getID()); + outstanding.erase( ev->getID() ); delete ev; - }else{ - output->fatal(CALL_INFO, -1, "Error : found unknown InvResp\n"); + } else { + output->fatal( CALL_INFO, -1, "Error : found unknown InvResp\n" ); } } -uint64_t RevBasicMemCtrl::getTotalRqsts(){ - return num_read + num_write + num_llsc + - num_readlock + num_writeunlock + num_custom; +uint64_t RevBasicMemCtrl::getTotalRqsts() { + return num_read + num_write + num_llsc + num_readlock + num_writeunlock + num_custom; } -bool RevBasicMemCtrl::outstandingRqsts(){ - return (requests.size() > 0 ); +bool RevBasicMemCtrl::outstandingRqsts() { + return ( requests.size() > 0 ); } -bool RevBasicMemCtrl::clockTick(Cycle_t cycle){ +bool RevBasicMemCtrl::clockTick( Cycle_t cycle ) { // check to see if the top request is a FENCE - if( num_fence > 0 ){ - if( (num_read + num_write + num_llsc + - num_readlock + num_writeunlock + - num_custom) != 0 ){ + if( num_fence > 0 ) { + if( ( num_read + num_write + num_llsc + num_readlock + num_writeunlock + num_custom ) != 0 ) { // waiting for the outstanding ops to clear - recordStat(RevBasicMemCtrl::MemCtrlStats::FencePending, 1); + recordStat( RevBasicMemCtrl::MemCtrlStats::FencePending, 1 ); return false; - }else{ + } else { // clear the fence and continue processing num_fence--; } } // process the memory queue - bool done = false; - unsigned t_max_ops = 0; - unsigned t_max_loads = 0; - unsigned t_max_stores = 0; - unsigned t_max_flush = 0; - unsigned t_max_llsc = 0; - unsigned t_max_readlock = 0; - unsigned t_max_writeunlock = 0; - unsigned t_max_custom = 0; - - while( !done ){ - if( !processNextRqst(t_max_loads, t_max_stores, t_max_flush, - t_max_llsc, t_max_readlock, t_max_writeunlock, - t_max_custom, t_max_ops) ){ + bool done = false; + uint32_t t_max_ops = 0; + uint32_t t_max_loads = 0; + uint32_t t_max_stores = 0; + uint32_t t_max_flush = 0; + uint32_t t_max_llsc = 0; + uint32_t t_max_readlock = 0; + uint32_t t_max_writeunlock = 0; + uint32_t t_max_custom = 0; + + while( !done ) { + if( !processNextRqst( + t_max_loads, t_max_stores, t_max_flush, t_max_llsc, t_max_readlock, t_max_writeunlock, t_max_custom, t_max_ops + ) ) { // error occurred - output->fatal(CALL_INFO, -1, "Error : failed to process next memory request"); + output->fatal( CALL_INFO, -1, "Error : failed to process next memory request" ); } - if( t_max_ops == max_ops ){ + if( t_max_ops == max_ops ) { done = true; } } @@ -1640,37 +1489,35 @@ bool RevBasicMemCtrl::clockTick(Cycle_t cycle){ // --------------------------------------------------------------- // RevStdMemHandlers // --------------------------------------------------------------- -RevBasicMemCtrl::RevStdMemHandlers::RevStdMemHandlers( RevBasicMemCtrl* Ctrl, - SST::Output* output) - : Interfaces::StandardMem::RequestHandler(output), Ctrl(Ctrl){ -} +RevBasicMemCtrl::RevStdMemHandlers::RevStdMemHandlers( RevBasicMemCtrl* Ctrl, SST::Output* output ) + : Interfaces::StandardMem::RequestHandler( output ), Ctrl( Ctrl ) {} -RevBasicMemCtrl::RevStdMemHandlers::~RevStdMemHandlers(){ -} +RevBasicMemCtrl::RevStdMemHandlers::~RevStdMemHandlers() {} -void RevBasicMemCtrl::RevStdMemHandlers::handle(StandardMem::ReadResp* ev){ - Ctrl->handleReadResp(ev); +void RevBasicMemCtrl::RevStdMemHandlers::handle( StandardMem::ReadResp* ev ) { + Ctrl->handleReadResp( ev ); } -void RevBasicMemCtrl::RevStdMemHandlers::handle(StandardMem::WriteResp* ev){ - Ctrl->handleWriteResp(ev); +void RevBasicMemCtrl::RevStdMemHandlers::handle( StandardMem::WriteResp* ev ) { + Ctrl->handleWriteResp( ev ); } -void RevBasicMemCtrl::RevStdMemHandlers::handle(StandardMem::FlushResp* ev){ - Ctrl->handleFlushResp(ev); +void RevBasicMemCtrl::RevStdMemHandlers::handle( StandardMem::FlushResp* ev ) { + Ctrl->handleFlushResp( ev ); } -void RevBasicMemCtrl::RevStdMemHandlers::handle(StandardMem::CustomResp* ev){ - Ctrl->handleCustomResp(ev); +void RevBasicMemCtrl::RevStdMemHandlers::handle( StandardMem::CustomResp* ev ) { + Ctrl->handleCustomResp( ev ); } -void RevBasicMemCtrl::RevStdMemHandlers::handle(StandardMem::InvNotify* ev){ - Ctrl->handleInvResp(ev); +void RevBasicMemCtrl::RevStdMemHandlers::handle( StandardMem::InvNotify* ev ) { + Ctrl->handleInvResp( ev ); } -void RevBasicMemCtrl::setTracer(RevTracer *tracer){ +void RevBasicMemCtrl::setTracer( RevTracer* tracer ) { Tracer = tracer; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevNIC.cc b/src/RevNIC.cc index 214f78d0a..ffc6ab0c4 100644 --- a/src/RevNIC.cc +++ b/src/RevNIC.cc @@ -10,118 +10,117 @@ #include "RevNIC.h" -using namespace SST; -using namespace RevCPU; +namespace SST::RevCPU { -RevNIC::RevNIC(ComponentId_t id, Params& params) - : nicAPI(id, params) { +RevNIC::RevNIC( ComponentId_t id, Params& params ) : nicAPI( id, params ) { // setup the initial logging functions - int verbosity = params.find("verbose", 0); - output = new SST::Output("", verbosity, 0, SST::Output::STDOUT); + auto verbosity = params.find( "verbose", 0 ); + output = new SST::Output( "", verbosity, 0, SST::Output::STDOUT ); - const std::string nicClock = params.find("clock", "1GHz"); - registerClock(nicClock, new Clock::Handler(this, &RevNIC::clockTick)); + const std::string nicClock = params.find( "clock", "1GHz" ); + registerClock( nicClock, new Clock::Handler( this, &RevNIC::clockTick ) ); // load the SimpleNetwork interfaces - iFace = loadUserSubComponent("iface", ComponentInfo::SHARE_NONE, 1); - if( !iFace ){ + iFace = loadUserSubComponent( "iface", ComponentInfo::SHARE_NONE, 1 ); + if( !iFace ) { // load the anonymous nic Params netparams; - netparams.insert("port_name", params.find("port", "network")); - netparams.insert("in_buf_size", "256B"); - netparams.insert("out_buf_size", "256B"); - netparams.insert("link_bw", "40GiB/s"); - iFace = loadAnonymousSubComponent("merlin.linkcontrol", - "iface", - 0, - ComponentInfo::SHARE_PORTS | ComponentInfo::INSERT_STATS, - netparams, - 1); + netparams.insert( "port_name", params.find( "port", "network" ) ); + netparams.insert( "in_buf_size", "256B" ); + netparams.insert( "out_buf_size", "256B" ); + netparams.insert( "link_bw", "40GiB/s" ); + iFace = loadAnonymousSubComponent( + "merlin.linkcontrol", "iface", 0, ComponentInfo::SHARE_PORTS | ComponentInfo::INSERT_STATS, netparams, 1 + ); } - iFace->setNotifyOnReceive(new SST::Interfaces::SimpleNetwork::Handler(this, &RevNIC::msgNotify)); + iFace->setNotifyOnReceive( new SST::Interfaces::SimpleNetwork::Handler( this, &RevNIC::msgNotify ) ); initBroadcastSent = false; - numDest = 0; + numDest = 0; - msgHandler = nullptr; + msgHandler = nullptr; } -RevNIC::~RevNIC(){ +RevNIC::~RevNIC() { delete output; } -void RevNIC::setMsgHandler(Event::HandlerBase* handler){ +void RevNIC::setMsgHandler( Event::HandlerBase* handler ) { msgHandler = handler; } -void RevNIC::init(unsigned int phase){ - iFace->init(phase); +void RevNIC::init( uint32_t phase ) { + iFace->init( phase ); - if( iFace->isNetworkInitialized() ){ - if( !initBroadcastSent) { - initBroadcastSent = true; - nicEvent *ev = new nicEvent(getName()); + if( iFace->isNetworkInitialized() ) { + if( !initBroadcastSent ) { + initBroadcastSent = true; + nicEvent* ev = new nicEvent( getName() ); - SST::Interfaces::SimpleNetwork::Request * req = new SST::Interfaces::SimpleNetwork::Request(); - req->dest = SST::Interfaces::SimpleNetwork::INIT_BROADCAST_ADDR; - req->src = iFace->getEndpointID(); - req->givePayload(ev); - iFace->sendInitData(req); + SST::Interfaces::SimpleNetwork::Request* req = new SST::Interfaces::SimpleNetwork::Request(); + req->dest = SST::Interfaces::SimpleNetwork::INIT_BROADCAST_ADDR; + req->src = iFace->getEndpointID(); + req->givePayload( ev ); + + //iFace->sendInitData( req ); // removed for SST 14.0.0 + iFace->sendUntimedData( req ); } } - - while( SST::Interfaces::SimpleNetwork::Request * req = iFace->recvInitData() ) { - nicEvent *ev = static_cast(req->takePayload()); + //while( SST::Interfaces::SimpleNetwork::Request* req = iFace->recvInitData() ) { + while( SST::Interfaces::SimpleNetwork::Request* req = iFace->recvUntimedData() ) { // SST 14.0.0 + nicEvent* ev = static_cast( req->takePayload() ); numDest++; - output->verbose(CALL_INFO, 1, 0, - "%s received init message from %s\n", - getName().c_str(), ev->getSource().c_str()); + output->verbose( CALL_INFO, 1, 0, "%s received init message from %s\n", getName().c_str(), ev->getSource().c_str() ); } } -void RevNIC::setup(){ - if( msgHandler == nullptr ){ - output->fatal(CALL_INFO, -1, - "%s, Error: RevNIC implements a callback-based notification and parent has not registerd a callback function\n", - getName().c_str()); +void RevNIC::setup() { + if( msgHandler == nullptr ) { + output->fatal( + CALL_INFO, + -1, + "%s, Error: RevNIC implements a callback-based notification " + "and parent has not registerd a callback function\n", + getName().c_str() + ); } } -bool RevNIC::msgNotify(int vn){ - SST::Interfaces::SimpleNetwork::Request* req = iFace->recv(0); - if( req != nullptr ){ - if( req != nullptr ){ - nicEvent *ev = static_cast(req->takePayload()); +bool RevNIC::msgNotify( int vn ) { + SST::Interfaces::SimpleNetwork::Request* req = iFace->recv( 0 ); + if( req != nullptr ) { + if( req != nullptr ) { + nicEvent* ev = static_cast( req->takePayload() ); delete req; - (*msgHandler)(ev); + ( *msgHandler )( ev ); } } return true; } -void RevNIC::send(nicEvent* event, int destination){ - SST::Interfaces::SimpleNetwork::Request *req = new SST::Interfaces::SimpleNetwork::Request(); - req->dest = destination; - req->src = iFace->getEndpointID(); - req->givePayload(event); - sendQ.push(req); +void RevNIC::send( nicEvent* event, int destination ) { + SST::Interfaces::SimpleNetwork::Request* req = new SST::Interfaces::SimpleNetwork::Request(); + req->dest = destination; + req->src = iFace->getEndpointID(); + req->givePayload( event ); + sendQ.push( req ); } -int RevNIC::getNumDestinations(){ +int RevNIC::getNumDestinations() { return numDest; } -SST::Interfaces::SimpleNetwork::nid_t RevNIC::getAddress(){ +SST::Interfaces::SimpleNetwork::nid_t RevNIC::getAddress() { return iFace->getEndpointID(); } -bool RevNIC::clockTick(Cycle_t cycle){ - while( !sendQ.empty() ){ - if( iFace->spaceToSend(0, 512) && iFace->send(sendQ.front(), 0)) { +bool RevNIC::clockTick( Cycle_t cycle ) { + while( !sendQ.empty() ) { + if( iFace->spaceToSend( 0, 512 ) && iFace->send( sendQ.front(), 0 ) ) { sendQ.pop(); - }else{ + } else { break; } } @@ -129,5 +128,6 @@ bool RevNIC::clockTick(Cycle_t cycle){ return false; } +} // namespace SST::RevCPU // EOF diff --git a/src/RevOpts.cc b/src/RevOpts.cc index c13d4838e..840a61a03 100644 --- a/src/RevOpts.cc +++ b/src/RevOpts.cc @@ -1,7 +1,7 @@ // // _RevOpts_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -9,269 +9,133 @@ // #include "RevOpts.h" -namespace SST::RevCPU{ -RevOpts::RevOpts( unsigned NumCores, unsigned NumHarts, const int Verbosity ) - : numCores(NumCores), numHarts(NumHarts), verbosity(Verbosity) { +namespace SST::RevCPU { - std::pair InitialPair; - InitialPair.first = 0; - InitialPair.second = 10; +void RevOpts::SetArgs( const SST::Params& params ) { + static constexpr char delim[] = " \t\v\n\r\f"; - // init all the standard options - // -- startAddr = 0x00000000 - // -- machine = "G" aka, "IMAFD" - // -- pipeLine = 5 - // -- table = internal - // -- memCosts[core] = 0:10 - // -- prefetch depth = 16 - for( unsigned i=0; i(i, 0) ); - machine.insert( std::pair(i, "G") ); - table.insert( std::pair(i, "_REV_INTERNAL_") ); - memCosts.push_back(InitialPair); - prefetchDepth.insert( std::pair(i, 16) ); + // If the "args" param does not start with a left bracket, split it up at whitespace + // Otherwise interpet it as an array + std::string args = params.find( "args" ); + auto nonspace = args.find_first_not_of( delim ); + if( nonspace == args.npos || args[nonspace] != '[' ) { + RevOpts::splitStr( args, delim, Argv ); + } else { + params.find_array( "args", Argv ); } } -RevOpts::~RevOpts(){ -} - -void RevOpts::splitStr(const std::string& s, - char c, - std::vector& v){ - std::string::size_type i = 0; - std::string::size_type j = s.find(c); - v.clear(); - - if( (j==std::string::npos) && (s.length() > 0) ){ - v.push_back(s); - return ; - } - - while (j != std::string::npos) { - v.push_back(s.substr(i, j-i)); - i = ++j; - j = s.find(c, j); - if (j == std::string::npos) - v.push_back(s.substr(i, s.length())); - } -} - -bool RevOpts::InitPrefetchDepth( std::vector Depths ){ +template +bool RevOpts::InitPropertyMap( const std::vector& Opts, MAP& map ) { std::vector vstr; - for(unsigned i=0; i numCores ) - return false; - - std::string::size_type sz = 0; - unsigned Depth = std::stoul(vstr[1], &sz, 0); - - prefetchDepth.find(Core)->second = Depth; - vstr.clear(); - } - return true; -} - -bool RevOpts::InitStartAddrs( std::vector StartAddrs ){ - std::vector vstr; - - // check to see if we expand into multiple cores - if( StartAddrs.size() == 1 ){ - std::string s = StartAddrs[0]; - splitStr(s, ':', vstr); - if( vstr.size() != 2 ) - return false; - if( vstr[0] == "CORES" ){ - // set all cores to the target machine model - std::string::size_type sz = 0; - uint64_t Addr = std::stoull(vstr[1], &sz, 0); - for( unsigned i=0; isecond = Addr; - } - return true; - } - } - - for(unsigned i=0; i numCores ) + auto Core = uint32_t( std::stoull( vstr[0], nullptr, 0 ) ); + if( Core >= numCores ) return false; - std::string::size_type sz = 0; - uint64_t Addr = std::stoull(vstr[1], &sz, 0); + // Store as cast integer if target is integer; otherwise store as string + auto parse = [&]( auto val ) { + if constexpr( std::is_integral_v ) { + map[Core] = decltype( val )( std::stoull( vstr[1], nullptr, 0 ) ); + } else if constexpr( is_vector::value ) { + map[Core] = make_dependent( std::move( vstr[1] ) ); + } else { + map.insert_or_assign( Core, make_dependent( std::move( vstr[1] ) ) ); + } + }; - startAddr.find(Core)->second = Addr; - vstr.clear(); + if constexpr( is_vector::value ) { + parse( typename MAP::value_type{} ); + } else { + parse( typename MAP::mapped_type{} ); + } } - return true; -} -bool RevOpts::InitStartSymbols( std::vector StartSymbols ){ - std::vector vstr; - for(unsigned i=0; i numCores ) - return false; - - startSym.insert(std::pair(Core, vstr[1])); - vstr.clear(); - } return true; } -bool RevOpts::InitMachineModels( std::vector Machines ){ - std::vector vstr; - +template +bool RevOpts::InitPropertyMapCores( const std::vector& Opts, MAP& map ) { // check to see if we expand into multiple cores - if( Machines.size() == 1 ){ - std::string s = Machines[0]; - splitStr(s, ':', vstr); + if( Opts.size() == 1 ) { + std::vector vstr; + + splitStr( Opts[0], ":", vstr ); if( vstr.size() != 2 ) return false; - if( vstr[0] == "CORES" ){ - // set all cores to the target machine model - for( unsigned i=0; i ) { + auto Val = decltype( val )( std::stoull( vstr[1], nullptr, 0 ) ); + for( size_t i = 0; i < numCores; i++ ) + map[i] = Val; + } else { + for( size_t i = 0; i < numCores; i++ ) + map[i] = make_dependent( vstr[1] ); + } + }; + + if constexpr( is_vector::value ) { + parse( typename MAP::value_type{} ); + } else { + parse( typename MAP::mapped_type{} ); } + return true; } } + return InitPropertyMap( Opts, map ); +} - // parse individual core configs - for( unsigned i=0; i numCores ) - return false; +/// RevOpts: initialize the set of starting addresses +bool RevOpts::InitStartAddrs( const std::vector& StartAddrs ) { + return InitPropertyMapCores( StartAddrs, startAddr ); +} - machine.at(Core) = vstr[1]; - vstr.clear(); - } - return true; +/// RevOpts: initialize the set of potential starting symbols +bool RevOpts::InitStartSymbols( const std::vector& StartSymbols ) { + return InitPropertyMap( StartSymbols, startSym ); } -bool RevOpts::InitInstTables( std::vector InstTables ){ - std::vector vstr; - for( unsigned i=0; i& Machines ) { + return InitPropertyMapCores( Machines, machine ); +} - unsigned Core = std::stoi(vstr[0], nullptr, 0); - if( Core > numCores ) - return false; +/// RevOpts: initalize the set of instruction tables +bool RevOpts::InitInstTables( const std::vector& InstTables ) { + return InitPropertyMap( InstTables, table ); +} - table.at(Core) = vstr[1]; - vstr.clear(); - } - return true; +/// RevOpts: initialize the prefetch depths +bool RevOpts::InitPrefetchDepth( const std::vector& Depths ) { + return InitPropertyMap( Depths, prefetchDepth ); } -bool RevOpts::InitMemCosts( std::vector MemCosts ){ +/// RevOpts: initialize the memory latency cost tables +bool RevOpts::InitMemCosts( const std::vector& MemCosts ) { std::vector vstr; - - for( unsigned i=0; i= numCores || !Min || !Max ) return false; - } - vstr.clear(); + memCosts[Core] = std::pair( Min, Max ); } - - return true; -} - -bool RevOpts::GetPrefetchDepth( unsigned Core, unsigned &Depth ){ - if( Core > numCores ) - return false; - - if( prefetchDepth.find(Core) == prefetchDepth.end() ) - return false; - - Depth = prefetchDepth.at(Core); - return true; -} - -bool RevOpts::GetStartAddr( unsigned Core, uint64_t &StartAddr ){ - if( Core > numCores ) - return false; - - if( startAddr.find(Core) == startAddr.end() ) - return false; - - StartAddr = startAddr.at(Core); - return true; -} - -bool RevOpts::GetStartSymbol( unsigned Core, std::string &Symbol ){ - if( Core > numCores ) - return false; - - if( startSym.find(Core) == startSym.end() ) - return false; - - Symbol = startSym.at(Core); - return true; -} - -bool RevOpts::GetMachineModel( unsigned Core, std::string &MachModel ){ - if( Core > numCores ) - return false; - - MachModel = machine.at(Core); - return true; -} - -bool RevOpts::GetInstTable( unsigned Core, std::string &Table ){ - if( Core > numCores ) - return false; - - Table = table.at(Core); - return true; -} - -bool RevOpts::GetMemCost( unsigned Core, unsigned &Min, unsigned &Max ){ - if( Core > numCores ) - return false; - - Min = memCosts[Core].first; - Max = memCosts[Core].second; - return true; } -} // namespace SST::RevCPU -// EOF +} // namespace SST::RevCPU diff --git a/src/RevPrefetcher.cc b/src/RevPrefetcher.cc index eb5f96ccd..942c6ad27 100644 --- a/src/RevPrefetcher.cc +++ b/src/RevPrefetcher.cc @@ -10,7 +10,7 @@ #include "RevPrefetcher.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { /*RevPrefetcher::~RevPrefetcher(){ // delete all the existing streams @@ -18,46 +18,47 @@ for(auto* s : iStack) delete[] s; }*/ -bool RevPrefetcher::IsAvail(uint64_t Addr){ +bool RevPrefetcher::IsAvail( uint64_t Addr ) { // note: this logic now considers compressed instructions - uint64_t lastAddr = 0x00ull; - for( unsigned i=0; i= baseAddr[i]) && (Addr < lastAddr) ){ + uint64_t lastAddr = 0; + for( uint32_t i = 0; i < baseAddr.size(); i++ ) { + lastAddr = baseAddr[i] + ( depth * 4 ); + if( ( Addr >= baseAddr[i] ) && ( Addr < lastAddr ) ) { // found it, fetch the address // first, calculate the vector offset - uint32_t Off = static_cast((Addr-baseAddr[i])/4); - if( Off > (depth-1) ){ + uint32_t Off = static_cast( ( Addr - baseAddr[i] ) / 4 ); + if( Off > ( depth - 1 ) ) { // some sort of error occurred return false; } - if( iStack[i][Off] == REVPREF_INIT_ADDR ){ + if( iStack[i][Off] == REVPREF_INIT_ADDR ) { // the instruction hasn't been filled yet, stall return false; } // we may be short of instruction width in our current stream // determine if an adjacent stream has the payload - if( (lastAddr-Addr < 4) || ( (Addr & 0x03) != 0) ){ + if( ( lastAddr - Addr < 4 ) || ( ( Addr & 0x03 ) != 0 ) ) { uint32_t TmpInst; - bool Fetched = false; - if( !FetchUpper(Addr+2, Fetched, TmpInst) ){ + bool Fetched = false; + if( !FetchUpper( Addr + 2, Fetched, TmpInst ) ) { return false; } - if( !Fetched ){ + if( !Fetched ) { // initiated a Fill return false; } } - if(!OutstandingFetchQ.empty()){ - auto it = LSQueue->equal_range(OutstandingFetchQ.back().LSQHash()); // Find all outstanding dependencies for this register - if( it.first != LSQueue->end()){ - for (auto i = it.first; i != it.second; ++i){ // Iterate over all outstanding loads for this reg (if any) - if(i->second.Addr == OutstandingFetchQ.back().Addr){ + if( !OutstandingFetchQ.empty() ) { + auto it = + LSQueue->equal_range( OutstandingFetchQ.back().LSQHash() ); // Find all outstanding dependencies for this register + if( it.first != LSQueue->end() ) { + for( auto i = it.first; i != it.second; ++i ) { // Iterate over all outstanding loads for this reg (if any) + if( i->second.Addr == OutstandingFetchQ.back().Addr ) { return false; } } @@ -70,86 +71,85 @@ bool RevPrefetcher::IsAvail(uint64_t Addr){ // if we reach this point, then the instruction hasn't even triggered // a stream prefetch. Lets go ahead and initiate one via a 'Fill' operation - Fill(Addr); + Fill( Addr ); return false; } -void RevPrefetcher::MarkInstructionLoadComplete(const MemReq& req){ +void RevPrefetcher::MarkInstructionLoadComplete( const MemReq& req ) { auto it = OutstandingFetchQ.begin(); - while((it != OutstandingFetchQ.end())){ - if(it->Addr == req.Addr){ - OutstandingFetchQ.erase(it++); + while( ( it != OutstandingFetchQ.end() ) ) { + if( it->Addr == req.Addr ) { + OutstandingFetchQ.erase( it++ ); break; } it++; - } } -bool RevPrefetcher::FetchUpper(uint64_t Addr, bool &Fetched, uint32_t &UInst){ - uint64_t lastAddr = 0x00ull; - for( unsigned i=0; i= baseAddr[i]) && (Addr < lastAddr) ){ - uint32_t Off = static_cast((Addr-baseAddr[i])/4); - if( Off > (depth-1) ){ +bool RevPrefetcher::FetchUpper( uint64_t Addr, bool& Fetched, uint32_t& UInst ) { + uint64_t lastAddr = 0; + for( uint32_t i = 0; i < baseAddr.size(); i++ ) { + lastAddr = baseAddr[i] + ( depth * 4 ); + if( ( Addr >= baseAddr[i] ) && ( Addr < lastAddr ) ) { + uint32_t Off = static_cast( ( Addr - baseAddr[i] ) / 4 ); + if( Off > ( depth - 1 ) ) { // some sort of error occurred Fetched = false; return false; } - if( iStack[i][Off] == REVPREF_INIT_ADDR ){ + if( iStack[i][Off] == REVPREF_INIT_ADDR ) { // the instruction hasn't been filled yet, stall Fetched = false; return true; } // fetch the instruction - if( Addr == (baseAddr[i]+(Off*4)) ){ - UInst = (iStack[i][Off]<<16); + if( Addr == ( baseAddr[i] + ( Off * 4 ) ) ) { + UInst = ( iStack[i][Off] << 16 ); Fetched = true; return true; } } } - Fill(Addr); + Fill( Addr ); Fetched = false; return true; } -bool RevPrefetcher::InstFetch(uint64_t Addr, bool &Fetched, uint32_t &Inst){ +bool RevPrefetcher::InstFetch( uint64_t Addr, bool& Fetched, uint32_t& Inst ) { // scan the baseAddr vector to see if the address is cached - uint64_t lastAddr = 0x00ull; - for( unsigned i=0; i= baseAddr[i]) && (Addr < lastAddr) ){ + uint64_t lastAddr = 0; + for( uint32_t i = 0; i < baseAddr.size(); i++ ) { + lastAddr = baseAddr[i] + ( depth * 4 ); + if( ( Addr >= baseAddr[i] ) && ( Addr < lastAddr ) ) { // found it, fetch the address // first, calculate the vector offset - uint32_t Off = static_cast((Addr-baseAddr[i])/4); - if( Off > (depth-1) ){ + uint32_t Off = static_cast( ( Addr - baseAddr[i] ) / 4 ); + if( Off > ( depth - 1 ) ) { // some sort of error occurred Fetched = false; return false; } - if( iStack[i][Off] == REVPREF_INIT_ADDR ){ + if( iStack[i][Off] == REVPREF_INIT_ADDR ) { // the instruction hasn't been filled yet, stall Fetched = false; return true; } // fetch the instruction - if( Addr == (baseAddr[i]+(Off*4)) ){ + if( Addr == ( baseAddr[i] + ( Off * 4 ) ) ) { Inst = iStack[i][Off]; - }else{ + } else { // compressed instruction, adjust the offset - Inst = (iStack[i][Off] >> 16); + Inst = ( iStack[i][Off] >> 16 ); uint32_t TmpInst; - if( !FetchUpper(Addr+2, Fetched, TmpInst) ) + if( !FetchUpper( Addr + 2, Fetched, TmpInst ) ) return false; - if( !Fetched ){ + if( !Fetched ) { // we initiated a fill return true; } @@ -159,9 +159,9 @@ bool RevPrefetcher::InstFetch(uint64_t Addr, bool &Fetched, uint32_t &Inst){ Fetched = true; // if this is the last instruction in the stream buffer, we need to deallocate the stream - if( Off == (depth-1) ){ - DeleteStream(i); - Fill(Addr+2); // go ahead and fill the next instruction + if( Off == ( depth - 1 ) ) { + DeleteStream( i ); + Fill( Addr + 2 ); // go ahead and fill the next instruction } return true; @@ -169,50 +169,47 @@ bool RevPrefetcher::InstFetch(uint64_t Addr, bool &Fetched, uint32_t &Inst){ } // we missed in the stream cache, lets perform a fill - Fill(Addr); + Fill( Addr ); Fetched = false; return true; } -void RevPrefetcher::Fill(uint64_t Addr){ +void RevPrefetcher::Fill( uint64_t Addr ) { // If address is not 32bit aligned... then make it aligned Addr &= 0xFFFFFFFFFFFFFFFC; // allocate a new stream buffer - baseAddr.push_back(Addr); - iStack.push_back( std::vector(depth) ); + baseAddr.push_back( Addr ); + iStack.push_back( std::vector( depth ) ); // initialize it size_t x = baseAddr.size() - 1; - for( size_t y = 0; y < depth; y++ ){ + for( size_t y = 0; y < depth; y++ ) { iStack[x][y] = REVPREF_INIT_ADDR; } // now fill it - for( size_t y=0; yGetHartToExecID(), MemOp::MemOpREAD, true, - MarkLoadAsComplete ); + for( size_t y = 0; y < depth; y++ ) { + MemReq req( + Addr + ( y * 4 ), RevReg::zero, RevRegClass::RegGPR, feature->GetHartToExecID(), MemOp::MemOpREAD, true, MarkLoadAsComplete + ); LSQueue->insert( req.LSQHashPair() ); - OutstandingFetchQ.emplace_back(req); - mem->ReadVal( feature->GetHartToExecID(), Addr+(y*4), - &iStack[x][y], - req, - RevFlag::F_NONE ); + OutstandingFetchQ.emplace_back( req ); + mem->ReadVal( feature->GetHartToExecID(), Addr + ( y * 4 ), &iStack[x][y], req, RevFlag::F_NONE ); //Track outstanding requests } - } -void RevPrefetcher::DeleteStream(size_t i){ +void RevPrefetcher::DeleteStream( size_t i ) { // delete the target stream as we no longer need it - if( i < baseAddr.size() ){ - iStack.erase(iStack.begin() + i); - baseAddr.erase(baseAddr.begin() + i); + if( i < baseAddr.size() ) { + iStack.erase( iStack.begin() + ptrdiff_t( i ) ); + baseAddr.erase( baseAddr.begin() + ptrdiff_t( i ) ); } } -} // namespace SST::RevCPU +} // namespace SST::RevCPU + // EOF diff --git a/src/RevProc.cc b/src/RevProc.cc deleted file mode 100644 index bc5c2192e..000000000 --- a/src/RevProc.cc +++ /dev/null @@ -1,2456 +0,0 @@ -// -// _RevProc_cc_ -// -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC -// All Rights Reserved -// contact@tactcomplabs.com -// -// See LICENSE in the top level directory for licensing details -// - -#include "RevProc.h" -#include "RevSysCalls.cc" -#include "sst/core/output.h" - -using namespace SST::RevCPU; -using MemSegment = RevMem::MemSegment; - -RevProc::RevProc( unsigned Id, - RevOpts *Opts, - unsigned NumHarts, - RevMem *Mem, - RevLoader *Loader, - std::function GetNewTID, - SST::Output *Output ) - : Halted(false), Stalled(false), SingleStep(false), - CrackFault(false), ALUFault(false), fault_width(0), - id(Id), HartToDecodeID(0), HartToExecID(0), - numHarts(NumHarts), opts(Opts), mem(Mem), coProc(nullptr), loader(Loader), - GetNewThreadID(std::move(GetNewTID)), output(Output), feature(nullptr), - sfetch(nullptr), Tracer(nullptr) { - - // initialize the machine model for the target core - std::string Machine; - if( !Opts->GetMachineModel(id, Machine) ) - output->fatal(CALL_INFO, -1, - "Error: failed to retrieve the machine model for core=%" PRIu32 "\n", id); - - unsigned MinCost = 0; - unsigned MaxCost = 0; - - Opts->GetMemCost(Id, MinCost, MaxCost); - - - LSQueue = std::make_shared>(); - LSQueue->clear(); - - // Create the Hart Objects - for( size_t i=0; i(i, LSQueue, [=](const MemReq& req){ this->MarkLoadComplete(req); })); - ValidHarts.set(i, true); - } - - featureUP = std::make_unique(Machine, output, MinCost, MaxCost, Id); - feature = featureUP.get(); - if( !feature ) - output->fatal(CALL_INFO, -1, - "Error: failed to create the RevFeature object for core=%" PRIu32 "\n", id); - - unsigned Depth = 0; - Opts->GetPrefetchDepth(Id, Depth); - if( Depth == 0 ){ - Depth = 16; - } - - sfetch = std::make_unique(Mem, feature, Depth, LSQueue, [=](const MemReq& req){ this->MarkLoadComplete(req); }); - if( !sfetch ) - output->fatal(CALL_INFO, -1, - "Error: failed to create the RevPrefetcher object for core=%" PRIu32 "\n", id); - - // load the instruction tables - if( !LoadInstructionTable() ) - output->fatal(CALL_INFO, -1, - "Error : failed to load instruction table for core=%" PRIu32 "\n", id ); - - // Initialize EcallTable - InitEcallTable(); - if( Ecalls.size() <= 0 ) - output->fatal(CALL_INFO, -1, - "Error: failed to initialize the Ecall Table for core=%" PRIu32 "\n", id ); - - // reset the core - if( !Reset() ) - output->fatal(CALL_INFO, -1, - "Error: failed to reset the core resources for core=%" PRIu32 "\n", id ); -} - -bool RevProc::Halt(){ - if( Halted ) - return false; - Halted = true; - SingleStep = false; - return true; -} - -bool RevProc::Resume(){ - if( Halted ){ - Halted = false; - SingleStep = false; - return true; - } - return false; -} - -bool RevProc::SingleStepHart(){ - if( SingleStep ) - return true; - if( Halted ){ - Halted = false; - SingleStep = true; - return true; - }else{ - // must be halted to single step - return false; - } -} - -void RevProc::SetCoProc(RevCoProc* coproc){ - if(coProc == nullptr){ - coProc = coproc; - }else{ - output->fatal(CALL_INFO, -1, - "CONFIG ERROR: Core %u : Attempting to assign a co-processor when one is already present\n", - id); - } -} - -bool RevProc::EnableExt(RevExt* Ext, bool Opt){ - if( !Ext ) - output->fatal(CALL_INFO, -1, "Error: failed to initialize RISC-V extensions\n"); - - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Enabling extension=%s\n", - id, Ext->GetName().data()); - - // add the extension to our vector of enabled objects - Extensions.push_back(std::unique_ptr(Ext)); - - // retrieve all the target instructions - const std::vector& IT = Ext->GetInstTable(); - - // setup the mapping of InstTable to Ext objects - InstTable.reserve(InstTable.size() + IT.size()); - - for( unsigned i=0; i(Extensions.size()-1, i); - EntryToExt.insert( - std::pair>(InstTable.size()-1, ExtObj)); - } - - // load the compressed instructions - if( feature->IsModeEnabled(RV_C) ){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Enabling compressed extension=%s\n", - id, Ext->GetName().data()); - - std::vector CT = Ext->GetCInstTable(); - InstTable.reserve(InstTable.size() + CT.size()); - - for( unsigned i=0; i ExtObj = - std::pair(Extensions.size()-1, i); - EntryToExt.insert( - std::pair>(InstTable.size()-1, ExtObj)); - } - // load the optional compressed instructions - if( Opt ){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Enabling optional compressed extension=%s\n", - id, Ext->GetName().data()); - CT = Ext->GetOInstTable(); - - InstTable.reserve(InstTable.size() + CT.size()); - - for( unsigned i=0; i ExtObj = - std::pair(Extensions.size()-1, i); - EntryToExt.insert( - std::pair>(InstTable.size()-1, ExtObj)); - } - } - } - - return true; -} - -bool RevProc::SeedInstTable(){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Seeding instruction table for machine model=%s\n", - id, feature->GetMachineModel().data()); - - // I-Extension - if( feature->IsModeEnabled(RV_I) ){ - if( feature->IsRV64() ){ - // load RV32I & RV64; no optional compressed - EnableExt(new RV32I(feature, mem, output), false); - EnableExt(new RV64I(feature, mem, output), false); - }else{ - // load RV32I w/ optional compressed - EnableExt(new RV32I(feature, mem, output), true); - } - } - - // M-Extension - if( feature->IsModeEnabled(RV_M) ){ - EnableExt(new RV32M(feature, mem, output), false); - if( feature->IsRV64() ){ - EnableExt(new RV64M(feature, mem, output), false); - } - } - - // A-Extension - if( feature->IsModeEnabled(RV_A) ){ - EnableExt(new RV32A(feature, mem, output), false); - if( feature->IsRV64() ){ - EnableExt(new RV64A(feature, mem, output), false); - } - } - - // F-Extension - if( feature->IsModeEnabled(RV_F) ){ - if( !feature->IsModeEnabled(RV_D) && feature->IsRV32() ){ - EnableExt(new RV32F(feature, mem, output), true); - }else{ - EnableExt(new RV32F(feature, mem, output), false); - EnableExt(new RV64F(feature, mem, output), false); - - } - } - - // D-Extension - if( feature->IsModeEnabled(RV_D) ){ - EnableExt(new RV32D(feature, mem, output), false); - if( feature->IsRV64() ){ - EnableExt(new RV64D(feature, mem, output), false); - } - } - - // Zicbom-Extension - if( feature->IsModeEnabled(RV_ZICBOM) ){ - EnableExt(new Zicbom(feature, mem, output), false); - } - - return true; -} - -uint32_t RevProc::CompressCEncoding(RevInstEntry Entry){ - uint32_t Value = 0x00; - - Value |= Entry.opcode; - Value |= uint32_t(Entry.funct2) << 2; - Value |= uint32_t(Entry.funct3) << 4; - Value |= uint32_t(Entry.funct4) << 8; - Value |= uint32_t(Entry.funct6) << 12; - - return Value; -} - -uint32_t RevProc::CompressEncoding(RevInstEntry Entry){ - uint32_t Value = 0x00; - - Value |= Entry.opcode; - Value |= uint32_t(Entry.funct3) << 8; - Value |= uint32_t(Entry.funct2or7)<< 11; - Value |= uint32_t(Entry.imm12) << 18; - Value |= uint32_t(Entry.fpcvtOp) << 30; //this is a 5 bit field, but only the lower two bits are used, so it *just* fits - //without going to a uint64 - - return Value; -} - -void RevProc::splitStr(const std::string& s, - char c, - std::vector& v){ - std::string::size_type i = 0; - std::string::size_type j = s.find(c); - - // catch strings with no delims - if( j == std::string::npos ){ - v.push_back(s); - } - - // break up the rest of the string - while (j != std::string::npos) { - v.push_back(s.substr(i, j-i)); - i = ++j; - j = s.find(c, j); - if (j == std::string::npos) - v.push_back(s.substr(i, s.length())); - } -} - -std::string RevProc::ExtractMnemonic(RevInstEntry Entry){ - std::string Tmp = Entry.mnemonic; - std::vector vstr; - splitStr(Tmp, ' ', vstr); - - return vstr[0]; -} - -bool RevProc::InitTableMapping(){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Initializing table mapping for machine model=%s\n", - id, feature->GetMachineModel().data()); - - for( unsigned i=0; i(ExtractMnemonic(InstTable[i]), i) ); - if( !InstTable[i].compressed ){ - // map normal instruction - EncToEntry.insert( - std::pair(CompressEncoding(InstTable[i]), i) ); - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Table Entry %" PRIu32 " = %s\n", - id, - CompressEncoding(InstTable[i]), - ExtractMnemonic(InstTable[i]).data() ); - }else{ - // map compressed instruction - CEncToEntry.insert( - std::pair(CompressCEncoding(InstTable[i]), i) ); - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Compressed Table Entry %" PRIu32 " = %s\n", - id, - CompressCEncoding(InstTable[i]), - ExtractMnemonic(InstTable[i]).data() ); - } - } - return true; -} - -bool RevProc::ReadOverrideTables(){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 " ; Reading override tables for machine model=%s\n", - id, feature->GetMachineModel().data()); - - std::string Table; - if( !opts->GetInstTable(id, Table) ) - return false; - - // if the length of the file name is 0, just return - if( Table == "_REV_INTERNAL_" ) - return true; - - // open the file - std::ifstream infile(Table); - if( !infile.is_open() ) - output->fatal(CALL_INFO, -1, "Error: failed to read instruction table for core=%" PRIu32 "\n", id); - - // read all the values - std::string Inst; - std::string Cost; - unsigned Entry; - std::map::iterator it; - while( infile >> Inst >> Cost ){ - it = NameToEntry.find(Inst); - if( it == NameToEntry.end() ) - output->fatal(CALL_INFO, -1, "Error: could not find instruction in table for map value=%s\n", Inst.data() ); - - Entry = it->second; - InstTable[Entry].cost = (unsigned)(std::stoi(Cost, nullptr, 0)); - } - - // close the file - infile.close(); - - return true; -} - -bool RevProc::LoadInstructionTable(){ - // Stage 1: load the instruction table for each enable feature - if( !SeedInstTable() ) - return false; - - // Stage 2: setup the internal mapping tables for performance - if( !InitTableMapping() ) - return false; - - // Stage 3: examine the user-defined cost tables to see if we need to override the defaults - if( !ReadOverrideTables() ) - return false; - - return true; -} - -bool RevProc::Reset(){ - - IdleHarts.reset(); - - // All harts are idle to start - for(unsigned i=0; i>7); - - if((CompInst.opcode == 0b10) && - (CompInst.funct3 == 0b001)){ - // c.fldsp - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1100000) >> 2); // [4:3] - CompInst.imm |= ((Inst & 0b1000000000000) >> 7); // [5] - CompInst.imm |= ((Inst & 0b11100) << 4); // [8:6] - CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) - }else if( (CompInst.opcode == 0b10) && - (CompInst.funct3 == 0b010) ){ - // c.lwsp - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1110000) >> 2); // [4:2] - CompInst.imm |= ((Inst & 0b1000000000000) >> 7); // [5] - CompInst.imm |= ((Inst & 1100) << 4); // [7:6] - CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) - }else if( (CompInst.opcode == 0b10) && - (CompInst.funct3 == 0b011) ){ - CompInst.imm = 0; - if( feature->IsRV64() ){ - // c.ldsp - CompInst.imm = ((Inst & 0b1100000) >> 2); // [4:3] - CompInst.imm |= ((Inst & 0b1000000000000) >> 7); // [5] - CompInst.imm |= ((Inst & 0b11100) << 4); // [8:6] - CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) - }else{ - // c.flwsp - CompInst.imm = ((Inst & 0b1110000) >> 2); // [4:2] - CompInst.imm |= ((Inst & 0b1000000000000) >> 7); // [5] - CompInst.imm |= ((Inst & 1100) << 4); // [7:6] - CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) - } - }else if( (CompInst.opcode == 0b01) && - (CompInst.funct3 == 0b011) && - (CompInst.rd == 2)){ - // c.addi16sp - // swizzle: nzimm[4|6|8:7|5] nzimm[9] - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1000000) >> 2); // bit 4 - CompInst.imm |= ((Inst & 0b100) << 3); // bit 5 - CompInst.imm |= ((Inst & 0b100000) << 1); // bit 6 - CompInst.imm |= ((Inst & 0b11000) << 4); // bit 8:7 - CompInst.imm |= ((Inst & 0b1000000000000) >> 3); // bit 9 - CompInst.rs1 = 2; // Force rs1 to be x2 (stack pointer) - if( (CompInst.imm & 0b1000000000) > 0 ){ - // sign extend - CompInst.imm |= 0b11111111111111111111111000000000; - } - }else if( (CompInst.opcode == 0b01) && - (CompInst.funct3 == 0b011) && - (CompInst.rd != 0) && (CompInst.rd != 2) ){ - // c.lui - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1111100) << 10); // [16:12] - CompInst.imm |= ((Inst & 0b1000000000000) << 5); // [17] - if( (CompInst.imm & 0b100000000000000000) > 0 ){ - // sign extend - CompInst.imm |= 0b11111111111111000000000000000000; - } - CompInst.imm >>= 12; //immd value will be re-aligned on execution - }else if( (CompInst.opcode == 0b01) && - (CompInst.funct3 == 0b010) && - (CompInst.rd != 0) ){ - // c.li - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1111100) >> 2); // [4:0] - CompInst.imm |= ((Inst & 0b1000000000000) >> 7); // [5] - CompInst.rs1 = 0; // Force rs1 to be x0, expands to add rd, x0, imm - if( (CompInst.imm & 0b100000) > 0 ){ - // sign extend - CompInst.imm |= 0b11111111111111111111111111000000; - } - }else if( (CompInst.imm & 0b100000) > 0 ){ - // sign extend - CompInst.imm |= 0b11111111111111111111111111100000; - } - - //if c.addi, expands to addi %rd, %rd, $imm so set rs1 to rd -or- - // c.slli, expands to slli %rd %rd $imm -or - - // c.addiw. expands to addiw %rd %rd $imm - if(((0b01 == CompInst.opcode) && (0b000 == CompInst.funct3)) || - ((0b10 == CompInst.opcode) && (0b000 == CompInst.funct3)) || - ((0b01 == CompInst.opcode) && (0b001 == CompInst.funct3))) { - CompInst.rs1 = CompInst.rd; - } - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCSSInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - CompInst.rs2 = DECODE_LOWER_CRS2(Inst); - CompInst.imm = ((Inst & 0b1111110000000) >> 7); - - if( CompInst.funct3 == 0b101 ){ - // c.fsdsp - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1110000000000) >> 7); // [5:3] - CompInst.imm |= ((Inst & 0b1110000000) >> 1); // [8:6] - CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) - }else if( CompInst.funct3 == 0b110 ){ - // c.swsp - CompInst.imm = 0; - CompInst.imm = ((Inst & 0b1111000000000) >> 7); // [5:2] - CompInst.imm |= ((Inst & 0b110000000) >> 1); // [7:6] - CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) - }else if( CompInst.funct3 == 0b111 ){ - CompInst.imm = 0; - if( feature->IsRV64() ){ - // c.sdsp - CompInst.imm = ((Inst & 0b1110000000000) >> 7); // [5:3] - CompInst.imm |= ((Inst & 0b1110000000) >> 1); // [8:6] - CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) - }else{ - // c.fswsp - CompInst.imm = ((Inst & 0b1111000000000) >> 7); // [5:2] - CompInst.imm |= ((Inst & 0b110000000) >> 1); // [7:6] - CompInst.rs1 = 2; // Force rs1 to x2 (stack pointer) - } - } - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCIWInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - CompInst.rd = ((Inst & 0b11100) >> 2); - CompInst.imm = ((Inst & 0b1111111100000) >> 5); - - // Apply compressed offset - CompInst.rd = CRegIdx(CompInst.rd); - - //Set rs1 to x2 if this is an addi4spn - if((0x00 == CompInst.opcode) && (0x00 == CompInst.funct3) ){ - CompInst.rs1 = 2; - } - - - //swizzle: nzuimm[5:4|9:6|2|3] - std::bitset<32> imm(CompInst.imm); - std::bitset<32> tmp(0); - tmp[0] = imm[1]; - tmp[1] = imm[0]; - tmp[2] = imm[6]; - tmp[3] = imm[7]; - tmp[4] = imm[2]; - tmp[5] = imm[3]; - tmp[6] = imm[4]; - tmp[7] = imm[5]; - - CompInst.imm = tmp.to_ulong(); - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCLInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - CompInst.rd = ((Inst & 0b11100) >> 2); - CompInst.rs1 = ((Inst & 0b1110000000) >> 7); - - //Apply compressed offset - CompInst.rd = CRegIdx(CompInst.rd); - CompInst.rs1 = CRegIdx(CompInst.rs1); - - if( CompInst.funct3 == 0b001 ){ - // c.fld - CompInst.imm = ((Inst & 0b1100000) << 1); // [7:6] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else if( CompInst.funct3 == 0b010 ){ - // c.lw - CompInst.imm = ((Inst & 0b100000) << 1); // [6] - CompInst.imm |= ((Inst & 0b1000000) >> 4); // [2] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else if( CompInst.funct3 == 0b011 ){ - if( feature->IsRV64() ){ - // c.ld - CompInst.imm = ((Inst & 0b1100000) << 1); // [7:6] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else{ - // c.flw - CompInst.imm = ((Inst & 0b100000) << 1); // [6] - CompInst.imm |= ((Inst & 0b1000000) >> 4); // [2] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - } - }else if( CompInst.funct3 == 0b101 ){ - // c.fsd - CompInst.imm = ((Inst & 0b1100000) << 1); // [7:6] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else if( CompInst.funct3 == 0b110 ){ - // c.sw - CompInst.imm = ((Inst & 0b100000) << 1); // [6] - CompInst.imm |= ((Inst & 0b1000000) >> 4); // [2] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else if( CompInst.funct3 == 0b111 ){ - if( feature->IsRV64() ){ - // c.sd - CompInst.imm = ((Inst & 0b1100000) << 1); // [7:6] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - }else{ - // c.fsw - CompInst.imm = ((Inst & 0b100000) << 1); // [6] - CompInst.imm |= ((Inst & 0b1000000) >> 4); // [2] - CompInst.imm |= ((Inst & 0b1110000000000) >> 7); // [5:3] - } - } - - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCSInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - CompInst.rs2 = ((Inst & 0b011100) >> 2); - CompInst.rs1 = ((Inst & 0b01110000000) >> 7); - - //Apply Compressed offset - CompInst.rs2 = CRegIdx(CompInst.rs2); - CompInst.rs1 = CRegIdx(CompInst.rs1); - - // The immd is pre-scaled in this instruction format - if(CompInst.funct3 == 0b110){ - //c.sw - CompInst.imm = ((Inst & 0b0100000) << 1); //offset[6] - CompInst.imm |= ((Inst & 0b01110000000000) >> 6); //offset[5:3] - CompInst.imm |= ((Inst & 0b01000000) >> 4); //offset[2] - }else{ - if( feature->IsRV32() ){ - //c.fsw - CompInst.imm = ((Inst & 0b00100000) << 1); //imm[6] - CompInst.imm = ((Inst & 0b01000000) << 4); //imm[2] - CompInst.imm |= ((Inst & 0b01110000000000) >> 7); //imm[5:3] - }else{ - //c.sd - CompInst.imm = ((Inst & 0b01100000) << 1); //imm[7:6] - CompInst.imm |= ((Inst & 0b01110000000000) >> 7); //imm[5:3] - } - } - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCAInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct2 = InstTable[Entry].funct2; - CompInst.funct6 = InstTable[Entry].funct6; - - // registers - CompInst.rs2 = ((Inst & 0b11100) >> 2); - CompInst.rd = CompInst.rs1 = ((Inst & 0b1110000000) >> 7); - - //Adjust registers for compressed offset - CompInst.rs2 = CRegIdx(CompInst.rs2); - CompInst.rs1 = CRegIdx(CompInst.rs1); - CompInst.rd = CRegIdx(CompInst.rd); - - //All instructions of this format expand to rd rd rs2, so set rs1 to rd - CompInst.rs1 = CompInst.rd; - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCBInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - CompInst.rd = CompInst.rs1 = ((Inst & 0b1110000000) >> 7); - CompInst.offset = ((Inst & 0b1111100) >> 2); - CompInst.offset |= ((Inst & 0b1110000000000) >> 5); - - //Apply compressed offset - CompInst.rs1 = CRegIdx(CompInst.rs1); - - //Set rs2 to x0 if c.beqz or c.bnez - if((0b01 == CompInst.opcode) && ((0b110 == CompInst.funct3) || (0b111 == CompInst.funct3))){ - CompInst.rs2 = 0; - } - - //If c.srli, c.srai or c.andi set rd to rs1 - if((0b01 == CompInst.opcode) && (0b100 == CompInst.funct3)){ - CompInst.rd = CompInst.rs1; - } - - //swizzle: offset[8|4:3] offset[7:6|2:1|5] - std::bitset<16> tmp(0); - // handle c.beqz/c.bnez offset - if( (CompInst.opcode == 0b01) && (CompInst.funct3 >= 0b110) ){ - std::bitset<16> o(CompInst.offset); - tmp[0] = o[1]; - tmp[1] = o[2]; - tmp[2] = o[5]; - tmp[3] = o[6]; - tmp[4] = o[0]; - tmp[5] = o[3]; - tmp[6] = o[4]; - tmp[7] = o[7]; - } else if( (CompInst.opcode == 0b01) && (CompInst.funct3 == 0b100)) { - //We have a shift or a andi - CompInst.rd = CompInst.rs1; //Already has compressed offset applied - } - - CompInst.offset = ((uint16_t)tmp.to_ulong()) << 1; // scale to corrrect position to be consistent with other compressed ops - CompInst.imm = ((Inst & 0b01111100) >> 2); - CompInst.imm |= ((Inst & 0b01000000000000) >> 7); - - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCJInst(uint16_t Inst, unsigned Entry) const { - RevInst CompInst; - - // cost - CompInst.cost = InstTable[Entry].cost; - - // encodings - CompInst.opcode = InstTable[Entry].opcode; - CompInst.funct3 = InstTable[Entry].funct3; - - // registers - uint16_t offset = ((Inst & 0b1111111111100) >> 2); - - //swizzle bits offset[11|4|9:8|10|6|7|3:1|5] - std::bitset<16> offsetBits(offset); - std::bitset<16> target; - target.reset(); - target[0] = offsetBits[1]; - target[1] = offsetBits[2]; - target[2] = offsetBits[3]; - target[3] = offsetBits[9]; - target[4] = offsetBits[0]; - target[5] = offsetBits[5]; - target[6] = offsetBits[4]; - target[7] = offsetBits[7]; - target[8] = offsetBits[8]; - target[9] = offsetBits[6]; - target[10] = offsetBits[10]; - CompInst.jumpTarget = ((u_int16_t)target.to_ulong()) << 1; - //CompInst.jumpTarget = ((u_int16_t)target.to_ulong()); - - //Set rd to x1 if this is a c.jal - if((0b01 == CompInst.opcode) && (0b001 == CompInst.funct3)){ - CompInst.rd = 1; - } - CompInst.instSize = 2; - CompInst.compressed = true; - - return CompInst; -} - -RevInst RevProc::DecodeCompressed(uint32_t Inst) const { - uint16_t TmpInst = (uint16_t)(Inst&0b1111111111111111); - uint8_t opc = 0; - uint8_t funct2 = 0; - uint8_t funct3 = 0; - uint8_t funct4 = 0; - uint8_t funct6 = 0; - uint8_t l3 = 0; - uint32_t Enc = 0x00ul; - - if( !feature->HasCompressed() ){ - output->fatal(CALL_INFO, -1, - "Error: failed to decode instruction at PC=0x%" PRIx64 "; Compressed instructions not enabled!\n", - GetPC()); - } - - // decode the opcode - opc = (TmpInst & 0b11); - l3 = ((TmpInst & 0b1110000000000000)>>13); - if( opc == 0b00 ){ - // quadrant 0 - funct3 = l3; - }else if( opc == 0b01){ - // quadrant 1 - if( l3 <= 0b011 ){ - // upper portion: misc - funct3 = l3; - }else if( (l3 > 0b011) && (l3 < 0b101) ){ - // middle portion: arithmetics - uint8_t opSelect = ((TmpInst & 0b110000000000) >> 10); - if( opSelect == 0b11 ){ - funct6 = ((TmpInst & 0b1111110000000000) >> 10); - funct2 = ((TmpInst & 0b01100000) >> 5 ); - }else{ - funct3 = l3; - funct2 = opSelect; - } - }else{ - // lower power: jumps/branches - funct3 = l3; - } - }else if( opc == 0b10){ - // quadrant 2 - if( l3 == 0b000 ){ - // slli{64} - funct3 = l3; - }else if( l3 < 0b100 ){ - // float/double/quad load - funct3 = l3; - }else if( l3 == 0b100 ){ - // jump, mv, break, add - funct4 = ((TmpInst & 0b1111000000000000) >> 12); - }else{ - // float/double/quad store - funct3 = l3; - } - } - - Enc |= (uint32_t)(opc); - Enc |= (uint32_t)(funct2 << 2); - Enc |= (uint32_t)(funct3 << 4); - Enc |= (uint32_t)(funct4 << 8); - Enc |= (uint32_t)(funct6 << 12); - - bool isCoProcInst = false; - - auto it = CEncToEntry.find(Enc); - if( it == CEncToEntry.end() ){ - if( coProc && coProc->IssueInst(feature, RegFile, mem, Inst) ){ - isCoProcInst = true; - //Create NOP - ADDI x0, x0, 0 - uint8_t caddi_op= 0b01; - Inst = 0; - Enc = 0; - Enc |= caddi_op; - it = CEncToEntry.find(Enc); - } - } - - if( it == CEncToEntry.end() ){ - output->fatal(CALL_INFO, -1, - "Error: failed to decode instruction at PC=0x%" PRIx64 "; Enc=%" PRIu32 "\n opc=%x; funct2=%x, funct3=%x, funct4=%x, funct6=%x\n", - GetPC(), Enc, opc, funct2, funct3, funct4, funct6 ); - } - - auto Entry = it->second; - if( Entry >= InstTable.size() ){ - output->fatal(CALL_INFO, -1, - "Error: no entry in table for instruction at PC=0x%" PRIx64 - " Opcode = %x Funct2 = %x Funct3 = %x Funct4 = %x Funct6 = %x Enc = %x \n", - GetPC(), opc, funct2, funct3, funct4, funct6, Enc ); - } - - RevInst ret{}; - - switch( InstTable[Entry].format ){ - case RVCTypeCR: - ret = DecodeCRInst(TmpInst, Entry); - break; - case RVCTypeCI: - ret = DecodeCIInst(TmpInst, Entry); - break; - case RVCTypeCSS: - ret = DecodeCSSInst(TmpInst, Entry); - break; - case RVCTypeCIW: - ret = DecodeCIWInst(TmpInst, Entry); - break; - case RVCTypeCL: - ret = DecodeCLInst(TmpInst, Entry); - break; - case RVCTypeCS: - ret = DecodeCSInst(TmpInst, Entry); - break; - case RVCTypeCA: - ret = DecodeCAInst(TmpInst, Entry); - break; - case RVCTypeCB: - ret = DecodeCBInst(TmpInst, Entry); - break; - case RVCTypeCJ: - ret = DecodeCJInst(TmpInst, Entry); - break; - default: - output->fatal(CALL_INFO, -1, - "Error: failed to decode instruction format at PC=%" PRIx64 ".", GetPC() ); - } - - ret.entry = Entry; - ret.isCoProcInst = isCoProcInst; - return ret; -} - -RevInst RevProc::DecodeRInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = InstTable[Entry].funct2or7; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ){ - DInst.rd = DECODE_RD(Inst); - } - if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ){ - DInst.rs1 = DECODE_RS1(Inst); - } - if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ){ - DInst.rs2 = DECODE_RS2(Inst); - } - - // imm - if( (InstTable[Entry].imm == FImm) && (InstTable[Entry].rs2Class == RevRegClass::RegUNKNOWN)){ - DInst.imm = DECODE_IMM12(Inst) & 0b011111; - }else{ - DInst.imm = 0x0; - } - - // Size - DInst.instSize = 4; - - // Decode the atomic RL/AQ fields - if( DInst.opcode == 0b0101111 ){ - DInst.rl = DECODE_RL(Inst); - DInst.aq = DECODE_AQ(Inst); - } - - // Decode any ancillary SP/DP float options - if( IsFloat(Entry) ){ - DInst.rm = DECODE_RM(Inst); - } - - DInst.compressed = false; - - return DInst; -} - -RevInst RevProc::DecodeIInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = 0x0; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ){ - DInst.rd = DECODE_RD(Inst); - } - if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ){ - DInst.rs1 = DECODE_RS1(Inst); - } - - // imm - DInst.imm = DECODE_IMM12(Inst); - - // Size - DInst.instSize = 4; - - // Decode any ancillary SP/DP float options - if( IsFloat(Entry) ){ - DInst.rm = DECODE_RM(Inst); - } - DInst.compressed = false; - - return DInst; -} - -RevInst RevProc::DecodeSInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = 0x0; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ){ - DInst.rs1 = DECODE_RS1(Inst); - } - if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ){ - DInst.rs2 = DECODE_RS2(Inst); - } - - // imm - DInst.imm = (DECODE_RD(Inst) | (DECODE_FUNCT7(Inst)<<5)); - - // Size - DInst.instSize = 4; - - // Decode any ancillary SP/DP float options - if( IsFloat(Entry) ){ - DInst.rm = DECODE_RM(Inst); - } - - DInst.compressed = false; - return DInst; -} - -RevInst RevProc::DecodeUInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = 0x0; - DInst.funct2or7 = 0x0; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ){ - DInst.rd = DECODE_RD(Inst); - } - - // imm - DInst.imm = DECODE_IMM20(Inst); - - // Size - DInst.instSize = 4; - - DInst.compressed = false; - return DInst; -} - -RevInst RevProc::DecodeBInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = 0x0; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ){ - DInst.rs1 = DECODE_RS1(Inst); - } - if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ){ - DInst.rs2 = DECODE_RS2(Inst); - } - - // imm - DInst.imm = - ( (Inst >> 19) & 0b1000000000000 ) | // [12] - ( (Inst << 4) & 0b100000000000 ) | // [11] - ( (Inst >> 20) & 0b11111100000 ) | // [10:5] - ( (Inst >> 7) & 0b11110 ) ; // [4:1] - - // Size - DInst.instSize = 4; - - DInst.compressed = false; - return DInst; -} - -RevInst RevProc::DecodeJInst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = 0x0; - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ){ - DInst.rd = DECODE_RD(Inst); - } - - // immA - DInst.imm = - ( (Inst >> 11) & 0b100000000000000000000 ) | // imm[20] - ( (Inst) & 0b11111111000000000000 ) | // imm[19:12] - ( (Inst >> 9) & 0b100000000000 ) | // imm[11] - ( (Inst >> 20) & 0b11111111110 ) ; // imm[10:1] - - // Size - DInst.instSize = 4; - - DInst.compressed = false; - return DInst; -} - -RevInst RevProc::DecodeR4Inst(uint32_t Inst, unsigned Entry) const { - RevInst DInst; - - // cost - DInst.cost = InstTable[Entry].cost; - - // encodings - DInst.opcode = InstTable[Entry].opcode; - DInst.funct3 = InstTable[Entry].funct3; - DInst.funct2or7 = DECODE_FUNCT2(Inst); - - // registers - DInst.rd = 0x0; - DInst.rs1 = 0x0; - DInst.rs2 = 0x0; - DInst.rs3 = 0x0; - - if( InstTable[Entry].rdClass != RevRegClass::RegUNKNOWN ){ - DInst.rd = DECODE_RD(Inst); - } - if( InstTable[Entry].rs1Class != RevRegClass::RegUNKNOWN ){ - DInst.rs1 = DECODE_RS1(Inst); - } - if( InstTable[Entry].rs2Class != RevRegClass::RegUNKNOWN ){ - DInst.rs2 = DECODE_RS2(Inst); - } - if( InstTable[Entry].rs3Class != RevRegClass::RegUNKNOWN ){ - DInst.rs3 = DECODE_RS3(Inst); - } - - // imm - DInst.imm = 0x0; - - // Size - DInst.instSize = 4; - - DInst.compressed = false; - return DInst; -} - -bool RevProc::DebugReadReg(unsigned Idx, uint64_t *Value) const { - if( !Halted ) - return false; - if( Idx >= _REV_NUM_REGS_ ){ - return false; - } - RevRegFile* regFile = GetRegFile(HartToExecID); - *Value = regFile->GetX(Idx); - return true; -} - -bool RevProc::DebugWriteReg(unsigned Idx, uint64_t Value) const { - RevRegFile* regFile = GetRegFile(HartToExecID); - if( !Halted ) - return false; - if( Idx >= _REV_NUM_REGS_ ){ - return false; - } - regFile->SetX(Idx, Value); - return true; -} - -bool RevProc::PrefetchInst(){ - uint64_t PC =Harts[HartToDecodeID]->RegFile->GetPC(); - - // These are addresses that we can't decode - // Return false back to the main program loop - if( PC == 0x00ull ){ - return false; - } - - return sfetch->IsAvail(PC); -} - -RevInst RevProc::FetchAndDecodeInst(){ - uint32_t Inst = 0x00ul; - uint64_t PC = GetPC(); - bool Fetched = false; - - // Stage 1: Retrieve the instruction - if( !sfetch->InstFetch(PC, Fetched, Inst) ){ - output->fatal(CALL_INFO, -1, - "Error: failed to retrieve prefetched instruction at PC=0x%" PRIx64 "\n", - PC); - } - - if(0 != Inst){ - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; PC:InstPayload = 0x%" PRIx64 ":0x%" PRIx32 "\n", - id, HartToDecodeID, ActiveThreadID, PC, Inst); - }else{ - output->fatal(CALL_INFO, -1, - "Error: Core %" PRIu32 " failed to decode instruction at PC=0x%" PRIx64 "; Inst=%" PRIu32 "\n", - id, - PC, - Inst ); - } - - // Trace capture fetched instruction - if (Tracer) Tracer->SetFetchedInsn(PC, Inst); - - // Stage 1a: handle the crack fault injection - if( CrackFault ){ - uint64_t rval = RevRand(0, (uint32_t{1} << fault_width) - 1); - Inst |= rval; - - // clear the fault - CrackFault = false; - } - - // Decode the instruction - RevInst DInst = DecodeInst(Inst); - - // Set RegFile Entry and cost, and clear trigger - RegFile->SetEntry(DInst.entry); - RegFile->SetCost(DInst.cost); - RegFile->SetTrigger(false); - - // Return decoded instruction - return DInst; -} - -// Decode the instruction -// This function is pure, with no side effects or dependencies -// on non-constant outside variables. This make it memoizable, -// but right now, there isn't enough benefit for memoization. -RevInst RevProc::DecodeInst(uint32_t Inst) const { - if( ~Inst & 0b11 ){ - // this is a compressed instruction - return DecodeCompressed(Inst); - } - - // Stage 2: Retrieve the opcode - const uint32_t Opcode = Inst & 0b1111111; - uint32_t Enc = 0; - - // Stage 3: Determine if we have a funct3 field - uint32_t Funct3 = 0x00ul; - const uint32_t inst42 = Opcode >> 2 & 0b111; - const uint32_t inst65 = Opcode >> 5 & 0b11; - - if( (inst42 == 0b011) && (inst65 == 0b11) ){ - // JAL - Funct3 = 0x00ul; - }else if( (inst42 == 0b101) && (inst65 == 0b00) ){ - // AUIPC - Funct3 = 0x00ul; - }else if( (inst42 == 0b101) && (inst65 == 0b01) ){ - // LUI - Funct3 = 0x00ul; - }else{ - // Retrieve the field - Funct3 = ((Inst&0b111000000000000) >> 12 ); - } - - // Stage 4: Determine if we have a funct7 field (R-Type and some specific I-Type) - uint32_t Funct2or7 = 0x00ul; - if( inst65 == 0b01 ) { - if( (inst42 == 0b011) || (inst42 == 0b100) || (inst42 == 0b110) ){ - // R-Type encodings - Funct2or7 = ((Inst >> 25) & 0b1111111); - //Atomics have a smaller funct7 field - trim out the aq and rl fields - if(Opcode == 0b0101111){ - Funct2or7 = (Funct2or7 &0b01111100) >> 2; - } - } - }else if((inst65== 0b10) && (inst42 < 0b100)){ - // R4-Type encodings -- we store the Funct2 precision field in Funct2or7 - Funct2or7 = DECODE_FUNCT2(Inst); - }else if((inst65== 0b10) && (inst42 == 0b100)){ - // R-Type encodings - Funct2or7 = ((Inst >> 25) & 0b1111111); - }else if((inst65 == 0b00) && (inst42 == 0b110) && (Funct3 != 0)){ - // R-Type encodings - Funct2or7 = ((Inst >> 25) & 0b1111111); - }else if((inst65 == 0b00) && (inst42 == 0b100) && (Funct3 == 0b101)){ - // Special I-Type encoding for SRAI - also, Funct7 is only 6 bits in this case - Funct2or7 = ((Inst >> 26) & 0b1111111); - } - - uint32_t fcvtOp = 0; - //Special encodings for FCVT instructions - if( Opcode == 0b1010011 ){ - switch(Funct2or7){ - case 0b1100000: - case 0b1101000: - case 0b0100000: - case 0b0100001: - case 0b1100001: - case 0b1101001: - fcvtOp = DECODE_RS2(Inst); - } - } - - // Stage 5: Determine if we have an imm12 field - uint32_t Imm12 = 0x00ul; - if( (inst42 == 0b100) && (inst65 == 0b11) && (Funct3 == 0)){ - Imm12 = ((Inst >> 19) & 0b111111111111); - } - - // Stage 6: Compress the encoding - Enc |= Opcode; - Enc |= Funct3<<8; - Enc |= Funct2or7<<11; - Enc |= Imm12<<18; - Enc |= fcvtOp<<30; - - // Stage 7: Look up the value in the table - auto it = EncToEntry.find(Enc); - - // This is kind of a hack, but we may not have found the instruction because - // Funct3 is overloaded with rounding mode, so if this is a RV32F or RV64F - // set Funct3 to zero and check again. We exclude if Funct3 == 0b101 || - // Funct3 == 0b110 because those are invalid FP rounding mode (rm) values. - if( inst65 == 0b10 && Funct3 != 0b101 && Funct3 != 0b110 && it == EncToEntry.end() ){ - Enc &= 0xfffff8ff; - it = EncToEntry.find(Enc); - } - - bool isCoProcInst = false; - - // If we did not find a valid instruction, look for a coprocessor instruction - if( it == EncToEntry.end() && coProc && coProc->IssueInst(feature, RegFile, mem, Inst) ){ - isCoProcInst = true; - //Create NOP - ADDI x0, x0, 0 - uint32_t addi_op = 0b0010011; - Inst = 0; - Enc = 0; - Enc |= addi_op; - it = EncToEntry.find(Enc); - } - - if( it == EncToEntry.end() ){ - // failed to decode the instruction - output->fatal(CALL_INFO, -1, - "Error: failed to decode instruction at PC=0x%" PRIx64 - "; Enc=%" PRIu32 "\n", GetPC(), Enc ); - } - - unsigned Entry = it->second; - if( Entry >= InstTable.size() ){ - if(coProc && coProc->IssueInst(feature, RegFile, mem, Inst)){ - isCoProcInst = true; - //Create NOP - ADDI x0, x0, 0 - uint32_t addi_op = 0b0010011; - Inst = 0; - Enc = 0; - Enc |= addi_op; - it = EncToEntry.find(Enc); - Entry = it->second; - } - } - - if ( Entry >= InstTable.size() ){ - output->fatal(CALL_INFO, -1, - "Error: no entry in table for instruction at PC=0x%" PRIx64 - " Opcode = %x Funct3 = %x Funct2or7 = %x Imm12 = %x Enc = %x \n", - GetPC(), Opcode, Funct3, Funct2or7, Imm12, Enc ); - } - - // Stage 8: Do a full deocode using the target format - RevInst ret{}; - switch( InstTable[Entry].format ){ - case RVTypeR: - ret = DecodeRInst(Inst, Entry); - break; - case RVTypeI: - ret = DecodeIInst(Inst, Entry); - break; - case RVTypeS: - ret = DecodeSInst(Inst, Entry); - break; - case RVTypeU: - ret = DecodeUInst(Inst, Entry); - break; - case RVTypeB: - ret = DecodeBInst(Inst, Entry); - break; - case RVTypeJ: - ret = DecodeJInst(Inst, Entry); - break; - case RVTypeR4: - ret = DecodeR4Inst(Inst, Entry); - break; - default: - output->fatal(CALL_INFO, -1, - "Error: failed to decode instruction format at PC=%" PRIx64 ".", - GetPC() ); - } - - ret.entry = Entry; - ret.isCoProcInst = isCoProcInst; - return ret; -} - -void RevProc::HandleRegFault(unsigned width){ - const char* RegPrefix; - RevRegFile* regFile = GetRegFile(HartToExecID); - - // select a register - unsigned RegIdx = RevRand(0, _REV_NUM_REGS_ - 1); - - if(!feature->HasF() || RevRand(0, 1)){ - // X registers - if( feature->IsRV32() ){ - regFile->RV32[RegIdx] |= RevRand(0, ~(~uint32_t{0} << width)); - }else{ - regFile->RV64[RegIdx] |= RevRand(0, ~(~uint64_t{0} << width)); - } - RegPrefix = "x"; - }else{ - // F registers - if( feature->HasD() ){ - uint64_t tmp; - memcpy(&tmp, ®File->DPF[RegIdx], sizeof(tmp)); - tmp |= RevRand(0, ~(~uint32_t{0} << width)); - memcpy(®File->DPF[RegIdx], &tmp, sizeof(tmp)); - }else{ - uint32_t tmp; - memcpy(&tmp, ®File->SPF[RegIdx], sizeof(tmp)); - tmp |= RevRand(0, ~(~uint64_t{0} << width)); - memcpy(®File->SPF[RegIdx], &tmp, sizeof(tmp)); - } - RegPrefix = "f"; - } - - output->verbose(CALL_INFO, 5, 0, - "FAULT:REG: Register fault of %" PRIu32 " bits into register %s%" PRIu32 "\n", - width, RegPrefix, RegIdx); -} - -void RevProc::HandleCrackFault(unsigned width){ - CrackFault = true; - fault_width = width; - output->verbose(CALL_INFO, 5, 0, - "FAULT:CRACK: Crack+Decode fault injected into next decode cycle\n"); -} - -void RevProc::HandleALUFault(unsigned width){ - ALUFault = true; - fault_width = true; - output->verbose(CALL_INFO, 5, 0, - "FAULT:ALU: ALU fault injected into next retire cycle\n"); -} - -bool RevProc::DependencyCheck(unsigned HartID, const RevInst* I) const { - const RevRegFile* regFile = GetRegFile(HartID); - const RevInstEntry* E = &InstTable[I->entry]; - - return - // check LS queue for outstanding load - LSQCheck(HartID, regFile, I->rs1, E->rs1Class) || - LSQCheck(HartID, regFile, I->rs2, E->rs2Class) || - LSQCheck(HartID, regFile, I->rs3, E->rs3Class) || - LSQCheck(HartID, regFile, I->rd , E->rdClass) || - - // Iterate through the source registers rs1, rs2, rs3 and find any dependency - // based on the class of the source register and the associated scoreboard - ScoreboardCheck(regFile, I->rs1, E->rs1Class) || - ScoreboardCheck(regFile, I->rs2, E->rs2Class) || - ScoreboardCheck(regFile, I->rs3, E->rs3Class); -} - -void RevProc::ExternalStallHart(RevProcPasskey, uint16_t HartID){ - if(HartID < Harts.size()){ - CoProcStallReq.set(HartID); - }else{ - output->fatal(CALL_INFO, -1, - "Core %u ; CoProc Request: Cannot stall Hart %" PRIu32 " as the ID is invalid\n", - id, HartID); - } -} - -void RevProc::ExternalReleaseHart(RevProcPasskey, uint16_t HartID){ - if(HartID < Harts.size()){ - CoProcStallReq.reset(HartID); - }else{ - output->fatal(CALL_INFO, -1, - "Core %u ; CoProc Request: Cannot release Hart %" PRIu32 " as the ID is invalid\n", - id, HartID); - } -} - - - -unsigned RevProc::GetNextHartToDecodeID() const { - if(HartsClearToDecode.none()) { return HartToDecodeID;}; - - unsigned nextID = HartToDecodeID; - if(HartsClearToDecode[HartToDecodeID]){ - nextID = HartToDecodeID; - }else{ - for(size_t tID = 0; tID < Harts.size(); tID++){ - nextID++; - if(nextID >= Harts.size()){ - nextID = 0; - } - if(HartsClearToDecode[nextID]){ break; }; - } - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 "; Hart switch from %" PRIu32 " to %" PRIu32 "\n", - id, HartToDecodeID, nextID); - } - return nextID; -} - -void RevProc::MarkLoadComplete(const MemReq& req){ - - auto it = LSQueue->equal_range(req.LSQHash()); // Find all outstanding dependencies for this register - bool addrMatch = false; - if( it.first != LSQueue->end()){ - for (auto i = it.first; i != it.second; ++i){ // Iterate over all outstanding loads for this reg (if any) - if(i->second.Addr == req.Addr){ - if(LSQueue->count(req.LSQHash()) == 1){ // Only clear the dependency if this is the LAST outstanding load for this register - DependencyClear(i->second.Hart, i->second.DestReg, (i->second.RegType == RevRegClass::RegFLOAT)); - } - sfetch->MarkInstructionLoadComplete(req); - LSQueue->erase(i); // Remove this load from the queue - addrMatch = true; // Flag that there was a succesful match (if left false an error condition occurs) - break; - } - } - }else if(0 != req.DestReg){ //instruction pre-fetch fills target x0, we can ignore these - output->fatal(CALL_INFO, -1, - "Core %" PRIu32 "; Hart %" PRIu32 "; Cannot find outstanding load for reg %" PRIu32 " from address %" PRIx64 "\n", - id, req.Hart, req.DestReg, req.Addr); - } - if(!addrMatch){ - output->fatal(CALL_INFO, -1, - "Core %" PRIu32 "; Hart %" PRIu32 "; Cannot find matching address for outstanding load for reg %" PRIu32 " from address %" PRIx64 "\n", - id, req.Hart, req.DestReg, req.Addr); - - } -} - -bool RevProc::ClockTick( SST::Cycle_t currentCycle ){ - RevInst Inst; - bool rtn = false; - Stats.totalCycles++; - - // -- MAIN PROGRAM LOOP -- - // - // If the clock is down to zero, then fetch the next instruction - // else if the the instruction has not yet been triggered, execute it - // else, wait until the counter is decremented to zero to retire the instruction - - // This function updates the bitset of Harts that are - // ready to decode - UpdateStatusOfHarts(); - - if( HartsClearToDecode.any() && (!Halted)) { - // Determine what hart is ready to decode - HartToDecodeID = GetNextHartToDecodeID(); - ActiveThreadID = Harts.at(HartToDecodeID)->GetAssignedThreadID(); - RegFile = Harts[HartToDecodeID]->RegFile.get(); - - feature->SetHartToExecID(HartToDecodeID); - - // fetch the next instruction - if( !PrefetchInst() ){ - Stalled = true; - Stats.cyclesStalled++; - }else{ - Stalled = false; - } - - if( !Stalled && !CoProcStallReq[HartToDecodeID]){ - Inst = FetchAndDecodeInst(); - Inst.entry = RegFile->GetEntry(); - } - - // Now that we have decoded the instruction, check for pipeline hazards - if(Stalled || DependencyCheck(HartToDecodeID, &Inst) || CoProcStallReq[HartToDecodeID]){ - RegFile->SetCost(0); // We failed dependency check, so set cost to 0 - this will - Stats.cyclesIdle_Pipeline++; // prevent the instruction from advancing to the next stage - HartsClearToExecute[HartToDecodeID] = false; - HartToExecID = _REV_INVALID_HART_ID_; - }else { - Stats.cyclesBusy++; - HartsClearToExecute[HartToDecodeID] = true; - HartToExecID = HartToDecodeID; - } - Inst.cost = RegFile->GetCost(); - Inst.entry = RegFile->GetEntry(); - rtn = true; - ExecPC = RegFile->GetPC(); - } - - if( ( (HartToExecID != _REV_INVALID_HART_ID_) - && !RegFile->GetTrigger()) - && !Halted - && HartsClearToExecute[HartToExecID]) { - // trigger the next instruction - // HartToExecID = HartToDecodeID; - RegFile->SetTrigger(true); - - #ifdef NO_REV_TRACER - // pull the PC - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; Executing PC= 0x%" PRIx64 "\n", - id, HartToExecID, ActiveThreadID, ExecPC); - #endif - - // Find the instruction extension - auto it = EntryToExt.find(RegFile->GetEntry()); - if( it == EntryToExt.end() ){ - // failed to find the extension - output->fatal(CALL_INFO, -1, - "Error: failed to find the instruction extension at PC=%" PRIx64 ".", ExecPC ); - } - - // found the instruction extension - std::pair EToE = it->second; - RevExt *Ext = Extensions[EToE.first].get(); - - // -- BEGIN new pipelining implementation - Pipeline.emplace_back(std::make_pair(HartToExecID, Inst)); - - if( (Ext->GetName() == "RV32F") || - (Ext->GetName() == "RV32D") || - (Ext->GetName() == "RV64F") || - (Ext->GetName() == "RV64D") ){ - Stats.floatsExec++; - } - - // set the hazarding - DependencySet(HartToExecID, &(Pipeline.back().second)); - // -- END new pipelining implementation - - #ifndef NO_REV_TRACER - // Tracer context - mem->SetTracer(Tracer); - RegFile->SetTracer(Tracer); - #endif - - // execute the instruction - if( !Ext->Execute(EToE.second, Pipeline.back().second, HartToExecID, RegFile) ){ - output->fatal(CALL_INFO, -1, - "Error: failed to execute instruction at PC=%" PRIx64 ".", ExecPC ); - } - - #ifndef NO_REV_TRACER - // Clear memory tracer so we don't pick up instruction fetches and other access. - // TODO: method to determine origin of memory access (core, cache, pan, host debugger, ... ) - mem->SetTracer(nullptr); - // Conditionally trace after execution - if (Tracer) Tracer->Exec(currentCycle, id, HartToExecID, ActiveThreadID, InstTable[Inst.entry].mnemonic); - #endif - -#ifdef __REV_DEEP_TRACE__ - if(feature->IsRV32()){ - std::cout << "RDT: Executed PC = " << std::hex << ExecPC - << " Inst: " << std::setw(23) - << InstTable[Inst.entry].mnemonic - << " r" << std::dec << (uint32_t)Inst.rd << "= " - << std::hex << RegFile->RV32[Inst.rd] - << " r" << std::dec << (uint32_t)Inst.rs1 << "= " - << std::hex << RegFile->RV32[Inst.rs1] - << " r" << std::dec << (uint32_t)Inst.rs2 << "= " - << std::hex << RegFile->RV32[Inst.rs2] - << " imm = " << std::hex << Inst.imm - << std::endl; - - }else{ - std::cout << "RDT: Executed PC = " << std::hex << ExecPC \ - << " Inst: " << std::setw(23) - << InstTable[Inst.entry].mnemonic - << " r" << std::dec << (uint32_t)Inst.rd << "= " - << std::hex << RegFile->RV64[Inst.rd] - << " r" << std::dec << (uint32_t)Inst.rs1 << "= " - << std::hex << RegFile->RV64[Inst.rs1] - << " r" << std::dec << (uint32_t)Inst.rs2 << "= " - << std::hex << RegFile->RV64[Inst.rs2] - << " imm = " << std::hex << Inst.imm - << std::endl; - std::cout << "RDT: Address of RD = 0x" << std::hex - << (uint64_t *)(&RegFile->RV64[Inst.rd]) - << std::dec << std::endl; - } -#endif - - /* - * Exception Handling - * - Currently this is only for ecall - */ - if( (RegFile->RV64_SCAUSE == EXCEPTION_CAUSE::ECALL_USER_MODE) || - (RegFile->RV32_SCAUSE == EXCEPTION_CAUSE::ECALL_USER_MODE) ){ - // Ecall found - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 " - Exception Raised: ECALL with code = %" PRIu64 "\n", - id, HartToExecID, ActiveThreadID, RegFile->GetX(RevReg::a7)); -#ifdef _REV_DEBUG_ - // std::cout << "Hart "<< HartToExec << " found ecall with code: " - // << cRegFile->RV64[17] << std::endl; -#endif - - /* Execute system call on this RevProc */ - ExecEcall(Pipeline.back().second); //ExecEcall will also set the exception cause registers - -#ifdef _REV_DEBUG_ - // std::cout << "Hart "<< HartToExec << " returned from ecall with code: " - // << rc << std::endl; -#endif - - // } else { - // ExecEcall(); -#ifdef _REV_DEBUG_ - // std::cout << "Hart "<< HartToExec << " found ecall with code: " - // << code << std::endl; -#endif - -#ifdef _REV_DEBUG_ - // std::cout << "Hart "<< HartToExec << " returned from ecall with code: " - // << rc << std::endl; -#endif - // } - } - - // inject the ALU fault - if( ALUFault ){ InjectALUFault(EToE, Inst); } - - // if this is a singlestep, clear the singlestep and halt - if( SingleStep ){ - SingleStep = false; - Halted = true; - } - - rtn = true; - }else{ - // wait until the counter has been decremented - // note that this will continue to occur until the counter is drained - // and the HART is halted - output->verbose(CALL_INFO, 9, 0, - "Core %" PRIu32 " ; No available thread to exec PC= 0x%" PRIx64 "\n", - id, ExecPC); - rtn = true; - Stats.cyclesIdle_Total++; - if( HartsClearToExecute.any() ){ - Stats.cyclesIdle_MemoryFetch++; - } - } - - // Check for pipeline hazards - if(!Pipeline.empty() && - (Pipeline.front().second.cost > 0)){ - Pipeline.front().second.cost--; - if(Pipeline.front().second.cost == 0){ // && - // Ready to retire this instruction - uint16_t HartID = Pipeline.front().first; - #ifdef NO_REV_TRACER - output->verbose(CALL_INFO, 6, 0, - "Core %" PRIu32 "; Hart %" PRIu32 "; ThreadID %" PRIu32 "; Retiring PC= 0x%" PRIx64 "\n", - id, HartID, ActiveThreadID, ExecPC); - #endif - Stats.retired++; - - // Only clear the dependency if there is no outstanding load - if((RegFile->GetLSQueue()->count(LSQHash(Pipeline.front().second.rd, - InstTable[Pipeline.front().second.entry].rdClass, - HartID))) == 0){ - DependencyClear(HartID, &(Pipeline.front().second)); - } - Pipeline.pop_front(); - RegFile->SetCost(0); - }else{ - // could not retire the instruction, bump the cost - Pipeline.front().second.cost++; - } - } - // Check for completion states and new tasks - if( RegFile->GetPC() == 0x00ull ){ - // look for more work on the execution queue - // if no work is found, don't update the PC - // just wait and spin - if( HartHasNoDependencies(HartToDecodeID) ){ - std::unique_ptr ActiveThread = PopThreadFromHart(HartToDecodeID); - ActiveThread->SetState(ThreadState::DONE); - HartsClearToExecute[HartToDecodeID] = false; - HartsClearToDecode[HartToDecodeID] = false; - IdleHarts.set(HartToDecodeID); - AddThreadsThatChangedState(std::move(ActiveThread)); - } - - if( HartToExecID != _REV_INVALID_HART_ID_ - && !IdleHarts[HartToExecID] - && HartHasNoDependencies(HartToExecID) ){ - std::unique_ptr ActiveThread = PopThreadFromHart(HartToDecodeID); - ActiveThread->SetState(ThreadState::DONE); - HartsClearToExecute[HartToExecID] = false; - HartsClearToDecode[HartToExecID] = false; - IdleHarts[HartToExecID] = true; - AddThreadsThatChangedState(std::move(ActiveThread)); - } - } - - #ifndef NO_REV_TRACER - // Dump trace state - if (Tracer) Tracer->Render(currentCycle); - #endif - - return rtn; -} - -std::unique_ptr RevProc::PopThreadFromHart(unsigned HartID){ - if( HartID >= numHarts ){ - output->fatal(CALL_INFO, -1, - "Error: tried to pop thread from hart %" PRIu32 " but there are only %" PRIu32 " hart(s)\n", - HartID, numHarts); - } - IdleHarts[HartID] = true; - return Harts.at(HartID)->PopThread(); -} - - -void RevProc::PrintStatSummary(){ - auto memStatsTotal = mem->GetMemStatsTotal(); - - double eff = StatsTotal.totalCycles ? double(StatsTotal.cyclesBusy)/StatsTotal.totalCycles : 0; - output->verbose(CALL_INFO, 2, 0, - "Program execution complete\n" - "Core %u Program Stats: Total Cycles: %" PRIu64 " Busy Cycles: %" PRIu64 - " Idle Cycles: %" PRIu64 " Eff: %f\n", - id, - StatsTotal.totalCycles, - StatsTotal.cyclesBusy, - StatsTotal.cyclesIdle_Total, - eff); - - output->verbose(CALL_INFO, 3, 0, "\t Bytes Read: %" PRIu64 " Bytes Written: %" PRIu64 - " Floats Read: %" PRIu64 " Doubles Read %" PRIu64 " Floats Exec: %" PRIu64 - " TLB Hits: %" PRIu64 " TLB Misses: %" PRIu64 " Inst Retired: %" PRIu64 "\n\n", - memStatsTotal.bytesRead, - memStatsTotal.bytesWritten, - memStatsTotal.floatsRead, - memStatsTotal.doublesRead, - StatsTotal.floatsExec, - memStatsTotal.TLBHits, - memStatsTotal.TLBMisses, - StatsTotal.retired); -} - -RevRegFile* RevProc::GetRegFile(unsigned HartID) const { - if( HartID >= Harts.size() ){ - output->fatal(CALL_INFO, -1, - "Error: tried to get RegFile for Hart %" PRIu32 " but there are only %" PRIu32 " hart(s)\n", - HartID, numHarts); - } - return Harts.at(HartID)->RegFile.get(); -} - -void RevProc::CreateThread(uint32_t NewTID, uint64_t firstPC, void* arg){ - // tidAddr is the address we have to write the new thread's id to - output->verbose(CALL_INFO, 2, 0, - "Creating new thread with PC = 0x%" PRIx64 "\n", firstPC); - uint32_t ParentThreadID = Harts.at(HartToExecID)->GetAssignedThreadID(); - - // Create the new thread's memory - std::shared_ptr NewThreadMem = mem->AddThreadMem(); - - // TODO: Copy TLS into new memory - - // Create new register file - std::unique_ptr NewThreadRegFile = std::make_unique(feature); - - // Copy the arg to the new threads a0 register - NewThreadRegFile->SetX(RevReg::a0, reinterpret_cast(arg)); - - // Set the global pointer - // TODO: Cleanup - NewThreadRegFile->SetX(RevReg::tp, NewThreadMem->getTopAddr()); - NewThreadRegFile->SetX(RevReg::sp, NewThreadMem->getTopAddr()-mem->GetTLSSize()); - NewThreadRegFile->SetX(RevReg::gp, loader->GetSymbolAddr("__global_pointer$")); - NewThreadRegFile->SetX(8, loader->GetSymbolAddr("__global_pointer$")); - NewThreadRegFile->SetPC(firstPC); - - // Create a new RevThread Object - std::unique_ptr NewThread = - std::make_unique(NewTID, - ParentThreadID, - NewThreadMem, - std::move(NewThreadRegFile)); - - // Add new thread to this vector so the RevCPU will add and schedule it - AddThreadsThatChangedState(std::move(NewThread)); - - return; -} - -/* ========================================= */ -/* System Call (ecall) Implementations Below */ -/* ========================================= */ -void RevProc::InitEcallTable(){ - Ecalls = { - { 0, &RevProc::ECALL_io_setup}, // rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) - { 1, &RevProc::ECALL_io_destroy}, // rev_io_destroy(aio_context_t ctx) - { 2, &RevProc::ECALL_io_submit}, // rev_io_submit(aio_context_t, long, struct iocb * *) - { 3, &RevProc::ECALL_io_cancel}, // rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) - { 4, &RevProc::ECALL_io_getevents}, // rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) - { 5, &RevProc::ECALL_setxattr}, // rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) - { 6, &RevProc::ECALL_lsetxattr}, // rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) - { 7, &RevProc::ECALL_fsetxattr}, // rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) - { 8, &RevProc::ECALL_getxattr}, // rev_getxattr(const char *path, const char *name, void *value, size_t size) - { 9, &RevProc::ECALL_lgetxattr}, // rev_lgetxattr(const char *path, const char *name, void *value, size_t size) - { 10, &RevProc::ECALL_fgetxattr}, // rev_fgetxattr(int fd, const char *name, void *value, size_t size) - { 11, &RevProc::ECALL_listxattr}, // rev_listxattr(const char *path, char *list, size_t size) - { 12, &RevProc::ECALL_llistxattr}, // rev_llistxattr(const char *path, char *list, size_t size) - { 13, &RevProc::ECALL_flistxattr}, // rev_flistxattr(int fd, char *list, size_t size) - { 14, &RevProc::ECALL_removexattr}, // rev_removexattr(const char *path, const char *name) - { 15, &RevProc::ECALL_lremovexattr}, // rev_lremovexattr(const char *path, const char *name) - { 16, &RevProc::ECALL_fremovexattr}, // rev_fremovexattr(int fd, const char *name) - { 17, &RevProc::ECALL_getcwd}, // rev_getcwd(char *buf, unsigned long size) - { 18, &RevProc::ECALL_lookup_dcookie}, // rev_lookup_dcookie(u64 cookie64, char *buf, size_t len) - { 19, &RevProc::ECALL_eventfd2}, // rev_eventfd2(unsigned int count, int flags) - { 20, &RevProc::ECALL_epoll_create1}, // rev_epoll_create1(int flags) - { 21, &RevProc::ECALL_epoll_ctl}, // rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { 22, &RevProc::ECALL_epoll_pwait}, // rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) - { 23, &RevProc::ECALL_dup}, // rev_dup(unsigned int fildes) - { 24, &RevProc::ECALL_dup3}, // rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) - { 25, &RevProc::ECALL_fcntl64}, // rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) - { 26, &RevProc::ECALL_inotify_init1}, // rev_inotify_init1(int flags) - { 27, &RevProc::ECALL_inotify_add_watch}, // rev_inotify_add_watch(int fd, const char *path, u32 mask) - { 28, &RevProc::ECALL_inotify_rm_watch}, // rev_inotify_rm_watch(int fd, __s32 wd) - { 29, &RevProc::ECALL_ioctl}, // rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) - { 30, &RevProc::ECALL_ioprio_set}, // rev_ioprio_set(int which, int who, int ioprio) - { 31, &RevProc::ECALL_ioprio_get}, // rev_ioprio_get(int which, int who) - { 32, &RevProc::ECALL_flock}, // rev_flock(unsigned int fd, unsigned int cmd) - { 33, &RevProc::ECALL_mknodat}, // rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) - { 34, &RevProc::ECALL_mkdirat}, // rev_mkdirat(int dfd, const char * pathname, umode_t mode) - { 35, &RevProc::ECALL_unlinkat}, // rev_unlinkat(int dfd, const char * pathname, int flag) - { 36, &RevProc::ECALL_symlinkat}, // rev_symlinkat(const char * oldname, int newdfd, const char * newname) - { 37, &RevProc::ECALL_linkat}, // rev_unlinkat(int dfd, const char * pathname, int flag) - { 38, &RevProc::ECALL_renameat}, // rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) - { 39, &RevProc::ECALL_umount}, // rev_umount(char *name, int flags) - { 40, &RevProc::ECALL_mount}, // rev_umount(char *name, int flags) - { 41, &RevProc::ECALL_pivot_root}, // rev_pivot_root(const char *new_root, const char *put_old) - { 42, &RevProc::ECALL_ni_syscall}, // rev_ni_syscall(void) - { 43, &RevProc::ECALL_statfs64}, // rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) - { 44, &RevProc::ECALL_fstatfs64}, // rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf) - { 45, &RevProc::ECALL_truncate64}, // rev_truncate64(const char *path, loff_t length) - { 46, &RevProc::ECALL_ftruncate64}, // rev_ftruncate64(unsigned int fd, loff_t length) - { 47, &RevProc::ECALL_fallocate}, // rev_fallocate(int fd, int mode, loff_t offset, loff_t len) - { 48, &RevProc::ECALL_faccessat}, // rev_faccessat(int dfd, const char *filename, int mode) - { 49, &RevProc::ECALL_chdir}, // rev_chdir(const char *filename) - { 50, &RevProc::ECALL_fchdir}, // rev_fchdir(unsigned int fd) - { 51, &RevProc::ECALL_chroot}, // rev_chroot(const char *filename) - { 52, &RevProc::ECALL_fchmod}, // rev_fchmod(unsigned int fd, umode_t mode) - { 53, &RevProc::ECALL_fchmodat}, // rev_fchmodat(int dfd, const char * filename, umode_t mode) - { 54, &RevProc::ECALL_fchownat}, // rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) - { 55, &RevProc::ECALL_fchown}, // rev_fchown(unsigned int fd, uid_t user, gid_t group) - { 56, &RevProc::ECALL_openat}, // rev_openat(int dfd, const char *filename, int flags, umode_t mode) - { 57, &RevProc::ECALL_close}, // rev_close(unsigned int fd) - { 58, &RevProc::ECALL_vhangup}, // rev_vhangup(void) - { 59, &RevProc::ECALL_pipe2}, // rev_pipe2(int *fildes, int flags) - { 60, &RevProc::ECALL_quotactl}, // rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) - { 61, &RevProc::ECALL_getdents64}, // rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) - { 62, &RevProc::ECALL_lseek}, // rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) - { 63, &RevProc::ECALL_read}, // rev_read(unsigned int fd, char *buf, size_t count) - { 64, &RevProc::ECALL_write}, // rev_write(unsigned int fd, const char *buf, size_t count) - { 65, &RevProc::ECALL_readv}, // rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) - { 66, &RevProc::ECALL_writev}, // rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) - { 67, &RevProc::ECALL_pread64}, // rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) - { 68, &RevProc::ECALL_pwrite64}, // rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) - { 69, &RevProc::ECALL_preadv}, // rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) - { 70, &RevProc::ECALL_pwritev}, // rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) - { 71, &RevProc::ECALL_sendfile64}, // rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) - { 72, &RevProc::ECALL_pselect6_time32}, // rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *) - { 73, &RevProc::ECALL_ppoll_time32}, // rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t) - { 74, &RevProc::ECALL_signalfd4}, // rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) - { 75, &RevProc::ECALL_vmsplice}, // rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) - { 76, &RevProc::ECALL_splice}, // rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) - { 77, &RevProc::ECALL_tee}, // rev_tee(int fdin, int fdout, size_t len, unsigned int flags) - { 78, &RevProc::ECALL_readlinkat}, // rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) - { 79, &RevProc::ECALL_newfstatat}, // rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) - { 80, &RevProc::ECALL_newfstat}, // rev_newfstat(unsigned int fd, struct stat *statbuf) - { 81, &RevProc::ECALL_sync}, // rev_sync(void) - { 82, &RevProc::ECALL_fsync}, // rev_fsync(unsigned int fd) - { 83, &RevProc::ECALL_fdatasync}, // rev_fdatasync(unsigned int fd) - { 84, &RevProc::ECALL_sync_file_range2}, // rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) - { 84, &RevProc::ECALL_sync_file_range}, // rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) - { 85, &RevProc::ECALL_timerfd_create}, // rev_timerfd_create(int clockid, int flags) - { 86, &RevProc::ECALL_timerfd_settime}, // rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) - { 87, &RevProc::ECALL_timerfd_gettime}, // rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) - { 88, &RevProc::ECALL_utimensat}, // rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) - { 89, &RevProc::ECALL_acct}, // rev_acct(const char *name) - { 90, &RevProc::ECALL_capget}, // rev_capget(cap_user_header_t header, cap_user_data_t dataptr) - { 91, &RevProc::ECALL_capset}, // rev_capset(cap_user_header_t header, const cap_user_data_t data) - { 92, &RevProc::ECALL_personality}, // rev_personality(unsigned int personality) - { 93, &RevProc::ECALL_exit}, // rev_exit(int error_code) - { 94, &RevProc::ECALL_exit_group}, // rev_exit_group(int error_code) - { 95, &RevProc::ECALL_waitid}, // rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) - { 96, &RevProc::ECALL_set_tid_address}, // rev_set_tid_address(int *tidptr) - { 97, &RevProc::ECALL_unshare}, // rev_unshare(unsigned long unshare_flags) - { 98, &RevProc::ECALL_futex}, // rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) - { 99, &RevProc::ECALL_set_robust_list}, // rev_set_robust_list(struct robust_list_head *head, size_t len) - { 100, &RevProc::ECALL_get_robust_list}, // rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) - { 101, &RevProc::ECALL_nanosleep}, // rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - { 102, &RevProc::ECALL_getitimer}, // rev_getitimer(int which, struct __kernel_old_itimerval *value) - { 103, &RevProc::ECALL_setitimer}, // rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) - { 104, &RevProc::ECALL_kexec_load}, // rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) - { 105, &RevProc::ECALL_init_module}, // rev_init_module(void *umod, unsigned long len, const char *uargs) - { 106, &RevProc::ECALL_delete_module}, // rev_delete_module(const char *name_user, unsigned int flags) - { 107, &RevProc::ECALL_timer_create}, // rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) - { 108, &RevProc::ECALL_timer_gettime}, // rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) - { 109, &RevProc::ECALL_timer_getoverrun}, // rev_timer_getoverrun(timer_t timer_id) - { 110, &RevProc::ECALL_timer_settime}, // rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) - { 111, &RevProc::ECALL_timer_delete}, // rev_timer_delete(timer_t timer_id) - { 112, &RevProc::ECALL_clock_settime}, // rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) - { 113, &RevProc::ECALL_clock_gettime}, // rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) - { 114, &RevProc::ECALL_clock_getres}, // rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) - { 115, &RevProc::ECALL_clock_nanosleep}, // rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - { 116, &RevProc::ECALL_syslog}, // rev_syslog(int type, char *buf, int len) - { 117, &RevProc::ECALL_ptrace}, // rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) - { 118, &RevProc::ECALL_sched_setparam}, // rev_sched_setparam(pid_t pid, struct sched_param *param) - { 119, &RevProc::ECALL_sched_setscheduler}, // rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) - { 120, &RevProc::ECALL_sched_getscheduler}, // rev_sched_getscheduler(pid_t pid) - { 121, &RevProc::ECALL_sched_getparam}, // rev_sched_getparam(pid_t pid, struct sched_param *param) - { 122, &RevProc::ECALL_sched_setaffinity}, // rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) - { 123, &RevProc::ECALL_sched_getaffinity}, // rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) - { 124, &RevProc::ECALL_sched_yield}, // rev_sched_yield(void) - { 125, &RevProc::ECALL_sched_get_priority_max}, // rev_sched_get_priority_max(int policy) - { 126, &RevProc::ECALL_sched_get_priority_min}, // rev_sched_get_priority_min(int policy) - { 127, &RevProc::ECALL_sched_rr_get_interval}, // rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) - { 128, &RevProc::ECALL_restart_syscall}, // rev_restart_syscall(void) - { 129, &RevProc::ECALL_kill}, // rev_kill(pid_t pid, int sig) - { 130, &RevProc::ECALL_tkill}, // rev_tkill(pid_t pid, int sig) - { 131, &RevProc::ECALL_tgkill}, // rev_tgkill(pid_t tgid, pid_t pid, int sig) - { 132, &RevProc::ECALL_sigaltstack}, // rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) - { 133, &RevProc::ECALL_rt_sigsuspend}, // rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) - { 134, &RevProc::ECALL_rt_sigaction}, // rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) - { 135, &RevProc::ECALL_rt_sigprocmask}, // rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) - { 136, &RevProc::ECALL_rt_sigpending}, // rev_rt_sigpending(sigset_t *set, size_t sigsetsize) - { 137, &RevProc::ECALL_rt_sigtimedwait_time32}, // rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) - { 138, &RevProc::ECALL_rt_sigqueueinfo}, // rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) - { 140, &RevProc::ECALL_setpriority}, // rev_setpriority(int which, int who, int niceval) - { 141, &RevProc::ECALL_getpriority}, // rev_getpriority(int which, int who) - { 142, &RevProc::ECALL_reboot}, // rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) - { 143, &RevProc::ECALL_setregid}, // rev_setregid(gid_t rgid, gid_t egid) - { 144, &RevProc::ECALL_setgid}, // rev_setgid(gid_t gid) - { 145, &RevProc::ECALL_setreuid}, // rev_setreuid(uid_t ruid, uid_t euid) - { 146, &RevProc::ECALL_setuid}, // rev_setuid(uid_t uid) - { 147, &RevProc::ECALL_setresuid}, // rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) - { 148, &RevProc::ECALL_getresuid}, // rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) - { 149, &RevProc::ECALL_setresgid}, // rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) - { 150, &RevProc::ECALL_getresgid}, // rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) - { 151, &RevProc::ECALL_setfsuid}, // rev_setfsuid(uid_t uid) - { 152, &RevProc::ECALL_setfsgid}, // rev_setfsgid(gid_t gid) - { 153, &RevProc::ECALL_times}, // rev_times(struct tms *tbuf) - { 154, &RevProc::ECALL_setpgid}, // rev_setpgid(pid_t pid, pid_t pgid) - { 155, &RevProc::ECALL_getpgid}, // rev_getpgid(pid_t pid) - { 156, &RevProc::ECALL_getsid}, // rev_getsid(pid_t pid) - { 157, &RevProc::ECALL_setsid}, // rev_setsid(void) - { 158, &RevProc::ECALL_getgroups}, // rev_getgroups(int gidsetsize, gid_t *grouplist) - { 159, &RevProc::ECALL_setgroups}, // rev_setgroups(int gidsetsize, gid_t *grouplist) - { 160, &RevProc::ECALL_newuname}, // rev_newuname(struct new_utsname *name) - { 161, &RevProc::ECALL_sethostname}, // rev_sethostname(char *name, int len) - { 162, &RevProc::ECALL_setdomainname}, // rev_setdomainname(char *name, int len) - { 163, &RevProc::ECALL_getrlimit}, // rev_getrlimit(unsigned int resource, struct rlimit *rlim) - { 164, &RevProc::ECALL_setrlimit}, // rev_setrlimit(unsigned int resource, struct rlimit *rlim) - { 165, &RevProc::ECALL_getrusage}, // rev_getrusage(int who, struct rusage *ru) - { 166, &RevProc::ECALL_umask}, // rev_umask(int mask) - { 167, &RevProc::ECALL_prctl}, // rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) - { 168, &RevProc::ECALL_getcpu}, // rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) - { 169, &RevProc::ECALL_gettimeofday}, // rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) - { 170, &RevProc::ECALL_settimeofday}, // rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) - { 171, &RevProc::ECALL_adjtimex}, // rev_adjtimex(struct __kernel_timex *txc_p) - { 172, &RevProc::ECALL_getpid}, // rev_getpid(void) - { 173, &RevProc::ECALL_getppid}, // rev_getppid(void) - { 174, &RevProc::ECALL_getuid}, // rev_getuid(void) - { 175, &RevProc::ECALL_geteuid}, // rev_geteuid(void) - { 176, &RevProc::ECALL_getgid}, // rev_getgid(void) - { 177, &RevProc::ECALL_getegid}, // rev_getegid(void) - { 178, &RevProc::ECALL_gettid}, // rev_gettid(void) - { 179, &RevProc::ECALL_sysinfo}, // rev_sysinfo(struct sysinfo *info) - { 180, &RevProc::ECALL_mq_open}, // rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) - { 181, &RevProc::ECALL_mq_unlink}, // rev_mq_unlink(const char *name) - { 182, &RevProc::ECALL_mq_timedsend}, // rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) - { 183, &RevProc::ECALL_mq_timedreceive}, // rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) - { 184, &RevProc::ECALL_mq_notify}, // rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) - { 185, &RevProc::ECALL_mq_getsetattr}, // rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) - { 186, &RevProc::ECALL_msgget}, // rev_msgget(key_t key, int msgflg) - { 187, &RevProc::ECALL_msgctl}, // rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) - { 188, &RevProc::ECALL_msgrcv}, // rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) - { 189, &RevProc::ECALL_msgsnd}, // rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) - { 190, &RevProc::ECALL_semget}, // rev_semget(key_t key, int nsems, int semflg) - { 191, &RevProc::ECALL_semctl}, // rev_semctl(int semid, int semnum, int cmd, unsigned long arg) - { 192, &RevProc::ECALL_semtimedop}, // rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) - { 193, &RevProc::ECALL_semop}, // rev_semop(int semid, struct sembuf *sops, unsigned nsops) - { 194, &RevProc::ECALL_shmget}, // rev_shmget(key_t key, size_t size, int flag) - { 195, &RevProc::ECALL_shmctl}, // rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) - { 196, &RevProc::ECALL_shmat}, // rev_shmat(int shmid, char *shmaddr, int shmflg) - { 197, &RevProc::ECALL_shmdt}, // rev_shmdt(char *shmaddr) - { 198, &RevProc::ECALL_socket}, // rev_socket(int, int, int) - { 199, &RevProc::ECALL_socketpair}, // rev_socketpair(int, int, int, int *) - { 200, &RevProc::ECALL_bind}, // rev_bind(int, struct sockaddr *, int) - { 201, &RevProc::ECALL_listen}, // rev_listen(int, int) - { 202, &RevProc::ECALL_accept}, // rev_accept(int, struct sockaddr *, int *) - { 203, &RevProc::ECALL_connect}, // rev_connect(int, struct sockaddr *, int) - { 204, &RevProc::ECALL_getsockname}, // rev_getsockname(int, struct sockaddr *, int *) - { 205, &RevProc::ECALL_getpeername}, // rev_getpeername(int, struct sockaddr *, int *) - { 206, &RevProc::ECALL_sendto}, // rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int) - { 207, &RevProc::ECALL_recvfrom}, // rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *) - { 208, &RevProc::ECALL_setsockopt}, // rev_setsockopt(int fd, int level, int optname, char *optval, int optlen) - { 209, &RevProc::ECALL_getsockopt}, // rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen) - { 210, &RevProc::ECALL_shutdown}, // rev_shutdown(int, int) - { 211, &RevProc::ECALL_sendmsg}, // rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags) - { 212, &RevProc::ECALL_recvmsg}, // rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags) - { 213, &RevProc::ECALL_readahead}, // rev_readahead(int fd, loff_t offset, size_t count) - { 214, &RevProc::ECALL_brk}, // rev_brk(unsigned long brk) - { 215, &RevProc::ECALL_munmap}, // rev_munmap(unsigned long addr, size_t len) - { 216, &RevProc::ECALL_mremap}, // rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) - { 217, &RevProc::ECALL_add_key}, // rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) - { 218, &RevProc::ECALL_request_key}, // rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) - { 219, &RevProc::ECALL_keyctl}, // rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) - { 220, &RevProc::ECALL_clone}, // rev_clone(unsigned long, unsigned long, int *, unsigned long, int *) - { 221, &RevProc::ECALL_execve}, // rev_execve(const char *filename, const char *const *argv, const char *const *envp) - { 222, &RevProc::ECALL_mmap}, // rev_old_mmap(struct mmap_arg_struct *arg) - { 223, &RevProc::ECALL_fadvise64_64}, // rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) - { 224, &RevProc::ECALL_swapon}, // rev_swapon(const char *specialfile, int swap_flags) - { 225, &RevProc::ECALL_swapoff}, // rev_swapoff(const char *specialfile) - { 226, &RevProc::ECALL_mprotect}, // rev_mprotect(unsigned long start, size_t len, unsigned long prot) - { 227, &RevProc::ECALL_msync}, // rev_msync(unsigned long start, size_t len, int flags) - { 228, &RevProc::ECALL_mlock}, // rev_mlock(unsigned long start, size_t len) - { 229, &RevProc::ECALL_munlock}, // rev_munlock(unsigned long start, size_t len) - { 230, &RevProc::ECALL_mlockall}, // rev_mlockall(int flags) - { 231, &RevProc::ECALL_munlockall}, // rev_munlockall(void) - { 232, &RevProc::ECALL_mincore}, // rev_mincore(unsigned long start, size_t len, unsigned char * vec) - { 233, &RevProc::ECALL_madvise}, // rev_madvise(unsigned long start, size_t len, int behavior) - { 234, &RevProc::ECALL_remap_file_pages}, // rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) - { 235, &RevProc::ECALL_mbind}, // rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) - { 236, &RevProc::ECALL_get_mempolicy}, // rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) - { 237, &RevProc::ECALL_set_mempolicy}, // rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) - { 238, &RevProc::ECALL_migrate_pages}, // rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) - { 239, &RevProc::ECALL_move_pages}, // rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) - { 240, &RevProc::ECALL_rt_tgsigqueueinfo}, // rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) - { 241, &RevProc::ECALL_perf_event_open}, // rev_perf_event_open(") - { 242, &RevProc::ECALL_accept4}, // rev_accept4(int, struct sockaddr *, int *, int) - { 243, &RevProc::ECALL_recvmmsg_time32}, // rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout) - { 260, &RevProc::ECALL_wait4}, // rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) - { 261, &RevProc::ECALL_prlimit64}, // rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) - { 262, &RevProc::ECALL_fanotify_init}, // rev_fanotify_init(unsigned int flags, unsigned int event_f_flags) - { 263, &RevProc::ECALL_fanotify_mark}, // rev_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char *pathname) - { 264, &RevProc::ECALL_name_to_handle_at}, // rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) - { 265, &RevProc::ECALL_open_by_handle_at}, // rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) - { 266, &RevProc::ECALL_clock_adjtime}, // rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) - { 267, &RevProc::ECALL_syncfs}, // rev_syncfs(int fd) - { 268, &RevProc::ECALL_setns}, // rev_setns(int fd, int nstype) - { 269, &RevProc::ECALL_sendmmsg}, // rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) - { 270, &RevProc::ECALL_process_vm_readv}, // rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) - { 271, &RevProc::ECALL_process_vm_writev}, // rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) - { 272, &RevProc::ECALL_kcmp}, // rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) - { 273, &RevProc::ECALL_finit_module}, // rev_finit_module(int fd, const char *uargs, int flags) - { 274, &RevProc::ECALL_sched_setattr}, // rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) - { 275, &RevProc::ECALL_sched_getattr}, // rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) - { 276, &RevProc::ECALL_renameat2}, // rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) - { 277, &RevProc::ECALL_seccomp}, // rev_seccomp(unsigned int op, unsigned int flags, void *uargs) - { 278, &RevProc::ECALL_getrandom}, // rev_getrandom(char *buf, size_t count, unsigned int flags) - { 279, &RevProc::ECALL_memfd_create}, // rev_memfd_create(const char *uname_ptr, unsigned int flags) - { 280, &RevProc::ECALL_bpf}, // rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) - { 281, &RevProc::ECALL_execveat}, // rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) - { 282, &RevProc::ECALL_userfaultfd}, // rev_userfaultfd(int flags) - { 283, &RevProc::ECALL_membarrier}, // rev_membarrier(int cmd, unsigned int flags, int cpu_id) - { 284, &RevProc::ECALL_mlock2}, // rev_mlock2(unsigned long start, size_t len, int flags) - { 285, &RevProc::ECALL_copy_file_range}, // rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) - { 286, &RevProc::ECALL_preadv2}, // rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) - { 287, &RevProc::ECALL_pwritev2}, // rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) - { 288, &RevProc::ECALL_pkey_mprotect}, // rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey) - { 289, &RevProc::ECALL_pkey_alloc}, // rev_pkey_alloc(unsigned long flags, unsigned long init_val) - { 290, &RevProc::ECALL_pkey_free}, // rev_pkey_free(int pkey) - { 291, &RevProc::ECALL_statx}, // rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) - { 292, &RevProc::ECALL_io_pgetevents}, // rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) - { 293, &RevProc::ECALL_rseq}, // rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) - { 294, &RevProc::ECALL_kexec_file_load}, // rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) - { 403, &RevProc::ECALL_clock_gettime}, // rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) - { 404, &RevProc::ECALL_clock_settime}, // rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) - { 405, &RevProc::ECALL_clock_adjtime}, // rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) - { 406, &RevProc::ECALL_clock_getres}, // rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) - { 407, &RevProc::ECALL_clock_nanosleep}, // rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) - { 408, &RevProc::ECALL_timer_gettime}, // rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) - { 409, &RevProc::ECALL_timer_settime}, // rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) - { 410, &RevProc::ECALL_timerfd_gettime}, // rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) - { 411, &RevProc::ECALL_timerfd_settime}, // rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) - { 412, &RevProc::ECALL_utimensat}, // rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) - { 416, &RevProc::ECALL_io_pgetevents}, // rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) - { 418, &RevProc::ECALL_mq_timedsend}, // rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) - { 419, &RevProc::ECALL_mq_timedreceive}, // rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) - { 420, &RevProc::ECALL_semtimedop}, // rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) - { 422, &RevProc::ECALL_futex}, // rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) - { 423, &RevProc::ECALL_sched_rr_get_interval}, // rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) - { 424, &RevProc::ECALL_pidfd_send_signal}, // rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) - { 425, &RevProc::ECALL_io_uring_setup}, // rev_io_uring_setup(u32 entries, struct io_uring_params *p) - { 426, &RevProc::ECALL_io_uring_enter}, // rev_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const sigset_t *sig, size_t sigsz) - { 427, &RevProc::ECALL_io_uring_register}, // rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args) - { 428, &RevProc::ECALL_open_tree}, // rev_open_tree(int dfd, const char *path, unsigned flags) - { 429, &RevProc::ECALL_move_mount}, // rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) - { 430, &RevProc::ECALL_fsopen}, // rev_fsopen(const char *fs_name, unsigned int flags) - { 431, &RevProc::ECALL_fsconfig}, // rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) - { 432, &RevProc::ECALL_fsmount}, // rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) - { 433, &RevProc::ECALL_fspick}, // rev_fspick(int dfd, const char *path, unsigned int flags) - { 434, &RevProc::ECALL_pidfd_open}, // rev_pidfd_open(pid_t pid, unsigned int flags) - { 435, &RevProc::ECALL_clone3}, // rev_clone3(struct clone_args *uargs, size_t size) - { 436, &RevProc::ECALL_close_range}, // rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags) - { 437, &RevProc::ECALL_openat2}, // rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) - { 438, &RevProc::ECALL_pidfd_getfd}, // rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) - { 439, &RevProc::ECALL_faccessat2}, // rev_faccessat2(int dfd, const char *filename, int mode, int flags) - { 440, &RevProc::ECALL_process_madvise}, // rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) - { 500, &RevProc::ECALL_cpuinfo}, // rev_cpuinfo(struct rev_cpuinfo *info) - { 501, &RevProc::ECALL_perf_stats}, // rev_cpuinfo(struct rev_perf_stats *stats) - { 1000, &RevProc::ECALL_pthread_create}, // - { 1001, &RevProc::ECALL_pthread_join}, // - }; -} - -// -// This is the function that is called when an ECALL exception is detected inside ClockTick -// - Currently the only way to set this exception is by Ext->Execute(....) an ECALL instruction -// -// Eventually this will be integrated into a TrapHandler however since ECALLs are the only -// supported exceptions at this point there is no need just yet. -// -void RevProc::ExecEcall(RevInst& inst){ - auto EcallCode =Harts[HartToDecodeID]->RegFile->GetX(RevReg::a7); - auto it = Ecalls.find(EcallCode); - if( it != Ecalls.end() ){ - EcallStatus status = it->second(this, inst); - - // Trap handled... 0 cause registers - RegFile->RV64_SCAUSE = uint64_t(status); - RegFile->RV32_SCAUSE = uint32_t(status); - - // For now, rewind the PC and keep executing the ECALL until we - // have completed - if(EcallStatus::SUCCESS != status){ - RegFile->SetPC( RegFile->GetPC() - inst.instSize ); - } - } else { - output->fatal(CALL_INFO, -1, "Ecall Code = %" PRIu64 " not found", EcallCode); - } -} - -// Looks for a hart without a thread assigned to it and then assigns it. -// This function should never be called if there are no available harts -// so if for some reason we can't find a hart without a thread assigned -// to it then we have a bug. -void RevProc::AssignThread(std::unique_ptr Thread){ - unsigned HartToAssign = FindIdleHartID(); - - if( HartToAssign == _REV_INVALID_HART_ID_ ){ - output->fatal(CALL_INFO, 1, "Attempted to assign a thread to a hart but no available harts were found.\n" - "We should never have tried to assign a thread to this Proc if it had no " - "harts available (ie. Proc->NumIdleHarts() == 0 ).\n" - "This is a bug\n"); - } - - // Assign the thread to the hart - Harts.at(HartToAssign)->AssignThread( std::move(Thread) ); - - IdleHarts[HartToAssign] = false; - - return; -} - -unsigned RevProc::FindIdleHartID() const { - unsigned IdleHartID = _REV_INVALID_HART_ID_; - // Iterate over IdleHarts to find the first idle hart - for( size_t i=0; ifatal(CALL_INFO, -1, "Attempted to find an idle hart but none were found. This is a bug\n"); - } - - return IdleHartID; -} - - -void RevProc::InjectALUFault(std::pair EToE, RevInst& Inst){ - // inject ALU fault - RevExt *Ext = Extensions[EToE.first].get(); - if( (Ext->GetName() == "RV64F") || - (Ext->GetName() == "RV64D") ){ - // write an rv64 float rd - uint64_t tmp; - static_assert(sizeof(tmp) == sizeof(RegFile->DPF[Inst.rd])); - memcpy(&tmp, &RegFile->DPF[Inst.rd], sizeof(tmp)); - tmp |= RevRand(0, ~(~uint64_t{0} << fault_width)); - memcpy(&RegFile->DPF[Inst.rd], &tmp, sizeof(tmp)); - }else if( (Ext->GetName() == "RV32F") || - (Ext->GetName() == "RV32D") ){ - // write an rv32 float rd - uint32_t tmp; - static_assert(sizeof(tmp) == sizeof(RegFile->SPF[Inst.rd])); - memcpy(&tmp, &RegFile->SPF[Inst.rd], sizeof(tmp)); - tmp |= RevRand(0, ~(uint32_t{0} << fault_width)); - memcpy(&RegFile->SPF[Inst.rd], &tmp, sizeof(tmp)); - }else{ - // write an X register - uint64_t rval = RevRand(0, ~(~uint64_t{0} << fault_width)); - RegFile->SetX(Inst.rd, rval | RegFile->GetX(Inst.rd)); - } - - // clear the fault - ALUFault = false; -} - -///< RevProc: Used by RevCPU to determine if it can disable this proc -/// based on the criteria there are no threads assigned to it and the -/// CoProc is done -bool RevProc::HasNoWork() const { return HasNoBusyHarts() && (!coProc || coProc->IsDone()); } - - -void RevProc::UpdateStatusOfHarts(){ - // A Hart is ClearToDecode if: - // 1. It has a thread assigned to it (ie. NOT Idle) - // 2. It's last instruction is done executing (ie. cost is set to 0) - for( size_t i=0; iRegFile->cost == 0; - } - return; -} - -// EOF diff --git a/src/RevRegFile.cc b/src/RevRegFile.cc index 444e8c9f8..357b51d2d 100644 --- a/src/RevRegFile.cc +++ b/src/RevRegFile.cc @@ -11,43 +11,56 @@ #include "RevRegFile.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { // Overload the printing -std::ostream& operator<<(std::ostream& os, const RevRegFile& regFile){ +std::ostream& operator<<( std::ostream& os, const RevRegFile& regFile ) { // Register aliases and descriptions - static constexpr const char* aliases[] = {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"}; - static constexpr const char* info[] = {"Zero Register", "Return Address", "Stack Pointer", "Global Pointer", "Thread Pointer", "Temporary Register", "Temporary Register", "Temporary Register", "Callee Saved Register", "Callee Saved Register", "Arg/Return Register", "Arg/Return Register", "Argument Register", "Argument Register", "Argument Register", "Argument Register", "Argument Register", "Argument Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Temporary Register", "Temporary Register", "Temporary Register", "Temporary Register"}; + static constexpr const char* aliases[] = { "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", + "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", + "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6" }; + static constexpr const char* info[] = { + "Zero Register", "Return Address", "Stack Pointer", "Global Pointer", "Thread Pointer", + "Temporary Register", "Temporary Register", "Temporary Register", "Callee Saved Register", "Callee Saved Register", + "Arg/Return Register", "Arg/Return Register", "Argument Register", "Argument Register", "Argument Register", + "Argument Register", "Argument Register", "Argument Register", "Callee Saved Register", "Callee Saved Register", + "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", + "Callee Saved Register", "Callee Saved Register", "Callee Saved Register", "Temporary Register", "Temporary Register", + "Temporary Register", "Temporary Register" }; // Update table width to accommodate the new "Dep" column constexpr int tableWidth = 6 /*Reg*/ + 7 /*Alias*/ + 19 /*Value*/ + 6 /*Dep*/ + 23 /*Info*/ + 11 /*Separators*/; - - os << '|' << std::string(tableWidth-3, '-') << '|' << '\n'; + os << '|' << std::string( tableWidth - 3, '-' ) << '|' << '\n'; // Table header - os << "| " << std::setw(4) << "Reg" << " | " << std::setw(5) << "Alias" << " | " << std::setw(21) << "Value" << " | " << std::setw(4) << "Dep" << " | " << std::setw(21) << "Info" << " |\n"; - os << "|------|-------|-----------------------|------|-----------------------|\n"; + os << "| " << std::setw( 4 ) << "Reg" + << " | " << std::setw( 5 ) << "Alias" + << " | " << std::setw( 21 ) << "Value" + << " | " << std::setw( 4 ) << "Dep" + << " | " << std::setw( 21 ) << "Info" + << " |\n"; + os << "|------|-------|-----------------------|------|-----------------------" + "|\n"; // Loop over the registers - for (size_t i = 0; i < _REV_NUM_REGS_; ++i) { - uint64_t value = regFile.GetX(i); + for( size_t i = 0; i < _REV_NUM_REGS_; ++i ) { + uint64_t value = regFile.GetX( i ); // if scoreboard is not 0, there is a dependency - char depValue = regFile.RV_Scoreboard[i] ? 'T' : 'F'; - os << "| " << std::setw(4) << ("x" + std::to_string(i)); - os << " | " << std::setw(5) << aliases[i]; + char depValue = regFile.RV_Scoreboard[i] ? 'T' : 'F'; + os << "| " << std::setw( 4 ) << ( "x" + std::to_string( i ) ); + os << " | " << std::setw( 5 ) << aliases[i]; std::ostringstream hs; hs << "0x" << std::hex << value; - os << " | " << std::setw(21) << hs.str(); - os << " | " << std::setw(4) << depValue; // New "Dep" column - os << " | " << std::setw(21) << info[i] << " |\n"; + os << " | " << std::setw( 21 ) << hs.str(); + os << " | " << std::setw( 4 ) << depValue; // New "Dep" column + os << " | " << std::setw( 21 ) << info[i] << " |\n"; } - os << "|" << std::string(tableWidth-3, '-') << "|" << '\n'; - + os << "|" << std::string( tableWidth - 3, '-' ) << "|" << '\n'; return os; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU diff --git a/src/RevSysCalls.cc b/src/RevSysCalls.cc index 10f7e649a..b8d7f39ca 100644 --- a/src/RevSysCalls.cc +++ b/src/RevSysCalls.cc @@ -1,28 +1,26 @@ -#include "RevProc.h" -#include "RevSysCalls.h" #include "RevCommon.h" +#include "RevCore.h" #include "RevMem.h" +#include "RevSysCalls.h" #include #include #include -namespace SST::RevCPU{ +namespace SST::RevCPU { /// Parse a string for an ECALL starting at address straddr, updating the state /// as characters are read, and call action() when the end of string is reached. -EcallStatus RevProc::EcallLoadAndParseString(RevInst& inst, - uint64_t straddr, - std::function action){ - auto rtval = EcallStatus::ERROR; - auto& EcallState = Harts.at(HartToExecID)->GetEcallState(); +EcallStatus RevCore::EcallLoadAndParseString( uint64_t straddr, std::function action ) { + auto rtval = EcallStatus::ERROR; + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); - if( RegFile->GetLSQueue()->count(LSQHash(RevReg::a0, RevRegClass::RegGPR, HartToExecID)) > 0 ){ + if( RegFile->GetLSQueue()->count( LSQHash( RevReg::a0, RevRegClass::RegGPR, HartToExecID ) ) > 0 ) { rtval = EcallStatus::CONTINUE; } else { // we don't know how long the path string is so read a byte (char) // at a time and search for the string terminator character '\0' - if(EcallState.bytesRead != 0){ - EcallState.string += std::string_view(EcallState.buf.data(), EcallState.bytesRead); + if( EcallState.bytesRead != 0 ) { + EcallState.string += std::string_view( EcallState.buf.data(), EcallState.bytesRead ); EcallState.bytesRead = 0; } @@ -30,30 +28,27 @@ EcallStatus RevProc::EcallLoadAndParseString(RevInst& inst, // C string from no data read at all. If we read an empty string in the // program, EcallState.string.size() == 1 with front() == back() == '\0'. If no // data has been read yet, EcallState.string.size() == 0. - if(EcallState.string.size() && !EcallState.string.back()){ + if( EcallState.string.size() && !EcallState.string.back() ) { //found the null terminator - we're done // action is usually passed in as a lambda with local code and captures // from the caller, such as performing a syscall using EcallState.string. action(); - - EcallState.string.clear(); //reset the ECALL buffers - EcallState.bytesRead = 0; - - DependencyClear(HartToExecID, RevReg::a0, false); + DependencyClear( HartToExecID, RevReg::a0, RevRegClass::RegGPR ); rtval = EcallStatus::SUCCESS; - }else{ + } else { //We are in the middle of the string - read one byte - MemReq req{straddr + EcallState.string.size(), RevReg::a0, - RevRegClass::RegGPR, HartToExecID, MemOp::MemOpREAD, - true, [=](const MemReq& req){this->MarkLoadComplete(req);}}; - LSQueue->insert(req.LSQHashPair()); - mem->ReadVal(HartToExecID, - straddr + EcallState.string.size(), - EcallState.buf.data(), - req, - RevFlag::F_NONE); + MemReq req{ + straddr + EcallState.string.size(), + RevReg::a0, + RevRegClass::RegGPR, + HartToExecID, + MemOp::MemOpREAD, + true, + [=]( const MemReq& req ) { this->MarkLoadComplete( req ); } }; + LSQueue->insert( req.LSQHashPair() ); + mem->ReadVal( HartToExecID, straddr + EcallState.string.size(), EcallState.buf.data(), req, RevFlag::F_NONE ); EcallState.bytesRead = 1; - DependencySet(HartToExecID, RevReg::a0, false); + DependencySet( HartToExecID, RevReg::a0, RevRegClass::RegGPR ); rtval = EcallStatus::CONTINUE; } } @@ -61,47 +56,47 @@ EcallStatus RevProc::EcallLoadAndParseString(RevInst& inst, } // 0, rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) -EcallStatus RevProc::ECALL_io_setup(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_setup called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_setup() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_setup called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 1, rev_io_destroy(aio_context_t ctx) -EcallStatus RevProc::ECALL_io_destroy(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_destroy called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_destroy() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_destroy called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 2, rev_io_submit(aio_context_t, long, struct iocb * *) -EcallStatus RevProc::ECALL_io_submit(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_submit called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_submit() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_submit called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 3, rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) -EcallStatus RevProc::ECALL_io_cancel(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_cancel called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_cancel() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_cancel called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 4, rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) -EcallStatus RevProc::ECALL_io_getevents(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_getevents called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_getevents() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_getevents called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 5, rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) -EcallStatus RevProc::ECALL_setxattr(RevInst& inst){ +EcallStatus RevCore::ECALL_setxattr() { #if 0 // TODO: Need to load the data from (value, size bytes) into // hostValue vector before it can be passed to setxattr() on host. @@ -120,8 +115,9 @@ EcallStatus RevProc::ECALL_setxattr(RevInst& inst){ // will move the ECALL.string to ECALL.path_string and continue below auto action = [&]{ ECALL.path_string = std::move(ECALL.string); + ECALL.string.clear(); }; - auto rtv = EcallLoadAndParseString(inst, path, action); + auto rtv = EcallLoadAndParseString(path, action); // When the parsing of path_string returns SUCCESS, we change it to // CONTINUE to continue the later stages @@ -147,15 +143,12 @@ EcallStatus RevProc::ECALL_setxattr(RevInst& inst){ flags); #endif - // Clear path_string so that later calls parse path_string first - ECALL.path_string.clear(); - // setxattr return code RegFile->SetX(RevReg::a0, rc); }; // Parse the name string, then call setxattr() using path and name - return EcallLoadAndParseString(inst, name, action); + return EcallLoadAndParseString(name, action); } #else return EcallStatus::SUCCESS; @@ -163,99 +156,99 @@ EcallStatus RevProc::ECALL_setxattr(RevInst& inst){ } // 6, rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) -EcallStatus RevProc::ECALL_lsetxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: lsetxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_lsetxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: lsetxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 7, rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) -EcallStatus RevProc::ECALL_fsetxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fsetxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fsetxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fsetxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 8, rev_getxattr(const char *path, const char *name, void *value, size_t size) -EcallStatus RevProc::ECALL_getxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 9, rev_lgetxattr(const char *path, const char *name, void *value, size_t size) -EcallStatus RevProc::ECALL_lgetxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: lgetxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_lgetxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: lgetxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 10, rev_fgetxattr(int fd, const char *name, void *value, size_t size) -EcallStatus RevProc::ECALL_fgetxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fgetxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fgetxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fgetxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 11, rev_listxattr(const char *path, char *list, size_t size) -EcallStatus RevProc::ECALL_listxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: listxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_listxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: listxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 12, rev_llistxattr(const char *path, char *list, size_t size) -EcallStatus RevProc::ECALL_llistxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: llistxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_llistxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: llistxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 13, rev_flistxattr(int fd, char *list, size_t size) -EcallStatus RevProc::ECALL_flistxattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: flistxattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_flistxattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: flistxattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 14, rev_removexattr(const char *path, const char *name) -EcallStatus RevProc::ECALL_removexattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: removexattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_removexattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: removexattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 15, rev_lremovexattr(const char *path, const char *name) -EcallStatus RevProc::ECALL_lremovexattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: lremovexattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_lremovexattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: lremovexattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 16, rev_fremovexattr(int fd, const char *name) -EcallStatus RevProc::ECALL_fremovexattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fremovexattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fremovexattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fremovexattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 17, rev_getcwd(char *buf, unsigned long size) -EcallStatus RevProc::ECALL_getcwd(RevInst& inst){ - auto BufAddr = RegFile->GetX(RevReg::a0); - auto size = RegFile->GetX(RevReg::a1); - auto CWD = std::filesystem::current_path(); - mem->WriteMem(HartToExecID, BufAddr, size, CWD.c_str()); +EcallStatus RevCore::ECALL_getcwd() { + auto BufAddr = RegFile->GetX( RevReg::a0 ); + auto size = RegFile->GetX( RevReg::a1 ); + auto CWD = std::filesystem::current_path(); + mem->WriteMem( HartToExecID, BufAddr, uint32_t( size ), CWD.c_str() ); // Returns null-terminated string in buf // (no need to set x10 since it's already got BufAddr) @@ -265,338 +258,344 @@ EcallStatus RevProc::ECALL_getcwd(RevInst& inst){ } // 18, rev_lookup_dcookie(u64 cookie64, char *buf, size_t len) -EcallStatus RevProc::ECALL_lookup_dcookie(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: lookup_dcookie called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_lookup_dcookie() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: lookup_dcookie called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 19, rev_eventfd2(unsigned int count, int flags) -EcallStatus RevProc::ECALL_eventfd2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: eventfd2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_eventfd2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: eventfd2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 20, rev_epoll_create1(int flags) -EcallStatus RevProc::ECALL_epoll_create1(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: epoll_create1 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_epoll_create1() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: epoll_create1 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 21, rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -EcallStatus RevProc::ECALL_epoll_ctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: epoll_ctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_epoll_ctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: epoll_ctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 22, rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) -EcallStatus RevProc::ECALL_epoll_pwait(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: epoll_pwait called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_epoll_pwait() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: epoll_pwait called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 23, rev_dup(unsigned int fildes) -EcallStatus RevProc::ECALL_dup(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: dup called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_dup() { + output->verbose( CALL_INFO, 2, 0, "ECALL: dup called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID ); return EcallStatus::SUCCESS; } // 24, rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) -EcallStatus RevProc::ECALL_dup3(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: dup3 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_dup3() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: dup3 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 25, rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -EcallStatus RevProc::ECALL_fcntl64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fcntl64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fcntl64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fcntl64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 26, rev_inotify_init1(int flags) -EcallStatus RevProc::ECALL_inotify_init1(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: inotify_init1 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_inotify_init1() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: inotify_init1 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 27, rev_inotify_add_watch(int fd, const char *path, u32 mask) -EcallStatus RevProc::ECALL_inotify_add_watch(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: inotify_add_watch called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_inotify_add_watch() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: inotify_add_watch called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 28, rev_inotify_rm_watch(int fd, __s32 wd) -EcallStatus RevProc::ECALL_inotify_rm_watch(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: inotify_rm_watch called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_inotify_rm_watch() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: inotify_rm_watch called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 29, rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -EcallStatus RevProc::ECALL_ioctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ioctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ioctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ioctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 30, rev_ioprio_set(int which, int who, int ioprio) -EcallStatus RevProc::ECALL_ioprio_set(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ioprio_set called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ioprio_set() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ioprio_set called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 31, rev_ioprio_get(int which, int who) -EcallStatus RevProc::ECALL_ioprio_get(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ioprio_get called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ioprio_get() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ioprio_get called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 32, rev_flock(unsigned int fd, unsigned int cmd) -EcallStatus RevProc::ECALL_flock(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: flock called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_flock() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: flock called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 33, rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) -EcallStatus RevProc::ECALL_mknodat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mknodat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mknodat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mknodat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // TODO: 34, rev_mkdirat(int dfd, const char * pathname, umode_t mode) -EcallStatus RevProc::ECALL_mkdirat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mkdirat called"); - EcallState& ECALL = Harts.at(HartToExecID)->GetEcallState(); - auto dirfd = RegFile->GetX(RevReg::a0); - auto path = RegFile->GetX(RevReg::a1); - auto mode = RegFile->GetX(RevReg::a2); - - auto action = [&]{ +EcallStatus RevCore::ECALL_mkdirat() { + output->verbose( CALL_INFO, 2, 0, "ECALL: mkdirat called" ); + EcallState& ECALL = Harts.at( HartToExecID )->GetEcallState(); + auto dirfd = RegFile->GetX( RevReg::a0 ); + auto path = RegFile->GetX( RevReg::a1 ); + auto mode = RegFile->GetX( RevReg::a2 ); + + auto action = [&] { // Do the mkdirat on the host - int rc = mkdirat(dirfd, ECALL.string.c_str(), mode); - RegFile->SetX(RevReg::a0, rc); + int rc = mkdirat( dirfd, ECALL.string.c_str(), mode ); + RegFile->SetX( RevReg::a0, rc ); }; - return EcallLoadAndParseString(inst, path, action); + return EcallLoadAndParseString( path, action ); } // 35, rev_unlinkat(int dfd, const char * pathname, int flag) -EcallStatus RevProc::ECALL_unlinkat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, +EcallStatus RevCore::ECALL_unlinkat() { + output->verbose( + CALL_INFO, + 2, + 0, - "ECALL: unlinkat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); + "ECALL: unlinkat called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 36, rev_symlinkat(const char * oldname, int newdfd, const char * newname) -EcallStatus RevProc::ECALL_symlinkat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: symlinkat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_symlinkat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: symlinkat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 37, rev_unlinkat(int dfd, const char * pathname, int flag) -EcallStatus RevProc::ECALL_linkat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: linkat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_linkat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: linkat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 38, rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) -EcallStatus RevProc::ECALL_renameat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: renameat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_renameat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: renameat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 39, rev_umount(char *name, int flags) -EcallStatus RevProc::ECALL_umount(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: umount called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_umount() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: umount called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 40, rev_umount(char *name, int flags) -EcallStatus RevProc::ECALL_mount(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mount called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mount() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mount called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 41, rev_pivot_root(const char *new_root, const char *put_old) -EcallStatus RevProc::ECALL_pivot_root(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pivot_root called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pivot_root() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pivot_root called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 42, rev_ni_syscall(void) -EcallStatus RevProc::ECALL_ni_syscall(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ni_syscall called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ni_syscall() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ni_syscall called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 43, rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) -EcallStatus RevProc::ECALL_statfs64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: statfs64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_statfs64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: statfs64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 44, rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf) -EcallStatus RevProc::ECALL_fstatfs64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fstatfs64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fstatfs64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fstatfs64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 45, rev_truncate64(const char *path, loff_t length) -EcallStatus RevProc::ECALL_truncate64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: truncate64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_truncate64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: truncate64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 46, rev_ftruncate64(unsigned int fd, loff_t length) -EcallStatus RevProc::ECALL_ftruncate64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ftruncate64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ftruncate64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ftruncate64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 47, rev_fallocate(int fd, int mode, loff_t offset, loff_t len) -EcallStatus RevProc::ECALL_fallocate(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fallocate called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fallocate() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fallocate called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 48, rev_faccessat(int dfd, const char *filename, int mode) -EcallStatus RevProc::ECALL_faccessat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: faccessat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_faccessat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: faccessat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 49, rev_chdir(const char *filename) -EcallStatus RevProc::ECALL_chdir(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: chdir called\n"); - auto path = RegFile->GetX(RevReg::a0); - auto action = [&]{ - int rc = chdir(Harts.at(HartToExecID)->GetEcallState().string.c_str()); - RegFile->SetX(RevReg::a0, rc); +EcallStatus RevCore::ECALL_chdir() { + output->verbose( CALL_INFO, 2, 0, "ECALL: chdir called\n" ); + auto path = RegFile->GetX( RevReg::a0 ); + auto action = [&] { + int rc = chdir( Harts.at( HartToExecID )->GetEcallState().string.c_str() ); + RegFile->SetX( RevReg::a0, rc ); }; - return EcallLoadAndParseString(inst, path, action); + return EcallLoadAndParseString( path, action ); } // 50, rev_fchdir(unsigned int fd) -EcallStatus RevProc::ECALL_fchdir(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, +EcallStatus RevCore::ECALL_fchdir() { + output->verbose( + CALL_INFO, + 2, + 0, - "ECALL: fchdir called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); + "ECALL: fchdir called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 51, rev_chroot(const char *filename) -EcallStatus RevProc::ECALL_chroot(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: chroot called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_chroot() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: chroot called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 52, rev_fchmod(unsigned int fd, umode_t mode) -EcallStatus RevProc::ECALL_fchmod(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fchmod called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fchmod() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fchmod called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 53, rev_fchmodat(int dfd, const char * filename, umode_t mode) -EcallStatus RevProc::ECALL_fchmodat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fchmodat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fchmodat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fchmodat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 54, rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) -EcallStatus RevProc::ECALL_fchownat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fchownat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fchownat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fchownat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 55, rev_fchown(unsigned int fd, uid_t user, gid_t group) -EcallStatus RevProc::ECALL_fchown(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fchown called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fchown() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fchown called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 56, rev_openat(int dfd, const char *filename, int flags, umode_t mode) -EcallStatus RevProc::ECALL_openat(RevInst& inst){ - auto& EcallState = Harts.at(HartToExecID)->GetEcallState(); - if( EcallState.bytesRead == 0 ){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: openat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_openat() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: openat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); } - auto dirfd = RegFile->GetX(RevReg::a0); - auto pathname = RegFile->GetX(RevReg::a1); + auto dirfd = RegFile->GetX( RevReg::a0 ); + auto pathname = RegFile->GetX( RevReg::a1 ); // commented out to remove warnings // auto flags = RegFile->GetX(RevReg::a2); - auto mode = RegFile->GetX(RevReg::a3); + auto mode = RegFile->GetX( RevReg::a3 ); /* * NOTE: this is currently only opening files in the current directory @@ -606,2111 +605,2153 @@ EcallStatus RevProc::ECALL_openat(RevInst& inst){ /* Read the filename from memory one character at a time until we find '\0' */ - - auto action = [&]{ + auto action = [&] { // Do the openat on the host - dirfd = open(std::filesystem::current_path().c_str(), mode); - int fd = openat(dirfd, EcallState.string.c_str(), mode); + dirfd = open( std::filesystem::current_path().c_str(), mode ); + int fd = openat( dirfd, EcallState.string.c_str(), mode ); // Add the file descriptor to this thread - Harts.at(HartToExecID)->Thread->AddFD(fd); + Harts.at( HartToExecID )->Thread->AddFD( fd ); // openat returns the file descriptor of the opened file - Harts.at(HartToExecID)->RegFile->SetX(RevReg::a0, fd); - + Harts.at( HartToExecID )->RegFile->SetX( RevReg::a0, fd ); }; - return EcallLoadAndParseString(inst, pathname, action); + return EcallLoadAndParseString( pathname, action ); } // 57, rev_close(unsigned int fd) -EcallStatus RevProc::ECALL_close(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: close called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); - auto fd = RegFile->GetX(RevReg::a0); - auto& ActiveThread = Harts.at(HartToExecID)->Thread; +EcallStatus RevCore::ECALL_close() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: close called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + auto fd = RegFile->GetX( RevReg::a0 ); + auto& ActiveThread = Harts.at( HartToExecID )->Thread; // Check if CurrCtx has fd in fildes vector - if( !ActiveThread->FindFD(fd) ){ - output->fatal(CALL_INFO, -1, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 - " tried to close file descriptor %" PRIu32 - " but did not have access to it\n", - id, HartToExecID, ActiveThreadID, fd); + if( !ActiveThread->FindFD( fd ) ) { + output->fatal( + CALL_INFO, + -1, + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 " tried to close file descriptor %" PRIu32 + " but did not have access to it\n", + id, + HartToExecID, + ActiveThreadID, + fd + ); return EcallStatus::SUCCESS; } // Close file on host - int rc = close(fd); + int rc = close( fd ); // Remove from Ctx's fildes - ActiveThread->RemoveFD(fd); + ActiveThread->RemoveFD( fd ); // rc is propogated to rev from host - RegFile->SetX(RevReg::a0, rc); + RegFile->SetX( RevReg::a0, rc ); return EcallStatus::SUCCESS; } // 58, rev_vhangup(void) -EcallStatus RevProc::ECALL_vhangup(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: vhangup called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_vhangup() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: vhangup called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 59, rev_pipe2(int *fildes, int flags) -EcallStatus RevProc::ECALL_pipe2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pipe2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pipe2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pipe2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 60, rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) -EcallStatus RevProc::ECALL_quotactl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: quotactl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_quotactl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: quotactl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 61, rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) -EcallStatus RevProc::ECALL_getdents64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getdents64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getdents64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getdents64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 62, rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) -EcallStatus RevProc::ECALL_lseek(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: lseek called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_lseek() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: lseek called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 63, rev_read(unsigned int fd -EcallStatus RevProc::ECALL_read(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: read called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); - auto fd = RegFile->GetX(RevReg::a0); - auto BufAddr = RegFile->GetX(RevReg::a1); - auto BufSize = RegFile->GetX(RevReg::a2); +EcallStatus RevCore::ECALL_read() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: read called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + auto fd = RegFile->GetX( RevReg::a0 ); + auto BufAddr = RegFile->GetX( RevReg::a1 ); + auto BufSize = RegFile->GetX( RevReg::a2 ); // Check if Current Ctx has access to the fd - auto& ActiveThread = Harts.at(HartToExecID)->Thread; - - if( !ActiveThread->FindFD(fd) ){ - output->fatal(CALL_INFO, -1, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 - " tried to read from file descriptor: %" PRIi32 - ", but did not have access to it\n", - id, HartToExecID, ActiveThreadID, fd); + auto& ActiveThread = Harts.at( HartToExecID )->Thread; + + if( !ActiveThread->FindFD( fd ) ) { + output->fatal( + CALL_INFO, + -1, + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 " tried to read from file descriptor: %" PRIi32 + ", but did not have access to it\n", + id, + HartToExecID, + ActiveThreadID, + fd + ); return EcallStatus::SUCCESS; } // This buffer is an intermediate buffer for storing the data read from host // for later use in writing to RevMem - std::vector TmpBuf(BufSize); + std::vector TmpBuf( BufSize ); // Do the read on the host - int rc = read(fd, &TmpBuf[0], BufSize); + auto rc = read( fd, &TmpBuf[0], BufSize ); // Write that data to the buffer inside of Rev - mem->WriteMem(HartToExecID, BufAddr, BufSize, &TmpBuf[0]); + mem->WriteMem( HartToExecID, BufAddr, uint32_t( BufSize ), &TmpBuf[0] ); - RegFile->SetX(RevReg::a0, rc); + RegFile->SetX( RevReg::a0, rc ); return EcallStatus::SUCCESS; } - -EcallStatus RevProc::ECALL_write(RevInst& inst){ - auto& EcallState = Harts.at(HartToExecID)->GetEcallState(); - if( EcallState.bytesRead == 0 ){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: write called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_write() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: write called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); } - auto fd = RegFile->GetX(RevReg::a0); - auto addr = RegFile->GetX(RevReg::a1); - auto nbytes = RegFile->GetX(RevReg::a2); + auto fd = RegFile->GetX( RevReg::a0 ); + auto addr = RegFile->GetX( RevReg::a1 ); + auto nbytes = RegFile->GetX( RevReg::a2 ); - auto lsq_hash = LSQHash(RevReg::a0, RevRegClass::RegGPR, HartToExecID); // Cached hash value + auto lsq_hash = LSQHash( RevReg::a0, RevRegClass::RegGPR, HartToExecID ); // Cached hash value - if(EcallState.bytesRead && LSQueue->count(lsq_hash) == 0){ - EcallState.string += std::string_view(EcallState.buf.data(), EcallState.bytesRead); + if( EcallState.bytesRead && LSQueue->count( lsq_hash ) == 0 ) { + EcallState.string += std::string_view( EcallState.buf.data(), EcallState.bytesRead ); EcallState.bytesRead = 0; } auto nleft = nbytes - EcallState.string.size(); - if(nleft == 0 && LSQueue->count(lsq_hash) == 0){ - int rc = write(fd, EcallState.string.data(), EcallState.string.size()); - RegFile->SetX(RevReg::a0, rc); - EcallState.clear(); - DependencyClear(HartToExecID, RevReg::a0, false); + if( nleft == 0 && LSQueue->count( lsq_hash ) == 0 ) { + auto rc = write( fd, EcallState.string.data(), EcallState.string.size() ); + RegFile->SetX( RevReg::a0, rc ); + DependencyClear( HartToExecID, RevReg::a0, RevRegClass::RegGPR ); return EcallStatus::SUCCESS; } - if (LSQueue->count(lsq_hash) == 0) { - MemReq req (addr + EcallState.string.size(), RevReg::a0, RevRegClass::RegGPR, - HartToExecID, MemOp::MemOpREAD, true, RegFile->GetMarkLoadComplete()); - LSQueue->insert(req.LSQHashPair()); - - if(nleft >= 8){ - mem->ReadVal(HartToExecID, addr+EcallState.string.size(), - reinterpret_cast(EcallState.buf.data()), - req, RevFlag::F_NONE); + if( LSQueue->count( lsq_hash ) == 0 ) { + MemReq req( + addr + EcallState.string.size(), + RevReg::a0, + RevRegClass::RegGPR, + HartToExecID, + MemOp::MemOpREAD, + true, + RegFile->GetMarkLoadComplete() + ); + LSQueue->insert( req.LSQHashPair() ); + + if( nleft >= 8 ) { + mem->ReadVal( + HartToExecID, addr + EcallState.string.size(), reinterpret_cast( EcallState.buf.data() ), req, RevFlag::F_NONE + ); EcallState.bytesRead = 8; - } else if(nleft >= 4){ - mem->ReadVal(HartToExecID, addr+EcallState.string.size(), - reinterpret_cast(EcallState.buf.data()), - req, RevFlag::F_NONE); + } else if( nleft >= 4 ) { + mem->ReadVal( + HartToExecID, addr + EcallState.string.size(), reinterpret_cast( EcallState.buf.data() ), req, RevFlag::F_NONE + ); EcallState.bytesRead = 4; - } else if(nleft >= 2){ - mem->ReadVal(HartToExecID, addr+EcallState.string.size(), - reinterpret_cast(EcallState.buf.data()), - req, RevFlag::F_NONE); + } else if( nleft >= 2 ) { + mem->ReadVal( + HartToExecID, addr + EcallState.string.size(), reinterpret_cast( EcallState.buf.data() ), req, RevFlag::F_NONE + ); EcallState.bytesRead = 2; - } else{ - mem->ReadVal(HartToExecID, addr+EcallState.string.size(), - reinterpret_cast(EcallState.buf.data()), - req, RevFlag::F_NONE); + } else { + mem->ReadVal( + HartToExecID, addr + EcallState.string.size(), reinterpret_cast( EcallState.buf.data() ), req, RevFlag::F_NONE + ); EcallState.bytesRead = 1; } - DependencySet(HartToExecID, RevReg::a0, false); + DependencySet( HartToExecID, RevReg::a0, RevRegClass::RegGPR ); return EcallStatus::CONTINUE; } return EcallStatus::CONTINUE; } + // 65, rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) -EcallStatus RevProc::ECALL_readv(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: readv called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_readv() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: readv called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 66, rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) -EcallStatus RevProc::ECALL_writev(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: writev called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_writev() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: writev called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 67, rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) -EcallStatus RevProc::ECALL_pread64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pread64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pread64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pread64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 68, rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) -EcallStatus RevProc::ECALL_pwrite64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pwrite64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pwrite64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pwrite64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 69, rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) -EcallStatus RevProc::ECALL_preadv(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: preadv called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_preadv() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: preadv called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 70, rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) -EcallStatus RevProc::ECALL_pwritev(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pwritev called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pwritev() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pwritev called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 71, rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) -EcallStatus RevProc::ECALL_sendfile64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sendfile64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sendfile64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sendfile64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 72, rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *) -EcallStatus RevProc::ECALL_pselect6_time32(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pselect6_time32 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pselect6_time32() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pselect6_time32 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 73, rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t) -EcallStatus RevProc::ECALL_ppoll_time32(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ppoll_time32 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ppoll_time32() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ppoll_time32 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 74, rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) -EcallStatus RevProc::ECALL_signalfd4(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: signalfd4 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_signalfd4() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: signalfd4 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 75, rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) -EcallStatus RevProc::ECALL_vmsplice(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: vmsplice called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_vmsplice() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: vmsplice called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 76, rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) -EcallStatus RevProc::ECALL_splice(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: splice called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_splice() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: splice called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 77, rev_tee(int fdin, int fdout, size_t len, unsigned int flags) -EcallStatus RevProc::ECALL_tee(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: tee called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_tee() { + output->verbose( CALL_INFO, 2, 0, "ECALL: tee called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID ); return EcallStatus::SUCCESS; } // 78, rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) -EcallStatus RevProc::ECALL_readlinkat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: readlinkat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_readlinkat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: readlinkat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 79, rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) -EcallStatus RevProc::ECALL_newfstatat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: newfstatat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_newfstatat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: newfstatat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 80, rev_newfstat(unsigned int fd, struct stat *statbuf) -EcallStatus RevProc::ECALL_newfstat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: newfstat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_newfstat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: newfstat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 81, rev_sync(void) -EcallStatus RevProc::ECALL_sync(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sync called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sync() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sync called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 82, rev_fsync(unsigned int fd) -EcallStatus RevProc::ECALL_fsync(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fsync called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fsync() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fsync called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 83, rev_fdatasync(unsigned int fd) -EcallStatus RevProc::ECALL_fdatasync(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fdatasync called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fdatasync() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fdatasync called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 84, rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) -EcallStatus RevProc::ECALL_sync_file_range2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sync_file_range2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sync_file_range2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sync_file_range2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 84, rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) -EcallStatus RevProc::ECALL_sync_file_range(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sync_file_range called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sync_file_range() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sync_file_range called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 85, rev_timerfd_create(int clockid, int flags) -EcallStatus RevProc::ECALL_timerfd_create(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timerfd_create called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timerfd_create() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timerfd_create called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 86, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) -EcallStatus RevProc::ECALL_timerfd_settime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timerfd_settime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timerfd_settime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timerfd_settime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 87, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) -EcallStatus RevProc::ECALL_timerfd_gettime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timerfd_gettime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timerfd_gettime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timerfd_gettime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 88, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) -EcallStatus RevProc::ECALL_utimensat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: utimensat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_utimensat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: utimensat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 89, rev_acct(const char *name) -EcallStatus RevProc::ECALL_acct(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: acct called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_acct() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: acct called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 90, rev_capget(cap_user_header_t header, cap_user_data_t dataptr) -EcallStatus RevProc::ECALL_capget(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: capget called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_capget() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: capget called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 91, rev_capset(cap_user_header_t header, const cap_user_data_t data) -EcallStatus RevProc::ECALL_capset(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: capset called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_capset() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: capset called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 92, rev_personality(unsigned int personality) -EcallStatus RevProc::ECALL_personality(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: personality called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_personality() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: personality called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 93, rev_exit(int error_code) -EcallStatus RevProc::ECALL_exit(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: exit called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); - auto status = RegFile->GetX(RevReg::a0); - - output->verbose(CALL_INFO, 0, 0, - "thread %" PRIu32 " on hart %" PRIu32 "exiting with" - " status %" PRIu64 "\n", - ActiveThreadID, HartToExecID, status ); - exit(status); - return EcallStatus::SUCCESS; +EcallStatus RevCore::ECALL_exit() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: exit called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + auto status = RegFile->GetX( RevReg::a0 ); + + output->verbose( + CALL_INFO, + 0, + 0, + "thread %" PRIu32 " on hart %" PRIu32 "exiting with" + " status %" PRIu64 "\n", + ActiveThreadID, + HartToExecID, + status + ); + exit( int( status ) ); + // return EcallStatus::SUCCESS; } - // 94, rev_exit_group(int error_code) -EcallStatus RevProc::ECALL_exit_group(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: exit_group called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_exit_group() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: exit_group called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 95, rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) -EcallStatus RevProc::ECALL_waitid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: waitid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_waitid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: waitid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 96, rev_set_tid_address(int *tidptr) -EcallStatus RevProc::ECALL_set_tid_address(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: set_tid_address called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_set_tid_address() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: set_tid_address called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 97, rev_unshare(unsigned long unshare_flags) -EcallStatus RevProc::ECALL_unshare(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: unshare called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_unshare() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: unshare called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 98, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) -EcallStatus RevProc::ECALL_futex(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: futex called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_futex() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: futex called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 99, rev_set_robust_list(struct robust_list_head *head, size_t len) -EcallStatus RevProc::ECALL_set_robust_list(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: set_robust_list called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_set_robust_list() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: set_robust_list called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 100, rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) -EcallStatus RevProc::ECALL_get_robust_list(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: get_robust_list called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_get_robust_list() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: get_robust_list called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 101, rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) -EcallStatus RevProc::ECALL_nanosleep(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: nanosleep called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_nanosleep() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: nanosleep called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 102, rev_getitimer(int which, struct __kernel_old_itimerval *value) -EcallStatus RevProc::ECALL_getitimer(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getitimer called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getitimer() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getitimer called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 103, rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) -EcallStatus RevProc::ECALL_setitimer(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setitimer called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setitimer() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setitimer called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 104, rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) -EcallStatus RevProc::ECALL_kexec_load(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: kexec_load called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_kexec_load() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: kexec_load called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 105, rev_init_module(void *umod, unsigned long len, const char *uargs) -EcallStatus RevProc::ECALL_init_module(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: init_module called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_init_module() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: init_module called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 106, rev_delete_module(const char *name_user, unsigned int flags) -EcallStatus RevProc::ECALL_delete_module(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: delete_module called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_delete_module() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: delete_module called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 107, rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) -EcallStatus RevProc::ECALL_timer_create(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timer_create called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timer_create() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timer_create called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 108, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) -EcallStatus RevProc::ECALL_timer_gettime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timer_gettime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timer_gettime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timer_gettime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 109, rev_timer_getoverrun(timer_t timer_id) -EcallStatus RevProc::ECALL_timer_getoverrun(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timer_getoverrun called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timer_getoverrun() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timer_getoverrun called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 110, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) -EcallStatus RevProc::ECALL_timer_settime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timer_settime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timer_settime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timer_settime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 111, rev_timer_delete(timer_t timer_id) -EcallStatus RevProc::ECALL_timer_delete(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: timer_delete called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_timer_delete() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: timer_delete called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 112, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) -EcallStatus RevProc::ECALL_clock_settime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clock_settime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clock_settime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clock_settime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 113, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) -EcallStatus RevProc::ECALL_clock_gettime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clock_gettime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); - struct timespec src, *tp = (struct timespec *) RegFile->GetX(RevReg::a1); - - if (timeConverter == nullptr) { - RegFile->SetX(RevReg::a0, EINVAL); +EcallStatus RevCore::ECALL_clock_gettime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clock_gettime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + struct timespec src, *tp = (struct timespec*) RegFile->GetX( RevReg::a1 ); + + if( timeConverter == nullptr ) { + RegFile->SetX( RevReg::a0, EINVAL ); return EcallStatus::SUCCESS; } - memset(&src, 0, sizeof(*tp)); - SimTime_t x = timeConverter->convertToCoreTime(Stats.totalCycles); - src.tv_sec = x / 1000000000000ull; - src.tv_nsec = (x / 1000) % 1000000000ull; - mem->WriteMem(HartToExecID, (size_t)tp, sizeof(*tp), &src); - RegFile->SetX(RevReg::a0, 0); + memset( &src, 0, sizeof( *tp ) ); + SimTime_t x = timeConverter->convertToCoreTime( Stats.totalCycles ); + src.tv_sec = time_t( x / 1000000000000 ); + src.tv_nsec = long( ( x / 1000 ) % 1000000000 ); + mem->WriteMem( HartToExecID, (size_t) tp, sizeof( *tp ), &src ); + RegFile->SetX( RevReg::a0, 0 ); return EcallStatus::SUCCESS; } // 114, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) -EcallStatus RevProc::ECALL_clock_getres(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clock_getres called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clock_getres() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clock_getres called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 115, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) -EcallStatus RevProc::ECALL_clock_nanosleep(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clock_nanosleep called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clock_nanosleep() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clock_nanosleep called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 116, rev_syslog(int type, char *buf, int len) -EcallStatus RevProc::ECALL_syslog(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: syslog called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_syslog() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: syslog called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 117, rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) -EcallStatus RevProc::ECALL_ptrace(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: ptrace called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_ptrace() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: ptrace called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 118, rev_sched_setparam(pid_t pid, struct sched_param *param) -EcallStatus RevProc::ECALL_sched_setparam(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_setparam called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_setparam() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_setparam called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 119, rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) -EcallStatus RevProc::ECALL_sched_setscheduler(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_setscheduler called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_setscheduler() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_setscheduler called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 120, rev_sched_getscheduler(pid_t pid) -EcallStatus RevProc::ECALL_sched_getscheduler(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_getscheduler called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_getscheduler() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_getscheduler called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 121, rev_sched_getparam(pid_t pid, struct sched_param *param) -EcallStatus RevProc::ECALL_sched_getparam(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_getparam called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_getparam() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_getparam called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 122, rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) -EcallStatus RevProc::ECALL_sched_setaffinity(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_setaffinity called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_setaffinity() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_setaffinity called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 123, rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) -EcallStatus RevProc::ECALL_sched_getaffinity(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_getaffinity called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_getaffinity() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_getaffinity called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 124, rev_sched_yield(void) -EcallStatus RevProc::ECALL_sched_yield(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_yield called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_yield() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_yield called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 125, rev_sched_get_priority_max(int policy) -EcallStatus RevProc::ECALL_sched_get_priority_max(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_get_priority_max called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_get_priority_max() { + output->verbose( + CALL_INFO, + 2, + 0, + "ECALL: sched_get_priority_max called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 126, rev_sched_get_priority_min(int policy) -EcallStatus RevProc::ECALL_sched_get_priority_min(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_get_priority_min called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_get_priority_min() { + output->verbose( + CALL_INFO, + 2, + 0, + "ECALL: sched_get_priority_min called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 127, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) -EcallStatus RevProc::ECALL_sched_rr_get_interval(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_rr_get_interval called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_rr_get_interval() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_rr_get_interval called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 128, rev_restart_syscall(void) -EcallStatus RevProc::ECALL_restart_syscall(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: restart_syscall called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_restart_syscall() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: restart_syscall called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 129, rev_kill(pid_t pid, int sig) -EcallStatus RevProc::ECALL_kill(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: kill called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_kill() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: kill called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 130, rev_tkill(pid_t pid, int sig) -EcallStatus RevProc::ECALL_tkill(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: tkill called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_tkill() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: tkill called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 131, rev_tgkill(pid_t tgid, pid_t pid, int sig) -EcallStatus RevProc::ECALL_tgkill(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: tgkill called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_tgkill() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: tgkill called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 132, rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) -EcallStatus RevProc::ECALL_sigaltstack(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sigaltstack called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sigaltstack() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sigaltstack called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 133, rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) -EcallStatus RevProc::ECALL_rt_sigsuspend(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigsuspend called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigsuspend() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_sigsuspend called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 134, rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) -EcallStatus RevProc::ECALL_rt_sigaction(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigaction called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigaction() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_sigaction called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 135, rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) -EcallStatus RevProc::ECALL_rt_sigprocmask(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigprocmask called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigprocmask() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_sigprocmask called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 136, rev_rt_sigpending(sigset_t *set, size_t sigsetsize) -EcallStatus RevProc::ECALL_rt_sigpending(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigpending called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigpending() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_sigpending called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 137, rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) -EcallStatus RevProc::ECALL_rt_sigtimedwait_time32(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigtimedwait_time32 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigtimedwait_time32() { + output->verbose( + CALL_INFO, + 2, + 0, + "ECALL: rt_sigtimedwait_time32 called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 138, rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) -EcallStatus RevProc::ECALL_rt_sigqueueinfo(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_sigqueueinfo called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_sigqueueinfo() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_sigqueueinfo called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 140, rev_setpriority(int which, int who, int niceval) -EcallStatus RevProc::ECALL_setpriority(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setpriority called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setpriority() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setpriority called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 141, rev_getpriority(int which, int who) -EcallStatus RevProc::ECALL_getpriority(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getpriority called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getpriority() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getpriority called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 142, rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) -EcallStatus RevProc::ECALL_reboot(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: reboot called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_reboot() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: reboot called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 143, rev_setregid(gid_t rgid, gid_t egid) -EcallStatus RevProc::ECALL_setregid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setregid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setregid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setregid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 144, rev_setgid(gid_t gid) -EcallStatus RevProc::ECALL_setgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 145, rev_setreuid(uid_t ruid, uid_t euid) -EcallStatus RevProc::ECALL_setreuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setreuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setreuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setreuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 146, rev_setuid(uid_t uid) -EcallStatus RevProc::ECALL_setuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 147, rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) -EcallStatus RevProc::ECALL_setresuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setresuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setresuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setresuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 148, rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) -EcallStatus RevProc::ECALL_getresuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getresuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getresuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getresuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 149, rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) -EcallStatus RevProc::ECALL_setresgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setresgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setresgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setresgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 150, rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) -EcallStatus RevProc::ECALL_getresgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getresgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getresgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getresgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 151, rev_setfsuid(uid_t uid) -EcallStatus RevProc::ECALL_setfsuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setfsuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setfsuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setfsuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 152, rev_setfsgid(gid_t gid) -EcallStatus RevProc::ECALL_setfsgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setfsgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setfsgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setfsgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 153, rev_times(struct tms *tbuf) -EcallStatus RevProc::ECALL_times(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: times called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_times() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: times called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 154, rev_setpgid(pid_t pid, pid_t pgid) -EcallStatus RevProc::ECALL_setpgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setpgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setpgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setpgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 155, rev_getpgid(pid_t pid) -EcallStatus RevProc::ECALL_getpgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getpgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getpgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getpgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 156, rev_getsid(pid_t pid) -EcallStatus RevProc::ECALL_getsid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getsid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getsid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getsid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 157, rev_setsid(void) -EcallStatus RevProc::ECALL_setsid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setsid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setsid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setsid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 158, rev_getgroups(int gidsetsize, gid_t *grouplist) -EcallStatus RevProc::ECALL_getgroups(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getgroups called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getgroups() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getgroups called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 159, rev_setgroups(int gidsetsize, gid_t *grouplist) -EcallStatus RevProc::ECALL_setgroups(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setgroups called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setgroups() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setgroups called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 160, rev_newuname(struct new_utsname *name) -EcallStatus RevProc::ECALL_newuname(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: newuname called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_newuname() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: newuname called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 161, rev_sethostname(char *name, int len) -EcallStatus RevProc::ECALL_sethostname(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sethostname called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sethostname() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sethostname called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 162, rev_setdomainname(char *name, int len) -EcallStatus RevProc::ECALL_setdomainname(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setdomainname called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setdomainname() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setdomainname called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 163, rev_getrlimit(unsigned int resource, struct rlimit *rlim) -EcallStatus RevProc::ECALL_getrlimit(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getrlimit called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getrlimit() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getrlimit called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 164, rev_setrlimit(unsigned int resource, struct rlimit *rlim) -EcallStatus RevProc::ECALL_setrlimit(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setrlimit called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setrlimit() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setrlimit called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 165, rev_getrusage(int who, struct rusage *ru) -EcallStatus RevProc::ECALL_getrusage(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getrusage called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getrusage() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getrusage called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 166, rev_umask(int mask) -EcallStatus RevProc::ECALL_umask(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: umask called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_umask() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: umask called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 167, rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) -EcallStatus RevProc::ECALL_prctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: prctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_prctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: prctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 168, rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) -EcallStatus RevProc::ECALL_getcpu(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getcpu called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getcpu() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getcpu called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 169, rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) -EcallStatus RevProc::ECALL_gettimeofday(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: gettimeofday called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_gettimeofday() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: gettimeofday called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 170, rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) -EcallStatus RevProc::ECALL_settimeofday(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: settimeofday called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_settimeofday() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: settimeofday called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 171, rev_adjtimex(struct __kernel_timex *txc_p) -EcallStatus RevProc::ECALL_adjtimex(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: adjtimex called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_adjtimex() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: adjtimex called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 172, rev_getpid(void) -EcallStatus RevProc::ECALL_getpid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getpid called (Rev only supports a single process)\n"); +EcallStatus RevCore::ECALL_getpid() { + output->verbose( CALL_INFO, 2, 0, "ECALL: getpid called (Rev only supports a single process)\n" ); return EcallStatus::SUCCESS; } // 173, rev_getppid(void) -EcallStatus RevProc::ECALL_getppid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, +EcallStatus RevCore::ECALL_getppid() { + output->verbose( + CALL_INFO, + 2, + 0, - "ECALL: getppid called (Rev only supports a single process)\n"); + "ECALL: getppid called (Rev only supports a single process)\n" + ); return EcallStatus::SUCCESS; } // 174, rev_getuid(void) -EcallStatus RevProc::ECALL_getuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, +EcallStatus RevCore::ECALL_getuid() { + output->verbose( + CALL_INFO, + 2, + 0, - "ECALL: getuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); + "ECALL: getuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); return EcallStatus::SUCCESS; } // 175, rev_geteuid(void) -EcallStatus RevProc::ECALL_geteuid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: geteuid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_geteuid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: geteuid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 176, rev_getgid(void) -EcallStatus RevProc::ECALL_getgid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getgid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getgid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getgid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 177, rev_getegid(void) -EcallStatus RevProc::ECALL_getegid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getegid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getegid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getegid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 178, rev_gettid(void) -EcallStatus RevProc::ECALL_gettid(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: gettid called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_gettid() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: gettid called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); /* rc = Currently Executing Hart */ - RegFile->SetX(RevReg::a0, ActiveThreadID); + RegFile->SetX( RevReg::a0, ActiveThreadID ); return EcallStatus::SUCCESS; } // 179, rev_sysinfo(struct sysinfo *info) -EcallStatus RevProc::ECALL_sysinfo(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sysinfo called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sysinfo() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sysinfo called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 180, rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) -EcallStatus RevProc::ECALL_mq_open(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_open called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_open() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_open called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 181, rev_mq_unlink(const char *name) -EcallStatus RevProc::ECALL_mq_unlink(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_unlink called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_unlink() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_unlink called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 182, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) -EcallStatus RevProc::ECALL_mq_timedsend(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_timedsend called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_timedsend() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_timedsend called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 183, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) -EcallStatus RevProc::ECALL_mq_timedreceive(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_timedreceive called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_timedreceive() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_timedreceive called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 184, rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) -EcallStatus RevProc::ECALL_mq_notify(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_notify called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_notify() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_notify called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 185, rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) -EcallStatus RevProc::ECALL_mq_getsetattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mq_getsetattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mq_getsetattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mq_getsetattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 186, rev_msgget(key_t key, int msgflg) -EcallStatus RevProc::ECALL_msgget(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: msgget called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_msgget() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: msgget called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 187, rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) -EcallStatus RevProc::ECALL_msgctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: msgctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_msgctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: msgctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 188, rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) -EcallStatus RevProc::ECALL_msgrcv(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: msgrcv called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_msgrcv() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: msgrcv called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 189, rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) -EcallStatus RevProc::ECALL_msgsnd(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: msgsnd called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_msgsnd() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: msgsnd called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 190, rev_semget(key_t key, int nsems, int semflg) -EcallStatus RevProc::ECALL_semget(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: semget called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_semget() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: semget called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 191, rev_semctl(int semid, int semnum, int cmd, unsigned long arg) -EcallStatus RevProc::ECALL_semctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: semctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_semctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: semctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 192, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) -EcallStatus RevProc::ECALL_semtimedop(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: semtimedop called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_semtimedop() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: semtimedop called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 193, rev_semop(int semid, struct sembuf *sops, unsigned nsops) -EcallStatus RevProc::ECALL_semop(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: semop called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_semop() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: semop called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 194, rev_shmget(key_t key, size_t size, int flag) -EcallStatus RevProc::ECALL_shmget(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: shmget called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_shmget() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: shmget called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 195, rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) -EcallStatus RevProc::ECALL_shmctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: shmctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_shmctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: shmctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 196, rev_shmat(int shmid, char *shmaddr, int shmflg) -EcallStatus RevProc::ECALL_shmat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: shmat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_shmat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: shmat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 197, rev_shmdt(char *shmaddr) -EcallStatus RevProc::ECALL_shmdt(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: shmdt called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_shmdt() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: shmdt called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 198, rev_socket(int, int, int) -EcallStatus RevProc::ECALL_socket(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: socket called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_socket() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: socket called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 199, rev_socketpair(int, int, int, int *) -EcallStatus RevProc::ECALL_socketpair(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: socketpair called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_socketpair() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: socketpair called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 200, rev_bind(int, struct sockaddr *, int) -EcallStatus RevProc::ECALL_bind(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: bind called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_bind() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: bind called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 201, rev_listen(int, int) -EcallStatus RevProc::ECALL_listen(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: listen called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_listen() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: listen called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 202, rev_accept(int, struct sockaddr *, int *) -EcallStatus RevProc::ECALL_accept(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: accept called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_accept() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: accept called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 203, rev_connect(int, struct sockaddr *, int) -EcallStatus RevProc::ECALL_connect(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: connect called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_connect() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: connect called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 204, rev_getsockname(int, struct sockaddr *, int *) -EcallStatus RevProc::ECALL_getsockname(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getsockname called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getsockname() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getsockname called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 205, rev_getpeername(int, struct sockaddr *, int *) -EcallStatus RevProc::ECALL_getpeername(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getpeername called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getpeername() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getpeername called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 206, rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int) -EcallStatus RevProc::ECALL_sendto(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sendto called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sendto() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sendto called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 207, rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *) -EcallStatus RevProc::ECALL_recvfrom(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: recvfrom called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_recvfrom() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: recvfrom called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 208, rev_setsockopt(int fd, int level, int optname, char *optval, int optlen) -EcallStatus RevProc::ECALL_setsockopt(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setsockopt called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setsockopt() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setsockopt called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 209, rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen) -EcallStatus RevProc::ECALL_getsockopt(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getsockopt called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getsockopt() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getsockopt called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 210, rev_shutdown(int, int) -EcallStatus RevProc::ECALL_shutdown(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: shutdown called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_shutdown() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: shutdown called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 211, rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags) -EcallStatus RevProc::ECALL_sendmsg(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sendmsg called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sendmsg() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sendmsg called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 212, rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags) -EcallStatus RevProc::ECALL_recvmsg(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: recvmsg called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_recvmsg() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: recvmsg called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 213, rev_readahead(int fd, loff_t offset, size_t count) -EcallStatus RevProc::ECALL_readahead(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: readahead called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_readahead() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: readahead called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 214, rev_brk(unsigned long brk) -EcallStatus RevProc::ECALL_brk(RevInst& inst){ - auto Addr = RegFile->GetX(RevReg::a0); +EcallStatus RevCore::ECALL_brk() { + auto Addr = RegFile->GetX( RevReg::a0 ); const uint64_t heapend = mem->GetHeapEnd(); - if( Addr > 0 && Addr > heapend ){ + if( Addr > 0 && Addr > heapend ) { uint64_t Size = Addr - heapend; - mem->ExpandHeap(Size); + mem->ExpandHeap( Size ); } else { - output->fatal(CALL_INFO, 11, - "Out of memory / Unable to expand system break (brk) to " - "Addr = 0x%" PRIx64 "\n", Addr); + output->fatal( + CALL_INFO, + 11, + "Out of memory / Unable to expand system break (brk) to " + "Addr = 0x%" PRIx64 "\n", + Addr + ); } return EcallStatus::SUCCESS; } // 215, rev_munmap(unsigned long addr, size_t len) -EcallStatus RevProc::ECALL_munmap(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: munmap called\n"); - auto Addr = RegFile->GetX(RevReg::a0); - auto Size = RegFile->GetX(RevReg::a1); - - int rc = mem->DeallocMem(Addr, Size) == uint64_t(-1); - if(rc == -1){ - output->fatal(CALL_INFO, 11, - "Failed to perform munmap(Addr = 0x%" PRIx64 ", Size = %" PRIu64 ")" - "likely because the memory was not allocated to begin with" , - Addr, Size); +EcallStatus RevCore::ECALL_munmap() { + output->verbose( CALL_INFO, 2, 0, "ECALL: munmap called\n" ); + auto Addr = RegFile->GetX( RevReg::a0 ); + auto Size = RegFile->GetX( RevReg::a1 ); + + int rc = mem->DeallocMem( Addr, Size ) == uint64_t( -1 ); + if( rc == -1 ) { + output->fatal( + CALL_INFO, + 11, + "Failed to perform munmap(Addr = 0x%" PRIx64 ", Size = %" PRIu64 ")" + "likely because the memory was not allocated to begin with", + Addr, + Size + ); } - RegFile->SetX(RevReg::a0, rc); + RegFile->SetX( RevReg::a0, rc ); return EcallStatus::SUCCESS; } // 216, rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) -EcallStatus RevProc::ECALL_mremap(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mremap called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mremap() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mremap called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 217, rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) -EcallStatus RevProc::ECALL_add_key(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: add_key called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_add_key() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: add_key called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 218, rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) -EcallStatus RevProc::ECALL_request_key(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: request_key called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_request_key() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: request_key called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 219, rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) -EcallStatus RevProc::ECALL_keyctl(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: keyctl called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_keyctl() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: keyctl called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 220, rev_clone(unsigned long, unsigned long, int *, unsigned long, int *) -EcallStatus RevProc::ECALL_clone(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clone called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clone() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clone called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); auto rtval = EcallStatus::SUCCESS; - // auto CloneArgsAddr = RegFile->GetX(RevReg::a0); - // // auto SizeOfCloneArgs = RegFile()->GetX(RevReg::a1); - - // if(0 == ECALL.bytesRead){ - // // First time through the function... - // /* Fetch the clone_args */ - // // struct clone_args args; // So while clone_args is a whole struct, we appear to be only - // // using the 1st uint64, so that's all we're going to fetch - // uint64_t* args = reinterpret_cast(ECALL.buf.data()); - // mem->ReadVal(HartToExecID, CloneArgsAddr, args, inst.hazard, RevFlag::F_NONE); - // ECALL.bytesRead = sizeof(*args); - // rtval = EcallStatus::CONTINUE; - // }else{ - // /* - // * Parse clone flags - // * NOTE: if no flags are set, we get fork() like behavior - // */ - // uint64_t* args = reinterpret_cast(ECALL.buf.data()); - // for( uint64_t bit=1; bit != 0; bit <<= 1 ){ - // switch (*args & bit) { - // case CLONE_VM: - // // std::cout << "CLONE_VM is true" << std::endl; - // break; - // case CLONE_FS: /* Set if fs info shared between processes */ - // // std::cout << "CLONE_FS is true" << std::endl; - // break; - // case CLONE_FILES: /* Set if open files shared between processes */ - // // std::cout << "CLONE_FILES is true" << std::endl; - // break; - // case CLONE_SIGHAND: /* Set if signal handlers shared */ - // // std::cout << "CLONE_SIGHAND is true" << std::endl; - // break; - // case CLONE_PIDFD: /* Set if a pidfd should be placed in the parent */ - // // std::cout << "CLONE_PIDFD is true" << std::endl; - // break; - // case CLONE_PTRACE: /* Set if tracing continues on the child */ - // // std::cout << "CLONE_PTRACE is true" << std::endl; - // break; - // case CLONE_VFORK: /* Set if the parent wants the child to wake it up on mm_release */ - // // std::cout << "CLONE_VFORK is true" << std::endl; - // break; - // case CLONE_PARENT: /* Set if we want to have the same parent as the cloner */ - // // std::cout << "CLONE_PARENT is true" << std::endl; - // break; - // case CLONE_THREAD: /* Set to add to same thread group */ - // // std::cout << "CLONE_THREAD is true" << std::endl; - // break; - // case CLONE_NEWNS: /* Set to create new namespace */ - // // std::cout << "CLONE_NEWNS is true" << std::endl; - // break; - // case CLONE_SYSVSEM: /* Set to shared SVID SEM_UNDO semantics */ - // // std::cout << "CLONE_SYSVSEM is true" << std::endl; - // break; - // case CLONE_SETTLS: /* Set TLS info */ - // // std::cout << "CLONE_SETTLS is true" << std::endl; - // break; - // case CLONE_PARENT_SETTID: /* Store TID in userlevel buffer before MM copy */ - // // std::cout << "CLONE_PARENT_SETTID is true" << std::endl; - // break; - // case CLONE_CHILD_CLEARTID: /* Register exit futex and memory location to clear */ - // // std::cout << "CLONE_CHILD_CLEARTID is true" << std::endl; - // break; - // case CLONE_DETACHED: /* Create clone detached */ - // // std::cout << "CLONE_DETACHED is true" << std::endl; - // break; - // case CLONE_UNTRACED: /* Set if the tracing process can't force CLONE_PTRACE on this clone */ - // // std::cout << "CLONE_UNTRACED is true" << std::endl; - // break; - // case CLONE_CHILD_SETTID: /* New cgroup namespace */ - // // std::cout << "CLONE_CHILD_SETTID is true" << std::endl; - // break; - // case CLONE_NEWCGROUP: /* New cgroup namespace */ - // // std::cout << "CLONE_NEWCGROUP is true" << std::endl; - // break; - // case CLONE_NEWUTS: /* New utsname group */ - // // std::cout << "CLONE_NEWUTS is true" << std::endl; - // break; - // case CLONE_NEWIPC: /* New ipcs */ - // // std::cout << "CLONE_NEWIPC is true" << std::endl; - // break; - // case CLONE_NEWUSER: /* New user namespace */ - // // std::cout << "CLONE_NEWUSER is true" << std::endl; - // break; - // case CLONE_NEWPID: /* New pid namespace */ - // // std::cout << "CLONE_NEWPID is true" << std::endl; - // break; - // case CLONE_NEWNET: /* New network namespace */ - // // std::cout << "CLONE_NEWNET is true" << std::endl; - // break; - // case CLONE_IO: /* Clone I/O Context */ - // // std::cout << "CLONE_IO is true" << std::endl; - // break; - // default: - // break; - // } // switch - // } // for - - // /* Get the parent ctx (Current active, executing PID) */ - // std::shared_ptr ParentCtx = ThreadTable.at(ActivePIDs.at(HartToExecID)); - - // /* Create the child ctx */ - // uint32_t ChildPID = CreateChildCtx(); - // std::shared_ptr ChildCtx = ThreadTable.at(ChildPID); - - // /* - // * =========================================================================================== - // * Register File - // * =========================================================================================== - // * We need to duplicate the parent's RegFile to to the Childs - // * - NOTE: when we return from this function, the return value will - // * be automatically stored in the Proc.RegFile[HartToExecID]'s a0 - // * register. In a traditional fork code this looks like: - // * - // * pid_t pid = fork() - // * if pid < 0: // Error - // * else if pid = 0: // New Child Process - // * else: // Parent Process - // * - // * In this case, the value of pid is the value thats returned to a0 - // * It follows that - // * - The child's regfile MUST have 0 in its a0 (despite its pid != 0 to the RevProc) - // * - The Parent's a0 register MUST have its PID in it - // * =========================================================================================== - // */ - - // /* - // Alert the Proc there needs to be a Ctx switch - // Pass the PID that will be switched to once the - // current pipeline is executed until completion - // */ - // CtxSwitchAlert(ChildPID); - - // // Parent's return value is the child's PID - // RegFile->SetX(RevReg::a0, ChildPID); - - // // Child's return value is 0 - // ChildCtx->GetRegFile()->SetX(RevReg::a0, 0); - - // // clean up ecall state - // rtval = EcallStatus::SUCCESS; - // ECALL.bytesRead = 0; - - // } //else + // auto CloneArgsAddr = RegFile->GetX(RevReg::a0); + // // auto SizeOfCloneArgs = RegFile()->GetX(RevReg::a1); + + // if(0 == ECALL.bytesRead){ + // // First time through the function... + // /* Fetch the clone_args */ + // // struct clone_args args; // So while clone_args is a whole struct, we appear to be only + // // using the 1st uint64, so that's all we're going to fetch + // uint64_t* args = reinterpret_cast(ECALL.buf.data()); + // mem->ReadVal(HartToExecID, CloneArgsAddr, args, inst.hazard, RevFlag::F_NONE); + // ECALL.bytesRead = sizeof(*args); + // rtval = EcallStatus::CONTINUE; + // }else{ + // /* + // * Parse clone flags + // * NOTE: if no flags are set, we get fork() like behavior + // */ + // uint64_t* args = reinterpret_cast(ECALL.buf.data()); + // for( uint64_t bit=1; bit != 0; bit <<= 1 ){ + // switch (*args & bit) { + // case CLONE_VM: + // // std::cout << "CLONE_VM is true" << std::endl; + // break; + // case CLONE_FS: /* Set if fs info shared between processes */ + // // std::cout << "CLONE_FS is true" << std::endl; + // break; + // case CLONE_FILES: /* Set if open files shared between processes */ + // // std::cout << "CLONE_FILES is true" << std::endl; + // break; + // case CLONE_SIGHAND: /* Set if signal handlers shared */ + // // std::cout << "CLONE_SIGHAND is true" << std::endl; + // break; + // case CLONE_PIDFD: /* Set if a pidfd should be placed in the parent */ + // // std::cout << "CLONE_PIDFD is true" << std::endl; + // break; + // case CLONE_PTRACE: /* Set if tracing continues on the child */ + // // std::cout << "CLONE_PTRACE is true" << std::endl; + // break; + // case CLONE_VFORK: /* Set if the parent wants the child to wake it up on mm_release */ + // // std::cout << "CLONE_VFORK is true" << std::endl; + // break; + // case CLONE_PARENT: /* Set if we want to have the same parent as the cloner */ + // // std::cout << "CLONE_PARENT is true" << std::endl; + // break; + // case CLONE_THREAD: /* Set to add to same thread group */ + // // std::cout << "CLONE_THREAD is true" << std::endl; + // break; + // case CLONE_NEWNS: /* Set to create new namespace */ + // // std::cout << "CLONE_NEWNS is true" << std::endl; + // break; + // case CLONE_SYSVSEM: /* Set to shared SVID SEM_UNDO semantics */ + // // std::cout << "CLONE_SYSVSEM is true" << std::endl; + // break; + // case CLONE_SETTLS: /* Set TLS info */ + // // std::cout << "CLONE_SETTLS is true" << std::endl; + // break; + // case CLONE_PARENT_SETTID: /* Store TID in userlevel buffer before MM copy */ + // // std::cout << "CLONE_PARENT_SETTID is true" << std::endl; + // break; + // case CLONE_CHILD_CLEARTID: /* Register exit futex and memory location to clear */ + // // std::cout << "CLONE_CHILD_CLEARTID is true" << std::endl; + // break; + // case CLONE_DETACHED: /* Create clone detached */ + // // std::cout << "CLONE_DETACHED is true" << std::endl; + // break; + // case CLONE_UNTRACED: /* Set if the tracing process can't force CLONE_PTRACE on this clone */ + // // std::cout << "CLONE_UNTRACED is true" << std::endl; + // break; + // case CLONE_CHILD_SETTID: /* New cgroup namespace */ + // // std::cout << "CLONE_CHILD_SETTID is true" << std::endl; + // break; + // case CLONE_NEWCGROUP: /* New cgroup namespace */ + // // std::cout << "CLONE_NEWCGROUP is true" << std::endl; + // break; + // case CLONE_NEWUTS: /* New utsname group */ + // // std::cout << "CLONE_NEWUTS is true" << std::endl; + // break; + // case CLONE_NEWIPC: /* New ipcs */ + // // std::cout << "CLONE_NEWIPC is true" << std::endl; + // break; + // case CLONE_NEWUSER: /* New user namespace */ + // // std::cout << "CLONE_NEWUSER is true" << std::endl; + // break; + // case CLONE_NEWPID: /* New pid namespace */ + // // std::cout << "CLONE_NEWPID is true" << std::endl; + // break; + // case CLONE_NEWNET: /* New network namespace */ + // // std::cout << "CLONE_NEWNET is true" << std::endl; + // break; + // case CLONE_IO: /* Clone I/O Context */ + // // std::cout << "CLONE_IO is true" << std::endl; + // break; + // default: + // break; + // } // switch + // } // for + + // /* Get the parent ctx (Current active, executing PID) */ + // std::shared_ptr ParentCtx = ThreadTable.at(ActivePIDs.at(HartToExecID)); + + // /* Create the child ctx */ + // uint32_t ChildPID = CreateChildCtx(); + // std::shared_ptr ChildCtx = ThreadTable.at(ChildPID); + + // /* + // * =========================================================================================== + // * Register File + // * =========================================================================================== + // * We need to duplicate the parent's RegFile to to the Childs + // * - NOTE: when we return from this function, the return value will + // * be automatically stored in the Proc.RegFile[HartToExecID]'s a0 + // * register. In a traditional fork code this looks like: + // * + // * pid_t pid = fork() + // * if pid < 0: // Error + // * else if pid = 0: // New Child Process + // * else: // Parent Process + // * + // * In this case, the value of pid is the value thats returned to a0 + // * It follows that + // * - The child's regfile MUST have 0 in its a0 (despite its pid != 0 to the RevCore) + // * - The Parent's a0 register MUST have its PID in it + // * =========================================================================================== + // */ + + // /* + // Alert the Proc there needs to be a Ctx switch + // Pass the PID that will be switched to once the + // current pipeline is executed until completion + // */ + // CtxSwitchAlert(ChildPID); + + // // Parent's return value is the child's PID + // RegFile->SetX(RevReg::a0, ChildPID); + + // // Child's return value is 0 + // ChildCtx->GetRegFile()->SetX(RevReg::a0, 0); + + // // clean up ecall state + // rtval = EcallStatus::SUCCESS; + + // } //else return rtval; } // 221, rev_execve(const char *filename, const char *const *argv, const char *const *envp) -EcallStatus RevProc::ECALL_execve(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: execve called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_execve() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: execve called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 222, rev_old_mmap(struct mmap_arg_struct *arg) -EcallStatus RevProc::ECALL_mmap(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mmap called\n"); +EcallStatus RevCore::ECALL_mmap() { + output->verbose( CALL_INFO, 2, 0, "ECALL: mmap called\n" ); - auto addr = RegFile->GetX(RevReg::a0); - auto size = RegFile->GetX(RevReg::a1); + auto addr = RegFile->GetX( RevReg::a0 ); + auto size = RegFile->GetX( RevReg::a1 ); // auto prot = RegFile->GetX(RevReg::a2); // auto Flags = RegFile->GetX(RevReg::a3); // auto fd = RegFile->GetX(RevReg::a4); // auto offset = RegFile->GetX(RevReg::a5); - if( !addr ){ + if( !addr ) { // If address is NULL... We add it to MemSegs.end()->getTopAddr()+1 - addr = mem->AllocMem(size); + addr = mem->AllocMem( size ); // addr = mem->AddMemSeg(Size); } else { // We were passed an address... try to put a segment there. // Currently there is no handling of getting it 'close' to the // suggested address... instead if it can't allocate a new segment // there it fails. - if( !mem->AllocMemAt(addr, size) ){ - output->fatal(CALL_INFO, 11, - "Failed to add mem segment\n"); + if( !mem->AllocMemAt( addr, size ) ) { + output->fatal( CALL_INFO, 11, "Failed to add mem segment\n" ); } } - RegFile->SetX(RevReg::a0, addr); + RegFile->SetX( RevReg::a0, addr ); return EcallStatus::SUCCESS; } // 223, rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) -EcallStatus RevProc::ECALL_fadvise64_64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fadvise64_64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fadvise64_64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fadvise64_64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 224, rev_swapon(const char *specialfile, int swap_flags) -EcallStatus RevProc::ECALL_swapon(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: swapon called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_swapon() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: swapon called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 225, rev_swapoff(const char *specialfile) -EcallStatus RevProc::ECALL_swapoff(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: swapoff called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_swapoff() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: swapoff called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 226, rev_mprotect(unsigned long start, size_t len, unsigned long prot) -EcallStatus RevProc::ECALL_mprotect(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mprotect called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mprotect() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mprotect called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 227, rev_msync(unsigned long start, size_t len, int flags) -EcallStatus RevProc::ECALL_msync(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: msync called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_msync() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: msync called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 228, rev_mlock(unsigned long start, size_t len) -EcallStatus RevProc::ECALL_mlock(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mlock called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mlock() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mlock called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 229, rev_munlock(unsigned long start, size_t len) -EcallStatus RevProc::ECALL_munlock(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: munlock called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_munlock() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: munlock called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 230, rev_mlockall(int flags) -EcallStatus RevProc::ECALL_mlockall(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mlockall called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mlockall() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mlockall called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 231, rev_munlockall(void) -EcallStatus RevProc::ECALL_munlockall(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: munlockall called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_munlockall() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: munlockall called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 232, rev_mincore(unsigned long start, size_t len, unsigned char * vec) -EcallStatus RevProc::ECALL_mincore(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mincore called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mincore() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mincore called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 233, rev_madvise(unsigned long start, size_t len, int behavior) -EcallStatus RevProc::ECALL_madvise(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: madvise called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_madvise() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: madvise called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 234, rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) -EcallStatus RevProc::ECALL_remap_file_pages(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: remap_file_pages called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_remap_file_pages() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: remap_file_pages called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 235, rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) -EcallStatus RevProc::ECALL_mbind(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mbind called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mbind() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mbind called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 236, rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) -EcallStatus RevProc::ECALL_get_mempolicy(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: get_mempolicy called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_get_mempolicy() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: get_mempolicy called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 237, rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) -EcallStatus RevProc::ECALL_set_mempolicy(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: set_mempolicy called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_set_mempolicy() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: set_mempolicy called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 238, rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) -EcallStatus RevProc::ECALL_migrate_pages(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: migrate_pages called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_migrate_pages() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: migrate_pages called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 239, rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) -EcallStatus RevProc::ECALL_move_pages(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: move_pages called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_move_pages() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: move_pages called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 240, rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) -EcallStatus RevProc::ECALL_rt_tgsigqueueinfo(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rt_tgsigqueueinfo called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rt_tgsigqueueinfo() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rt_tgsigqueueinfo called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 241, rev_perf_event_open(") -EcallStatus RevProc::ECALL_perf_event_open(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: perf_event_open called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_perf_event_open() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: perf_event_open called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 242, rev_accept4(int, struct sockaddr *, int *, int) -EcallStatus RevProc::ECALL_accept4(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: accept4 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_accept4() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: accept4 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 243, rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout) -EcallStatus RevProc::ECALL_recvmmsg_time32(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: recvmmsg_time32 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_recvmmsg_time32() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: recvmmsg_time32 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 260, rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) -EcallStatus RevProc::ECALL_wait4(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: wait4 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_wait4() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: wait4 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 261, rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) -EcallStatus RevProc::ECALL_prlimit64(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: prlimit64 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_prlimit64() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: prlimit64 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 262, rev_fanotify_init(unsigned int flags, unsigned int event_f_flags) -EcallStatus RevProc::ECALL_fanotify_init(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fanotify_init called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fanotify_init() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fanotify_init called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 263, rev_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char *pathname) -EcallStatus RevProc::ECALL_fanotify_mark(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fanotify_mark called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fanotify_mark() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fanotify_mark called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 264, rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) -EcallStatus RevProc::ECALL_name_to_handle_at(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: name_to_handle_at called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_name_to_handle_at() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: name_to_handle_at called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 265, rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) -EcallStatus RevProc::ECALL_open_by_handle_at(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: open_by_handle_at called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_open_by_handle_at() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: open_by_handle_at called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 266, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) -EcallStatus RevProc::ECALL_clock_adjtime(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clock_adjtime called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clock_adjtime() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clock_adjtime called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 267, rev_syncfs(int fd) -EcallStatus RevProc::ECALL_syncfs(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: syncfs called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_syncfs() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: syncfs called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 268, rev_setns(int fd, int nstype) -EcallStatus RevProc::ECALL_setns(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: setns called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_setns() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: setns called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 269, rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) -EcallStatus RevProc::ECALL_sendmmsg(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sendmmsg called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sendmmsg() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sendmmsg called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 270, rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) -EcallStatus RevProc::ECALL_process_vm_readv(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: process_vm_readv called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_process_vm_readv() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: process_vm_readv called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 271, rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) -EcallStatus RevProc::ECALL_process_vm_writev(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: process_vm_writev called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_process_vm_writev() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: process_vm_writev called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 272, rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) -EcallStatus RevProc::ECALL_kcmp(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: kcmp called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_kcmp() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: kcmp called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 273, rev_finit_module(int fd, const char *uargs, int flags) -EcallStatus RevProc::ECALL_finit_module(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: finit_module called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_finit_module() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: finit_module called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 274, rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) -EcallStatus RevProc::ECALL_sched_setattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_setattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_setattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_setattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 275, rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) -EcallStatus RevProc::ECALL_sched_getattr(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: sched_getattr called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_sched_getattr() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: sched_getattr called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 276, rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) -EcallStatus RevProc::ECALL_renameat2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: renameat2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_renameat2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: renameat2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 277, rev_seccomp(unsigned int op, unsigned int flags, void *uargs) -EcallStatus RevProc::ECALL_seccomp(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: seccomp called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_seccomp() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: seccomp called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 278, rev_getrandom(char *buf, size_t count, unsigned int flags) -EcallStatus RevProc::ECALL_getrandom(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: getrandom called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_getrandom() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: getrandom called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 279, rev_memfd_create(const char *uname_ptr, unsigned int flags) -EcallStatus RevProc::ECALL_memfd_create(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: memfd_create called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_memfd_create() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: memfd_create called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 280, rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) -EcallStatus RevProc::ECALL_bpf(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: bpf called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_bpf() { + output->verbose( CALL_INFO, 2, 0, "ECALL: bpf called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID ); return EcallStatus::SUCCESS; } // 281, rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) -EcallStatus RevProc::ECALL_execveat(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: execveat called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_execveat() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: execveat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 282, rev_userfaultfd(int flags) -EcallStatus RevProc::ECALL_userfaultfd(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: userfaultfd called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_userfaultfd() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: userfaultfd called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 283, rev_membarrier(int cmd, unsigned int flags, int cpu_id) -EcallStatus RevProc::ECALL_membarrier(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: membarrier called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_membarrier() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: membarrier called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 284, rev_mlock2(unsigned long start, size_t len, int flags) -EcallStatus RevProc::ECALL_mlock2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: mlock2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_mlock2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: mlock2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 285, rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) -EcallStatus RevProc::ECALL_copy_file_range(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: copy_file_range called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_copy_file_range() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: copy_file_range called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 286, rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) -EcallStatus RevProc::ECALL_preadv2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: preadv2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_preadv2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: preadv2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 287, rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) -EcallStatus RevProc::ECALL_pwritev2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pwritev2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pwritev2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pwritev2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 288, rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey) -EcallStatus RevProc::ECALL_pkey_mprotect(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pkey_mprotect called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pkey_mprotect() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pkey_mprotect called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 289, rev_pkey_alloc(unsigned long flags, unsigned long init_val) -EcallStatus RevProc::ECALL_pkey_alloc(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pkey_alloc called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pkey_alloc() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pkey_alloc called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 290, rev_pkey_free(int pkey) -EcallStatus RevProc::ECALL_pkey_free(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pkey_free called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pkey_free() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pkey_free called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 291, rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) -EcallStatus RevProc::ECALL_statx(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: statx called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_statx() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: statx called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 292, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) -EcallStatus RevProc::ECALL_io_pgetevents(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_pgetevents called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_pgetevents() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_pgetevents called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 293, rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) -EcallStatus RevProc::ECALL_rseq(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: rseq called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_rseq() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: rseq called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 294, rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) -EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: kexec_file_load called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_kexec_file_load() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: kexec_file_load called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // // 403, rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) -// EcallStatus RevProc::ECALL_clock_gettime(RevInst& inst){ +// EcallStatus RevCore::ECALL_clock_gettime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: clock_gettime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2718,7 +2759,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 404, rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) -// EcallStatus RevProc::ECALL_clock_settime(RevInst& inst){ +// EcallStatus RevCore::ECALL_clock_settime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: clock_settime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2726,7 +2767,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 405, rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) -// EcallStatus RevProc::ECALL_clock_adjtime(RevInst& inst){ +// EcallStatus RevCore::ECALL_clock_adjtime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: clock_adjtime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2734,7 +2775,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 406, rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) -// EcallStatus RevProc::ECALL_clock_getres(RevInst& inst){ +// EcallStatus RevCore::ECALL_clock_getres(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: clock_getres called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2742,7 +2783,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 407, rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) -// EcallStatus RevProc::ECALL_clock_nanosleep(RevInst& inst){ +// EcallStatus RevCore::ECALL_clock_nanosleep(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: clock_nanosleep called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2750,7 +2791,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 408, rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) -// EcallStatus RevProc::ECALL_timer_gettime(RevInst& inst){ +// EcallStatus RevCore::ECALL_timer_gettime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: timer_gettime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2758,7 +2799,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 409, rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) -// EcallStatus RevProc::ECALL_timer_settime(RevInst& inst){ +// EcallStatus RevCore::ECALL_timer_settime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: timer_settime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2766,7 +2807,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 410, rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) -// EcallStatus RevProc::ECALL_timerfd_gettime(RevInst& inst){ +// EcallStatus RevCore::ECALL_timerfd_gettime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: timerfd_gettime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2774,7 +2815,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 411, rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) -// EcallStatus RevProc::ECALL_timerfd_settime(RevInst& inst){ +// EcallStatus RevCore::ECALL_timerfd_settime(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: timerfd_settime called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2782,7 +2823,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 412, rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) -// EcallStatus RevProc::ECALL_utimensat(RevInst& inst){ +// EcallStatus RevCore::ECALL_utimensat(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: utimensat called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2790,7 +2831,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 416, rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) -// EcallStatus RevProc::ECALL_io_pgetevents(RevInst& inst){ +// EcallStatus RevCore::ECALL_io_pgetevents(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: io_pgetevents called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2798,7 +2839,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 418, rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) -// EcallStatus RevProc::ECALL_mq_timedsend(RevInst& inst){ +// EcallStatus RevCore::ECALL_mq_timedsend(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: mq_timedsend called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2806,7 +2847,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 419, rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) -// EcallStatus RevProc::ECALL_mq_timedreceive(RevInst& inst){ +// EcallStatus RevCore::ECALL_mq_timedreceive(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: mq_timedreceive called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2814,7 +2855,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 420, rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) -// EcallStatus RevProc::ECALL_semtimedop(RevInst& inst){ +// EcallStatus RevCore::ECALL_semtimedop(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: semtimedop called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2822,7 +2863,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 422, rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) -// EcallStatus RevProc::ECALL_futex(RevInst& inst){ +// EcallStatus RevCore::ECALL_futex(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: futex called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2830,7 +2871,7 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // } // // 423, rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) -// EcallStatus RevProc::ECALL_sched_rr_get_interval(RevInst& inst){ +// EcallStatus RevCore::ECALL_sched_rr_get_interval(){ // output->verbose(CALL_INFO, 2, 0, // "ECALL: sched_rr_get_interval called by thread %" PRIu32 // " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); @@ -2839,310 +2880,305 @@ EcallStatus RevProc::ECALL_kexec_file_load(RevInst& inst){ // // 424, rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) -EcallStatus RevProc::ECALL_pidfd_send_signal(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pidfd_send_signal called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pidfd_send_signal() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pidfd_send_signal called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 425, rev_io_uring_setup(u32 entries, struct io_uring_params *p) -EcallStatus RevProc::ECALL_io_uring_setup(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_uring_setup called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_uring_setup() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_uring_setup called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 426, rev_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const sigset_t *sig, size_t sigsz) -EcallStatus RevProc::ECALL_io_uring_enter(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_uring_enter called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_uring_enter() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_uring_enter called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 427, rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args) -EcallStatus RevProc::ECALL_io_uring_register(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: io_uring_register called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_io_uring_register() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: io_uring_register called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 428, rev_open_tree(int dfd, const char *path, unsigned flags) -EcallStatus RevProc::ECALL_open_tree(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: open_tree called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_open_tree() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: open_tree called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 429, rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) -EcallStatus RevProc::ECALL_move_mount(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: move_mount called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_move_mount() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: move_mount called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 430, rev_fsopen(const char *fs_name, unsigned int flags) -EcallStatus RevProc::ECALL_fsopen(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fsopen called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fsopen() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fsopen called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 431, rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) -EcallStatus RevProc::ECALL_fsconfig(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fsconfig called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fsconfig() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fsconfig called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 432, rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) -EcallStatus RevProc::ECALL_fsmount(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fsmount called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fsmount() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fsmount called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 433, rev_fspick(int dfd, const char *path, unsigned int flags) -EcallStatus RevProc::ECALL_fspick(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: fspick called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_fspick() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: fspick called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 434, rev_pidfd_open(pid_t pid, unsigned int flags) -EcallStatus RevProc::ECALL_pidfd_open(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pidfd_open called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pidfd_open() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pidfd_open called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 435, rev_clone3(struct clone_args *uargs, size_t size) -EcallStatus RevProc::ECALL_clone3(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: clone3 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_clone3() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: clone3 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); auto rtval = EcallStatus::SUCCESS; - // auto CloneArgsAddr = RegFile->GetX(RevReg::a0); - // auto SizeOfCloneArgs = RegFile()->GetX(RevReg::a1); - - // if(0 == ECALL.bytesRead){ - // // First time through the function... - // /* Fetch the clone_args */ - // // struct clone_args args; // So while clone_args is a whole struct, we appear to be only - // // using the 1st uint64, so that's all we're going to fetch - // uint64_t* args = reinterpret_cast(ECALL.buf.data()); - // mem->ReadVal(HartToExecID, CloneArgsAddr, args, inst.hazard, RevFlag::F_NONE); - // ECALL.bytesRead = sizeof(*args); - // rtval = EcallStatus::CONTINUE; - // }else{ - // /* - // * Parse clone flags - // * NOTE: if no flags are set, we get fork() like behavior - // */ - // uint64_t* args = reinterpret_cast(ECALL.buf.data()); - // for( uint64_t bit=1; bit != 0; bit <<= 1 ){ - // switch (*args & bit) { - // case CLONE_VM: - // // std::cout << "CLONE_VM is true" << std::endl; - // break; - // case CLONE_FS: /* Set if fs info shared between processes */ - // // std::cout << "CLONE_FS is true" << std::endl; - // break; - // case CLONE_FILES: /* Set if open files shared between processes */ - // // std::cout << "CLONE_FILES is true" << std::endl; - // break; - // case CLONE_SIGHAND: /* Set if signal handlers shared */ - // // std::cout << "CLONE_SIGHAND is true" << std::endl; - // break; - // case CLONE_PIDFD: /* Set if a pidfd should be placed in the parent */ - // // std::cout << "CLONE_PIDFD is true" << std::endl; - // break; - // case CLONE_PTRACE: /* Set if tracing continues on the child */ - // // std::cout << "CLONE_PTRACE is true" << std::endl; - // break; - // case CLONE_VFORK: /* Set if the parent wants the child to wake it up on mm_release */ - // // std::cout << "CLONE_VFORK is true" << std::endl; - // break; - // case CLONE_PARENT: /* Set if we want to have the same parent as the cloner */ - // // std::cout << "CLONE_PARENT is true" << std::endl; - // break; - // case CLONE_THREAD: /* Set to add to same thread group */ - // // std::cout << "CLONE_THREAD is true" << std::endl; - // break; - // case CLONE_NEWNS: /* Set to create new namespace */ - // // std::cout << "CLONE_NEWNS is true" << std::endl; - // break; - // case CLONE_SYSVSEM: /* Set to shared SVID SEM_UNDO semantics */ - // // std::cout << "CLONE_SYSVSEM is true" << std::endl; - // break; - // case CLONE_SETTLS: /* Set TLS info */ - // // std::cout << "CLONE_SETTLS is true" << std::endl; - // break; - // case CLONE_PARENT_SETTID: /* Store TID in userlevel buffer before MM copy */ - // // std::cout << "CLONE_PARENT_SETTID is true" << std::endl; - // break; - // case CLONE_CHILD_CLEARTID: /* Register exit futex and memory location to clear */ - // // std::cout << "CLONE_CHILD_CLEARTID is true" << std::endl; - // break; - // case CLONE_DETACHED: /* Create clone detached */ - // // std::cout << "CLONE_DETACHED is true" << std::endl; - // break; - // case CLONE_UNTRACED: /* Set if the tracing process can't force CLONE_PTRACE on this clone */ - // // std::cout << "CLONE_UNTRACED is true" << std::endl; - // break; - // case CLONE_CHILD_SETTID: /* New cgroup namespace */ - // // std::cout << "CLONE_CHILD_SETTID is true" << std::endl; - // break; - // case CLONE_NEWCGROUP: /* New cgroup namespace */ - // // std::cout << "CLONE_NEWCGROUP is true" << std::endl; - // break; - // case CLONE_NEWUTS: /* New utsname group */ - // // std::cout << "CLONE_NEWUTS is true" << std::endl; - // break; - // case CLONE_NEWIPC: /* New ipcs */ - // // std::cout << "CLONE_NEWIPC is true" << std::endl; - // break; - // case CLONE_NEWUSER: /* New user namespace */ - // // std::cout << "CLONE_NEWUSER is true" << std::endl; - // break; - // case CLONE_NEWPID: /* New pid namespace */ - // // std::cout << "CLONE_NEWPID is true" << std::endl; - // break; - // case CLONE_NEWNET: /* New network namespace */ - // // std::cout << "CLONE_NEWNET is true" << std::endl; - // break; - // case CLONE_IO: /* Clone I/O Context */ - // // std::cout << "CLONE_IO is true" << std::endl; - // break; - // default: - // break; - // } // switch - // } // for - - // /* Get the parent ctx (Current active, executing PID) */ - // std::shared_ptr ParentCtx = ThreadTable.at(ActivePIDs.at(HartToExecID)); - - // /* Create the child ctx */ - // uint32_t ChildPID = CreateChildCtx(); - // std::shared_ptr ChildCtx = ThreadTable.at(ChildPID); - - // /* - // * =========================================================================================== - // * Register File - // * =========================================================================================== - // * We need to duplicate the parent's RegFile to to the Childs - // * - NOTE: when we return from this function, the return value will - // * be automatically stored in the Proc.RegFile[HartToExecID]'s a0 - // * register. In a traditional fork code this looks like: - // * - // * pid_t pid = fork() - // * if pid < 0: // Error - // * else if pid = 0: // New Child Process - // * else: // Parent Process - // * - // * In this case, the value of pid is the value thats returned to a0 - // * It follows that - // * - The child's regfile MUST have 0 in its a0 (despite its pid != 0 to the RevProc) - // * - The Parent's a0 register MUST have its PID in it - // * =========================================================================================== - // */ - - // /* - // Alert the Proc there needs to be a Ctx switch - // Pass the PID that will be switched to once the - // current pipeline is executed until completion - // */ - // CtxSwitchAlert(ChildPID); - - // // Parent's return value is the child's PID - // RegFile->SetX(RevReg::a0, ChildPID); - - // // Child's return value is 0 - // ChildCtx->GetRegFile()->SetX(RevReg::a0, 0); - - // // clean up ecall state - // rtval = EcallStatus::SUCCESS; - // ECALL.bytesRead = 0; - - // } //else + // auto CloneArgsAddr = RegFile->GetX(RevReg::a0); + // auto SizeOfCloneArgs = RegFile()->GetX(RevReg::a1); + + // if(0 == ECALL.bytesRead){ + // // First time through the function... + // /* Fetch the clone_args */ + // // struct clone_args args; // So while clone_args is a whole struct, we appear to be only + // // using the 1st uint64, so that's all we're going to fetch + // uint64_t* args = reinterpret_cast(ECALL.buf.data()); + // mem->ReadVal(HartToExecID, CloneArgsAddr, args, inst.hazard, RevFlag::F_NONE); + // ECALL.bytesRead = sizeof(*args); + // rtval = EcallStatus::CONTINUE; + // }else{ + // /* + // * Parse clone flags + // * NOTE: if no flags are set, we get fork() like behavior + // */ + // uint64_t* args = reinterpret_cast(ECALL.buf.data()); + // for( uint64_t bit=1; bit != 0; bit <<= 1 ){ + // switch (*args & bit) { + // case CLONE_VM: + // // std::cout << "CLONE_VM is true" << std::endl; + // break; + // case CLONE_FS: /* Set if fs info shared between processes */ + // // std::cout << "CLONE_FS is true" << std::endl; + // break; + // case CLONE_FILES: /* Set if open files shared between processes */ + // // std::cout << "CLONE_FILES is true" << std::endl; + // break; + // case CLONE_SIGHAND: /* Set if signal handlers shared */ + // // std::cout << "CLONE_SIGHAND is true" << std::endl; + // break; + // case CLONE_PIDFD: /* Set if a pidfd should be placed in the parent */ + // // std::cout << "CLONE_PIDFD is true" << std::endl; + // break; + // case CLONE_PTRACE: /* Set if tracing continues on the child */ + // // std::cout << "CLONE_PTRACE is true" << std::endl; + // break; + // case CLONE_VFORK: /* Set if the parent wants the child to wake it up on mm_release */ + // // std::cout << "CLONE_VFORK is true" << std::endl; + // break; + // case CLONE_PARENT: /* Set if we want to have the same parent as the cloner */ + // // std::cout << "CLONE_PARENT is true" << std::endl; + // break; + // case CLONE_THREAD: /* Set to add to same thread group */ + // // std::cout << "CLONE_THREAD is true" << std::endl; + // break; + // case CLONE_NEWNS: /* Set to create new namespace */ + // // std::cout << "CLONE_NEWNS is true" << std::endl; + // break; + // case CLONE_SYSVSEM: /* Set to shared SVID SEM_UNDO semantics */ + // // std::cout << "CLONE_SYSVSEM is true" << std::endl; + // break; + // case CLONE_SETTLS: /* Set TLS info */ + // // std::cout << "CLONE_SETTLS is true" << std::endl; + // break; + // case CLONE_PARENT_SETTID: /* Store TID in userlevel buffer before MM copy */ + // // std::cout << "CLONE_PARENT_SETTID is true" << std::endl; + // break; + // case CLONE_CHILD_CLEARTID: /* Register exit futex and memory location to clear */ + // // std::cout << "CLONE_CHILD_CLEARTID is true" << std::endl; + // break; + // case CLONE_DETACHED: /* Create clone detached */ + // // std::cout << "CLONE_DETACHED is true" << std::endl; + // break; + // case CLONE_UNTRACED: /* Set if the tracing process can't force CLONE_PTRACE on this clone */ + // // std::cout << "CLONE_UNTRACED is true" << std::endl; + // break; + // case CLONE_CHILD_SETTID: /* New cgroup namespace */ + // // std::cout << "CLONE_CHILD_SETTID is true" << std::endl; + // break; + // case CLONE_NEWCGROUP: /* New cgroup namespace */ + // // std::cout << "CLONE_NEWCGROUP is true" << std::endl; + // break; + // case CLONE_NEWUTS: /* New utsname group */ + // // std::cout << "CLONE_NEWUTS is true" << std::endl; + // break; + // case CLONE_NEWIPC: /* New ipcs */ + // // std::cout << "CLONE_NEWIPC is true" << std::endl; + // break; + // case CLONE_NEWUSER: /* New user namespace */ + // // std::cout << "CLONE_NEWUSER is true" << std::endl; + // break; + // case CLONE_NEWPID: /* New pid namespace */ + // // std::cout << "CLONE_NEWPID is true" << std::endl; + // break; + // case CLONE_NEWNET: /* New network namespace */ + // // std::cout << "CLONE_NEWNET is true" << std::endl; + // break; + // case CLONE_IO: /* Clone I/O Context */ + // // std::cout << "CLONE_IO is true" << std::endl; + // break; + // default: + // break; + // } // switch + // } // for + + // /* Get the parent ctx (Current active, executing PID) */ + // std::shared_ptr ParentCtx = ThreadTable.at(ActivePIDs.at(HartToExecID)); + + // /* Create the child ctx */ + // uint32_t ChildPID = CreateChildCtx(); + // std::shared_ptr ChildCtx = ThreadTable.at(ChildPID); + + // /* + // * =========================================================================================== + // * Register File + // * =========================================================================================== + // * We need to duplicate the parent's RegFile to to the Childs + // * - NOTE: when we return from this function, the return value will + // * be automatically stored in the Proc.RegFile[HartToExecID]'s a0 + // * register. In a traditional fork code this looks like: + // * + // * pid_t pid = fork() + // * if pid < 0: // Error + // * else if pid = 0: // New Child Process + // * else: // Parent Process + // * + // * In this case, the value of pid is the value thats returned to a0 + // * It follows that + // * - The child's regfile MUST have 0 in its a0 (despite its pid != 0 to the RevCore) + // * - The Parent's a0 register MUST have its PID in it + // * =========================================================================================== + // */ + + // /* + // Alert the Proc there needs to be a Ctx switch + // Pass the PID that will be switched to once the + // current pipeline is executed until completion + // */ + // CtxSwitchAlert(ChildPID); + + // // Parent's return value is the child's PID + // RegFile->SetX(RevReg::a0, ChildPID); + + // // Child's return value is 0 + // ChildCtx->GetRegFile()->SetX(RevReg::a0, 0); + + // // clean up ecall state + // rtval = EcallStatus::SUCCESS; + + // } //else return rtval; } // 436, rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags) -EcallStatus RevProc::ECALL_close_range(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: close_range called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_close_range() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: close_range called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 437, rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) -EcallStatus RevProc::ECALL_openat2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: openat2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_openat2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: openat2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 438, rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) -EcallStatus RevProc::ECALL_pidfd_getfd(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pidfd_getfd called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_pidfd_getfd() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pidfd_getfd called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } - // 439, rev_faccessat2(int dfd, const char *filename, int mode, int flags) -EcallStatus RevProc::ECALL_faccessat2(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: faccessat2 called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_faccessat2() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: faccessat2 called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } - // 440, rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) -EcallStatus RevProc::ECALL_process_madvise(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: process_madvise called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); +EcallStatus RevCore::ECALL_process_madvise() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: process_madvise called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); return EcallStatus::SUCCESS; } // 500, rev_cpuinfo(struct rev_cpuinfo *info) -EcallStatus RevProc::ECALL_cpuinfo(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: cpuinfoc called by thread %" PRIu32 - "\n", ActiveThreadID); - struct rev_cpuinfo info; - auto addr = RegFile->GetX(RevReg::a0); - info.cores = opts->GetNumCores(); - info.harts_per_core = opts->GetNumHarts(); - mem->WriteMem(HartToExecID, addr, sizeof(info), &info); - RegFile->SetX(RevReg::a0, 0); +EcallStatus RevCore::ECALL_cpuinfo() { + output->verbose( CALL_INFO, 2, 0, "ECALL: cpuinfoc called by thread %" PRIu32 "\n", ActiveThreadID ); + struct rev_cpuinfo info; + auto addr = RegFile->GetX( RevReg::a0 ); + info.cores = opts->GetNumCores(); + info.harts_per_core = opts->GetNumHarts(); + mem->WriteMem( HartToExecID, uint64_t( addr ), sizeof( info ), &info ); + RegFile->SetX( RevReg::a0, 0 ); return EcallStatus::SUCCESS; } // 501, rev_perf_stats(struct rev_perf_stats *stats) -EcallStatus RevProc::ECALL_perf_stats(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, "ECALL: perf_stats called by thread %" PRIu32 "\n", GetActiveThreadID()); - rev_stats rs, *dest = reinterpret_cast(RegFile->GetX(RevReg::a0)); +EcallStatus RevCore::ECALL_perf_stats() { + output->verbose( CALL_INFO, 2, 0, "ECALL: perf_stats called by thread %" PRIu32 "\n", GetActiveThreadID() ); + rev_stats rs, *dest = reinterpret_cast( RegFile->GetX( RevReg::a0 ) ); - rs.cycles = Stats.totalCycles; + rs.cycles = Stats.totalCycles; rs.instructions = Stats.retired; - mem->WriteMem(HartToExecID, (uint64_t)dest, sizeof(rev_stats), &rs); - RegFile->SetX(RevReg::a0 ,0); + mem->WriteMem( HartToExecID, (uint64_t) dest, sizeof( rev_stats ), &rs ); + RegFile->SetX( RevReg::a0, 0 ); return EcallStatus::SUCCESS; } @@ -3150,39 +3186,38 @@ EcallStatus RevProc::ECALL_perf_stats(RevInst& inst){ // const pthread_attr_t *restrict attr, // void *(*start_routine)(void *), // void *restrict arg); -EcallStatus RevProc::ECALL_pthread_create(RevInst& inst){ - output->verbose(CALL_INFO, 2, 0, - "ECALL: pthread_create called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); - uint64_t tidAddr = RegFile->GetX(RevReg::a0); +EcallStatus RevCore::ECALL_pthread_create() { + output->verbose( + CALL_INFO, 2, 0, "ECALL: pthread_create called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + uint64_t tidAddr = RegFile->GetX( RevReg::a0 ); //uint64_t AttrPtr = RegFile->GetX(RevReg::a1); - uint64_t NewThreadPC = RegFile->GetX(RevReg::a2); - uint64_t ArgPtr = RegFile->GetX(RevReg::a3); - unsigned long int NewTID = GetNewThreadID(); - CreateThread(NewTID, - NewThreadPC, reinterpret_cast(ArgPtr)); + uint64_t NewThreadPC = RegFile->GetX( RevReg::a2 ); + uint64_t ArgPtr = RegFile->GetX( RevReg::a3 ); + uint32_t NewTID = GetNewThreadID(); + CreateThread( NewTID, NewThreadPC, reinterpret_cast( ArgPtr ) ); - mem->WriteMem(HartToExecID, tidAddr, sizeof(NewTID), &NewTID, RevFlag::F_NONE); + mem->WriteMem( HartToExecID, tidAddr, sizeof( NewTID ), &NewTID, RevFlag::F_NONE ); return EcallStatus::SUCCESS; } // 1001, int rev_pthread_join(pthread_t thread, void **retval); -EcallStatus RevProc::ECALL_pthread_join(RevInst& inst){ +EcallStatus RevCore::ECALL_pthread_join() { EcallStatus rtval = EcallStatus::CONTINUE; - output->verbose(CALL_INFO, 2, 0, - "ECALL: pthread_join called by thread %" PRIu32 - " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID); + output->verbose( + CALL_INFO, 2, 0, "ECALL: pthread_join called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); - if( HartHasNoDependencies(HartToExecID) ){ - rtval = EcallStatus::SUCCESS; + if( HartHasNoDependencies( HartToExecID ) ) { + rtval = EcallStatus::SUCCESS; // Set current thread to blocked - std::unique_ptr BlockedThread = PopThreadFromHart(HartToExecID); - BlockedThread->SetState(ThreadState::BLOCKED); - BlockedThread->SetWaitingToJoinTID(RegFile->GetX(RevReg::a0)); + std::unique_ptr BlockedThread = PopThreadFromHart( HartToExecID ); + BlockedThread->SetState( ThreadState::BLOCKED ); + BlockedThread->SetWaitingToJoinTID( RegFile->GetX( RevReg::a0 ) ); // Signal to RevCPU this thread is has changed state - AddThreadsThatChangedState(std::move(BlockedThread)); + AddThreadsThatChangedState( std::move( BlockedThread ) ); // Output the ecall buf @@ -3201,4 +3236,532 @@ EcallStatus RevProc::ECALL_pthread_join(RevInst& inst){ return rtval; } -} // namespace SST::RevCPU +// 9000, rev_dump_mem_range(uint64_t addr, uint64_t size) +EcallStatus RevCore::ECALL_dump_mem_range() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: openat called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + } + auto addr = RegFile->GetX( RevReg::a1 ); + auto size = RegFile->GetX( RevReg::a2 ); + + // TODO: Add error handling if memh is enabled + mem->DumpMem( addr, size, 16 ); + + return EcallStatus::SUCCESS; +} + +// 9001, rev_dump_mem_range(const unsigned char* outputFile, uint64_t addr, uint64_t size) +EcallStatus RevCore::ECALL_dump_mem_range_to_file() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: dump_mem_range called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + } + auto pathname = RegFile->GetX( RevReg::a0 ); + auto addr = RegFile->GetX( RevReg::a1 ); + auto size = RegFile->GetX( RevReg::a2 ); + + /* Read the filename from memory one character at a time until we find '\0' */ + auto action = [&] { + // open the current directory and the file + // open the file in write mode + std::ofstream outputFile( EcallState.string, std::ios::out | std::ios::binary ); + mem->DumpMem( addr, size, 16, outputFile ); + }; + + return EcallLoadAndParseString( pathname, action ); +} + +// 9002, rev_mem_dump_stack() +EcallStatus RevCore::ECALL_dump_stack() { + output->verbose( CALL_INFO, 2, 0, "ECALL: dump_stack called" ); + // TODO: Factor in TLS + // Check if sp + _STACK_SIZE_ is in the valid memory range + // if not, dump the memory that is valid + mem->DumpMem( + RegFile->GetX( RevReg::sp ), RegFile->GetX( RevReg::tp ) - RegFile->GetX( RevReg::sp ) + ); + return EcallStatus::SUCCESS; +} + +// 9003, rev_dump_stck_to_file(const unsigned char* outputFile) +EcallStatus RevCore::ECALL_dump_stack_to_file() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: dump_stack_to_file called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + } + auto pathname = RegFile->GetX( RevReg::a0 ); + + /* Read the filename from memory one character at a time until we find '\0' */ + auto action = [&] { + // open the current directory and the file + // open the file in write mode + std::ofstream outputFile( EcallState.string, std::ios::out | std::ios::binary ); + + mem->DumpMem( + RegFile->GetX( RevReg::sp ), + RegFile->GetX( RevReg::tp ) - RegFile->GetX( RevReg::sp ), + 16, + outputFile + ); + }; + + return EcallLoadAndParseString( pathname, action ); +} + +EcallStatus RevCore::ECALL_dump_valid_mem() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: dump_valid_mem called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + } + + mem->DumpValidMem(); + return EcallStatus::SUCCESS; +} + +EcallStatus RevCore::ECALL_dump_valid_mem_to_file() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, + 2, + 0, + "ECALL: dump_valid_mem_to_file called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); + } + auto pathname = RegFile->GetX( RevReg::a0 ); + + /* Read the filename from memory one character at a time until we find '\0' */ + auto action = [&] { + // open the current directory and the file + // open the file in write mode + std::ofstream outputFile( EcallState.string, std::ios::out | std::ios::binary ); + mem->DumpValidMem( 16, outputFile ); + }; + + return EcallLoadAndParseString( pathname, action ); +} + +EcallStatus RevCore::ECALL_dump_thread_mem() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, 2, 0, "ECALL: dump_thread_mem called by thread %" PRIu32 " on hart %" PRIu32 "\n", ActiveThreadID, HartToExecID + ); + } + + mem->DumpThreadMem(); + return EcallStatus::SUCCESS; +} + +EcallStatus RevCore::ECALL_dump_thread_mem_to_file() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + if( EcallState.bytesRead == 0 ) { + output->verbose( + CALL_INFO, + 2, + 0, + "ECALL: dump_thread_mem_to_file called by thread %" PRIu32 " on hart %" PRIu32 "\n", + ActiveThreadID, + HartToExecID + ); + } + auto pathname = RegFile->GetX( RevReg::a0 ); + + /* Read the filename from memory one character at a time until we find '\0' */ + auto action = [&] { + // open the current directory and the file + // open the file in write mode + std::ofstream outputFile( EcallState.string, std::ios::out | std::ios::binary ); + mem->DumpThreadMem( 16, outputFile ); + }; + + return EcallLoadAndParseString( pathname, action ); +} + +// 9110, rev_fast_printf(const char *, ...) +// printf helper executed on host rather than rev. +// Use xml-like tags to define start/end of printed text to allow post processor extraction +// Restrictions: +// - 6 data, all XLEN in size +EcallStatus RevCore::ECALL_fast_printf() { + auto& EcallState = Harts.at( HartToExecID )->GetEcallState(); + uint64_t pFormat = RegFile->GetX( RevReg::a0 ); + auto action = [&] { + const char* format = EcallState.string.c_str(); + char buffer[1024]; + // This is sort of a hack -- we pass XLEN-sized values from a1-a6 which go into va_args slots + if( feature->IsRV64() ) { + snprintf( + buffer, + sizeof( buffer ), + format, + RegFile->GetX( RevReg::a1 ), + RegFile->GetX( RevReg::a2 ), + RegFile->GetX( RevReg::a3 ), + RegFile->GetX( RevReg::a4 ), + RegFile->GetX( RevReg::a5 ), + RegFile->GetX( RevReg::a6 ) + ); + } else { + snprintf( + buffer, + sizeof( buffer ), + format, + RegFile->GetX( RevReg::a1 ), + RegFile->GetX( RevReg::a2 ), + RegFile->GetX( RevReg::a3 ), + RegFile->GetX( RevReg::a4 ), + RegFile->GetX( RevReg::a5 ), + RegFile->GetX( RevReg::a6 ) + ); + } + output->verbose( CALL_INFO, 0, 0, "%s\n", buffer ); + }; + return EcallLoadAndParseString( pFormat, action ); +} + +/* ========================================= */ +/* System Call (ecall) Implementations Below */ +/* ========================================= */ +// clang-format off +const std::unordered_map RevCore::Ecalls = { + { 0, &RevCore::ECALL_io_setup }, // rev_io_setup(unsigned nr_reqs, aio_context_t *ctx) + { 1, &RevCore::ECALL_io_destroy }, // rev_io_destroy(aio_context_t ctx) + { 2, &RevCore::ECALL_io_submit }, // rev_io_submit(aio_context_t, long, struct iocb * *) + { 3, &RevCore::ECALL_io_cancel }, // rev_io_cancel(aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) + { 4, &RevCore::ECALL_io_getevents }, // rev_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) + { 5, &RevCore::ECALL_setxattr }, // rev_setxattr(const char *path, const char *name, const void *value, size_t size, int flags) + { 6, &RevCore::ECALL_lsetxattr }, // rev_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags) + { 7, &RevCore::ECALL_fsetxattr }, // rev_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags) + { 8, &RevCore::ECALL_getxattr }, // rev_getxattr(const char *path, const char *name, void *value, size_t size) + { 9, &RevCore::ECALL_lgetxattr }, // rev_lgetxattr(const char *path, const char *name, void *value, size_t size) + { 10, &RevCore::ECALL_fgetxattr }, // rev_fgetxattr(int fd, const char *name, void *value, size_t size) + { 11, &RevCore::ECALL_listxattr }, // rev_listxattr(const char *path, char *list, size_t size) + { 12, &RevCore::ECALL_llistxattr }, // rev_llistxattr(const char *path, char *list, size_t size) + { 13, &RevCore::ECALL_flistxattr }, // rev_flistxattr(int fd, char *list, size_t size) + { 14, &RevCore::ECALL_removexattr }, // rev_removexattr(const char *path, const char *name) + { 15, &RevCore::ECALL_lremovexattr }, // rev_lremovexattr(const char *path, const char *name) + { 16, &RevCore::ECALL_fremovexattr }, // rev_fremovexattr(int fd, const char *name) + { 17, &RevCore::ECALL_getcwd }, // rev_getcwd(char *buf, unsigned long size) + { 18, &RevCore::ECALL_lookup_dcookie }, // rev_lookup_dcookie(u64 cookie64, char *buf, size_t len) + { 19, &RevCore::ECALL_eventfd2 }, // rev_eventfd2(unsigned int count, int flags) + { 20, &RevCore::ECALL_epoll_create1 }, // rev_epoll_create1(int flags) + { 21, &RevCore::ECALL_epoll_ctl }, // rev_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) + { 22, &RevCore::ECALL_epoll_pwait }, // rev_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize) + { 23, &RevCore::ECALL_dup }, // rev_dup(unsigned int fildes) + { 24, &RevCore::ECALL_dup3 }, // rev_dup3(unsigned int oldfd, unsigned int newfd, int flags) + { 25, &RevCore::ECALL_fcntl64 }, // rev_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) + { 26, &RevCore::ECALL_inotify_init1 }, // rev_inotify_init1(int flags) + { 27, &RevCore::ECALL_inotify_add_watch }, // rev_inotify_add_watch(int fd, const char *path, u32 mask) + { 28, &RevCore::ECALL_inotify_rm_watch }, // rev_inotify_rm_watch(int fd, __s32 wd) + { 29, &RevCore::ECALL_ioctl }, // rev_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + { 30, &RevCore::ECALL_ioprio_set }, // rev_ioprio_set(int which, int who, int ioprio) + { 31, &RevCore::ECALL_ioprio_get }, // rev_ioprio_get(int which, int who) + { 32, &RevCore::ECALL_flock }, // rev_flock(unsigned int fd, unsigned int cmd) + { 33, &RevCore::ECALL_mknodat }, // rev_mknodat(int dfd, const char * filename, umode_t mode, unsigned dev) + { 34, &RevCore::ECALL_mkdirat }, // rev_mkdirat(int dfd, const char * pathname, umode_t mode) + { 35, &RevCore::ECALL_unlinkat }, // rev_unlinkat(int dfd, const char * pathname, int flag) + { 36, &RevCore::ECALL_symlinkat }, // rev_symlinkat(const char * oldname, int newdfd, const char * newname) + { 37, &RevCore::ECALL_linkat }, // rev_unlinkat(int dfd, const char * pathname, int flag) + { 38, &RevCore::ECALL_renameat }, // rev_renameat(int olddfd, const char * oldname, int newdfd, const char * newname) + { 39, &RevCore::ECALL_umount }, // rev_umount(char *name, int flags) + { 40, &RevCore::ECALL_mount }, // rev_umount(char *name, int flags) + { 41, &RevCore::ECALL_pivot_root }, // rev_pivot_root(const char *new_root, const char *put_old) + { 42, &RevCore::ECALL_ni_syscall }, // rev_ni_syscall(void) + { 43, &RevCore::ECALL_statfs64 }, // rev_statfs64(const char *path, size_t sz, struct statfs64 *buf) + { 44, &RevCore::ECALL_fstatfs64 }, // rev_fstatfs64(unsigned int fd, size_t sz, struct statfs64 *buf) + { 45, &RevCore::ECALL_truncate64 }, // rev_truncate64(const char *path, loff_t length) + { 46, &RevCore::ECALL_ftruncate64 }, // rev_ftruncate64(unsigned int fd, loff_t length) + { 47, &RevCore::ECALL_fallocate }, // rev_fallocate(int fd, int mode, loff_t offset, loff_t len) + { 48, &RevCore::ECALL_faccessat }, // rev_faccessat(int dfd, const char *filename, int mode) + { 49, &RevCore::ECALL_chdir }, // rev_chdir(const char *filename) + { 50, &RevCore::ECALL_fchdir }, // rev_fchdir(unsigned int fd) + { 51, &RevCore::ECALL_chroot }, // rev_chroot(const char *filename) + { 52, &RevCore::ECALL_fchmod }, // rev_fchmod(unsigned int fd, umode_t mode) + { 53, &RevCore::ECALL_fchmodat }, // rev_fchmodat(int dfd, const char * filename, umode_t mode) + { 54, &RevCore::ECALL_fchownat }, // rev_fchownat(int dfd, const char *filename, uid_t user, gid_t group, int flag) + { 55, &RevCore::ECALL_fchown }, // rev_fchown(unsigned int fd, uid_t user, gid_t group) + { 56, &RevCore::ECALL_openat }, // rev_openat(int dfd, const char *filename, int flags, umode_t mode) + { 57, &RevCore::ECALL_close }, // rev_close(unsigned int fd) + { 58, &RevCore::ECALL_vhangup }, // rev_vhangup(void) + { 59, &RevCore::ECALL_pipe2 }, // rev_pipe2(int *fildes, int flags) + { 60, &RevCore::ECALL_quotactl }, // rev_quotactl(unsigned int cmd, const char *special, qid_t id, void *addr) + { 61, &RevCore::ECALL_getdents64 }, // rev_getdents64(unsigned int fd, struct linux_dirent64 *dirent, unsigned int count) + { 62, &RevCore::ECALL_lseek }, // rev_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence) + { 63, &RevCore::ECALL_read }, // rev_read(unsigned int fd, char *buf, size_t count) + { 64, &RevCore::ECALL_write }, // rev_write(unsigned int fd, const char *buf, size_t count) + { 65, &RevCore::ECALL_readv }, // rev_readv(unsigned long fd, const struct iovec *vec, unsigned long vlen) + { 66, &RevCore::ECALL_writev }, // rev_writev(unsigned long fd, const struct iovec *vec, unsigned long vlen) + { 67, &RevCore::ECALL_pread64 }, // rev_pread64(unsigned int fd, char *buf, size_t count, loff_t pos) + { 68, &RevCore::ECALL_pwrite64 }, // rev_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos) + { 69, &RevCore::ECALL_preadv }, // rev_preadv(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) + { 70, &RevCore::ECALL_pwritev }, // rev_pwritev(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) + { 71, &RevCore::ECALL_sendfile64 }, // rev_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) + { 72, &RevCore::ECALL_pselect6_time32 }, // rev_pselect6_time32(int, fd_set *, fd_set *, fd_set *, struct old_timespec32 *, void *) + { 73, &RevCore::ECALL_ppoll_time32 }, // rev_ppoll_time32(struct pollfd *, unsigned int, struct old_timespec32 *, const sigset_t *, size_t) + { 74, &RevCore::ECALL_signalfd4 }, // rev_signalfd4(int ufd, sigset_t *user_mask, size_t sizemask, int flags) + { 75, &RevCore::ECALL_vmsplice }, // rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) + { 76, &RevCore::ECALL_splice }, // rev_vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) + { 77, &RevCore::ECALL_tee }, // rev_tee(int fdin, int fdout, size_t len, unsigned int flags) + { 78, &RevCore::ECALL_readlinkat }, // rev_readlinkat(int dfd, const char *path, char *buf, int bufsiz) + { 79, &RevCore::ECALL_newfstatat }, // rev_newfstatat(int dfd, const char *filename, struct stat *statbuf, int flag) + { 80, &RevCore::ECALL_newfstat }, // rev_newfstat(unsigned int fd, struct stat *statbuf) + { 81, &RevCore::ECALL_sync }, // rev_sync(void) + { 82, &RevCore::ECALL_fsync }, // rev_fsync(unsigned int fd) + { 83, &RevCore::ECALL_fdatasync }, // rev_fdatasync(unsigned int fd) + { 84, &RevCore::ECALL_sync_file_range2 }, // rev_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) + { 84, &RevCore::ECALL_sync_file_range }, // rev_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags) + { 85, &RevCore::ECALL_timerfd_create }, // rev_timerfd_create(int clockid, int flags) + { 86, &RevCore::ECALL_timerfd_settime }, // rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) + { 87, &RevCore::ECALL_timerfd_gettime }, // rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) + { 88, &RevCore::ECALL_utimensat }, // rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) + { 89, &RevCore::ECALL_acct }, // rev_acct(const char *name) + { 90, &RevCore::ECALL_capget }, // rev_capget(cap_user_header_t header, cap_user_data_t dataptr) + { 91, &RevCore::ECALL_capset }, // rev_capset(cap_user_header_t header, const cap_user_data_t data) + { 92, &RevCore::ECALL_personality }, // rev_personality(unsigned int personality) + { 93, &RevCore::ECALL_exit }, // rev_exit(int error_code) + { 94, &RevCore::ECALL_exit_group }, // rev_exit_group(int error_code) + { 95, &RevCore::ECALL_waitid }, // rev_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) + { 96, &RevCore::ECALL_set_tid_address }, // rev_set_tid_address(int *tidptr) + { 97, &RevCore::ECALL_unshare }, // rev_unshare(unsigned long unshare_flags) + { 98, &RevCore::ECALL_futex }, // rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) + { 99, &RevCore::ECALL_set_robust_list }, // rev_set_robust_list(struct robust_list_head *head, size_t len) + { 100, &RevCore::ECALL_get_robust_list }, // rev_get_robust_list(int pid, struct robust_list_head * *head_ptr, size_t *len_ptr) + { 101, &RevCore::ECALL_nanosleep }, // rev_nanosleep(struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + { 102, &RevCore::ECALL_getitimer }, // rev_getitimer(int which, struct __kernel_old_itimerval *value) + { 103, &RevCore::ECALL_setitimer }, // rev_setitimer(int which, struct __kernel_old_itimerval *value, struct __kernel_old_itimerval *ovalue) + { 104, &RevCore::ECALL_kexec_load }, // rev_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags) + { 105, &RevCore::ECALL_init_module }, // rev_init_module(void *umod, unsigned long len, const char *uargs) + { 106, &RevCore::ECALL_delete_module }, // rev_delete_module(const char *name_user, unsigned int flags) + { 107, &RevCore::ECALL_timer_create }, // rev_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id) + { 108, &RevCore::ECALL_timer_gettime }, // rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) + { 109, &RevCore::ECALL_timer_getoverrun }, // rev_timer_getoverrun(timer_t timer_id) + { 110, &RevCore::ECALL_timer_settime }, // rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) + { 111, &RevCore::ECALL_timer_delete }, // rev_timer_delete(timer_t timer_id) + { 112, &RevCore::ECALL_clock_settime }, // rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) + { 113, &RevCore::ECALL_clock_gettime }, // rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) + { 114, &RevCore::ECALL_clock_getres }, // rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) + { 115, &RevCore::ECALL_clock_nanosleep }, // rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + { 116, &RevCore::ECALL_syslog }, // rev_syslog(int type, char *buf, int len) + { 117, &RevCore::ECALL_ptrace }, // rev_ptrace(long request, long pid, unsigned long addr, unsigned long data) + { 118, &RevCore::ECALL_sched_setparam }, // rev_sched_setparam(pid_t pid, struct sched_param *param) + { 119, &RevCore::ECALL_sched_setscheduler }, // rev_sched_setscheduler(pid_t pid, int policy, struct sched_param *param) + { 120, &RevCore::ECALL_sched_getscheduler }, // rev_sched_getscheduler(pid_t pid) + { 121, &RevCore::ECALL_sched_getparam }, // rev_sched_getparam(pid_t pid, struct sched_param *param) + { 122, &RevCore::ECALL_sched_setaffinity }, // rev_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) + { 123, &RevCore::ECALL_sched_getaffinity }, // rev_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr) + { 124, &RevCore::ECALL_sched_yield }, // rev_sched_yield(void) + { 125, &RevCore::ECALL_sched_get_priority_max }, // rev_sched_get_priority_max(int policy) + { 126, &RevCore::ECALL_sched_get_priority_min }, // rev_sched_get_priority_min(int policy) + { 127, &RevCore::ECALL_sched_rr_get_interval }, // rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) + { 128, &RevCore::ECALL_restart_syscall }, // rev_restart_syscall(void) + { 129, &RevCore::ECALL_kill }, // rev_kill(pid_t pid, int sig) + { 130, &RevCore::ECALL_tkill }, // rev_tkill(pid_t pid, int sig) + { 131, &RevCore::ECALL_tgkill }, // rev_tgkill(pid_t tgid, pid_t pid, int sig) + { 132, &RevCore::ECALL_sigaltstack }, // rev_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss) + { 133, &RevCore::ECALL_rt_sigsuspend }, // rev_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) + { 134, &RevCore::ECALL_rt_sigaction }, // rev_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t) + { 135, &RevCore::ECALL_rt_sigprocmask }, // rev_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize) + { 136, &RevCore::ECALL_rt_sigpending }, // rev_rt_sigpending(sigset_t *set, size_t sigsetsize) + { 137, &RevCore::ECALL_rt_sigtimedwait_time32 }, // rev_rt_sigtimedwait_time32(const sigset_t *uthese, siginfo_t *uinfo, const struct old_timespec32 *uts, size_t sigsetsize) + { 138, &RevCore::ECALL_rt_sigqueueinfo }, // rev_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo) + { 140, &RevCore::ECALL_setpriority }, // rev_setpriority(int which, int who, int niceval) + { 141, &RevCore::ECALL_getpriority }, // rev_getpriority(int which, int who) + { 142, &RevCore::ECALL_reboot }, // rev_reboot(int magic1, int magic2, unsigned int cmd, void *arg) + { 143, &RevCore::ECALL_setregid }, // rev_setregid(gid_t rgid, gid_t egid) + { 144, &RevCore::ECALL_setgid }, // rev_setgid(gid_t gid) + { 145, &RevCore::ECALL_setreuid }, // rev_setreuid(uid_t ruid, uid_t euid) + { 146, &RevCore::ECALL_setuid }, // rev_setuid(uid_t uid) + { 147, &RevCore::ECALL_setresuid }, // rev_setresuid(uid_t ruid, uid_t euid, uid_t suid) + { 148, &RevCore::ECALL_getresuid }, // rev_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) + { 149, &RevCore::ECALL_setresgid }, // rev_setresgid(gid_t rgid, gid_t egid, gid_t sgid) + { 150, &RevCore::ECALL_getresgid }, // rev_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) + { 151, &RevCore::ECALL_setfsuid }, // rev_setfsuid(uid_t uid) + { 152, &RevCore::ECALL_setfsgid }, // rev_setfsgid(gid_t gid) + { 153, &RevCore::ECALL_times }, // rev_times(struct tms *tbuf) + { 154, &RevCore::ECALL_setpgid }, // rev_setpgid(pid_t pid, pid_t pgid) + { 155, &RevCore::ECALL_getpgid }, // rev_getpgid(pid_t pid) + { 156, &RevCore::ECALL_getsid }, // rev_getsid(pid_t pid) + { 157, &RevCore::ECALL_setsid }, // rev_setsid(void) + { 158, &RevCore::ECALL_getgroups }, // rev_getgroups(int gidsetsize, gid_t *grouplist) + { 159, &RevCore::ECALL_setgroups }, // rev_setgroups(int gidsetsize, gid_t *grouplist) + { 160, &RevCore::ECALL_newuname }, // rev_newuname(struct new_utsname *name) + { 161, &RevCore::ECALL_sethostname }, // rev_sethostname(char *name, int len) + { 162, &RevCore::ECALL_setdomainname }, // rev_setdomainname(char *name, int len) + { 163, &RevCore::ECALL_getrlimit }, // rev_getrlimit(unsigned int resource, struct rlimit *rlim) + { 164, &RevCore::ECALL_setrlimit }, // rev_setrlimit(unsigned int resource, struct rlimit *rlim) + { 165, &RevCore::ECALL_getrusage }, // rev_getrusage(int who, struct rusage *ru) + { 166, &RevCore::ECALL_umask }, // rev_umask(int mask) + { 167, &RevCore::ECALL_prctl }, // rev_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) + { 168, &RevCore::ECALL_getcpu }, // rev_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache) + { 169, &RevCore::ECALL_gettimeofday }, // rev_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) + { 170, &RevCore::ECALL_settimeofday }, // rev_settimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) + { 171, &RevCore::ECALL_adjtimex }, // rev_adjtimex(struct __kernel_timex *txc_p) + { 172, &RevCore::ECALL_getpid }, // rev_getpid(void) + { 173, &RevCore::ECALL_getppid }, // rev_getppid(void) + { 174, &RevCore::ECALL_getuid }, // rev_getuid(void) + { 175, &RevCore::ECALL_geteuid }, // rev_geteuid(void) + { 176, &RevCore::ECALL_getgid }, // rev_getgid(void) + { 177, &RevCore::ECALL_getegid }, // rev_getegid(void) + { 178, &RevCore::ECALL_gettid }, // rev_gettid(void) + { 179, &RevCore::ECALL_sysinfo }, // rev_sysinfo(struct sysinfo *info) + { 180, &RevCore::ECALL_mq_open }, // rev_mq_open(const char *name, int oflag, umode_t mode, struct mq_attr *attr) + { 181, &RevCore::ECALL_mq_unlink }, // rev_mq_unlink(const char *name) + { 182, &RevCore::ECALL_mq_timedsend }, // rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) + { 183, &RevCore::ECALL_mq_timedreceive }, // rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) + { 184, &RevCore::ECALL_mq_notify }, // rev_mq_notify(mqd_t mqdes, const struct sigevent *notification) + { 185, &RevCore::ECALL_mq_getsetattr }, // rev_mq_getsetattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) + { 186, &RevCore::ECALL_msgget }, // rev_msgget(key_t key, int msgflg) + { 187, &RevCore::ECALL_msgctl }, // rev_old_msgctl(int msqid, int cmd, struct msqid_ds *buf) + { 188, &RevCore::ECALL_msgrcv }, // rev_msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) + { 189, &RevCore::ECALL_msgsnd }, // rev_msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) + { 190, &RevCore::ECALL_semget }, // rev_semget(key_t key, int nsems, int semflg) + { 191, &RevCore::ECALL_semctl }, // rev_semctl(int semid, int semnum, int cmd, unsigned long arg) + { 192, &RevCore::ECALL_semtimedop }, // rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) + { 193, &RevCore::ECALL_semop }, // rev_semop(int semid, struct sembuf *sops, unsigned nsops) + { 194, &RevCore::ECALL_shmget }, // rev_shmget(key_t key, size_t size, int flag) + { 195, &RevCore::ECALL_shmctl }, // rev_old_shmctl(int shmid, int cmd, struct shmid_ds *buf) + { 196, &RevCore::ECALL_shmat }, // rev_shmat(int shmid, char *shmaddr, int shmflg) + { 197, &RevCore::ECALL_shmdt }, // rev_shmdt(char *shmaddr) + { 198, &RevCore::ECALL_socket }, // rev_socket(int, int, int) + { 199, &RevCore::ECALL_socketpair }, // rev_socketpair(int, int, int, int *) + { 200, &RevCore::ECALL_bind }, // rev_bind(int, struct sockaddr *, int) + { 201, &RevCore::ECALL_listen }, // rev_listen(int, int) + { 202, &RevCore::ECALL_accept }, // rev_accept(int, struct sockaddr *, int *) + { 203, &RevCore::ECALL_connect }, // rev_connect(int, struct sockaddr *, int) + { 204, &RevCore::ECALL_getsockname }, // rev_getsockname(int, struct sockaddr *, int *) + { 205, &RevCore::ECALL_getpeername }, // rev_getpeername(int, struct sockaddr *, int *) + { 206, &RevCore::ECALL_sendto }, // rev_sendto(int, void *, size_t, unsigned, struct sockaddr *, int) + { 207, &RevCore::ECALL_recvfrom }, // rev_recvfrom(int, void *, size_t, unsigned, struct sockaddr *, int *) + { 208, &RevCore::ECALL_setsockopt }, // rev_setsockopt(int fd, int level, int optname, char *optval, int optlen) + { 209, &RevCore::ECALL_getsockopt }, // rev_getsockopt(int fd, int level, int optname, char *optval, int *optlen) + { 210, &RevCore::ECALL_shutdown }, // rev_shutdown(int, int) + { 211, &RevCore::ECALL_sendmsg }, // rev_sendmsg(int fd, struct user_msghdr *msg, unsigned flags) + { 212, &RevCore::ECALL_recvmsg }, // rev_recvmsg(int fd, struct user_msghdr *msg, unsigned flags) + { 213, &RevCore::ECALL_readahead }, // rev_readahead(int fd, loff_t offset, size_t count) + { 214, &RevCore::ECALL_brk }, // rev_brk(unsigned long brk) + { 215, &RevCore::ECALL_munmap }, // rev_munmap(unsigned long addr, size_t len) + { 216, &RevCore::ECALL_mremap }, // rev_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) + { 217, &RevCore::ECALL_add_key }, // rev_add_key(const char *_type, const char *_description, const void *_payload, size_t plen, key_serial_t destringid) + { 218, &RevCore::ECALL_request_key }, // rev_request_key(const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid) + { 219, &RevCore::ECALL_keyctl }, // rev_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) + { 220, &RevCore::ECALL_clone }, // rev_clone(unsigned long, unsigned long, int *, unsigned long, int *) + { 221, &RevCore::ECALL_execve }, // rev_execve(const char *filename, const char *const *argv, const char *const *envp) + { 222, &RevCore::ECALL_mmap }, // rev_old_mmap(struct mmap_arg_struct *arg) + { 223, &RevCore::ECALL_fadvise64_64 }, // rev_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) + { 224, &RevCore::ECALL_swapon }, // rev_swapon(const char *specialfile, int swap_flags) + { 225, &RevCore::ECALL_swapoff }, // rev_swapoff(const char *specialfile) + { 226, &RevCore::ECALL_mprotect }, // rev_mprotect(unsigned long start, size_t len, unsigned long prot) + { 227, &RevCore::ECALL_msync }, // rev_msync(unsigned long start, size_t len, int flags) + { 228, &RevCore::ECALL_mlock }, // rev_mlock(unsigned long start, size_t len) + { 229, &RevCore::ECALL_munlock }, // rev_munlock(unsigned long start, size_t len) + { 230, &RevCore::ECALL_mlockall }, // rev_mlockall(int flags) + { 231, &RevCore::ECALL_munlockall }, // rev_munlockall(void) + { 232, &RevCore::ECALL_mincore }, // rev_mincore(unsigned long start, size_t len, unsigned char * vec) + { 233, &RevCore::ECALL_madvise }, // rev_madvise(unsigned long start, size_t len, int behavior) + { 234, &RevCore::ECALL_remap_file_pages }, // rev_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) + { 235, &RevCore::ECALL_mbind }, // rev_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned flags) + { 236, &RevCore::ECALL_get_mempolicy }, // rev_get_mempolicy(int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags) + { 237, &RevCore::ECALL_set_mempolicy }, // rev_set_mempolicy(int mode, const unsigned long *nmask, unsigned long maxnode) + { 238, &RevCore::ECALL_migrate_pages }, // rev_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long *from, const unsigned long *to) + { 239, &RevCore::ECALL_move_pages }, // rev_move_pages(pid_t pid, unsigned long nr_pages, const void * *pages, const int *nodes, int *status, int flags) + { 240, &RevCore::ECALL_rt_tgsigqueueinfo }, // rev_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) + { 241, &RevCore::ECALL_perf_event_open }, // rev_perf_event_open(") + { 242, &RevCore::ECALL_accept4 }, // rev_accept4(int, struct sockaddr *, int *, int) + { 243, &RevCore::ECALL_recvmmsg_time32 }, // rev_recvmmsg_time32(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags, struct old_timespec32 *timeout) + { 260, &RevCore::ECALL_wait4 }, // rev_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru) + { 261, &RevCore::ECALL_prlimit64 }, // rev_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim) + { 262, &RevCore::ECALL_fanotify_init }, // rev_fanotify_init(unsigned int flags, unsigned int event_f_flags) + { 263, &RevCore::ECALL_fanotify_mark }, // rev_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char *pathname) + { 264, &RevCore::ECALL_name_to_handle_at }, // rev_name_to_handle_at(int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag) + { 265, &RevCore::ECALL_open_by_handle_at }, // rev_open_by_handle_at(int mountdirfd, struct file_handle *handle, int flags) + { 266, &RevCore::ECALL_clock_adjtime }, // rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) + { 267, &RevCore::ECALL_syncfs }, // rev_syncfs(int fd) + { 268, &RevCore::ECALL_setns }, // rev_setns(int fd, int nstype) + { 269, &RevCore::ECALL_sendmmsg }, // rev_sendmmsg(int fd, struct mmsghdr *msg, unsigned int vlen, unsigned flags) + { 270, &RevCore::ECALL_process_vm_readv }, // rev_process_vm_readv(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) + { 271, &RevCore::ECALL_process_vm_writev }, // rev_process_vm_writev(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags) + { 272, &RevCore::ECALL_kcmp }, // rev_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) + { 273, &RevCore::ECALL_finit_module }, // rev_finit_module(int fd, const char *uargs, int flags) + { 274, &RevCore::ECALL_sched_setattr }, // rev_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) + { 275, &RevCore::ECALL_sched_getattr }, // rev_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) + { 276, &RevCore::ECALL_renameat2 }, // rev_renameat2(int olddfd, const char *oldname, int newdfd, const char *newname, unsigned int flags) + { 277, &RevCore::ECALL_seccomp }, // rev_seccomp(unsigned int op, unsigned int flags, void *uargs) + { 278, &RevCore::ECALL_getrandom }, // rev_getrandom(char *buf, size_t count, unsigned int flags) + { 279, &RevCore::ECALL_memfd_create }, // rev_memfd_create(const char *uname_ptr, unsigned int flags) + { 280, &RevCore::ECALL_bpf }, // rev_bpf(int cmd, union bpf_attr *attr, unsigned int size) + { 281, &RevCore::ECALL_execveat }, // rev_execveat(int dfd, const char *filename, const char *const *argv, const char *const *envp, int flags) + { 282, &RevCore::ECALL_userfaultfd }, // rev_userfaultfd(int flags) + { 283, &RevCore::ECALL_membarrier }, // rev_membarrier(int cmd, unsigned int flags, int cpu_id) + { 284, &RevCore::ECALL_mlock2 }, // rev_mlock2(unsigned long start, size_t len, int flags) + { 285, &RevCore::ECALL_copy_file_range }, // rev_copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) + { 286, &RevCore::ECALL_preadv2 }, // rev_preadv2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) + { 287, &RevCore::ECALL_pwritev2 }, // rev_pwritev2(unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) + { 288, &RevCore::ECALL_pkey_mprotect }, // rev_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey) + { 289, &RevCore::ECALL_pkey_alloc }, // rev_pkey_alloc(unsigned long flags, unsigned long init_val) + { 290, &RevCore::ECALL_pkey_free }, // rev_pkey_free(int pkey) + { 291, &RevCore::ECALL_statx }, // rev_statx(int dfd, const char *path, unsigned flags, unsigned mask, struct statx *buffer) + { 292, &RevCore::ECALL_io_pgetevents }, // rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) + { 293, &RevCore::ECALL_rseq }, // rev_rseq(struct rseq *rseq, uint32_t rseq_len, int flags, uint32_t sig) + { 294, &RevCore::ECALL_kexec_file_load }, // rev_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags) + { 403, &RevCore::ECALL_clock_gettime }, // rev_clock_gettime(clockid_t which_clock, struct __kernel_timespec *tp) + { 404, &RevCore::ECALL_clock_settime }, // rev_clock_settime(clockid_t which_clock, const struct __kernel_timespec *tp) + { 405, &RevCore::ECALL_clock_adjtime }, // rev_clock_adjtime(clockid_t which_clock, struct __kernel_timex *tx) + { 406, &RevCore::ECALL_clock_getres }, // rev_clock_getres(clockid_t which_clock, struct __kernel_timespec *tp) + { 407, &RevCore::ECALL_clock_nanosleep }, // rev_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) + { 408, &RevCore::ECALL_timer_gettime }, // rev_timer_gettime(timer_t timer_id, struct __kernel_itimerspec *setting) + { 409, &RevCore::ECALL_timer_settime }, // rev_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec *new_setting, struct __kernel_itimerspec *old_setting) + { 410, &RevCore::ECALL_timerfd_gettime }, // rev_timerfd_gettime(int ufd, struct __kernel_itimerspec *otmr) + { 411, &RevCore::ECALL_timerfd_settime }, // rev_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec *utmr, struct __kernel_itimerspec *otmr) + { 412, &RevCore::ECALL_utimensat }, // rev_utimensat(int dfd, const char *filename, struct __kernel_timespec *utimes, int flags) + { 416, &RevCore::ECALL_io_pgetevents }, // rev_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout, const struct __aio_sigset *sig) + { 418, &RevCore::ECALL_mq_timedsend }, // rev_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec *abs_timeout) + { 419, &RevCore::ECALL_mq_timedreceive }, // rev_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct __kernel_timespec *abs_timeout) + { 420, &RevCore::ECALL_semtimedop }, // rev_semtimedop(int semid, struct sembuf *sops, unsigned nsops, const struct __kernel_timespec *timeout) + { 422, &RevCore::ECALL_futex }, // rev_futex(u32 *uaddr, int op, u32 val, struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) + { 423, &RevCore::ECALL_sched_rr_get_interval }, // rev_sched_rr_get_interval(pid_t pid, struct __kernel_timespec *interval) + { 424, &RevCore::ECALL_pidfd_send_signal }, // rev_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) + { 425, &RevCore::ECALL_io_uring_setup }, // rev_io_uring_setup(u32 entries, struct io_uring_params *p) + { 426, &RevCore::ECALL_io_uring_enter }, // rev_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const sigset_t *sig, size_t sigsz) + { 427, &RevCore::ECALL_io_uring_register }, // rev_io_uring_register(unsigned int fd, unsigned int op, void *arg, unsigned int nr_args) + { 428, &RevCore::ECALL_open_tree }, // rev_open_tree(int dfd, const char *path, unsigned flags) + { 429, &RevCore::ECALL_move_mount }, // rev_move_mount(int from_dfd, const char *from_path, int to_dfd, const char *to_path, unsigned int ms_flags) + { 430, &RevCore::ECALL_fsopen }, // rev_fsopen(const char *fs_name, unsigned int flags) + { 431, &RevCore::ECALL_fsconfig }, // rev_fsconfig(int fs_fd, unsigned int cmd, const char *key, const void *value, int aux) + { 432, &RevCore::ECALL_fsmount }, // rev_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags) + { 433, &RevCore::ECALL_fspick }, // rev_fspick(int dfd, const char *path, unsigned int flags) + { 434, &RevCore::ECALL_pidfd_open }, // rev_pidfd_open(pid_t pid, unsigned int flags) + { 435, &RevCore::ECALL_clone3 }, // rev_clone3(struct clone_args *uargs, size_t size) + { 436, &RevCore::ECALL_close_range }, // rev_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags) + { 437, &RevCore::ECALL_openat2 }, // rev_openat2(int dfd, const char *filename, struct open_how *how, size_t size) + { 438, &RevCore::ECALL_pidfd_getfd }, // rev_pidfd_getfd(int pidfd, int fd, unsigned int flags) + { 439, &RevCore::ECALL_faccessat2 }, // rev_faccessat2(int dfd, const char *filename, int mode, int flags) + { 440, &RevCore::ECALL_process_madvise }, // rev_process_madvise(int pidfd, const struct iovec *vec, size_t vlen, int behavior, unsigned int flags) + { 500, &RevCore::ECALL_cpuinfo }, // rev_cpuinfo(struct rev_cpuinfo *info) + { 501, &RevCore::ECALL_perf_stats }, // rev_cpuinfo(struct rev_perf_stats *stats) + { 1000, &RevCore::ECALL_pthread_create }, // + { 1001, &RevCore::ECALL_pthread_join }, // + { 9000, &RevCore::ECALL_dump_mem_range }, // rev_dump_mem_range(uint64_t addr, uint64_t size) + { 9001, &RevCore::ECALL_dump_mem_range_to_file }, // rev_dump_mem_range_to_file(const unsigned char* outputFile, uint64_t addr, uint64_t size) + { 9002, &RevCore::ECALL_dump_stack }, // rev_dump_stack() + { 9003, &RevCore::ECALL_dump_stack_to_file }, // rev_dump_stack(const unsigned char* outputFile) + { 9004, &RevCore::ECALL_dump_valid_mem }, // rev_dump_valid_mem() + { 9005, &RevCore::ECALL_dump_valid_mem_to_file }, // rev_dump_valid_mem_to_file(const unsigned char* filename) + { 9004, &RevCore::ECALL_dump_thread_mem }, // rev_dump_thread_mem() + { 9005, &RevCore::ECALL_dump_thread_mem_to_file }, // rev_dump_thread_mem_to_file(const unsigned char* filename) + { 9110, &RevCore::ECALL_fast_printf }, // rev_fast_printf(const char *, ...) +}; +// clang-format on + +} // namespace SST::RevCPU diff --git a/src/RevThread.cc b/src/RevThread.cc index 900445843..ec15fa425 100644 --- a/src/RevThread.cc +++ b/src/RevThread.cc @@ -11,49 +11,37 @@ #include "RevThread.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { -std::ostream& operator<<(std::ostream& os, const RevThread& Thread){ +std::ostream& operator<<( std::ostream& os, const RevThread& Thread ) { os << "\n"; // Calculate total width of the table - int tableWidth = 6 /*Reg*/ + 7 /*Alias*/ + 16 /*Value*/ + 23 /*Info*/ + 9 /*Separators*/; + size_t tableWidth = 6 /*Reg*/ + 7 /*Alias*/ + 16 /*Value*/ + 23 /*Info*/ + 9 /*Separators*/; // Print a top border - os << "|" << std::string(tableWidth-1, '=') << "|" << '\n'; + os << "|" << std::string( tableWidth - 1, '=' ) << "|" << '\n'; // Print Thread ID - os << "| Thread " << Thread.GetID() << std::setw(6) << std::string(tableWidth-10, ' ') << "|\n"; + os << "| Thread " << Thread.GetID() << std::setw( 6 ) << std::string( tableWidth - 10, ' ' ) << "|\n"; // Print the middle border - os << "|" << std::string(tableWidth-1, '-') << "|" << '\n'; + os << "|" << std::string( tableWidth - 1, '-' ) << "|" << '\n'; std::string StateString = ""; - switch (Thread.GetState()){ - case ThreadState::START: - StateString = "START"; - break; - case ThreadState::READY: - StateString = "READY"; - break; - case ThreadState::RUNNING: - StateString = "RUNNING"; - break; - case ThreadState::BLOCKED: - StateString = "BLOCKED"; - break; - case ThreadState::DONE: - StateString = "DONE"; - break; - default: - StateString = "UNKNOWN"; - break; + switch( Thread.GetState() ) { + case ThreadState::START: StateString = "START"; break; + case ThreadState::READY: StateString = "READY"; break; + case ThreadState::RUNNING: StateString = "RUNNING"; break; + case ThreadState::BLOCKED: StateString = "BLOCKED"; break; + case ThreadState::DONE: StateString = "DONE"; break; + default: StateString = "UNKNOWN"; break; } // Print a nice header os << " ==> State: " << StateString << "\n"; os << " ==> ParentTID: " << Thread.GetParentID() << "\n"; - os << " ==> Blocked by TID: " ; - if (Thread.GetWaitingToJoinTID() != _INVALID_TID_) { + os << " ==> Blocked by TID: "; + if( Thread.GetWaitingToJoinTID() != _INVALID_TID_ ) { os << Thread.GetWaitingToJoinTID(); } else { os << "N/A"; @@ -65,4 +53,4 @@ std::ostream& operator<<(std::ostream& os, const RevThread& Thread){ return os; } -} // namespace SST::RevCPU +} // namespace SST::RevCPU diff --git a/src/RevTracer.cc b/src/RevTracer.cc index b2d8297f2..84f61ced2 100644 --- a/src/RevTracer.cc +++ b/src/RevTracer.cc @@ -1,7 +1,7 @@ // // _RevTracer_cc_ // -// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// Copyright (C) 2017-2025 Tactical Computing Laboratories, LLC // All Rights Reserved // contact@tactcomplabs.com // @@ -9,391 +9,376 @@ // // -#include #include +#include #include #include "RevTracer.h" -namespace SST::RevCPU{ - -RevTracer::RevTracer(std::string Name, SST::Output *o): name(Name), pOutput(o) { - - enableQ.resize(MAX_ENABLE_Q); - enableQ.assign(MAX_ENABLE_Q,0); - enableQindex = 0; - - // Initialize NOP trace controls - uint32_t cmd_template = s2op.at(TRC_OP_DEFAULT); - for (unsigned i=0;i *TraceSymbols) -{ - traceSymbols = TraceSymbols; +void RevTracer::SetTraceSymbols( std::map* TraceSymbols ) { + traceSymbols = TraceSymbols; } -void RevTracer::SetStartCycle(uint64_t c) -{ - startCycle = c; +void RevTracer::SetStartCycle( uint64_t c ) { + startCycle = c; } -void RevTracer::SetCycleLimit(uint64_t c) -{ - cycleLimit = c; +void RevTracer::SetCycleLimit( uint64_t c ) { + cycleLimit = c; } -void RevTracer::SetCmdTemplate(std::string cmd) -{ - if (s2op.find(cmd) == s2op.end()) { - std::stringstream s; - for (auto it = s2op.begin(); it != s2op.end(); it++) { - s << it->first << " "; - } - pOutput->fatal(CALL_INFO, -1, "Unsupported parameter [trcCmd=%s]. Supported values are: %s\n",cmd.c_str(),s.str().c_str()); +void RevTracer::SetCmdTemplate( std::string cmd ) { + if( s2op.find( cmd ) == s2op.end() ) { + std::stringstream s; + for( auto it = s2op.begin(); it != s2op.end(); it++ ) { + s << it->first << " "; } + pOutput->fatal( CALL_INFO, -1, "Unsupported parameter [trcCmd=%s]. Supported values are: %s\n", cmd.c_str(), s.str().c_str() ); + } - unsigned cmd_template = s2op.at(cmd); - for (unsigned i=0;icycleLimit) { - disabled = true; - if (outputEnabled) { - outputEnabled = false; - events.f.trc_ctl = 1; - } - return; - } - - // Using a startCycle will override programmatic controls. - if (startCycle>0) { - bool enable = startCycle && cycle > startCycle; - if (enable != outputEnabled) { - outputEnabled = enable; - events.f.trc_ctl = 1; - } - return; - } - - // programatic controls - bool nextState = outputEnabled; - if ( insn == nops[static_cast(TRC_CMD_IDX::TRACE_OFF)] ) { - nextState = false; - } else if ( insn == nops[static_cast(TRC_CMD_IDX::TRACE_ON)] ) { - nextState = true; - } else if ( insn == nops[static_cast(TRC_CMD_IDX::TRACE_PUSH_OFF)] ) { - enableQ[enableQindex] = outputEnabled; - enableQindex = (enableQindex + 1 ) % MAX_ENABLE_Q; - nextState = false; - } else if ( insn == nops[static_cast(TRC_CMD_IDX::TRACE_PUSH_ON)] ) { - enableQ[enableQindex] = outputEnabled; - enableQindex = (enableQindex + 1 ) % MAX_ENABLE_Q; - nextState = true; - } else if ( insn == nops[static_cast(TRC_CMD_IDX::TRACE_POP)] ) { - enableQindex = (enableQindex - 1 ) % MAX_ENABLE_Q; - nextState = enableQ[enableQindex]; +void RevTracer::CheckUserControls( uint64_t cycle ) { + // bail out early if disabled + if( disabled ) + return; + if( cycleLimit && traceCycles > cycleLimit ) { + disabled = true; + if( outputEnabled ) { + outputEnabled = false; + events.f.trc_ctl = 1; } - // prevent trace clutter with unnecessary events - if (nextState != outputEnabled) { - events.f.trc_ctl = 1; - outputEnabled = nextState; + return; + } + + // Using a startCycle will override programmatic controls. + if( startCycle > 0 ) { + bool enable = startCycle && cycle > startCycle; + if( enable != outputEnabled ) { + outputEnabled = enable; + events.f.trc_ctl = 1; } + return; + } + + // programatic controls + bool nextState = outputEnabled; + if( insn == nops[safe_static_cast( TRC_CMD_IDX::TRACE_OFF )] ) { + nextState = false; + } else if( insn == nops[safe_static_cast( TRC_CMD_IDX::TRACE_ON )] ) { + nextState = true; + } else if( insn == nops[safe_static_cast( TRC_CMD_IDX::TRACE_PUSH_OFF )] ) { + enableQ[enableQindex] = outputEnabled; + enableQindex = ( enableQindex + 1 ) % MAX_ENABLE_Q; + nextState = false; + } else if( insn == nops[safe_static_cast( TRC_CMD_IDX::TRACE_PUSH_ON )] ) { + enableQ[enableQindex] = outputEnabled; + enableQindex = ( enableQindex + 1 ) % MAX_ENABLE_Q; + nextState = true; + } else if( insn == nops[safe_static_cast( TRC_CMD_IDX::TRACE_POP )] ) { + enableQindex = ( enableQindex - 1 ) % MAX_ENABLE_Q; + nextState = enableQ[enableQindex]; + } + // prevent trace clutter with unnecessary events + if( nextState != outputEnabled ) { + events.f.trc_ctl = 1; + outputEnabled = nextState; + } } -void RevTracer::SetFetchedInsn(uint64_t _pc, uint32_t _insn) -{ - insn = _insn; - pc = _pc; +void RevTracer::SetFetchedInsn( uint64_t _pc, uint32_t _insn ) { + insn = _insn; + pc = _pc; } -bool RevTracer::OutputOK() -{ - return outputEnabled || events.f.trc_ctl; +bool RevTracer::OutputOK() { + return outputEnabled || events.f.trc_ctl; } -void RevTracer::regRead(size_t r, uint64_t v) -{ - traceRecs.emplace_back(TraceRec_t(RegRead,r,v)); +void RevTracer::regRead( uint64_t r, uint64_t v ) { + traceRecs.emplace_back( RegRead, r, v ); } -void RevTracer::regWrite(size_t r, uint64_t v) -{ - traceRecs.emplace_back(TraceRec_t(RegWrite,r,v)); +void RevTracer::regWrite( uint64_t r, uint64_t v ) { + traceRecs.emplace_back( RegWrite, r, v ); } -void RevTracer::memWrite(uint64_t adr, size_t len, const void *data) -{ - // Only tracing the first 8 bytes. Retaining pointer in case we change that. - uint64_t d = 0; - memcpy(&d, data, len > sizeof(d) ? sizeof(d) : len); - traceRecs.emplace_back(TraceRec_t(MemStore,adr,len,d)); +void RevTracer::memWrite( uint64_t adr, size_t len, const void* data ) { + // Only tracing the first 8 bytes. Retaining pointer in case we change that. + uint64_t d = 0; + memcpy( &d, data, len > sizeof( d ) ? sizeof( d ) : len ); + traceRecs.emplace_back( MemStore, adr, len, d ); } -void RevTracer::memRead(uint64_t adr, size_t len, void *data) -{ - uint64_t d = 0; - memcpy(&d, data, len > sizeof(d) ? sizeof(d) : len); - traceRecs.emplace_back(TraceRec_t(MemLoad,adr,len,d)); +void RevTracer::memRead( uint64_t adr, size_t len, void* data ) { + uint64_t d = 0; + memcpy( &d, data, len > sizeof( d ) ? sizeof( d ) : len ); + traceRecs.emplace_back( MemLoad, adr, len, d ); } -void SST::RevCPU::RevTracer::memhSendRead(uint64_t adr, size_t len, uint16_t reg) -{ - traceRecs.emplace_back(TraceRec_t(MemhSendLoad, adr, len, reg)); +void SST::RevCPU::RevTracer::memhSendRead( uint64_t adr, size_t len, uint16_t reg ) { + traceRecs.emplace_back( MemhSendLoad, adr, len, reg ); } -void RevTracer::memReadResponse(size_t len, void *data, const MemReq* req) -{ - if (req->DestReg==0) return; - CompletionRec_t c(req->Hart, req->DestReg, len, req->Addr, data, req->RegType); - completionRecs.emplace_back(c); +void RevTracer::memReadResponse( size_t len, void* data, const MemReq* req ) { + if( req->DestReg == 0 ) + return; + CompletionRec_t c( req->Hart, req->DestReg, len, req->Addr, data, req->RegType ); + completionRecs.emplace_back( c ); } -void RevTracer::pcWrite(uint32_t newpc) -{ - traceRecs.emplace_back(TraceRec_t(PcWrite,newpc,0,0)); +void RevTracer::pcWrite( uint32_t newpc ) { + traceRecs.emplace_back( PcWrite, newpc, 0, 0 ); } -void RevTracer::pcWrite(uint64_t newpc) -{ - traceRecs.emplace_back(TraceRec_t(PcWrite,newpc,0,0)); +void RevTracer::pcWrite( uint64_t newpc ) { + traceRecs.emplace_back( PcWrite, newpc, 0, 0 ); } -void RevTracer::Exec(size_t cycle, unsigned id, unsigned hart, unsigned tid, const std::string& fallbackMnemonic) -{ - instHeader.set(cycle, id, hart, tid, fallbackMnemonic); +void RevTracer::Exec( size_t cycle, uint32_t id, uint32_t hart, uint32_t tid, const std::string& fallbackMnemonic ) { + instHeader.set( cycle, id, hart, tid, fallbackMnemonic ); } -void RevTracer::Render(size_t cycle) -{ - // Trace on/off controls - CheckUserControls(cycle); - - // memory completions - if (completionRecs.size()>0) { - if (OutputOK()) { - for (auto r : completionRecs) { - std::string data_str = fmt_data(r.len, r.data); - std::stringstream s; - s << data_str << "<-[0x" << std::hex << r.addr << "," << std::dec << r.len << "] "; - s << fmt_reg(r.destReg) << "<-" << data_str << " "; - pOutput->verbose(CALL_INFO, 5, 0, - "Hart %" PRIu32 "; *A %s\n", - r.hart, s.str().c_str()); - } - } - // reset completion reqs - completionRecs.clear(); - } +void RevTracer::Render( size_t cycle ) { + // Trace on/off controls + CheckUserControls( cycle ); - // Instruction Trace - if (instHeader.valid) { - if (OutputOK()){ - pOutput->verbose(CALL_INFO, 5, 0, - "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; *I %s\n", - instHeader.id, instHeader.hart, instHeader.tid, RenderExec(instHeader.fallbackMnemonic).c_str()); - } - InstTraceReset(); + // memory completions + if( completionRecs.size() > 0 ) { + if( OutputOK() ) { + for( const auto& r : completionRecs ) { + std::string data_str = fmt_data( r.len, r.data ); + std::stringstream s; + s << data_str << "<-[0x" << std::hex << r.addr << "," << std::dec << r.len << "] "; + s << fmt_reg( r.destReg ) << "<-" << data_str << " "; + pOutput->verbose( CALL_INFO, 5, 0, "Hart %" PRIu32 "; *A %s\n", r.hart, s.str().c_str() ); + } } - + // reset completion reqs + completionRecs.clear(); + } + + // Instruction Trace + if( instHeader.valid ) { + if( OutputOK() ) { + pOutput->verbose( + CALL_INFO, + 5, + 0, + "Core %" PRIu32 "; Hart %" PRIu32 "; Thread %" PRIu32 "; *I %s\n", + instHeader.id, + instHeader.hart, + instHeader.tid, + RenderExec( instHeader.fallbackMnemonic ).c_str() + ); + } + InstTraceReset(); + } } -void SST::RevCPU::RevTracer::Reset() -{ - InstTraceReset(); - completionRecs.clear(); +void SST::RevCPU::RevTracer::Reset() { + InstTraceReset(); + completionRecs.clear(); } -std::string RevTracer::RenderExec(const std::string& fallbackMnemonic) -{ - // Flow Control Events - std::stringstream ss_events; - if (events.v) { - if (events.f.trc_ctl) { - EVENT_SYMBOL e = outputEnabled ? EVENT_SYMBOL::TRACE_ON : EVENT_SYMBOL::TRACE_OFF; - ss_events << event2char.at(e); - } +std::string RevTracer::RenderExec( const std::string& fallbackMnemonic ) { + // Flow Control Events + std::stringstream ss_events; + if( events.v ) { + if( events.f.trc_ctl ) { + EVENT_SYMBOL e = outputEnabled ? EVENT_SYMBOL::TRACE_ON : EVENT_SYMBOL::TRACE_OFF; + ss_events << event2char.at( e ); } - - // Disassembly - std::stringstream ss_disasm; - #ifdef REV_USE_SPIKE - if (diasm) - ss_disasm << std::hex << diasm->disassemble(insn) << "\t"; - else - #endif - {; - // TODO internal rev disassembler - #if 0 + } + + // Disassembly + std::stringstream ss_disasm; +#ifdef REV_USE_SPIKE + if( diasm ) + ss_disasm << std::hex << diasm->disassemble( insn ) << "\t"; + else +#endif + { + ; +// TODO internal rev disassembler +#if 0 // only show mnemonic auto pos = fallbackMnemonic.find(' '); if (pos != std::string::npos) ss_disasm << fallbackMnemonic.substr(0, pos) << "\t"; else ss_disasm << "?" << "\n"; - #else - // show mnemonic and field format strings. - ss_disasm << fallbackMnemonic << "\t"; - #endif - } +#else + // show mnemonic and field format strings. + ss_disasm << std::left << std::setw( 20 ) << fallbackMnemonic << std::right << "\t"; +#endif + } + + // Initial rendering + std::stringstream os; + os << "0x" << std::hex << pc << ":" << std::setfill( '0' ); + if( ~insn & 3 ) { + os << std::setw( 4 ) << ( insn & 0xffff ) << " "; + } else { + os << std::setw( 8 ) << insn; + } + os << " " << std::setfill( ' ' ) << std::setw( 2 ) << ss_events.str() << " " << ss_disasm.str(); + + // register and memory read/write events preserving code ordering + if( traceRecs.empty() ) + return os.str(); - // Initial rendering - std::stringstream os; - os << "0x" << std::hex << pc << ":" << std::setfill('0') << std::setw(8) << insn; - os << " " << std::setfill(' ') << std::setw(2) << ss_events.str() << " " << ss_disasm.str(); - - // register and memory read/write events preserving code ordering - if (traceRecs.empty()) - return os.str(); - - // We got something, count it and render it - traceCycles++; - - // For Memh, the target register is corrupted after ReadVal (See RevInstHelpers.h::load) - // This is a transitory value that would only be observed if the register file is accessible - // by an external agent (e.g. IO or JTAG scan). A functional issue would occur - // if an error response is received from the network in which case the scoreboard - // should be cleared and the register would be expected to retain its previous value. - // Until this is resolved, the trace supresses the extra register write when - // we encounter a memhSendRead event. - // TODO remove this if/when extra register write is removed. - bool squashNextSetX = false; - - std::stringstream ss_rw; - for (TraceRec_t r : traceRecs) { - switch (r.key) { - case RegRead: - // a:reg b:data - ss_rw << "0x" << std::hex << r.b << "<-"; - ss_rw << fmt_reg(r.a) << " "; - break; - case RegWrite: - // a:reg b:data - if (squashNextSetX) { - squashNextSetX=false; - } else { - ss_rw << fmt_reg(r.a) << "<-0x" << std::hex << r.b << " "; - } - break; - case MemStore: - { - // a:adr b:len c:data - ss_rw << "[0x" << std::hex << r.a << "," << std::dec << r.b << "]<-" - << fmt_data(r.b, r.c) << " "; - break; - } - case MemLoad: - // a:adr b:len c:data - ss_rw << fmt_data(r.b, r.c) << "<-[0x" << std::hex << r.a << "," << std::dec << r.b << "]"; - ss_rw << " "; - break; - case MemhSendLoad: - // a:adr b:len c:reg - ss_rw << fmt_reg(r.c) << "<-[0x" << std::hex << r.a << "," << std::dec << r.b << "]"; - ss_rw << " "; - squashNextSetX = true; // register corrupted after ReadVal in RevInstHelpers.h::load - break; - case PcWrite: - // a:pc - uint64_t pc = r.a; - if ( lastPC+4 != pc ) { - // only render if non-sequential instruction - ss_rw << "pc<-0x" << std::hex << pc; - if (traceSymbols and (traceSymbols->find(pc) != traceSymbols->end())) - ss_rw << " <" << traceSymbols->at(pc) << ">"; - ss_rw << " "; - } - lastPC = pc; - break; - } + // We got something, count it and render it + traceCycles++; + + // For Memh, the target register is corrupted after ReadVal (See RevInstHelpers.h::load) + // This is a transitory value that would only be observed if the register file is accessible + // by an external agent (e.g. IO or JTAG scan). A functional issue would occur + // if an error response is received from the network in which case the scoreboard + // should be cleared and the register would be expected to retain its previous value. + // Until this is resolved, the trace supresses the extra register write when + // we encounter a memhSendRead event. + // TODO remove this if/when extra register write is removed. + bool squashNextSetX = false; + + std::stringstream ss_rw; + for( const TraceRec_t& r : traceRecs ) { + switch( r.key ) { + case RegRead: + // a:reg b:data + ss_rw << "0x" << std::hex << r.b << "<-"; + ss_rw << fmt_reg( r.a ) << " "; + break; + case RegWrite: + // a:reg b:data + if( squashNextSetX ) { + squashNextSetX = false; + } else { + ss_rw << fmt_reg( r.a ) << "<-0x" << std::hex << r.b << " "; + } + break; + case MemStore: { + // a:adr b:len c:data + ss_rw << "[0x" << std::hex << r.a << "," << std::dec << r.b << "]<-" << fmt_data( r.b, r.c ) << " "; + break; } + case MemLoad: + // a:adr b:len c:data + ss_rw << fmt_data( r.b, r.c ) << "<-[0x" << std::hex << r.a << "," << std::dec << r.b << "]"; + ss_rw << " "; + break; + case MemhSendLoad: + // a:adr b:len c:reg + ss_rw << fmt_reg( r.c ) << "<-[0x" << std::hex << r.a << "," << std::dec << r.b << "]"; + ss_rw << " "; + squashNextSetX = true; // register corrupted after ReadVal in RevInstHelpers.h::load + break; + case PcWrite: + // a:pc + uint64_t pc = r.a; + if( lastPC + 4 != pc ) { + // only render if non-sequential instruction + ss_rw << "pc<-0x" << std::hex << pc; + if( traceSymbols and ( traceSymbols->find( pc ) != traceSymbols->end() ) ) + ss_rw << " <" << traceSymbols->at( pc ) << ">"; + ss_rw << " "; + } + lastPC = pc; + break; + } + } - // Finalize string - os << " " << ss_rw.str(); - return os.str(); + // Finalize string + os << " " << ss_rw.str(); + return os.str(); } -void RevTracer::InstTraceReset() -{ - events.v = 0; - insn = 0; - traceRecs.clear(); - instHeader.clear(); +void RevTracer::InstTraceReset() { + events.v = 0; + insn = 0; + traceRecs.clear(); + instHeader.clear(); } -std::string RevTracer::fmt_reg(uint8_t r) -{ - std::stringstream s; - #ifdef REV_USE_SPIKE - if (r<32) { - s< 8) - s << std::setw(8 * 2) << d << "..+" << std::dec << (8-len); - else if (len == 8) - s << std::setw(8 * 2) << d; - else { - unsigned shift = (8-len) * 8; - uint64_t mask = (~0ULL) >> shift; - s << std::setw(len * 2) << (d & mask); - } - return s.str(); +std::string RevTracer::fmt_data( size_t len, uint64_t d ) { + std::stringstream s; + if( len == 0 ) + return ""; + s << "0x" << std::hex << std::setfill( '0' ); + if( len > sizeof( d ) ) + s << std::setw( int( sizeof( d ) * 2 ) ) << d << "..+" << std::dec << len - sizeof( d ); + else { + s << std::setw( int( len * 2 ) ) << ( d & ~( ~uint64_t{} << len * 8 ) ); + } + return s.str(); } -} // namespace SST::RevCPU +} // namespace SST::RevCPU diff --git a/src/librevcpu.cc b/src/librevcpu.cc index 877ea3515..4b0af0dc2 100644 --- a/src/librevcpu.cc +++ b/src/librevcpu.cc @@ -8,36 +8,34 @@ // See LICENSE in the top level directory for licensing details // -#include "SST.h" #include "RevCPU.h" +#include "SST.h" -namespace SST::RevCPU{ +namespace SST::RevCPU { char pyrevcpu[] = { #include "pyrevcpu.inc" - 0x00}; + 0x00 }; class RevCPUPyModule : public SSTElementPythonModule { public: - /// Constructor - explicit RevCPUPyModule(std::string library) : - SSTElementPythonModule(std::move(library)) { - createPrimaryModule(pyrevcpu, "pyrevcpu.py"); + explicit RevCPUPyModule( std::string library ) : SSTElementPythonModule( std::move( library ) ) { + createPrimaryModule( pyrevcpu, "pyrevcpu.py" ); } // Register the library with ELI SST_ELI_REGISTER_PYTHON_MODULE( - SST::RevCPU::RevCPUPyModule, // python class - "revcpu", // component library - SST_ELI_ELEMENT_VERSION(1, 0, 0) - ) + SST::RevCPU::RevCPUPyModule, // python class + "revcpu", // component library + SST_ELI_ELEMENT_VERSION( 1, 0, 0 ) + ) // Export the library via ELI - SST_ELI_EXPORT(SST::RevCPU::RevCPUPyModule) + SST_ELI_EXPORT( SST::RevCPU::RevCPUPyModule ) -}; // RevCPUPyModule +}; // RevCPUPyModule -} // namespace SST::RevCPU +} // namespace SST::RevCPU // EOF diff --git a/src/pyrevcpu.py b/src/pyrevcpu.py old mode 100644 new mode 100755 index 095f65e9e..7c1ca0b77 --- a/src/pyrevcpu.py +++ b/src/pyrevcpu.py @@ -1,90 +1,90 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Rev Python Infrastructure # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # # See LICENSE in the top level directory for licensing details # -import sys import sst -from sst.merlin.base import * +from sst.merlin.base import (startAdd, _CPUS, Job, mem_size, cpu_type, _rev, _num_nodes) + class RevCPU(): - def __init__(self): - print("Initializing RevCPU") - self.declareClassVariables(["_numCores"]) - self._numCPU = 0 - - def getName(self): - return "RevCPU" - - def getNumCPU(self): - return self._numCPU - - def enableRevSim(self,cpus,cores,clock,memSize,machine,startAddr,memCost,program,verbose): - print("Enabling Rev CPU component params") - self._numCPU = cpus - for i in range(0, cpus) - print("Building RevCPU " + str(i)) - sst.pushNamePrefix("CPU"+str(i)) - - # build component name = "CPUx.rev" - cpu = sst.Component("rev","revcpu.RevCPU") - cpu.addParam("verbose", verbose) - cpu.addParam("numCores", cores) - cpu.addParam("clock", clock) - cpu.addParam("memSize", memSize) - cpu.addParam("machine",machine) - cpu.addParam("startAddr",startAdd) - cpu.addParam("memCost",memCost) - cpu.addParam("program",program) - _CPUS.append(cpu) - sst.popNamePrefix() - - - def enableStatistics(self, level): - print("Enabling Rev statistics") - sst.setStatisticLoadLevel(level) - sst.setStatisticsOutput("sst.statOutputCSV") - sst.enableAllStatisticsForComponentType("revcpu.RevCPU") - - #-- private variables - _CPUS = [] + def __init__(self): + print("Initializing RevCPU") + self.declareClassVariables(["_numCores"]) + self._numCPU = 0 + + def getName(self): + return "RevCPU" + + def getNumCPU(self): + return self._numCPU + + def enableRevSim(self, cpus, cores, clock, memSize, machine, startAddr, memCost, program, verbose): + print("Enabling Rev CPU component params") + self._numCPU = cpus + for i in range(0, cpus): + print("Building RevCPU " + str(i)) + sst.pushNamePrefix("CPU"+str(i)) + + # build component name = "CPUx.rev" + cpu = sst.Component("rev", "revcpu.RevCPU") + cpu.addParam("verbose", verbose) + cpu.addParam("numCores", cores) + cpu.addParam("clock", clock) + cpu.addParam("memSize", memSize) + cpu.addParam("machine", machine) + cpu.addParam("startAddr", startAdd) + cpu.addParam("memCost", memCost) + cpu.addParam("program", program) + _CPUS.append(cpu) + sst.popNamePrefix() + + def enableStatistics(self, level): + print("Enabling Rev statistics") + sst.setStatisticLoadLevel(level) + sst.setStatisticsOutput("sst.statOutputCSV") + sst.enableAllStatisticsForComponentType("revcpu.RevCPU") + + # -- private variables + _CPUS = [] + class RevJob(Job): - def __init__(self, job_id, num_nodes): - Job.__init__(self,job_id,num_nodes) - _rev = RevCPU() + def __init__(self, job_id, num_nodes): + Job.__init__(self, job_id, num_nodes) +# _rev = RevCPU() - self.declareClassVariables(["_memSize", "_cpuType"]) + self.declareClassVariables(["_memSize", "_cpuType"]) - self._memSize = mem_size - self._cpuType = cpu_type + self._memSize = mem_size + self._cpuType = cpu_type - def initCPUS(self,cores,clock,memSize,machine,startAddr,memCost,program,verbose): - _rev.enableRevSim(self,_num_nodes,cores,clock,memSize,machine,startAddr,memCost,program,verbose) + def initCPUS(self, cores, clock, memSize, machine, startAddr, memCost, program, verbose): + _rev.enableRevSim(self, _num_nodes, cores, clock, memSize, machine, startAddr, memCost, program, verbose) - def getName(self): - return "RevJob" + def getName(self): + return "RevJob" - def build(self, nodeID, extraKeys): - if self._check_first_build() - sst.addGlobalParam("params_%s"%self._instance_name, 'jobId', self.job_id) + def build(self, nodeID, extraKeys): + if self._check_first_build(): + sst.addGlobalParam("params_%s" % self._instance_name, 'jobId', self.job_id) - nic, slot_name = self.nic.build(nodeID,self._numCores) + nic, slot_name = self.nic.build(nodeID, self._numCores) - logical_id = self._nid_map[nodeID] - networkif, port_name = self.network_interface.build(nic,slot_name,0,self.job_id,self.size,logical_id,False) + logical_id = self._nid_map[nodeID] + networkif, port_name = self.network_interface.build(nic, slot_name, 0, self.job_id, self.size, logical_id, False) - retval = ( networkif, port_name ) + retval = (networkif, port_name) - return retval + return retval - #-- private variables - _rev + # -- private variables + _rev -#-- EOF +# -- EOF diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c0c4dffba..d43620e81 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,11 +1,20 @@ # RevCPU test/CMakeLists.txt # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # # See LICENSE in the top level directory for licensing details # +if(NOT DEFINED TEST_LEVEL) + set(TEST_LEVEL "$ENV{TEST_LEVEL}") +endif() + +if(NOT TEST_LEVEL OR TEST_LEVEL GREATER 3 OR TEST_LEVEL LESS 1) + set(TEST_LEVEL 3) +endif() + +message("TEST_LEVEL=${TEST_LEVEL}") set(RISCV_ENV "$ENV{RISCV}") if(RISCV_ENV) @@ -39,6 +48,7 @@ else() message(FATAL_ERROR "RVCXX environment varible is not set.") endif() +set(RVOBJDUMP "$ENV{RVOBJDUMP}") if(NOT RVOBJDUMP) file(GLOB RVOBJDUMP_FILES "${RISCV_BIN_PATH}/*objdump") list(GET RVOBJDUMP_FILES 0 RVOBJDUMP) @@ -83,12 +93,27 @@ macro(add_rev_test test_name test_dir timeout labels) set(add_memh_test FALSE) set(startSymbol "\"[0:main]\"") + set(test_level 1) + string(FIND "${labels}" "test_level=2" test_level_2_index) + if(NOT ${test_level_2_index} EQUAL -1) + set(test_level 2) + endif() + string(FIND "${labels}" "test_level=3" test_level_3_index) + if(NOT ${test_level_3_index} EQUAL -1) + set(test_level 3) + endif() + # Adjust parameters based on the labels that are passed string(FIND "${labels}" "rv32" rv32_label_index) if(NOT ${rv32_label_index} EQUAL -1) set(machine_args "\"[CORES:RV32GC]\"") endif() + string(FIND "${labels}" "zicntr" zicntr_label_index) + if(NOT ${zicntr_label_index} EQUAL -1) + set(machine_args "\"[CORES:RV64GC_zicntr]\"") + endif() + string(FIND "${labels}" "multihart" multihart_label_index) if(NOT ${multihart_label_index} EQUAL -1) set(numHartsList 1 2 4) @@ -110,9 +135,9 @@ macro(add_rev_test test_name test_dir timeout labels) set(add_memh_test TRUE) endif() - string(FIND "${labels}" "cpp" cpp_label_index) + string(FIND "${labels}" "c++" cpp_label_index) if(NOT ${cpp_label_index} EQUAL -1) - set(startSymbol "\"[0:_start]\"") + # set(startSymbol "\"[0:_start]\"") endif() if(NOT optional_script) @@ -121,46 +146,53 @@ macro(add_rev_test test_name test_dir timeout labels) # Define revmem target with the new naming convention add_custom_target(run_${test_name_lower}_revmem_${numHarts}_harts_${numCores}_cores - COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/${test_name_lower} && sst --add-lib-path=${CMAKE_SOURCE_DIR}/build/src/ ${CMAKE_SOURCE_DIR}/test/rev-model-options-config.py -- --program="${test_name_lower}.exe" --numHarts=${numHarts} --numCores=${numCores} --machine "${machine_args}" --startSymbol "${startSymbol}" - DEPENDS build_${test_name_lower} - COMMENT "Running ${test_name_lower} test with revmem, numHarts=${numHarts}, numCores=${numCores}" - ) + COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/${test_name_lower} && sst --add-lib-path=${CMAKE_SOURCE_DIR}/build/src/ ${CMAKE_SOURCE_DIR}/test/rev-model-options-config.py -- --program="${test_name_lower}.exe" --numHarts=${numHarts} --numCores=${numCores} --machine "${machine_args}" --startSymbol "${startSymbol}" + DEPENDS build_${test_name_lower} + COMMENT "Running ${test_name_lower} test with revmem, numHarts=${numHarts}, numCores=${numCores}" + ) add_test(NAME ${test_name_lower}_revmem_${numHarts}_harts_${numCores}_cores COMMAND ${CMAKE_COMMAND} --build . --target run_${test_name_lower}_revmem_${numHarts}_harts_${numCores}_cores) + if(((NOT ${rv32_label_index} EQUAL -1) AND DEFINED RV32_DISABLED) OR test_level GREATER TEST_LEVEL) + set_tests_properties(${test_name_lower}_revmem_${numHarts}_harts_${numCores}_cores PROPERTIES DISABLED TRUE) + endif() + # If 'memh' label found, add a memHierarchy test if(add_memh_test) add_custom_target(run_${test_name_lower}_memh_${numHarts}_harts_${numCores}_cores - COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/${test_name_lower} && sst --add-lib-path=${CMAKE_SOURCE_DIR}/build/src/ ${CMAKE_SOURCE_DIR}/test/rev-model-options-config.py -- --program="${test_name_lower}.exe" --numHarts=${numHarts} --numCores=${numCores} --machine "${machine_args}" --enableMemH=1 --startSymbol "${startSymbol}" - DEPENDS build_${test_name_lower} - COMMENT "Running ${test_name_lower} test with memHierarchy enabled, numHarts=${numHarts}, numCores=${numCores}" - ) + COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/${test_name_lower} && sst --add-lib-path=${CMAKE_SOURCE_DIR}/build/src/ ${CMAKE_SOURCE_DIR}/test/rev-model-options-config.py -- --program="${test_name_lower}.exe" --numHarts=${numHarts} --numCores=${numCores} --machine "${machine_args}" --enableMemH=1 --startSymbol "${startSymbol}" + DEPENDS build_${test_name_lower} + COMMENT "Running ${test_name_lower} test with memHierarchy enabled, numHarts=${numHarts}, numCores=${numCores}" + ) add_test(NAME ${test_name_lower}_memh_${numHarts}_harts_${numCores}_cores COMMAND ${CMAKE_COMMAND} --build . --target run_${test_name_lower}_memh_${numHarts}_harts_${numCores}_cores) + if(((NOT ${rv32_label_index} EQUAL -1) AND DEFINED RV32_DISABLED) OR test_level GREATER TEST_LEVEL) + set_tests_properties(${test_name_lower}_memh_${numHarts}_harts_${numCores}_cores PROPERTIES DISABLED TRUE) + endif() endif() set_tests_properties(${test_name_lower}_revmem_${numHarts}_harts_${numCores}_cores - PROPERTIES - ENVIRONMENT "RVCC=${RVCC}" + PROPERTIES + ENVIRONMENT "RVCC=${RVCC};RVCXX=${RVCXX}" TIMEOUT ${timeout} PASS_REGULAR_EXPRESSION "${passRegex}" LABELS "${labels}" - ) + ) if(add_memh_test) set_tests_properties(${test_name_lower}_memh_${numHarts}_harts_${numCores}_cores - PROPERTIES - ENVIRONMENT "RVCC=${RVCC}" + PROPERTIES + ENVIRONMENT "RVCC=${RVCC};RVCXX=${RVCXX}" TIMEOUT ${timeout} PASS_REGULAR_EXPRESSION "${passRegex}" LABELS "${labels}" - ) + ) endif() endforeach() endforeach() - else() # Custom target for running the specified script add_custom_target(run_${test_name_lower}_script COMMAND ${CMAKE_COMMAND} -E echo "Executing script ${optional_script}" - COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/${test_name_lower} && bash ${optional_script} + COMMAND bash ${optional_script} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir_lower} DEPENDS build_${test_name_lower} COMMENT "Running script for ${test_name_lower} test" ) @@ -171,52 +203,85 @@ macro(add_rev_test test_name test_dir timeout labels) # Set test properties for the script test set_tests_properties(${test_name_lower}_script PROPERTIES - ENVIRONMENT "RVCC=${RVCC}" - TIMEOUT ${timeout} - PASS_REGULAR_EXPRESSION "${passRegex}" - LABELS "${labels}" + ENVIRONMENT "RVCC=${RVCC};RVCXX=${RVCXX}" + TIMEOUT ${timeout} + PASS_REGULAR_EXPRESSION "${passRegex}" + LABELS "${labels}" ) + if(((NOT ${rv32_label_index} EQUAL -1) AND DEFINED RV32_DISABLED) OR test_level GREATER TEST_LEVEL) + set_tests_properties(${test_name_lower}_script PROPERTIES DISABLED TRUE) + endif() endif() endmacro() +# Not all toolchains have support RV32, so we test and skip RV32 tests with a warning +execute_process(COMMAND ${RVCC} -march=rv32i -mabi=ilp32 -o /dev/null ex1.c WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/ex1 ERROR_VARIABLE RV32_Missing) +if(RV32_Missing MATCHES "Cannot find suitable multilib set for '-march=rv32") + set(RV32_DISABLED TRUE) + message(WARNING "RV32 tests disabled because ${RVCC} does not support RV32") +endif() + # add_rev_test(test_name test_dir timeout labels) -add_rev_test(EX1 ex1 30 "all;memh;rv32") -add_rev_test(EX2 ex2 30 "all;memh;rv64") -add_rev_test(EX3 ex3 30 "all;memh;rv32") -add_rev_test(EX4 ex4 30 "all;memh;rv32") -add_rev_test(EX5 ex5 30 "all;memh;rv64") -add_rev_test(EX6 ex6 45 "all;memh;rv64") -add_rev_test(EX7 ex7 30 "all;memh;rv64") -add_rev_test(BIG_LOOP big_loop 100 "all;rv64;benchmark") -add_rev_test(LARGE_BSS large_bss 60 "all;memh;rv64") -add_rev_test(DEP_CHECK dep_check 30 "all;memh;rv32") -add_rev_test(CACHE_1 cache_1 30 "all;memh;rv32" SCRIPT "run_cache_1.sh") -add_rev_test(CACHE_2 cache_2 30 "all;memh;rv64" SCRIPT "run_cache_2.sh") -add_rev_test(STRLEN_C strlen_c 30 "all;memh;rv64") -add_rev_test(STRLEN_CXX strlen_cxx 30 "all;memh;rv64;cxx") -add_rev_test(STRSTR strstr 30 "all;memh;rv64") -add_rev_test(MEMSET memset 30 "all;memh;rv64") -add_rev_test(MEMSET_2 memset_2 60 "all;memh;rv64") -add_rev_test(MANY_CORE many_core 30 "all;memh;rv64" SCRIPT "run_many_core.sh") -add_rev_test(DIVW divw 30 "all;memh;rv64") -add_rev_test(DIVW2 divw2 30 "all;memh;rv64") -add_rev_test(X0 x0 30 "all;memh;rv64") -add_rev_test(ARGC argc 30 "all;memh;rv64;loader;" SCRIPT "run_argc.sh") -add_rev_test(ARGC_SHORT argc 30 "all;memh;rv64;loader;" SCRIPT "run_argc_short.sh") -add_rev_test(COPROC_EX coproc_ex 30 "all;memh;rv64;coproc" SCRIPT "run_coproc_ex.sh") -add_rev_test(ZICBOM zicbom 45 "all;memh;rv64" SCRIPT "run_zicbom.sh") -add_rev_test(BACKINGSTORE backingstore 100 "all;rv64" SCRIPT "run_backingstore.sh") -# add_rev_test(TRACER tracer 30 "all;rv64;tracer") -# add_rev_test(PAN_TEST1 pan_test1 30 "all;rv64;pan") -# add_rev_test(PAN_TEST2 pan_test2 30 "all;rv64;pan") -# add_rev_test(DOT_SINGLE dot_single 30 "all;rv64;blas-required") -# add_rev_test(DOT_DOUBLE dot_double 30 "all;rv64;blas-required") -# add_rev_test(BGE_BLE bge_ble 30 "all;rv64") +add_rev_test(EXT_VERSION ext_version 20 "rv64") +add_rev_test(EX1 ex1 30 "memh;rv32") +add_rev_test(EX2 ex2 30 "memh;rv64") +add_rev_test(EX3 ex3 30 "memh;rv32") +add_rev_test(EX4 ex4 30 "memh;rv32") +add_rev_test(EX5 ex5 30 "memh;rv64") +add_rev_test(EX6 ex6 45 "memh;rv64") +add_rev_test(EX7 ex7 30 "memh;rv64") +add_rev_test(BIG_LOOP big_loop 140 "test_level=2;rv64;benchmark") +add_rev_test(LARGE_BSS large_bss 60 "test_level=2;memh;rv64") +add_rev_test(DEP_CHECK dep_check 30 "memh;rv32") +add_rev_test(CACHE_1 cache_1 30 "memh;rv32" SCRIPT "run_cache_1.sh") +add_rev_test(CACHE_2 cache_2 30 "memh;rv64" SCRIPT "run_cache_2.sh") +add_rev_test(STRLEN_C strlen_c 30 "memh;rv64") +add_rev_test(STRLEN_CXX strlen_cxx 30 "memh;rv64;c++") +add_rev_test(STRSTR strstr 30 "memh;rv64") +add_rev_test(MEMSET memset 30 "memh;rv64") +add_rev_test(MEMSET_2 memset_2 90 "test_level=2;memh;rv64") +add_rev_test(MANY_CORE many_core 30 "memh;rv64" SCRIPT "run_many_core.sh") +add_rev_test(DIVW divw 30 "memh;rv64") +add_rev_test(DIVW2 divw2 30 "memh;rv64") +add_rev_test(X0 x0 30 "memh;rv64") +add_rev_test(ARGC argc 30 "test_level=2;memh;rv64;loader;" SCRIPT "run_argc.sh") +add_rev_test(ARGC_SHORT argc_short 30 "test_level=2;memh;rv64;loader;" SCRIPT "run_argc_short.sh") +add_rev_test(ARGV argv 30 "test_level=2;memh;rv64;loader;c++" SCRIPT "run_argv.sh") +add_rev_test(ARGV_layout argv_layout 30 "test_level=2;memh;rv32;loader;" SCRIPT "run_argv_layout.sh") +add_rev_test(ARGV_limit argv_limit 90 "test_level=2;memh;rv32;loader;" SCRIPT "run_argv_limit.sh") +add_rev_test(ARGV_stack argv_stack 10 "memh;rv64") +add_rev_test(COPROC_EX coproc_ex 30 "memh;rv64;coproc" SCRIPT "run_coproc_ex.sh") +add_rev_test(ZICBOM zicbom 45 "test_level=2;memh;rv64" SCRIPT "run_zicbom.sh") + +add_rev_test(BACKINGSTORE backingstore 100 "test_level=2;rv64" SCRIPT "run_backingstore.sh") +add_rev_test(MEM_DUMP mem_dump 10 "rv64" SCRIPT "run_mem_dump.sh") +add_rev_test(LWSP lwsp 30 "test_level=2;memh;rv64") +add_rev_test(CSR csr 30 "rv64") +add_rev_test(RDCYCLE rdcycle 5 "test_level=2;rv64;zicntr") +add_rev_test(RDTIME rdtime 5 "test_level=2;rv64;zicntr") +add_rev_test(RDINSTRET rdinstret 5 "test_level=2;memh;rv64;zicntr") +add_rev_test(Zfa zfa 30 "rv64" SCRIPT "run_zfa_tests.sh") + +# Not all toolchains have support for Zfa yet, so we test and skip Zfa tests with a warning +execute_process(COMMAND ${RVCXX} -c -march=rv64gc_zfa zfa.cc WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/zfa ERROR_VARIABLE ZFA_Missing) +if(ZFA_Missing MATCHES "unknown prefixed ISA extension .zfa") + set_tests_properties(zfa_script PROPERTIES DISABLED TRUE) + message(WARNING "Zfa tests being skipped because ${RVCXX} does not support Zfa") +endif() + +# add_rev_test(TRACER tracer 30 "rv64;tracer") +# add_rev_test(PAN_TEST1 pan_test1 30 "rv64;pan") +# add_rev_test(PAN_TEST2 pan_test2 30 "rv64;pan") +# add_rev_test(DOT_SINGLE dot_single 30 "rv64;blas-required") +# add_rev_test(DOT_DOUBLE dot_double 30 "rv64;blas-required") +# add_rev_test(BGE_BLE bge_ble 30 "rv64") add_subdirectory(isa) add_subdirectory(amo) add_subdirectory(benchmarks) add_subdirectory(syscalls) add_subdirectory(threading) +add_subdirectory(cxx) +add_subdirectory(fenv) # EOF diff --git a/test/amo/CMakeLists.txt b/test/amo/CMakeLists.txt index dc4fafb8e..fb1961607 100644 --- a/test/amo/CMakeLists.txt +++ b/test/amo/CMakeLists.txt @@ -1,3 +1,3 @@ -add_rev_test(AMOADD_C amoadd_c 30 "all;rv64;amo;memh") -add_rev_test(AMOADD_CXX amoadd_cxx 30 "all;rv64;amo;memh") -add_rev_test(AMOSWAP_C amoswap_c 30 "all;rv64;amo;memh") +add_rev_test(AMOADD_C amoadd_c 30 "rv64;amo;memh") +add_rev_test(AMOADD_CXX amoadd_cxx 30 "rv64;amo;memh") +add_rev_test(AMOSWAP_C amoswap_c 30 "rv64;amo;memh") diff --git a/test/amo/amoadd_c/Makefile b/test/amo/amoadd_c/Makefile index eac5edda0..468e0084e 100644 --- a/test/amo/amoadd_c/Makefile +++ b/test/amo/amoadd_c/Makefile @@ -3,7 +3,7 @@ # # makefile: amoadd_c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/amo/amoadd_c/amoadd_c.c b/test/amo/amoadd_c/amoadd_c.c index df4bfc0d1..d196be9c8 100644 --- a/test/amo/amoadd_c/amoadd_c.c +++ b/test/amo/amoadd_c/amoadd_c.c @@ -1,21 +1,22 @@ -#include #include +#include uint64_t atom64 = 0; uint32_t atom32 = 0; + int main() { - __atomic_fetch_add(&atom64, 2, __ATOMIC_RELAXED); - __atomic_fetch_add(&atom64, 2, __ATOMIC_CONSUME); - __atomic_fetch_add(&atom64, 2, __ATOMIC_ACQUIRE); - __atomic_fetch_add(&atom64, 2, __ATOMIC_RELEASE); - __atomic_fetch_add(&atom64, 2, __ATOMIC_ACQ_REL); - __atomic_fetch_add(&atom64, 2, __ATOMIC_SEQ_CST); + __atomic_fetch_add( &atom64, 2, __ATOMIC_RELAXED ); + __atomic_fetch_add( &atom64, 2, __ATOMIC_CONSUME ); + __atomic_fetch_add( &atom64, 2, __ATOMIC_ACQUIRE ); + __atomic_fetch_add( &atom64, 2, __ATOMIC_RELEASE ); + __atomic_fetch_add( &atom64, 2, __ATOMIC_ACQ_REL ); + __atomic_fetch_add( &atom64, 2, __ATOMIC_SEQ_CST ); - __atomic_fetch_add(&atom32, 2, __ATOMIC_RELAXED); - __atomic_fetch_add(&atom32, 2, __ATOMIC_CONSUME); - __atomic_fetch_add(&atom32, 2, __ATOMIC_ACQUIRE); - __atomic_fetch_add(&atom32, 2, __ATOMIC_RELEASE); - __atomic_fetch_add(&atom32, 2, __ATOMIC_ACQ_REL); - __atomic_fetch_add(&atom32, 2, __ATOMIC_SEQ_CST); - return 0; + __atomic_fetch_add( &atom32, 2, __ATOMIC_RELAXED ); + __atomic_fetch_add( &atom32, 2, __ATOMIC_CONSUME ); + __atomic_fetch_add( &atom32, 2, __ATOMIC_ACQUIRE ); + __atomic_fetch_add( &atom32, 2, __ATOMIC_RELEASE ); + __atomic_fetch_add( &atom32, 2, __ATOMIC_ACQ_REL ); + __atomic_fetch_add( &atom32, 2, __ATOMIC_SEQ_CST ); + return 0; } diff --git a/test/amo/amoadd_cxx/Makefile b/test/amo/amoadd_cxx/Makefile index 104f9c0fa..765f6e61b 100644 --- a/test/amo/amoadd_cxx/Makefile +++ b/test/amo/amoadd_cxx/Makefile @@ -3,7 +3,7 @@ # # makefile: strlen_c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/amo/amoadd_cxx/amoadd_cxx.cc b/test/amo/amoadd_cxx/amoadd_cxx.cc index 3a3bd4a0e..6d8b614b6 100644 --- a/test/amo/amoadd_cxx/amoadd_cxx.cc +++ b/test/amo/amoadd_cxx/amoadd_cxx.cc @@ -1,21 +1,21 @@ #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { - std::atomic a; - a = 1; //amoswap - assert(a == 1); - a++; //amoadd - assert(a == 2); + std::atomic a; + a = 1; //amoswap + assert( a == 1 ); + a++; //amoadd + assert( a == 2 ); - std::atomic b; - b = 1; //amoswap - assert(b == 1); - b++; //amoadd - assert(b == 2); + std::atomic b; + b = 1; //amoswap + assert( b == 1 ); + b++; //amoadd + assert( b == 2 ); } diff --git a/test/amo/amoswap_c/Makefile b/test/amo/amoswap_c/Makefile index d1f033d35..219a00779 100644 --- a/test/amo/amoswap_c/Makefile +++ b/test/amo/amoswap_c/Makefile @@ -3,7 +3,7 @@ # # makefile: amoswap_c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/amo/amoswap_c/amoswap_c.c b/test/amo/amoswap_c/amoswap_c.c index 4c38f388f..a20878301 100644 --- a/test/amo/amoswap_c/amoswap_c.c +++ b/test/amo/amoswap_c/amoswap_c.c @@ -2,35 +2,35 @@ #include #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) -uint64_t swap_dest = 0xfee1dead; -uint64_t swap_src = (((uint64_t)0xdeadbeef) << 32); -uint64_t swap_prev = 0; +uint64_t swap_dest = 0xfee1dead; +uint64_t swap_src = ( ( (uint64_t) 0xdeadbeef ) << 32 ); +uint64_t swap_prev = 0; uint32_t swap_dest32 = 0xfee1dead; -uint32_t swap_src32 = (((uint32_t)0xdeadbeef) << 16); +uint32_t swap_src32 = ( ( (uint32_t) 0xdeadbeef ) << 16 ); uint32_t swap_prev32 = 0; void test_single_thread32() { // swap_prev should become swap_dest // swap_dest should become swap_src - __atomic_exchange(&swap_dest32, &swap_src32, &swap_prev32, __ATOMIC_SEQ_CST); - assert(swap_dest32 == (((uint32_t)0xdeadbeef) << 16)); - assert(swap_prev32 == 0xfee1dead); + __atomic_exchange( &swap_dest32, &swap_src32, &swap_prev32, __ATOMIC_SEQ_CST ); + assert( swap_dest32 == ( ( (uint32_t) 0xdeadbeef ) << 16 ) ); + assert( swap_prev32 == 0xfee1dead ); } void test_single_thread64() { // swap_prev should become swap_dest // swap_dest should become swap_src - __atomic_exchange(&swap_dest, &swap_src, &swap_prev, __ATOMIC_SEQ_CST); - assert(swap_dest == (((uint64_t)0xdeadbeef) << 32)); - assert(swap_prev == 0xfee1dead); + __atomic_exchange( &swap_dest, &swap_src, &swap_prev, __ATOMIC_SEQ_CST ); + assert( swap_dest == ( ( (uint64_t) 0xdeadbeef ) << 32 ) ); + assert( swap_prev == 0xfee1dead ); } int main() { diff --git a/test/argc/Makefile b/test/argc/Makefile index 5c627c3d2..606c373ce 100644 --- a/test/argc/Makefile +++ b/test/argc/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/argc/argc.c b/test/argc/argc.c index 93ad20595..ebd7938cb 100644 --- a/test/argc/argc.c +++ b/test/argc/argc.c @@ -1,7 +1,7 @@ /* * argc.c * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,35 +11,35 @@ #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) // called with "argc.exe one two three; so argc == 4" -int main(int argc, char **argv) { +int main( int argc, char** argv ) { int a = argc; - assert(a == 4); - assert(argv[0][0] == 'a'); - assert(argv[0][1] == 'r'); - assert(argv[0][2] == 'g'); - assert(argv[0][3] == 'c'); - assert(argv[0][4] == '.'); - assert(argv[0][5] == 'e'); - assert(argv[0][6] == 'x'); - assert(argv[0][7] == 'e'); - assert(argv[1][0] == 'o'); - assert(argv[1][1] == 'n'); - assert(argv[1][2] == 'e'); - assert(argv[2][0] == 't'); - assert(argv[2][1] == 'w'); - assert(argv[2][2] == 'o'); - assert(argv[3][0] == 't'); - assert(argv[3][1] == 'h'); - assert(argv[3][2] == 'r'); - assert(argv[3][3] == 'e'); - assert(argv[3][4] == 'e'); + assert( a == 4 ); + assert( argv[0][0] == 'a' ); + assert( argv[0][1] == 'r' ); + assert( argv[0][2] == 'g' ); + assert( argv[0][3] == 'c' ); + assert( argv[0][4] == '.' ); + assert( argv[0][5] == 'e' ); + assert( argv[0][6] == 'x' ); + assert( argv[0][7] == 'e' ); + assert( argv[1][0] == 'o' ); + assert( argv[1][1] == 'n' ); + assert( argv[1][2] == 'e' ); + assert( argv[2][0] == 't' ); + assert( argv[2][1] == 'w' ); + assert( argv[2][2] == 'o' ); + assert( argv[3][0] == 't' ); + assert( argv[3][1] == 'h' ); + assert( argv[3][2] == 'r' ); + assert( argv[3][3] == 'e' ); + assert( argv[3][4] == 'e' ); return 0; } diff --git a/test/argc/run_argc.sh b/test/argc/run_argc.sh index 92c979134..28d4217c0 100755 --- a/test/argc/run_argc.sh +++ b/test/argc/run_argc.sh @@ -5,6 +5,7 @@ make clean && make # Check that the exec was built... if [[ -x argc.exe ]]; then + set -e sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argc.exe" --args "one two three" --enableMemH=0 echo "Test ARGC_REVMEM: Completed" sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argc.exe" --args "one two three" --enableMemH=1 diff --git a/test/argc_bug/Makefile b/test/argc_bug/Makefile index 12d92e647..6c6a0e5a4 100644 --- a/test/argc_bug/Makefile +++ b/test/argc_bug/Makefile @@ -3,7 +3,7 @@ # # makefile: argc bug # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -16,22 +16,19 @@ REVCFG ?= ./rev-test-basim.py # Rev toolchain (for host Rev) CC=${RVCC} INCLUDE = -I$(REVHOME)/test/include -FLAGS = -O2 -g -static -lm +# FLAGS = -O2 -g -static -lm +FLAGS = -O0 -g -static -lm OBJDUMP = ${RISCV}/bin/riscv64-unknown-elf-objdump -D --source -C -l -# REV simulator includes BASim +# REV simulator REVHOME ?= $(realpath ../..) REVLIBPATH ?= $(REVHOME)/build/src # configuration # rev core needs to use rv64imfdc to support compact instructions in stdlib (apparantly) -ARCH ?= rv64imfd -ABI ?= -mabi=lp64d -NUM_LANES ?= 64 -NUM_THR_PER_LANE ?= 4 -NUM_ELEM_PER_THREAD ?= 2 -CHUNK ?= 0 +ARCH ?= rv64gc +# ABI ?= -mabi=lp64d # Targets TLIST = $(patsubst %.c,%,$(wildcard *.c)) diff --git a/test/argc_bug/argc_bug.c b/test/argc_bug/argc_bug.c index a54b6d26f..5f8478281 100644 --- a/test/argc_bug/argc_bug.c +++ b/test/argc_bug/argc_bug.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64G * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -12,58 +12,56 @@ * bug test */ -#include "stdlib.h" #include "rev-macros.h" +#include "stdlib.h" #define assert TRACE_ASSERT -// uncomment to cause argc bug failure -#define INDUCE_ARGC_BUG +unsigned slow_accumulate( unsigned count, unsigned initial_value ); -unsigned slow_accumulate(unsigned count, unsigned initial_value); +int main( int argc, char** argv ) { -int main(int argc, char **argv){ + assert( argc == 5 ); + assert( argv[1][0] == '6' ); + assert( argv[1][1] == '4' ); + assert( argv[1][2] == 0 ); + assert( argv[2][0] == '4' ); + assert( argv[2][1] == 0 ); + assert( argv[3][0] == '2' ); + assert( argv[3][1] == 0 ); + assert( argv[4][0] == '3' ); + assert( argv[4][1] == 0 ); - assert(argc==4 || argc==5); + int arg1 = atoi( argv[1] ); + int arg2 = atoi( argv[2] ); + int arg3 = atoi( argv[3] ); + int arg4 = atoi( argv[4] ); - int arg1 = atoi(argv[1]); - int arg2 = atoi(argv[2]); - int arg3 = atoi(argv[3]); - int arg4 = 0; - if(argc == 5) arg4 = atoi(argv[4]); + assert( arg1 == 64 ); + assert( arg2 == 4 ); + assert( arg3 == 2 ); + assert( arg4 == 3 ); -#if 0 // playing around with small code changes affects the bug unsigned v = 0; - v = slow_accumulate(6,arg1); - assert(v==70); - v = slow_accumulate(v,arg2); - assert(v==74); - v = slow_accumulate(v,arg3); - assert(v==76); - v = slow_accumulate(v,arg4); - assert(v==76); -#endif - -#ifndef INDUCE_ARGC_BUG - assert(arg1==64); - assert(arg2==4); - assert(arg3==2); - assert(arg4==0); -#endif - + v = slow_accumulate( 6, arg1 ); + assert( v == 70 ); + v = slow_accumulate( v, arg2 ); + assert( v == 74 ); + v = slow_accumulate( v, arg3 ); + assert( v == 76 ); + v = slow_accumulate( v, arg4 ); + assert( v == 79 ); + return 0; } -unsigned slow_accumulate(unsigned count, unsigned initial_value) { +unsigned slow_accumulate( unsigned count, unsigned initial_value ) { int rc; - asm volatile ( - ".rept 25 \n\t" - "xor x0,x0,x0 \n\t" - ".endr \n\t" - "add %0, %1, %2 \n\t" - : "=r" (rc) - : "r" (count), "r" (initial_value) - ); + asm volatile( ".rept 25 \n\t" + "xor x0,x0,x0 \n\t" + ".endr \n\t" + "add %0, %1, %2 \n\t" + : "=r"( rc ) + : "r"( count ), "r"( initial_value ) ); return rc; } - diff --git a/test/argc_bug/argc_bug.trace_annotated b/test/argc_bug/argc_bug.trace_annotated new file mode 100644 index 000000000..6da0c90b7 --- /dev/null +++ b/test/argc_bug/argc_bug.trace_annotated @@ -0,0 +1,500 @@ +[2000]: *I 0x101a8:fc010113 + addi sp, sp, -64 0x3ffffbfc<-sp sp<-0x3ffffbbc +[3000]: *I 0x101ac:02113c23 sd ra, 56(sp) 0x3ffffbbc<-sp 0x0<-ra [0x3ffffbf4,8]<-0x0000000000000000 +[4000]: *I 0x101b0:02813823 sd s0, 48(sp) 0x3ffffbbc<-sp 0x11880<-s0 [0x3ffffbec,8]<-0x0000000000011880 +[5000]: *I 0x101b4:04010413 addi s0, sp, 64 0x3ffffbbc<-sp s0<-0x3ffffbfc +[6000]: *I 0x101b8:00050793 mv a5, a0 0x5<-a0 a5<-0x5 +[7000]: *I 0x101bc:fcb43023 sd a1, -64(s0) 0x3ffffbfc<-s0 0x3ffffb94<-a1 [0x3ffffbbc,8]<-0x000000003ffffb94 +[8000]: *I 0x101c0:fcf42623 sw a5, -52(s0) 0x3ffffbfc<-s0 0x5<-a5 [0x3ffffbc8,4]<-0x00000005 +[9000]: *I 0x101c4:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[10000]: *I 0x101c8:fcc42783 lw a5, -52(s0) 0x3ffffbfc<-s0 0x00000005<-[0x3ffffbc8,4] a5<-0x5 +[11000]: *I 0x101cc:0007871b sext.w a4, a5 0x5<-a5 a4<-0x5 +[12000]: *I 0x101d0:00500793 li a5, 5 0x0<-zero a5<-0x5 +[13000]: *I 0x101d4:00f70463 beq a4, a5, pc + 8 0x5<-a4 0x5<-a5 pc<-0x101dc +[14000]: *I 0x101dc:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +### assert(argv[1][0]=='6'); +[15000]: *I 0x101e0:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[16000]: *I 0x101e4:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[17000]: *I 0x101e8:00878793 addi a5, a5, 8 0x3ffffb94<-a5 a5<-0x3ffffb9c +[18000]: *I 0x101ec:0007b783 ld a5, 0(a5) 0x3ffffb9c<-a5 0x000000003ffffff7<-[0x3ffffb9c,8] a5<-0x3ffffff7 +### ascii 6 lives at 0x3ffffff7 +[19000]: *I 0x101f0:0007c783 lbu a5, 0(a5) 0x3ffffff7<-a5 0x36<-[0x3ffffff7,1] a5<-0x36 +[20000]: *I 0x101f4:00078713 mv a4, a5 0x36<-a5 a4<-0x36 +[21000]: *I 0x101f8:03600793 li a5, 54 0x0<-zero a5<-0x36 +[22000]: *I 0x101fc:00f70463 beq a4, a5, pc + 8 0x36<-a4 0x36<-a5 pc<-0x10204 +[23000]: *I 0x10204:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +### assert(argv[1][1]=='4'); +[24000]: *I 0x10208:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[25000]: *I 0x1020c:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[26000]: *I 0x10210:00878793 addi a5, a5, 8 0x3ffffb94<-a5 a5<-0x3ffffb9c +[27000]: *I 0x10214:0007b783 ld a5, 0(a5) 0x3ffffb9c<-a5 0x000000003ffffff7<-[0x3ffffb9c,8] a5<-0x3ffffff7 +[28000]: *I 0x10218:00178793 addi a5, a5, 1 0x3ffffff7<-a5 a5<-0x3ffffff8 +### ascii 0x4 lives at 0x3ffffff8 +[29000]: *I 0x1021c:0007c783 lbu a5, 0(a5) 0x3ffffff8<-a5 0x34<-[0x3ffffff8,1] a5<-0x34 +[30000]: *I 0x10220:00078713 mv a4, a5 0x34<-a5 a4<-0x34 +[31000]: *I 0x10224:03400793 li a5, 52 0x0<-zero a5<-0x34 +[32000]: *I 0x10228:00f70463 beq a4, a5, pc + 8 0x34<-a4 0x34<-a5 pc<-0x10230 + +[33000]: *I 0x10230:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[34000]: *I 0x10234:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[35000]: *I 0x10238:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[36000]: *I 0x1023c:00878793 addi a5, a5, 8 0x3ffffb94<-a5 a5<-0x3ffffb9c +[37000]: *I 0x10240:0007b783 ld a5, 0(a5) 0x3ffffb9c<-a5 0x000000003ffffff7<-[0x3ffffb9c,8] a5<-0x3ffffff7 +[38000]: *I 0x10244:00278793 addi a5, a5, 2 0x3ffffff7<-a5 a5<-0x3ffffff9 +[39000]: *I 0x10248:0007c783 lbu a5, 0(a5) 0x3ffffff9<-a5 0x00<-[0x3ffffff9,1] a5<-0x0 +[40000]: *I 0x1024c:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x10254 +[41000]: *I 0x10254:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +### assert(argv[2][0]=='4'); +[42000]: *I 0x10258:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[43000]: *I 0x1025c:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[44000]: *I 0x10260:01078793 addi a5, a5, 16 0x3ffffb94<-a5 a5<-0x3ffffba4 +# Load 0x34 ('4') from Mem[0x3ffffffa] +[45000]: *I 0x10264:0007b783 ld a5, 0(a5) 0x3ffffba4<-a5 0x000000003ffffffa<-[0x3ffffba4,8] a5<-0x3ffffffa +[46000]: *I 0x10268:0007c783 lbu a5, 0(a5) 0x3ffffffa<-a5 0x34<-[0x3ffffffa,1] a5<-0x34 +[47000]: *I 0x1026c:00078713 mv a4, a5 0x34<-a5 a4<-0x34 +[48000]: *I 0x10270:03400793 li a5, 52 0x0<-zero a5<-0x34 +# Passes: assert(argv[2][0]=='4'); +[49000]: *I 0x10274:00f70463 beq a4, a5, pc + 8 0x34<-a4 0x34<-a5 pc<-0x1027c +[50000]: *I 0x1027c:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[51000]: *I 0x10280:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[52000]: *I 0x10284:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[53000]: *I 0x10288:01078793 addi a5, a5, 16 0x3ffffb94<-a5 a5<-0x3ffffba4 +### Here load 0x3ffffffa from 0x3fffffba4 (pointer to argv[2][0] - correct +[54000]: *I 0x1028c:0007b783 ld a5, 0(a5) 0x3ffffba4<-a5 0x000000003ffffffa<-[0x3ffffba4,8] a5<-0x3ffffffa +[55000]: *I 0x10290:00178793 addi a5, a5, 1 0x3ffffffa<-a5 a5<-0x3ffffffb +[56000]: *I 0x10294:0007c783 lbu a5, 0(a5) 0x3ffffffb<-a5 0x00<-[0x3ffffffb,1] a5<-0x0 +[57000]: *I 0x10298:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x102a0 +[58000]: *I 0x102a0:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[59000]: *I 0x102a4:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[60000]: *I 0x102a8:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[61000]: *I 0x102ac:01878793 addi a5, a5, 24 0x3ffffb94<-a5 a5<-0x3ffffbac +[62000]: *I 0x102b0:0007b783 ld a5, 0(a5) 0x3ffffbac<-a5 0x000000003ffffffc<-[0x3ffffbac,8] a5<-0x3ffffffc +[63000]: *I 0x102b4:0007c783 lbu a5, 0(a5) 0x3ffffffc<-a5 0x32<-[0x3ffffffc,1] a5<-0x32 +[64000]: *I 0x102b8:00078713 mv a4, a5 0x32<-a5 a4<-0x32 +[65000]: *I 0x102bc:03200793 li a5, 50 0x0<-zero a5<-0x32 +[66000]: *I 0x102c0:00f70463 beq a4, a5, pc + 8 0x32<-a4 0x32<-a5 pc<-0x102c8 +[67000]: *I 0x102c8:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[68000]: *I 0x102cc:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[69000]: *I 0x102d0:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[70000]: *I 0x102d4:01878793 addi a5, a5, 24 0x3ffffb94<-a5 a5<-0x3ffffbac +[71000]: *I 0x102d8:0007b783 ld a5, 0(a5) 0x3ffffbac<-a5 0x000000003ffffffc<-[0x3ffffbac,8] a5<-0x3ffffffc +[72000]: *I 0x102dc:00178793 addi a5, a5, 1 0x3ffffffc<-a5 a5<-0x3ffffffd +[73000]: *I 0x102e0:0007c783 lbu a5, 0(a5) 0x3ffffffd<-a5 0x00<-[0x3ffffffd,1] a5<-0x0 +[74000]: *I 0x102e4:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x102ec +[75000]: *I 0x102ec:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[76000]: *I 0x102f0:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[77000]: *I 0x102f4:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[78000]: *I 0x102f8:02078793 addi a5, a5, 32 0x3ffffb94<-a5 a5<-0x3ffffbb4 +[79000]: *I 0x102fc:0007b783 ld a5, 0(a5) 0x3ffffbb4<-a5 0x000000003ffffffe<-[0x3ffffbb4,8] a5<-0x3ffffffe +[80000]: *I 0x10300:0007c783 lbu a5, 0(a5) 0x3ffffffe<-a5 0x33<-[0x3ffffffe,1] a5<-0x33 +[81000]: *I 0x10304:00078713 mv a4, a5 0x33<-a5 a4<-0x33 +[82000]: *I 0x10308:03300793 li a5, 51 0x0<-zero a5<-0x33 +[83000]: *I 0x1030c:00f70463 beq a4, a5, pc + 8 0x33<-a4 0x33<-a5 pc<-0x10314 +[85000]: *I 0x10314:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 +[86000]: *I 0x10318:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[87000]: *I 0x1031c:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[88000]: *I 0x10320:02078793 addi a5, a5, 32 0x3ffffb94<-a5 a5<-0x3ffffbb4 +[89000]: *I 0x10324:0007b783 ld a5, 0(a5) 0x3ffffbb4<-a5 0x000000003ffffffe<-[0x3ffffbb4,8] a5<-0x3ffffffe +[90000]: *I 0x10328:00178793 addi a5, a5, 1 0x3ffffffe<-a5 a5<-0x3fffffff +[91000]: *I 0x1032c:0007c783 lbu a5, 0(a5) 0x3fffffff<-a5 0x00<-[0x3fffffff,1] a5<-0x0 +[92000]: *I 0x10330:00078463 beqz a5, pc + 8 0x0<-a5 0x0<-zero pc<-0x10338 +[93000]: *I 0x10338:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 + +### int arg1 = atoi(argv[1]); +### argv[1][0] at 0x3ffffff7 +### Note: s0=sp+64; a=mem[mem[s0-64]+8] +[94000]: *I 0x1033c:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[95000]: *I 0x10340:00878793 addi a5, a5, 8 0x3ffffb94<-a5 a5<-0x3ffffb9c +[96000]: *I 0x10344:0007b783 ld a5, 0(a5) 0x3ffffb9c<-a5 0x000000003ffffff7<-[0x3ffffb9c,8] a5<-0x3ffffff7 +[97000]: *I 0x10348:00078513 mv a0, a5 0x3ffffff7<-a5 a0<-0x3ffffff7 +[98000]: *I 0x1034c:270000ef jal pc + 0x270 ra<-0x10350 pc<-0x105bc + +[100000]: *I 0x105bc:46291141 c.addi sp, -16 0x3ffffbbc<-sp sp<-0x3ffffbac +[101000]: *I 0x105be:45814629 c.li a2, 10 0x0<-zero a2<-0xa +[102000]: *I 0x105c0:e4064581 c.li a1, 0 0x0<-zero a1<-0x0 +[103000]: *I 0x105c2:00efe406 c.sdsp ra, 8(sp) 0x3ffffbac<-sp 0x10350<-ra [0x3ffffbb4,8]<-0x0000000000010350 +### ra updated +[104000]: *I 0x105c4:2c8000ef jal pc + 0x2c8 ra<-0x105c8 pc<-0x1088c +[106000]: *I 0x1088c:862e86b2 c.mv a3, a2 0x0<-zero 0xa<-a2 a3<-0xa +[107000]: *I 0x1088e:85aa862e c.mv a2, a1 0x0<-zero 0x0<-a1 a2<-0x0 +[108000]: *I 0x10890:b50385aa c.mv a1, a0 0x0<-zero 0x3ffffff7<-a0 a1<-0x3ffffff7 +[109000]: *I 0x10892:f581b503 ld a0, -168(gp) 0x11880<-gp 0x0000000000011080<-[0x117d8,8] a0<-0x11080 +[110000]: *I 0x10896:715db58d c.j pc - 414 zero<-0x0 pc<-0x106f8 <_strtol_l.constprop.0> +[112000]: *I 0x106f8:ec061101 c.addi sp, -32 0x3ffffbac<-sp sp<-0x3ffffb8c + +###!!! For some reason &(argv[2][0] 0x3ffffba4 is being overwritten with the value of ra which is a link register updated at 0x105c4 jal +###!!! Later, we try to read this value to try to access argv[2][0] and crash + +[113000]: *I 0x106fa:e822ec06 c.sdsp ra, 24(sp) 0x3ffffb8c<-sp 0x105c8<-ra [0x3ffffba4,8]<-0x00000000000105c8 +[114000]: *I 0x106fc:e426e822 c.sdsp s0, 16(sp) 0x3ffffb8c<-sp 0x3ffffbfc<-s0 [0x3ffffb9c,8]<-0x000000003ffffbfc +[115000]: *I 0x106fe:e04ae426 c.sdsp s1, 8(sp) 0x3ffffb8c<-sp 0x0<-s1 [0x3ffffb94,8]<-0x0000000000000000 +[116000]: *I 0x10700:0793e04a c.sdsp s2, 0(sp) 0x3ffffb8c<-sp 0x0<-s2 [0x3ffffb8c,8]<-0x0000000000000000 +[117000]: *I 0x10702:02400793 li a5, 36 0x0<-zero a5<-0x24 +[118000]: *I 0x10706:0cd7e963 bltu a5, a3, pc + 210 0x24<-a5 0xa<-a3 +[119000]: *I 0x1070a:88ae4785 c.li a5, 1 0x0<-zero a5<-0x1 +[120000]: *I 0x1070c:081788ae c.mv a7, a1 0x0<-zero 0x3ffffff7<-a1 a7<-0x3ffffff7 +[121000]: *I 0x1070e:00000817 auipc a6, 0x0 a6<-0x1070e +[122000]: *I 0x10712:33380813 addi a6, a6, 819 0x1070e<-a6 a6<-0x10a41 +[123000]: *I 0x10716:0cf68163 beq a3, a5, pc + 194 0xa<-a3 0x1<-a5 + +### read '6' from 0x3ffffff7 (correct) +[124000]: *I 0x1071a:0008c703 lbu a4, 0(a7) 0x3ffffff7<-a7 0x36<-[0x3ffffff7,1] a4<-0x36 +[125000]: *I 0x1071e:08858346 c.mv t1, a7 0x0<-zero 0x3ffffff7<-a7 t1<-0x3ffffff7 +[126000]: *I 0x10720:07b30885 c.addi a7, 1 0x3ffffff7<-a7 a7<-0x3ffffff8 +[127000]: *I 0x10722:00e807b3 add a5, a6, a4 0x10a41<-a6 0x36<-a4 a5<-0x10a77 +[128000]: *I 0x10726:0007c783 lbu a5, 0(a5) 0x10a77<-a5 0x04<-[0x10a77,1] a5<-0x4 +[129000]: *I 0x1072a:f7fd8ba1 c.andi a5, 8 0x4<-a5 a5<-0x0 +[130000]: *I 0x1072c:0813f7fd c.bnez a5, pc - 18 0x0<-a5 0x0<-zero +[131000]: *I 0x1072e:02d00813 li a6, 45 0x0<-zero a6<-0x2d +[132000]: *I 0x10732:0007079b sext.w a5, a4 0x36<-a4 a5<-0x36 +[134000]: *I 0x10736:11070f63 beq a4, a6, pc + 286 0x36<-a4 0x2d<-a6 +[135000]: *I 0x1073a:02b00713 li a4, 43 0x0<-zero a4<-0x2b +[136000]: *I 0x1073e:0ae78863 beq a5, a4, pc + 176 0x36<-a5 0x2b<-a4 +[137000]: *I 0x10742:808554fd c.li s1, -1 0x0<-zero s1<-0xffffffffffffffff +[138000]: *I 0x10744:49018085 c.srli s1, 1 0xffffffffffffffff<-s1 s1<-0x7fffffffffffffff +[139000]: *I 0x10746:eadd4901 c.li s2, 0 0x0<-zero s2<-0x0 +[140000]: *I 0x10748:0713eadd c.bnez a3, pc + 182 0xa<-a3 0x0<-zero pc<-0x107fe +[142000]: *I 0x107fe:83b64741 c.li a4, 16 0x0<-zero a4<-0x10 +[143000]: *I 0x10800:9ae383b6 c.mv t2, a3 0x0<-zero 0xa<-a3 t2<-0xa +[144000]: *I 0x10802:f4e69ae3 bne a3, a4, pc - 172 0xa<-a3 0x10<-a4 pc<-0x10756 +[145000]: *I 0x10756:0274f433 remu s0, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 s0<-0x7 +[146000]: *I 0x1075a:871b4ea5 c.li t4, 9 0x0<-zero t4<-0x9 +[147000]: *I 0x1075c:fd07871b addiw a4, a5, -48 0x36<-a5 a4<-0x6 +[148000]: *I 0x10760:48014e01 c.li t3, 0 0x0<-zero t3<-0x0 +[149000]: *I 0x10762:42e54801 c.li a6, 0 0x0<-zero a6<-0x0 +[150000]: *I 0x10764:5f7d42e5 c.li t0, 25 0x0<-zero t0<-0x19 +[151000]: *I 0x10766:831b5f7d c.li t5, -1 0x0<-zero t5<-0xffffffffffffffff +[152000]: *I 0x10768:0007831b sext.w t1, a5 0x36<-a5 t1<-0x36 +[153000]: *I 0x1076c:0274dfb3 divu t6, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 t6<-0xccccccccccccccc +[154000]: *I 0x10770:e9632401 c.addiw s0, 0 0x7<-s0 s0<-0x7 +[155000]: *I 0x10772:02eee963 bltu t4, a4, pc + 50 0x9<-t4 0x6<-a4 +[157000]: *I 0x10776:de6387ba c.mv a5, a4 0x0<-zero 0x6<-a4 a5<-0x6 +[158000]: *I 0x10778:02d7de63 bge a5, a3, pc + 60 0x6<-a5 0xa<-a3 +[159000]: *I 0x1077c:01ee0b63 beq t3, t5, pc + 22 0x0<-t3 0xffffffffffffffff<-t5 +[160000]: *I 0x10780:e8635e7d c.li t3, -1 0x0<-zero t3<-0xffffffffffffffff +[161000]: *I 0x10782:010fe863 bltu t6, a6, pc + 16 0xccccccccccccccc<-t6 0x0<-a6 +[162000]: *I 0x10786:0b0f8a63 beq t6, a6, pc + 180 0xccccccccccccccc<-t6 0x0<-a6 +[163000]: *I 0x1078a:08334e05 c.li t3, 1 0x0<-zero t3<-0x1 +[164000]: *I 0x1078c:02780833 mul a6, a6, t2 0x0<-a6 0xa<-t2 a6<-0x0 +[165000]: *I 0x10790:c783983e c.add a6, a5 0x0<-a6 0x6<-a5 a6<-0x6 +### read '4' from 0x3ffffff8 (correct) +[166000]: *I 0x10792:0008c783 lbu a5, 0(a7) 0x3ffffff8<-a7 0x34<-[0x3ffffff8,1] a5<-0x34 +[167000]: *I 0x10796:871b0885 c.addi a7, 1 0x3ffffff8<-a7 a7<-0x3ffffff9 +[168000]: *I 0x10798:fd07871b addiw a4, a5, -48 0x34<-a5 a4<-0x4 +[169000]: *I 0x1079c:0007831b sext.w t1, a5 0x34<-a5 t1<-0x34 +[170000]: *I 0x107a0:fceefbe3 bgeu t4, a4, pc - 42 0x9<-t4 0x4<-a4 pc<-0x10776 +[171000]: *I 0x10776:de6387ba c.mv a5, a4 0x0<-zero 0x4<-a4 a5<-0x4 +[172000]: *I 0x10778:02d7de63 bge a5, a3, pc + 60 0x4<-a5 0xa<-a3 +[173000]: *I 0x1077c:01ee0b63 beq t3, t5, pc + 22 0x1<-t3 0xffffffffffffffff<-t5 +[174000]: *I 0x10780:e8635e7d c.li t3, -1 0x0<-zero t3<-0xffffffffffffffff +[175000]: *I 0x10782:010fe863 bltu t6, a6, pc + 16 0xccccccccccccccc<-t6 0x6<-a6 +[176000]: *I 0x10786:0b0f8a63 beq t6, a6, pc + 180 0xccccccccccccccc<-t6 0x6<-a6 +[177000]: *I 0x1078a:08334e05 c.li t3, 1 0x0<-zero t3<-0x1 +[178000]: *I 0x1078c:02780833 mul a6, a6, t2 0x6<-a6 0xa<-t2 a6<-0x3c +[179000]: *I 0x10790:c783983e c.add a6, a5 0x3c<-a6 0x4<-a5 a6<-0x40 +### read null from 0x3ffffff9 (correct string termination) +[180000]: *I 0x10792:0008c783 lbu a5, 0(a7) 0x3ffffff9<-a7 0x00<-[0x3ffffff9,1] a5<-0x0 +[181000]: *I 0x10796:871b0885 c.addi a7, 1 0x3ffffff9<-a7 a7<-0x3ffffffa +[182000]: *I 0x10798:fd07871b addiw a4, a5, -48 0x0<-a5 a4<-0xffffffffffffffd0 +[183000]: *I 0x1079c:0007831b sext.w t1, a5 0x0<-a5 t1<-0x0 +[184000]: *I 0x107a0:fceefbe3 bgeu t4, a4, pc - 42 0x9<-t4 0xffffffffffffffd0<-a4 +[185000]: *I 0x107a4:fbf3071b addiw a4, t1, -65 0x0<-t1 a4<-0xffffffffffffffbf +[186000]: *I 0x107a8:08e2e263 bltu t0, a4, pc + 132 0x19<-t0 0xffffffffffffffbf<-a4 pc<-0x1082c +[187000]: *I 0x1082c:f9f3031b addiw t1, t1, -97 0x0<-t1 t1<-0xffffffffffffff9f +[188000]: *I 0x10830:f862e2e3 bltu t0, t1, pc - 124 0x19<-t0 0xffffffffffffff9f<-t1 pc<-0x107b4 +[189000]: *I 0x107b4:056357fd c.li a5, -1 0x0<-zero a5<-0xffffffffffffffff +[190000]: *I 0x107b6:08fe0563 beq t3, a5, pc + 138 0x1<-t3 0xffffffffffffffff<-a5 +[191000]: *I 0x107ba:00090463 beqz s2, pc + 8 0x0<-s2 0x0<-zero pc<-0x107c2 +[192000]: *I 0x107c2:1b63c601 c.beqz a2, pc + 8 0x0<-a2 0x0<-zero pc<-0x107ca +[193000]: *I 0x107ca:644260e2 c.ldsp ra, 24(sp) 0x3ffffb8c<-sp 0x00000000000105c8<-[0x3ffffba4,8] ra<-0x105c8 +[194000]: *I 0x107cc:64a26442 c.ldsp s0, 16(sp) 0x3ffffb8c<-sp 0x000000003ffffbfc<-[0x3ffffb9c,8] s0<-0x3ffffbfc +[195000]: *I 0x107ce:690264a2 c.ldsp s1, 8(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb94,8] s1<-0x0 +[196000]: *I 0x107d0:85426902 c.ldsp s2, 0(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb8c,8] s2<-0x0 +[197000]: *I 0x107d2:61058542 c.mv a0, a6 0x0<-zero 0x40<-a6 a0<-0x40 +[198000]: *I 0x107d4:80826105 c.addi16sp sp, 32 0x3ffffb8c<-sp sp<-0x3ffffbac +[199000]: *I 0x107d6:00ef8082 ret 0x105c8<-ra pc<-0x105c8 zero<-0x0 +[200000]: *I 0x105c8:250160a2 c.ldsp ra, 8(sp) 0x3ffffbac<-sp 0x0000000000010350<-[0x3ffffbb4,8] ra<-0x10350 +[201000]: *I 0x105ca:01412501 c.addiw a0, 0 0x40<-a0 a0<-0x40 +[202000]: *I 0x105cc:80820141 c.addi sp, 16 0x3ffffbac<-sp sp<-0x3ffffbbc +[203000]: *I 0x105ce:11418082 ret 0x10350<-ra pc<-0x10350 zero<-0x0 +[204000]: *I 0x10350:00050793 mv a5, a0 0x40<-a0 a5<-0x40 +### result for argv[1] is 64 - correct +[205000]: *I 0x10354:fef42623 sw a5, -20(s0) 0x3ffffbfc<-s0 0x40<-a5 [0x3ffffbe8,4]<-0x00000040 + +### int arg2 = atoi(argv[2]); +### argv[2][0] should be at 0x3ffffffa but we are getting some wild value of 0x105c8 which is in program space +### +[206000]: *I 0x10358:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[207000]: *I 0x1035c:01078793 addi a5, a5, 16 0x3ffffb94<-a5 a5<-0x3ffffba4 +[208000]: *I 0x10360:0007b783 ld a5, 0(a5) 0x3ffffba4<-a5 0x00000000000105c8<-[0x3ffffba4,8] a5<-0x105c8 +[209000]: *I 0x10364:00078513 mv a0, a5 0x105c8<-a5 a0<-0x105c8 +[210000]: *I 0x10368:254000ef jal pc + 0x254 ra<-0x1036c pc<-0x105bc + +[211000]: *I 0x105bc:46291141 c.addi sp, -16 0x3ffffbbc<-sp sp<-0x3ffffbac +[212000]: *I 0x105be:45814629 c.li a2, 10 0x0<-zero a2<-0xa +[213000]: *I 0x105c0:e4064581 c.li a1, 0 0x0<-zero a1<-0x0 +[214000]: *I 0x105c2:00efe406 c.sdsp ra, 8(sp) 0x3ffffbac<-sp 0x1036c<-ra [0x3ffffbb4,8]<-0x000000000001036c +[215000]: *I 0x105c4:2c8000ef jal pc + 0x2c8 ra<-0x105c8 pc<-0x1088c +[216000]: *I 0x1088c:862e86b2 c.mv a3, a2 0x0<-zero 0xa<-a2 a3<-0xa +[217000]: *I 0x1088e:85aa862e c.mv a2, a1 0x0<-zero 0x0<-a1 a2<-0x0 +[218000]: *I 0x10890:b50385aa c.mv a1, a0 0x0<-zero 0x105c8<-a0 a1<-0x105c8 +[219000]: *I 0x10892:f581b503 ld a0, -168(gp) 0x11880<-gp 0x0000000000011080<-[0x117d8,8] a0<-0x11080 +[220000]: *I 0x10896:715db58d c.j pc - 414 zero<-0x0 pc<-0x106f8 <_strtol_l.constprop.0> +[222000]: *I 0x106f8:ec061101 c.addi sp, -32 0x3ffffbac<-sp sp<-0x3ffffb8c +[223000]: *I 0x106fa:e822ec06 c.sdsp ra, 24(sp) 0x3ffffb8c<-sp 0x105c8<-ra [0x3ffffba4,8]<-0x00000000000105c8 +[224000]: *I 0x106fc:e426e822 c.sdsp s0, 16(sp) 0x3ffffb8c<-sp 0x3ffffbfc<-s0 [0x3ffffb9c,8]<-0x000000003ffffbfc +[225000]: *I 0x106fe:e04ae426 c.sdsp s1, 8(sp) 0x3ffffb8c<-sp 0x0<-s1 [0x3ffffb94,8]<-0x0000000000000000 +[226000]: *I 0x10700:0793e04a c.sdsp s2, 0(sp) 0x3ffffb8c<-sp 0x0<-s2 [0x3ffffb8c,8]<-0x0000000000000000 +[227000]: *I 0x10702:02400793 li a5, 36 0x0<-zero a5<-0x24 +[228000]: *I 0x10706:0cd7e963 bltu a5, a3, pc + 210 0x24<-a5 0xa<-a3 +[229000]: *I 0x1070a:88ae4785 c.li a5, 1 0x0<-zero a5<-0x1 +[230000]: *I 0x1070c:081788ae c.mv a7, a1 0x0<-zero 0x105c8<-a1 a7<-0x105c8 +[231000]: *I 0x1070e:00000817 auipc a6, 0x0 a6<-0x1070e +[232000]: *I 0x10712:33380813 addi a6, a6, 819 0x1070e<-a6 a6<-0x10a41 +[233000]: *I 0x10716:0cf68163 beq a3, a5, pc + 194 0xa<-a3 0x1<-a5 +###!!! READING FROM PROGRAM SPACE!!! +[234000]: *I 0x1071a:0008c703 lbu a4, 0(a7) 0x105c8<-a7 0xa2<-[0x105c8,1] a4<-0xa2 +[235000]: *I 0x1071e:08858346 c.mv t1, a7 0x0<-zero 0x105c8<-a7 t1<-0x105c8 +[236000]: *I 0x10720:07b30885 c.addi a7, 1 0x105c8<-a7 a7<-0x105c9 +[237000]: *I 0x10722:00e807b3 add a5, a6, a4 0x10a41<-a6 0xa2<-a4 a5<-0x10ae3 +[238000]: *I 0x10726:0007c783 lbu a5, 0(a5) 0x10ae3<-a5 0x00<-[0x10ae3,1] a5<-0x0 +[239000]: *I 0x1072a:f7fd8ba1 c.andi a5, 8 0x0<-a5 a5<-0x0 +[240000]: *I 0x1072c:0813f7fd c.bnez a5, pc - 18 0x0<-a5 0x0<-zero +[241000]: *I 0x1072e:02d00813 li a6, 45 0x0<-zero a6<-0x2d +[242000]: *I 0x10732:0007079b sext.w a5, a4 0xa2<-a4 a5<-0xa2 +[244000]: *I 0x10736:11070f63 beq a4, a6, pc + 286 0xa2<-a4 0x2d<-a6 +[245000]: *I 0x1073a:02b00713 li a4, 43 0x0<-zero a4<-0x2b +[246000]: *I 0x1073e:0ae78863 beq a5, a4, pc + 176 0xa2<-a5 0x2b<-a4 +[247000]: *I 0x10742:808554fd c.li s1, -1 0x0<-zero s1<-0xffffffffffffffff +[248000]: *I 0x10744:49018085 c.srli s1, 1 0xffffffffffffffff<-s1 s1<-0x7fffffffffffffff +[249000]: *I 0x10746:eadd4901 c.li s2, 0 0x0<-zero s2<-0x0 +[250000]: *I 0x10748:0713eadd c.bnez a3, pc + 182 0xa<-a3 0x0<-zero pc<-0x107fe +[251000]: *I 0x107fe:83b64741 c.li a4, 16 0x0<-zero a4<-0x10 +[252000]: *I 0x10800:9ae383b6 c.mv t2, a3 0x0<-zero 0xa<-a3 t2<-0xa +[253000]: *I 0x10802:f4e69ae3 bne a3, a4, pc - 172 0xa<-a3 0x10<-a4 pc<-0x10756 +[254000]: *I 0x10756:0274f433 remu s0, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 s0<-0x7 +[255000]: *I 0x1075a:871b4ea5 c.li t4, 9 0x0<-zero t4<-0x9 +[256000]: *I 0x1075c:fd07871b addiw a4, a5, -48 0xa2<-a5 a4<-0x72 +[257000]: *I 0x10760:48014e01 c.li t3, 0 0x0<-zero t3<-0x0 +[258000]: *I 0x10762:42e54801 c.li a6, 0 0x0<-zero a6<-0x0 +[259000]: *I 0x10764:5f7d42e5 c.li t0, 25 0x0<-zero t0<-0x19 +[260000]: *I 0x10766:831b5f7d c.li t5, -1 0x0<-zero t5<-0xffffffffffffffff +[261000]: *I 0x10768:0007831b sext.w t1, a5 0xa2<-a5 t1<-0xa2 +[262000]: *I 0x1076c:0274dfb3 divu t6, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 t6<-0xccccccccccccccc +[263000]: *I 0x10770:e9632401 c.addiw s0, 0 0x7<-s0 s0<-0x7 +[264000]: *I 0x10772:02eee963 bltu t4, a4, pc + 50 0x9<-t4 0x72<-a4 pc<-0x107a4 +[265000]: *I 0x107a4:fbf3071b addiw a4, t1, -65 0xa2<-t1 a4<-0x61 +[266000]: *I 0x107a8:08e2e263 bltu t0, a4, pc + 132 0x19<-t0 0x61<-a4 pc<-0x1082c +[267000]: *I 0x1082c:f9f3031b addiw t1, t1, -97 0xa2<-t1 t1<-0x41 +[268000]: *I 0x10830:f862e2e3 bltu t0, t1, pc - 124 0x19<-t0 0x41<-t1 pc<-0x107b4 +[269000]: *I 0x107b4:056357fd c.li a5, -1 0x0<-zero a5<-0xffffffffffffffff +[270000]: *I 0x107b6:08fe0563 beq t3, a5, pc + 138 0x0<-t3 0xffffffffffffffff<-a5 +[271000]: *I 0x107ba:00090463 beqz s2, pc + 8 0x0<-s2 0x0<-zero pc<-0x107c2 +[272000]: *I 0x107c2:1b63c601 c.beqz a2, pc + 8 0x0<-a2 0x0<-zero pc<-0x107ca +[273000]: *I 0x107ca:644260e2 c.ldsp ra, 24(sp) 0x3ffffb8c<-sp 0x00000000000105c8<-[0x3ffffba4,8] ra<-0x105c8 +[274000]: *I 0x107cc:64a26442 c.ldsp s0, 16(sp) 0x3ffffb8c<-sp 0x000000003ffffbfc<-[0x3ffffb9c,8] s0<-0x3ffffbfc +[275000]: *I 0x107ce:690264a2 c.ldsp s1, 8(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb94,8] s1<-0x0 +[276000]: *I 0x107d0:85426902 c.ldsp s2, 0(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb8c,8] s2<-0x0 +[277000]: *I 0x107d2:61058542 c.mv a0, a6 0x0<-zero 0x0<-a6 a0<-0x0 +[278000]: *I 0x107d4:80826105 c.addi16sp sp, 32 0x3ffffb8c<-sp sp<-0x3ffffbac +[279000]: *I 0x107d6:00ef8082 ret 0x105c8<-ra pc<-0x105c8 zero<-0x0 +[280000]: *I 0x105c8:250160a2 c.ldsp ra, 8(sp) 0x3ffffbac<-sp 0x000000000001036c<-[0x3ffffbb4,8] ra<-0x1036c +[281000]: *I 0x105ca:01412501 c.addiw a0, 0 0x0<-a0 a0<-0x0 +[282000]: *I 0x105cc:80820141 c.addi sp, 16 0x3ffffbac<-sp sp<-0x3ffffbbc +[283000]: *I 0x105ce:11418082 ret 0x1036c<-ra pc<-0x1036c zero<-0x0 +[284000]: *I 0x1036c:00050793 mv a5, a0 0x0<-a0 a5<-0x0 + +###!!! result for argv2 = 0 : Incorrect. +[285000]: *I 0x10370:fef42423 sw a5, -24(s0) 0x3ffffbfc<-s0 0x0<-a5 [0x3ffffbe4,4]<-0x00000000 + +### int arg3 = atoi(argv[3]); +[286000]: *I 0x10374:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[287000]: *I 0x10378:01878793 addi a5, a5, 24 0x3ffffb94<-a5 a5<-0x3ffffbac +[288000]: *I 0x1037c:0007b783 ld a5, 0(a5) 0x3ffffbac<-a5 0x000000003ffffffc<-[0x3ffffbac,8] a5<-0x3ffffffc +[289000]: *I 0x10380:00078513 mv a0, a5 0x3ffffffc<-a5 a0<-0x3ffffffc +[290000]: *I 0x10384:238000ef jal pc + 0x238 ra<-0x10388 pc<-0x105bc +[291000]: *I 0x105bc:46291141 c.addi sp, -16 0x3ffffbbc<-sp sp<-0x3ffffbac +[292000]: *I 0x105be:45814629 c.li a2, 10 0x0<-zero a2<-0xa +[293000]: *I 0x105c0:e4064581 c.li a1, 0 0x0<-zero a1<-0x0 +[294000]: *I 0x105c2:00efe406 c.sdsp ra, 8(sp) 0x3ffffbac<-sp 0x10388<-ra [0x3ffffbb4,8]<-0x0000000000010388 +[295000]: *I 0x105c4:2c8000ef jal pc + 0x2c8 ra<-0x105c8 pc<-0x1088c +[296000]: *I 0x1088c:862e86b2 c.mv a3, a2 0x0<-zero 0xa<-a2 a3<-0xa +[297000]: *I 0x1088e:85aa862e c.mv a2, a1 0x0<-zero 0x0<-a1 a2<-0x0 +[298000]: *I 0x10890:b50385aa c.mv a1, a0 0x0<-zero 0x3ffffffc<-a0 a1<-0x3ffffffc +[299000]: *I 0x10892:f581b503 ld a0, -168(gp) 0x11880<-gp 0x0000000000011080<-[0x117d8,8] a0<-0x11080 +[300000]: *I 0x10896:715db58d c.j pc - 414 zero<-0x0 pc<-0x106f8 <_strtol_l.constprop.0> +[302000]: *I 0x106f8:ec061101 c.addi sp, -32 0x3ffffbac<-sp sp<-0x3ffffb8c +[303000]: *I 0x106fa:e822ec06 c.sdsp ra, 24(sp) 0x3ffffb8c<-sp 0x105c8<-ra [0x3ffffba4,8]<-0x00000000000105c8 +[304000]: *I 0x106fc:e426e822 c.sdsp s0, 16(sp) 0x3ffffb8c<-sp 0x3ffffbfc<-s0 [0x3ffffb9c,8]<-0x000000003ffffbfc +[305000]: *I 0x106fe:e04ae426 c.sdsp s1, 8(sp) 0x3ffffb8c<-sp 0x0<-s1 [0x3ffffb94,8]<-0x0000000000000000 +[306000]: *I 0x10700:0793e04a c.sdsp s2, 0(sp) 0x3ffffb8c<-sp 0x0<-s2 [0x3ffffb8c,8]<-0x0000000000000000 +[307000]: *I 0x10702:02400793 li a5, 36 0x0<-zero a5<-0x24 +[308000]: *I 0x10706:0cd7e963 bltu a5, a3, pc + 210 0x24<-a5 0xa<-a3 +[309000]: *I 0x1070a:88ae4785 c.li a5, 1 0x0<-zero a5<-0x1 +[310000]: *I 0x1070c:081788ae c.mv a7, a1 0x0<-zero 0x3ffffffc<-a1 a7<-0x3ffffffc +[311000]: *I 0x1070e:00000817 auipc a6, 0x0 a6<-0x1070e +[312000]: *I 0x10712:33380813 addi a6, a6, 819 0x1070e<-a6 a6<-0x10a41 +[313000]: *I 0x10716:0cf68163 beq a3, a5, pc + 194 0xa<-a3 0x1<-a5 +[314000]: *I 0x1071a:0008c703 lbu a4, 0(a7) 0x3ffffffc<-a7 0x32<-[0x3ffffffc,1] a4<-0x32 +[315000]: *I 0x1071e:08858346 c.mv t1, a7 0x0<-zero 0x3ffffffc<-a7 t1<-0x3ffffffc +[316000]: *I 0x10720:07b30885 c.addi a7, 1 0x3ffffffc<-a7 a7<-0x3ffffffd +[317000]: *I 0x10722:00e807b3 add a5, a6, a4 0x10a41<-a6 0x32<-a4 a5<-0x10a73 +[318000]: *I 0x10726:0007c783 lbu a5, 0(a5) 0x10a73<-a5 0x04<-[0x10a73,1] a5<-0x4 +[319000]: *I 0x1072a:f7fd8ba1 c.andi a5, 8 0x4<-a5 a5<-0x0 +[320000]: *I 0x1072c:0813f7fd c.bnez a5, pc - 18 0x0<-a5 0x0<-zero +[321000]: *I 0x1072e:02d00813 li a6, 45 0x0<-zero a6<-0x2d +[322000]: *I 0x10732:0007079b sext.w a5, a4 0x32<-a4 a5<-0x32 +[323000]: *I 0x10736:11070f63 beq a4, a6, pc + 286 0x32<-a4 0x2d<-a6 +[324000]: *I 0x1073a:02b00713 li a4, 43 0x0<-zero a4<-0x2b +[325000]: *I 0x1073e:0ae78863 beq a5, a4, pc + 176 0x32<-a5 0x2b<-a4 +[326000]: *I 0x10742:808554fd c.li s1, -1 0x0<-zero s1<-0xffffffffffffffff +[327000]: *I 0x10744:49018085 c.srli s1, 1 0xffffffffffffffff<-s1 s1<-0x7fffffffffffffff +[328000]: *I 0x10746:eadd4901 c.li s2, 0 0x0<-zero s2<-0x0 +[329000]: *I 0x10748:0713eadd c.bnez a3, pc + 182 0xa<-a3 0x0<-zero pc<-0x107fe +[330000]: *I 0x107fe:83b64741 c.li a4, 16 0x0<-zero a4<-0x10 +[331000]: *I 0x10800:9ae383b6 c.mv t2, a3 0x0<-zero 0xa<-a3 t2<-0xa +[332000]: *I 0x10802:f4e69ae3 bne a3, a4, pc - 172 0xa<-a3 0x10<-a4 pc<-0x10756 +[333000]: *I 0x10756:0274f433 remu s0, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 s0<-0x7 +[334000]: *I 0x1075a:871b4ea5 c.li t4, 9 0x0<-zero t4<-0x9 +[335000]: *I 0x1075c:fd07871b addiw a4, a5, -48 0x32<-a5 a4<-0x2 +[336000]: *I 0x10760:48014e01 c.li t3, 0 0x0<-zero t3<-0x0 +[337000]: *I 0x10762:42e54801 c.li a6, 0 0x0<-zero a6<-0x0 +[338000]: *I 0x10764:5f7d42e5 c.li t0, 25 0x0<-zero t0<-0x19 +[339000]: *I 0x10766:831b5f7d c.li t5, -1 0x0<-zero t5<-0xffffffffffffffff +[340000]: *I 0x10768:0007831b sext.w t1, a5 0x32<-a5 t1<-0x32 +[341000]: *I 0x1076c:0274dfb3 divu t6, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 t6<-0xccccccccccccccc +[342000]: *I 0x10770:e9632401 c.addiw s0, 0 0x7<-s0 s0<-0x7 +[343000]: *I 0x10772:02eee963 bltu t4, a4, pc + 50 0x9<-t4 0x2<-a4 +[345000]: *I 0x10776:de6387ba c.mv a5, a4 0x0<-zero 0x2<-a4 a5<-0x2 +[346000]: *I 0x10778:02d7de63 bge a5, a3, pc + 60 0x2<-a5 0xa<-a3 +[347000]: *I 0x1077c:01ee0b63 beq t3, t5, pc + 22 0x0<-t3 0xffffffffffffffff<-t5 +[348000]: *I 0x10780:e8635e7d c.li t3, -1 0x0<-zero t3<-0xffffffffffffffff +[349000]: *I 0x10782:010fe863 bltu t6, a6, pc + 16 0xccccccccccccccc<-t6 0x0<-a6 +[350000]: *I 0x10786:0b0f8a63 beq t6, a6, pc + 180 0xccccccccccccccc<-t6 0x0<-a6 +[351000]: *I 0x1078a:08334e05 c.li t3, 1 0x0<-zero t3<-0x1 +[352000]: *I 0x1078c:02780833 mul a6, a6, t2 0x0<-a6 0xa<-t2 a6<-0x0 +[353000]: *I 0x10790:c783983e c.add a6, a5 0x0<-a6 0x2<-a5 a6<-0x2 +[354000]: *I 0x10792:0008c783 lbu a5, 0(a7) 0x3ffffffd<-a7 0x00<-[0x3ffffffd,1] a5<-0x0 +[355000]: *I 0x10796:871b0885 c.addi a7, 1 0x3ffffffd<-a7 a7<-0x3ffffffe +[356000]: *I 0x10798:fd07871b addiw a4, a5, -48 0x0<-a5 a4<-0xffffffffffffffd0 +[357000]: *I 0x1079c:0007831b sext.w t1, a5 0x0<-a5 t1<-0x0 +[358000]: *I 0x107a0:fceefbe3 bgeu t4, a4, pc - 42 0x9<-t4 0xffffffffffffffd0<-a4 +[359000]: *I 0x107a4:fbf3071b addiw a4, t1, -65 0x0<-t1 a4<-0xffffffffffffffbf +[360000]: *I 0x107a8:08e2e263 bltu t0, a4, pc + 132 0x19<-t0 0xffffffffffffffbf<-a4 pc<-0x1082c +[361000]: *I 0x1082c:f9f3031b addiw t1, t1, -97 0x0<-t1 t1<-0xffffffffffffff9f +[362000]: *I 0x10830:f862e2e3 bltu t0, t1, pc - 124 0x19<-t0 0xffffffffffffff9f<-t1 pc<-0x107b4 +[363000]: *I 0x107b4:056357fd c.li a5, -1 0x0<-zero a5<-0xffffffffffffffff +[364000]: *I 0x107b6:08fe0563 beq t3, a5, pc + 138 0x1<-t3 0xffffffffffffffff<-a5 +[365000]: *I 0x107ba:00090463 beqz s2, pc + 8 0x0<-s2 0x0<-zero pc<-0x107c2 +[366000]: *I 0x107c2:1b63c601 c.beqz a2, pc + 8 0x0<-a2 0x0<-zero pc<-0x107ca +[367000]: *I 0x107ca:644260e2 c.ldsp ra, 24(sp) 0x3ffffb8c<-sp 0x00000000000105c8<-[0x3ffffba4,8] ra<-0x105c8 +[368000]: *I 0x107cc:64a26442 c.ldsp s0, 16(sp) 0x3ffffb8c<-sp 0x000000003ffffbfc<-[0x3ffffb9c,8] s0<-0x3ffffbfc +[369000]: *I 0x107ce:690264a2 c.ldsp s1, 8(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb94,8] s1<-0x0 +[370000]: *I 0x107d0:85426902 c.ldsp s2, 0(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb8c,8] s2<-0x0 +[371000]: *I 0x107d2:61058542 c.mv a0, a6 0x0<-zero 0x2<-a6 a0<-0x2 +[372000]: *I 0x107d4:80826105 c.addi16sp sp, 32 0x3ffffb8c<-sp sp<-0x3ffffbac +[373000]: *I 0x107d6:00ef8082 ret 0x105c8<-ra pc<-0x105c8 zero<-0x0 +[374000]: *I 0x105c8:250160a2 c.ldsp ra, 8(sp) 0x3ffffbac<-sp 0x0000000000010388<-[0x3ffffbb4,8] ra<-0x10388 +[375000]: *I 0x105ca:01412501 c.addiw a0, 0 0x2<-a0 a0<-0x2 +[376000]: *I 0x105cc:80820141 c.addi sp, 16 0x3ffffbac<-sp sp<-0x3ffffbbc +[377000]: *I 0x105ce:11418082 ret 0x10388<-ra pc<-0x10388 zero<-0x0 +[378000]: *I 0x10388:00050793 mv a5, a0 0x2<-a0 a5<-0x2 + +### result for argv[3]==2: Correct +[379000]: *I 0x1038c:fef42223 sw a5, -28(s0) 0x3ffffbfc<-s0 0x2<-a5 [0x3ffffbe0,4]<-0x00000002 + +### int arg4 = atoi(argv[4]); +[380000]: *I 0x10390:fc043783 ld a5, -64(s0) 0x3ffffbfc<-s0 0x000000003ffffb94<-[0x3ffffbbc,8] a5<-0x3ffffb94 +[381000]: *I 0x10394:02078793 addi a5, a5, 32 0x3ffffb94<-a5 a5<-0x3ffffbb4 +[382000]: *I 0x10398:0007b783 ld a5, 0(a5) 0x3ffffbb4<-a5 0x0000000000010388<-[0x3ffffbb4,8] a5<-0x10388 +[383000]: *I 0x1039c:00078513 mv a0, a5 0x10388<-a5 a0<-0x10388 +[384000]: *I 0x103a0:21c000ef jal pc + 0x21c ra<-0x103a4 pc<-0x105bc +[385000]: *I 0x105bc:46291141 c.addi sp, -16 0x3ffffbbc<-sp sp<-0x3ffffbac +[386000]: *I 0x105be:45814629 c.li a2, 10 0x0<-zero a2<-0xa +[387000]: *I 0x105c0:e4064581 c.li a1, 0 0x0<-zero a1<-0x0 +[388000]: *I 0x105c2:00efe406 c.sdsp ra, 8(sp) 0x3ffffbac<-sp 0x103a4<-ra [0x3ffffbb4,8]<-0x00000000000103a4 +[389000]: *I 0x105c4:2c8000ef jal pc + 0x2c8 ra<-0x105c8 pc<-0x1088c +[390000]: *I 0x1088c:862e86b2 c.mv a3, a2 0x0<-zero 0xa<-a2 a3<-0xa +[391000]: *I 0x1088e:85aa862e c.mv a2, a1 0x0<-zero 0x0<-a1 a2<-0x0 +[392000]: *I 0x10890:b50385aa c.mv a1, a0 0x0<-zero 0x10388<-a0 a1<-0x10388 +[393000]: *I 0x10892:f581b503 ld a0, -168(gp) 0x11880<-gp 0x0000000000011080<-[0x117d8,8] a0<-0x11080 +[394000]: *I 0x10896:715db58d c.j pc - 414 zero<-0x0 pc<-0x106f8 <_strtol_l.constprop.0> +[396000]: *I 0x106f8:ec061101 c.addi sp, -32 0x3ffffbac<-sp sp<-0x3ffffb8c +[397000]: *I 0x106fa:e822ec06 c.sdsp ra, 24(sp) 0x3ffffb8c<-sp 0x105c8<-ra [0x3ffffba4,8]<-0x00000000000105c8 +[398000]: *I 0x106fc:e426e822 c.sdsp s0, 16(sp) 0x3ffffb8c<-sp 0x3ffffbfc<-s0 [0x3ffffb9c,8]<-0x000000003ffffbfc +[399000]: *I 0x106fe:e04ae426 c.sdsp s1, 8(sp) 0x3ffffb8c<-sp 0x0<-s1 [0x3ffffb94,8]<-0x0000000000000000 +[400000]: *I 0x10700:0793e04a c.sdsp s2, 0(sp) 0x3ffffb8c<-sp 0x0<-s2 [0x3ffffb8c,8]<-0x0000000000000000 +[401000]: *I 0x10702:02400793 li a5, 36 0x0<-zero a5<-0x24 +[402000]: *I 0x10706:0cd7e963 bltu a5, a3, pc + 210 0x24<-a5 0xa<-a3 +[403000]: *I 0x1070a:88ae4785 c.li a5, 1 0x0<-zero a5<-0x1 +[404000]: *I 0x1070c:081788ae c.mv a7, a1 0x0<-zero 0x10388<-a1 a7<-0x10388 +[405000]: *I 0x1070e:00000817 auipc a6, 0x0 a6<-0x1070e +[406000]: *I 0x10712:33380813 addi a6, a6, 819 0x1070e<-a6 a6<-0x10a41 +[407000]: *I 0x10716:0cf68163 beq a3, a5, pc + 194 0xa<-a3 0x1<-a5 +[408000]: *I 0x1071a:0008c703 lbu a4, 0(a7) 0x10388<-a7 0x93<-[0x10388,1] a4<-0x93 +[409000]: *I 0x1071e:08858346 c.mv t1, a7 0x0<-zero 0x10388<-a7 t1<-0x10388 +[410000]: *I 0x10720:07b30885 c.addi a7, 1 0x10388<-a7 a7<-0x10389 +[411000]: *I 0x10722:00e807b3 add a5, a6, a4 0x10a41<-a6 0x93<-a4 a5<-0x10ad4 +[412000]: *I 0x10726:0007c783 lbu a5, 0(a5) 0x10ad4<-a5 0x00<-[0x10ad4,1] a5<-0x0 +[413000]: *I 0x1072a:f7fd8ba1 c.andi a5, 8 0x0<-a5 a5<-0x0 +[414000]: *I 0x1072c:0813f7fd c.bnez a5, pc - 18 0x0<-a5 0x0<-zero +[415000]: *I 0x1072e:02d00813 li a6, 45 0x0<-zero a6<-0x2d +[416000]: *I 0x10732:0007079b sext.w a5, a4 0x93<-a4 a5<-0x93 +[417000]: *I 0x10736:11070f63 beq a4, a6, pc + 286 0x93<-a4 0x2d<-a6 +[418000]: *I 0x1073a:02b00713 li a4, 43 0x0<-zero a4<-0x2b +[419000]: *I 0x1073e:0ae78863 beq a5, a4, pc + 176 0x93<-a5 0x2b<-a4 +[420000]: *I 0x10742:808554fd c.li s1, -1 0x0<-zero s1<-0xffffffffffffffff +[421000]: *I 0x10744:49018085 c.srli s1, 1 0xffffffffffffffff<-s1 s1<-0x7fffffffffffffff +[422000]: *I 0x10746:eadd4901 c.li s2, 0 0x0<-zero s2<-0x0 +[423000]: *I 0x10748:0713eadd c.bnez a3, pc + 182 0xa<-a3 0x0<-zero pc<-0x107fe +[424000]: *I 0x107fe:83b64741 c.li a4, 16 0x0<-zero a4<-0x10 +[425000]: *I 0x10800:9ae383b6 c.mv t2, a3 0x0<-zero 0xa<-a3 t2<-0xa +[426000]: *I 0x10802:f4e69ae3 bne a3, a4, pc - 172 0xa<-a3 0x10<-a4 pc<-0x10756 +[427000]: *I 0x10756:0274f433 remu s0, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 s0<-0x7 +[428000]: *I 0x1075a:871b4ea5 c.li t4, 9 0x0<-zero t4<-0x9 +[429000]: *I 0x1075c:fd07871b addiw a4, a5, -48 0x93<-a5 a4<-0x63 +[430000]: *I 0x10760:48014e01 c.li t3, 0 0x0<-zero t3<-0x0 +[431000]: *I 0x10762:42e54801 c.li a6, 0 0x0<-zero a6<-0x0 +[432000]: *I 0x10764:5f7d42e5 c.li t0, 25 0x0<-zero t0<-0x19 +[433000]: *I 0x10766:831b5f7d c.li t5, -1 0x0<-zero t5<-0xffffffffffffffff +[434000]: *I 0x10768:0007831b sext.w t1, a5 0x93<-a5 t1<-0x93 +[435000]: *I 0x1076c:0274dfb3 divu t6, s1, t2 0x7fffffffffffffff<-s1 0xa<-t2 t6<-0xccccccccccccccc +[436000]: *I 0x10770:e9632401 c.addiw s0, 0 0x7<-s0 s0<-0x7 +[437000]: *I 0x10772:02eee963 bltu t4, a4, pc + 50 0x9<-t4 0x63<-a4 pc<-0x107a4 +[438000]: *I 0x107a4:fbf3071b addiw a4, t1, -65 0x93<-t1 a4<-0x52 +[439000]: *I 0x107a8:08e2e263 bltu t0, a4, pc + 132 0x19<-t0 0x52<-a4 pc<-0x1082c +[440000]: *I 0x1082c:f9f3031b addiw t1, t1, -97 0x93<-t1 t1<-0x32 +[441000]: *I 0x10830:f862e2e3 bltu t0, t1, pc - 124 0x19<-t0 0x32<-t1 pc<-0x107b4 +[442000]: *I 0x107b4:056357fd c.li a5, -1 0x0<-zero a5<-0xffffffffffffffff +[443000]: *I 0x107b6:08fe0563 beq t3, a5, pc + 138 0x0<-t3 0xffffffffffffffff<-a5 +[444000]: *I 0x107ba:00090463 beqz s2, pc + 8 0x0<-s2 0x0<-zero pc<-0x107c2 +[445000]: *I 0x107c2:1b63c601 c.beqz a2, pc + 8 0x0<-a2 0x0<-zero pc<-0x107ca +[446000]: *I 0x107ca:644260e2 c.ldsp ra, 24(sp) 0x3ffffb8c<-sp 0x00000000000105c8<-[0x3ffffba4,8] ra<-0x105c8 +[447000]: *I 0x107cc:64a26442 c.ldsp s0, 16(sp) 0x3ffffb8c<-sp 0x000000003ffffbfc<-[0x3ffffb9c,8] s0<-0x3ffffbfc +[448000]: *I 0x107ce:690264a2 c.ldsp s1, 8(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb94,8] s1<-0x0 +[449000]: *I 0x107d0:85426902 c.ldsp s2, 0(sp) 0x3ffffb8c<-sp 0x0000000000000000<-[0x3ffffb8c,8] s2<-0x0 +[450000]: *I 0x107d2:61058542 c.mv a0, a6 0x0<-zero 0x0<-a6 a0<-0x0 +[451000]: *I 0x107d4:80826105 c.addi16sp sp, 32 0x3ffffb8c<-sp sp<-0x3ffffbac +[452000]: *I 0x107d6:00ef8082 ret 0x105c8<-ra pc<-0x105c8 zero<-0x0 +[453000]: *I 0x105c8:250160a2 c.ldsp ra, 8(sp) 0x3ffffbac<-sp 0x00000000000103a4<-[0x3ffffbb4,8] ra<-0x103a4 +[454000]: *I 0x105ca:01412501 c.addiw a0, 0 0x0<-a0 a0<-0x0 +[455000]: *I 0x105cc:80820141 c.addi sp, 16 0x3ffffbac<-sp sp<-0x3ffffbbc +[456000]: *I 0x105ce:11418082 ret 0x103a4<-ra pc<-0x103a4 zero<-0x0 +[457000]: *I 0x103a4:00050793 mv a5, a0 0x0<-a0 a5<-0x0 +###!!! result for argv[4] = 0 : Incorrect +[458000]: *I 0x103a8:fef42023 sw a5, -32(s0) 0x3ffffbfc<-s0 0x0<-a5 [0x3ffffbdc,4]<-0x00000000 + +### assert(arg1==64); +[459000]: *I 0x103ac:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[460000]: *I 0x103b0:fec42783 lw a5, -20(s0) 0x3ffffbfc<-s0 0x00000040<-[0x3ffffbe8,4] a5<-0x40 +[461000]: *I 0x103b4:0007871b sext.w a4, a5 0x40<-a5 a4<-0x40 +[462000]: *I 0x103b8:04000793 li a5, 64 0x0<-zero a5<-0x40 +[463000]: *I 0x103bc:00f70463 beq a4, a5, pc + 8 0x40<-a4 0x40<-a5 pc<-0x103c4 +[464000]: *I 0x103c4:00201013 slli zero, zero, 2 0x0<-zero zero<-0x0 + +### assert(arg2==4); +[465000]: *I 0x103c8:00301013 slli zero, zero, 3 0x0<-zero zero<-0x0 +[466000]: *I 0x103cc:fe842783 lw a5, -24(s0) 0x3ffffbfc<-s0 0x00000000<-[0x3ffffbe4,4] a5<-0x0 +[467000]: *I 0x103d0:0007871b sext.w a4, a5 0x0<-a5 a4<-0x0 +[468000]: *I 0x103d4:00400793 li a5, 4 0x0<-zero a5<-0x4 +# Fails: assert(arg2==4); +[469000]: *I 0x103d8:00f70463 beq a4, a5, pc + 8 0x0<-a4 0x4<-a5 diff --git a/test/argc_bug/rev-test-basim.py b/test/argc_bug/rev-test-basim.py old mode 100644 new mode 100755 index 54bbb0fe5..6bed62d0c --- a/test/argc_bug/rev-test-basim.py +++ b/test/argc_bug/rev-test-basim.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,17 +23,17 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMFDC]", # Core:Config - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "dram_tests.exe"), # Target executable - "args" : "64 4 2", # Target command line arguments - "trcStartCycle" : "1", # Trace all instructions - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMFDC]", # Core:Config + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "dram_tests.exe"), # Target executable + "args": "64 4 2 3", # Target command line arguments + "trcStartCycle": "1", # Trace all instructions + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/argc_short/Makefile b/test/argc_short/Makefile index 5c627c3d2..606c373ce 100644 --- a/test/argc_short/Makefile +++ b/test/argc_short/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/argc_short/argc.c b/test/argc_short/argc.c index 1a2628479..5b419cf4c 100644 --- a/test/argc_short/argc.c +++ b/test/argc_short/argc.c @@ -1,7 +1,7 @@ /* * argc.c * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,26 +11,26 @@ #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) -int main(int argc, char **argv) { +int main( int argc, char** argv ) { int a = argc; - assert(a == 2); - assert(argv[0][0] == 'a'); - assert(argv[0][1] == 'r'); - assert(argv[0][2] == 'g'); - assert(argv[0][3] == 'c'); - assert(argv[0][4] == '.'); - assert(argv[0][5] == 'e'); - assert(argv[0][6] == 'x'); - assert(argv[0][7] == 'e'); - assert(argv[1][0] == 'o'); - assert(argv[1][1] == 'n'); - assert(argv[1][2] == 'e'); + assert( a == 2 ); + assert( argv[0][0] == 'a' ); + assert( argv[0][1] == 'r' ); + assert( argv[0][2] == 'g' ); + assert( argv[0][3] == 'c' ); + assert( argv[0][4] == '.' ); + assert( argv[0][5] == 'e' ); + assert( argv[0][6] == 'x' ); + assert( argv[0][7] == 'e' ); + assert( argv[1][0] == 'o' ); + assert( argv[1][1] == 'n' ); + assert( argv[1][2] == 'e' ); return 0; } diff --git a/test/argc_short/run_argc_short.sh b/test/argc_short/run_argc_short.sh index c72c31dbc..996e45406 100755 --- a/test/argc_short/run_argc_short.sh +++ b/test/argc_short/run_argc_short.sh @@ -4,7 +4,8 @@ make clean && make # Check that the exec was built... -if [ -x argc.exe ]; then +if [[ -x argc.exe ]]; then + set -e sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argc.exe" --args "one" --enableMemH=0 echo "Test ARGC_SHORT_REVMEM: Completed" sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argc.exe" --args "one" --enableMemH=1 diff --git a/test/argv/Makefile b/test/argv/Makefile new file mode 100644 index 000000000..857a1a9ac --- /dev/null +++ b/test/argv/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: argv +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=argv +CXX=${RVCXX} +ARCH=rv64imafdc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CXX) -march=$(ARCH) -O3 -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/argv/argv.c b/test/argv/argv.c new file mode 100644 index 000000000..61453c341 --- /dev/null +++ b/test/argv/argv.c @@ -0,0 +1,20 @@ +/* + * argv.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +[[gnu::noipa]] void foo() { + volatile char data[81]; + data[2] = '\0'; +} + +int main( int argc, char** argv ) { + foo(); + return argv[0][0] != 'a'; +} diff --git a/test/argv/run_argv.sh b/test/argv/run_argv.sh new file mode 100755 index 000000000..85f4daeea --- /dev/null +++ b/test/argv/run_argv.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x argv.exe ]]; then + set -e + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv.exe" --args "one" --enableMemH=0 + echo "Test ARGV_REVMEM: Completed" + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv.exe" --args "one" --enableMemH=1 + echo "Test ARGV_MEMH: Completed" +else + echo "Test ARGV: argv.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/argv_layout/Makefile b/test/argv_layout/Makefile new file mode 100644 index 000000000..69e5dcc9a --- /dev/null +++ b/test/argv_layout/Makefile @@ -0,0 +1,26 @@ +# +# Makefile +# +# makefile: argv_layout +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=argv_layout +CC=${RVCC} +ARCH=rv32i +ABI=ilp32 + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -mabi=$(ABI) -o $(EXAMPLE).exe $(EXAMPLE).c -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/argv_layout/argv_layout.c b/test/argv_layout/argv_layout.c new file mode 100644 index 000000000..6ba4f3c71 --- /dev/null +++ b/test/argv_layout/argv_layout.c @@ -0,0 +1,17 @@ +/* + * argv_layout.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include + +int main( int argc, char** argv ) { + if( argc != 3 || !argv[1][0] || !argv[2][0] || strcmp( argv[1], argv[2] ) || (size_t) &argv[2] - (size_t) &argv[1] != sizeof( void* ) ) + asm( " .word 0" ); +} diff --git a/test/argv_layout/run_argv_layout.sh b/test/argv_layout/run_argv_layout.sh new file mode 100755 index 000000000..b6e46bf6c --- /dev/null +++ b/test/argv_layout/run_argv_layout.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x argv_layout.exe ]]; then + set -e + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv_layout.exe" --args "test test" --enableMemH=0 + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv_layout.exe" --args "test test" --enableMemH=1 +else + echo "Test ARGV_LAYOUT: argv_layout.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/argv_limit/Makefile b/test/argv_limit/Makefile new file mode 100644 index 000000000..341843b27 --- /dev/null +++ b/test/argv_limit/Makefile @@ -0,0 +1,24 @@ +# +# Makefile +# +# makefile: argv_limit +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src +EXAMPLE=argv_limit +CC=${RVCC} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/argv_limit/argv_limit.c b/test/argv_limit/argv_limit.c new file mode 100644 index 000000000..8b2b3799e --- /dev/null +++ b/test/argv_limit/argv_limit.c @@ -0,0 +1,23 @@ +/* + * argv_limit.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include + +int main( int argc, char** argv ) { + unsigned long sum = 0; + if( argc != 4097 ) + asm( " .word 0" ); + for( int i = 1; i < argc; ++i ) + sum += strtoul( argv[i], NULL, 0 ); + if( sum != 8390656 ) + asm( " .word 0" ); + return 0; +} diff --git a/test/argv_limit/run_argv_limit.sh b/test/argv_limit/run_argv_limit.sh new file mode 100755 index 000000000..b613b563d --- /dev/null +++ b/test/argv_limit/run_argv_limit.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +#Build the test +make clean && make + +args=() +for arg in {1..4096} +do + args+=("$arg") +done + +IFS=, +argstr="[${args[*]}]" +IFS= + +# Check that the exec was built... +if [[ -x argv_limit.exe ]]; then + set -e + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv_limit.exe" --enableMemH=0 --args "$argstr" + echo "Test ARGV_LIMIT_REVMEM: Completed" + sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "argv_limit.exe" --enableMemH=1 --args "$argstr" + echo "Test ARGV_LIMIT_MEMH: Completed" +else + echo "Test ARGV_LIMIT: argv_limit.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/argv_stack/Makefile b/test/argv_stack/Makefile new file mode 100644 index 000000000..2dfa4ecf8 --- /dev/null +++ b/test/argv_stack/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: argv_stack +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=argv_stack +CC=${RVCC} +ARCH=rv64imafdc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -O3 -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/argv_stack/argv_stack.c b/test/argv_stack/argv_stack.c new file mode 100644 index 000000000..c62de73ac --- /dev/null +++ b/test/argv_stack/argv_stack.c @@ -0,0 +1,17 @@ +/* + * argv_stack.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +int main( int argc, char** argv ) { + char a[1024]; + if( a + sizeof( a ) > (char*) argv ) + asm( ".word 0" ); + return 0; +} diff --git a/test/backingstore/Makefile b/test/backingstore/Makefile index 08c255017..2953ceb9a 100644 --- a/test/backingstore/Makefile +++ b/test/backingstore/Makefile @@ -3,7 +3,7 @@ # # makefile: backingstore # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/backingstore/backingstore.c b/test/backingstore/backingstore.c index 392795971..0eee43f9e 100644 --- a/test/backingstore/backingstore.c +++ b/test/backingstore/backingstore.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -19,19 +19,19 @@ int A[LOOP]; int B[LOOP]; int C[LOOP]; -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 0; - for( i=0; i -#include +#include "util.h" +#include #include +#include #include -#include +#include #include -#include "util.h" #define SYS_write 64 @@ -15,17 +15,16 @@ extern volatile uint64_t tohost; extern volatile uint64_t fromhost; -static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t arg2) -{ - volatile uint64_t magic_mem[8] __attribute__((aligned(64))); +static uintptr_t syscall( uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t arg2 ) { + volatile uint64_t magic_mem[8] __attribute__( ( aligned( 64 ) ) ); magic_mem[0] = which; magic_mem[1] = arg0; magic_mem[2] = arg1; magic_mem[3] = arg2; __sync_synchronize(); - tohost = (uintptr_t)magic_mem; - while (fromhost == 0) + tohost = (uintptr_t) magic_mem; + while( fromhost == 0 ) ; fromhost = 0; @@ -35,202 +34,187 @@ static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t #define NUM_COUNTERS 2 static uintptr_t counters[NUM_COUNTERS]; -static char* counter_names[NUM_COUNTERS]; +static char* counter_names[NUM_COUNTERS]; -void setStats(int enable) -{ +void setStats( int enable ) { int i = 0; -#define READ_CTR(name) do { \ - while (i >= NUM_COUNTERS) ; \ - uintptr_t csr = read_csr(name); \ - if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \ - counters[i++] = csr; \ - } while (0) - - READ_CTR(mcycle); - READ_CTR(minstret); +#define READ_CTR( name ) \ + do { \ + while( i >= NUM_COUNTERS ) \ + ; \ + uintptr_t csr = read_csr( name ); \ + if( !enable ) { \ + csr -= counters[i]; \ + counter_names[i] = #name; \ + } \ + counters[i++] = csr; \ + } while( 0 ) + + READ_CTR( mcycle ); + READ_CTR( minstret ); #undef READ_CTR } -void __attribute__((noreturn)) tohost_exit(uintptr_t code) -{ - tohost = (code << 1) | 1; - while (1); +void __attribute__( ( noreturn ) ) tohost_exit( uintptr_t code ) { + tohost = ( code << 1 ) | 1; + while( 1 ) + ; } -uintptr_t __attribute__((weak)) handle_trap(uintptr_t cause, uintptr_t epc, uintptr_t regs[32]) -{ - tohost_exit(1337); +uintptr_t __attribute__( ( weak ) ) handle_trap( uintptr_t cause, uintptr_t epc, uintptr_t regs[32] ) { + tohost_exit( 1337 ); } -void exit(int code) -{ - tohost_exit(code); +void exit( int code ) { + tohost_exit( code ); } -void abort() -{ - exit(128 + SIGABRT); +void abort() { + exit( 128 + SIGABRT ); } -void printstr(const char* s) -{ - syscall(SYS_write, 1, (uintptr_t)s, strlen(s)); +void printstr( const char* s ) { + syscall( SYS_write, 1, (uintptr_t) s, strlen( s ) ); } -void __attribute__((weak)) thread_entry(int cid, int nc) -{ +void __attribute__( ( weak ) ) thread_entry( int cid, int nc ) { // multi-threaded programs override this function. // for the case of single-threaded programs, only let core 0 proceed. - while (cid != 0); + while( cid != 0 ) + ; } -int __attribute__((weak)) main(int argc, char** argv) -{ +int __attribute__( ( weak ) ) main( int argc, char** argv ) { // single-threaded programs override this function. - printstr("Implement main(), foo!\n"); + printstr( "Implement main(), foo!\n" ); return -1; } -static void init_tls() -{ - register void* thread_pointer asm("tp"); - extern char _tdata_begin, _tdata_end, _tbss_end; - size_t tdata_size = &_tdata_end - &_tdata_begin; - memcpy(thread_pointer, &_tdata_begin, tdata_size); +static void init_tls() { + register void* thread_pointer asm( "tp" ); + extern char _tdata_begin, _tdata_end, _tbss_end; + size_t tdata_size = &_tdata_end - &_tdata_begin; + memcpy( thread_pointer, &_tdata_begin, tdata_size ); size_t tbss_size = &_tbss_end - &_tdata_end; - memset(thread_pointer + tdata_size, 0, tbss_size); + memset( thread_pointer + tdata_size, 0, tbss_size ); } -void _init(int cid, int nc) -{ +void _init( int cid, int nc ) { init_tls(); - thread_entry(cid, nc); + thread_entry( cid, nc ); // only single-threaded programs should ever get here. - int ret = main(0, 0); + int ret = main( 0, 0 ); - char buf[NUM_COUNTERS * 32] __attribute__((aligned(64))); + char buf[NUM_COUNTERS * 32] __attribute__( ( aligned( 64 ) ) ); char* pbuf = buf; - for (int i = 0; i < NUM_COUNTERS; i++) - if (counters[i]) - pbuf += sprintf(pbuf, "%s = %d\n", counter_names[i], counters[i]); - if (pbuf != buf) - printstr(buf); + for( int i = 0; i < NUM_COUNTERS; i++ ) + if( counters[i] ) + pbuf += sprintf( pbuf, "%s = %d\n", counter_names[i], counters[i] ); + if( pbuf != buf ) + printstr( buf ); - exit(ret); + exit( ret ); } #undef putchar -int putchar(int ch) -{ - static __thread char buf[64] __attribute__((aligned(64))); - static __thread int buflen = 0; - buf[buflen++] = ch; +int putchar( int ch ) { + static __thread char buf[64] __attribute__( ( aligned( 64 ) ) ); + static __thread int buflen = 0; + + buf[buflen++] = ch; - if (ch == '\n' || buflen == sizeof(buf)) - { - syscall(SYS_write, 1, (uintptr_t)buf, buflen); + if( ch == '\n' || buflen == sizeof( buf ) ) { + syscall( SYS_write, 1, (uintptr_t) buf, buflen ); buflen = 0; } return 0; } -void printhex(uint64_t x) -{ +void printhex( uint64_t x ) { char str[17]; - int i; - for (i = 0; i < 16; i++) - { - str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); + int i; + for( i = 0; i < 16; i++ ) { + str[15 - i] = ( x & 0xF ) + ( ( x & 0xF ) < 10 ? '0' : 'a' - 10 ); x >>= 4; } str[16] = 0; - printstr(str); + printstr( str ); } -static inline void printnum(void (*putch)(int, void**), void **putdat, - unsigned long long num, unsigned base, int width, int padc) -{ - unsigned digs[sizeof(num)*CHAR_BIT]; - int pos = 0; +static inline void + printnum( void ( *putch )( int, void** ), void** putdat, unsigned long long num, unsigned base, int width, int padc ) { + unsigned digs[sizeof( num ) * CHAR_BIT]; + int pos = 0; - while (1) - { + while( 1 ) { digs[pos++] = num % base; - if (num < base) + if( num < base ) break; num /= base; } - while (width-- > pos) - putch(padc, putdat); + while( width-- > pos ) + putch( padc, putdat ); - while (pos-- > 0) - putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + while( pos-- > 0 ) + putch( digs[pos] + ( digs[pos] >= 10 ? 'a' - 10 : '0' ), putdat ); } -static unsigned long long getuint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, unsigned long long); - else if (lflag) - return va_arg(*ap, unsigned long); +static unsigned long long getuint( va_list* ap, int lflag ) { + if( lflag >= 2 ) + return va_arg( *ap, unsigned long long ); + else if( lflag ) + return va_arg( *ap, unsigned long ); else - return va_arg(*ap, unsigned int); + return va_arg( *ap, unsigned int ); } -static long long getint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, long long); - else if (lflag) - return va_arg(*ap, long); +static long long getint( va_list* ap, int lflag ) { + if( lflag >= 2 ) + return va_arg( *ap, long long ); + else if( lflag ) + return va_arg( *ap, long ); else - return va_arg(*ap, int); + return va_arg( *ap, int ); } -static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) -{ +static void vprintfmt( void ( *putch )( int, void** ), void** putdat, const char* fmt, va_list ap ) { register const char* p; - const char* last_fmt; - register int ch, err; - unsigned long long num; - int base, lflag, width, precision, altflag; - char padc; - - while (1) { - while ((ch = *(unsigned char *) fmt) != '%') { - if (ch == '\0') + const char* last_fmt; + register int ch, err; + unsigned long long num; + int base, lflag, width, precision, altflag; + char padc; + + while( 1 ) { + while( ( ch = *(unsigned char*) fmt ) != '%' ) { + if( ch == '\0' ) return; fmt++; - putch(ch, putdat); + putch( ch, putdat ); } fmt++; // Process a %-escape sequence - last_fmt = fmt; - padc = ' '; - width = -1; + last_fmt = fmt; + padc = ' '; + width = -1; precision = -1; - lflag = 0; - altflag = 0; + lflag = 0; + altflag = 0; reswitch: - switch (ch = *(unsigned char *) fmt++) { + switch( ch = *(unsigned char*) fmt++ ) { // flag to pad on the right - case '-': - padc = '-'; - goto reswitch; - + case '-': padc = '-'; goto reswitch; + // flag to pad with 0's instead of spaces - case '0': - padc = '0'; - goto reswitch; + case '0': padc = '0'; goto reswitch; // width field case '1': @@ -242,20 +226,18 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt case '7': case '8': case '9': - for (precision = 0; ; ++fmt) { + for( precision = 0;; ++fmt ) { precision = precision * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') + ch = *fmt; + if( ch < '0' || ch > '9' ) break; } goto process_precision; - case '*': - precision = va_arg(ap, int); - goto process_precision; + case '*': precision = va_arg( ap, int ); goto process_precision; case '.': - if (width < 0) + if( width < 0 ) width = 0; goto reswitch; @@ -264,49 +246,43 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt goto reswitch; process_precision: - if (width < 0) + if( width < 0 ) width = precision, precision = -1; goto reswitch; // long flag (doubled for long long) - case 'l': - lflag++; - goto reswitch; + case 'l': lflag++; goto reswitch; // character - case 'c': - putch(va_arg(ap, int), putdat); - break; + case 'c': putch( va_arg( ap, int ), putdat ); break; // string case 's': - if ((p = va_arg(ap, char *)) == NULL) + if( ( p = va_arg( ap, char* ) ) == NULL ) p = "(null)"; - if (width > 0 && padc != '-') - for (width -= strnlen(p, precision); width > 0; width--) - putch(padc, putdat); - for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { - putch(ch, putdat); + if( width > 0 && padc != '-' ) + for( width -= strnlen( p, precision ); width > 0; width-- ) + putch( padc, putdat ); + for( ; ( ch = *p ) != '\0' && ( precision < 0 || --precision >= 0 ); width-- ) { + putch( ch, putdat ); p++; } - for (; width > 0; width--) - putch(' ', putdat); + for( ; width > 0; width-- ) + putch( ' ', putdat ); break; // (signed) decimal case 'd': - num = getint(&ap, lflag); - if ((long long) num < 0) { - putch('-', putdat); + num = getint( &ap, lflag ); + if( (long long) num < 0 ) { + putch( '-', putdat ); num = -(long long) num; } base = 10; goto signed_number; // unsigned decimal - case 'u': - base = 10; - goto unsigned_number; + case 'u': base = 10; goto unsigned_number; // (unsigned) octal case 'o': @@ -316,165 +292,153 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt // pointer case 'p': - static_assert(sizeof(long) == sizeof(void*)); + static_assert( sizeof( long ) == sizeof( void* ) ); lflag = 1; - putch('0', putdat); - putch('x', putdat); + putch( '0', putdat ); + putch( 'x', putdat ); /* fall through to 'x' */ // (unsigned) hexadecimal case 'x': base = 16; unsigned_number: - num = getuint(&ap, lflag); + num = getuint( &ap, lflag ); signed_number: - printnum(putch, putdat, num, base, width, padc); + printnum( putch, putdat, num, base, width, padc ); break; // escaped '%' character - case '%': - putch(ch, putdat); - break; - + case '%': putch( ch, putdat ); break; + // unrecognized escape sequence - just print it literally default: - putch('%', putdat); + putch( '%', putdat ); fmt = last_fmt; break; } } } -int printf(const char* fmt, ...) -{ +int printf( const char* fmt, ... ) { va_list ap; - va_start(ap, fmt); + va_start( ap, fmt ); - vprintfmt((void*)putchar, 0, fmt, ap); + vprintfmt( (void*) putchar, 0, fmt, ap ); - va_end(ap); - return 0; // incorrect return value, but who cares, anyway? + va_end( ap ); + return 0; // incorrect return value, but who cares, anyway? } -int sprintf(char* str, const char* fmt, ...) -{ +int sprintf( char* str, const char* fmt, ... ) { va_list ap; - char* str0 = str; - va_start(ap, fmt); - - void sprintf_putch(int ch, void** data) - { - char** pstr = (char**)data; - **pstr = ch; - (*pstr)++; + char* str0 = str; + va_start( ap, fmt ); + + void sprintf_putch( int ch, void** data ) { + char** pstr = (char**) data; + **pstr = ch; + ( *pstr )++; } - vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + vprintfmt( sprintf_putch, (void**) &str, fmt, ap ); *str = 0; - va_end(ap); + va_end( ap ); return str - str0; } -void* memcpy(void* dest, const void* src, size_t len) -{ - if ((((uintptr_t)dest | (uintptr_t)src | len) & (sizeof(uintptr_t)-1)) == 0) { - const uintptr_t* s = src; - uintptr_t *d = dest; - uintptr_t *end = dest + len; - while (d + 8 < end) { - uintptr_t reg[8] = {s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]}; - d[0] = reg[0]; - d[1] = reg[1]; - d[2] = reg[2]; - d[3] = reg[3]; - d[4] = reg[4]; - d[5] = reg[5]; - d[6] = reg[6]; - d[7] = reg[7]; +void* memcpy( void* dest, const void* src, size_t len ) { + if( ( ( (uintptr_t) dest | (uintptr_t) src | len ) & ( sizeof( uintptr_t ) - 1 ) ) == 0 ) { + const uintptr_t* s = src; + uintptr_t* d = dest; + uintptr_t* end = dest + len; + while( d + 8 < end ) { + uintptr_t reg[8] = { s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7] }; + d[0] = reg[0]; + d[1] = reg[1]; + d[2] = reg[2]; + d[3] = reg[3]; + d[4] = reg[4]; + d[5] = reg[5]; + d[6] = reg[6]; + d[7] = reg[7]; d += 8; s += 8; } - while (d < end) + while( d < end ) *d++ = *s++; } else { const char* s = src; - char *d = dest; - while (d < (char*)(dest + len)) + char* d = dest; + while( d < (char*) ( dest + len ) ) *d++ = *s++; } return dest; } -void* memset(void* dest, int byte, size_t len) -{ - if ((((uintptr_t)dest | len) & (sizeof(uintptr_t)-1)) == 0) { +void* memset( void* dest, int byte, size_t len ) { + if( ( ( (uintptr_t) dest | len ) & ( sizeof( uintptr_t ) - 1 ) ) == 0 ) { uintptr_t word = byte & 0xFF; word |= word << 8; word |= word << 16; word |= word << 16 << 16; - uintptr_t *d = dest; - while (d < (uintptr_t*)(dest + len)) + uintptr_t* d = dest; + while( d < (uintptr_t*) ( dest + len ) ) *d++ = word; } else { - char *d = dest; - while (d < (char*)(dest + len)) + char* d = dest; + while( d < (char*) ( dest + len ) ) *d++ = byte; } return dest; } -size_t strlen(const char *s) -{ - const char *p = s; - while (*p) +size_t strlen( const char* s ) { + const char* p = s; + while( *p ) p++; return p - s; } -size_t strnlen(const char *s, size_t n) -{ - const char *p = s; - while (n-- && *p) +size_t strnlen( const char* s, size_t n ) { + const char* p = s; + while( n-- && *p ) p++; return p - s; } -int strcmp(const char* s1, const char* s2) -{ +int strcmp( const char* s1, const char* s2 ) { unsigned char c1, c2; do { c1 = *s1++; c2 = *s2++; - } while (c1 != 0 && c1 == c2); + } while( c1 != 0 && c1 == c2 ); return c1 - c2; } -char* strcpy(char* dest, const char* src) -{ +char* strcpy( char* dest, const char* src ) { char* d = dest; - while ((*d++ = *src++)) + while( ( *d++ = *src++ ) ) ; return dest; } -long atol(const char* str) -{ - long res = 0; - int sign = 0; +long atol( const char* str ) { + long res = 0; + int sign = 0; - while (*str == ' ') + while( *str == ' ' ) str++; - if (*str == '-' || *str == '+') { + if( *str == '-' || *str == '+' ) { sign = *str == '-'; str++; } - while (*str) { + while( *str ) { res *= 10; res += *str++ - '0'; } diff --git a/test/benchmarks/common/util.h b/test/benchmarks/common/util.h index b6208081c..79ff36ec1 100644 --- a/test/benchmarks/common/util.h +++ b/test/benchmarks/common/util.h @@ -1,5 +1,5 @@ // See LICENSE for license details. - +// clang-format off #ifndef __UTIL_H #define __UTIL_H diff --git a/test/benchmarks/env/encoding.h b/test/benchmarks/env/encoding.h index 01889d1a9..ebd6fc557 100644 --- a/test/benchmarks/env/encoding.h +++ b/test/benchmarks/env/encoding.h @@ -6,7 +6,7 @@ * This file is auto-generated by running 'make' in * https://github.com/riscv/riscv-opcodes (02b4866) */ - +// clang-format off #ifndef RISCV_CSR_ENCODING_H #define RISCV_CSR_ENCODING_H diff --git a/test/benchmarks/memcpy/Makefile b/test/benchmarks/memcpy/Makefile index 09f67e65d..feca41ad0 100644 --- a/test/benchmarks/memcpy/Makefile +++ b/test/benchmarks/memcpy/Makefile @@ -3,7 +3,7 @@ # # makefile: big_loop.c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/benchmarks/memcpy/dataset1.h b/test/benchmarks/memcpy/dataset1.h index 3300a016b..c243fbefe 100644 --- a/test/benchmarks/memcpy/dataset1.h +++ b/test/benchmarks/memcpy/dataset1.h @@ -1,207 +1,207 @@ +// clang-format off +#define DATA_SIZE 4000 -#define DATA_SIZE 4000 - -int input_data[DATA_SIZE] = +int input_data[DATA_SIZE] = { - 41, 454, 833, 335, 564, 1, 187, 989, 749, 365, 350, 572, 132, 64, 949, 153, 584, 216, 805, 140, - 621, 210, 6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961, 12, 110, 883, 116, 750, 296, 646, - 426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, - 539, 647, 569, 509, 203, 88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592, 81, 569, - 267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388, - 195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657, 79, 181, 208, 111, 998, 859, 629, 65, 847, - 288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761, 4, 241, 494, - 478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317, 78, 224, 351, 937, 540, - 288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358, 92, - 584, 989, 62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332, - 778, 684, 598, 740, 143, 446, 33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796, - 648, 357, 952, 891, 287, 666, 19, 514, 49, 557, 86, 870, 95, 853, 441, 440, 587, 61, 614, 678, - 382, 396, 280, 9, 808, 17, 971, 170, 819, 291, 344, 380, 450, 536, 512, 185, 965, 917, 347, 539, - 808, 983, 882, 887, 537, 54, 946, 612, 701, 951, 356, 479, 567, 151, 891, 7, 22, 641, 568, 335, - 665, 730, 423, 95, 434, 728, 158, 280, 2, 395, 84, 688, 247, 911, 49, 476, 435, 815, 792, 729, - 869, 265, 486, 127, 414, 236, 369, 214, 548, 180, 518, 6, 888, 503, 682, 596, 284, 173, 264, 643, - 499, 346, 290, 599, 897, 68, 215, 849, 731, 658, 688, 619, 251, 121, 786, 131, 555, 828, 302, 667, - 528, 433, 544, 487, 322, 753, 947, 125, 287, 626, 824, 14, 304, 10, 788, 403, 733, 106, 959, 703, - 366, 818, 722, 964, 294, 406, 975, 874, 653, 856, 748, 86, 91, 60, 378, 660, 105, 667, 102, 153, - 381, 121, 651, 98, 825, 412, 840, 236, 356, 12, 148, 423, 54, 965, 140, 216, 955, 621, 343, 361, - 533, 921, 757, 715, 521, 647, 837, 299, 592, 886, 13, 682, 173, 36, 63, 493, 121, 551, 133, 537, - 758, 969, 372, 643, 951, 434, 39, 415, 129, 303, 110, 438, 847, 860, 437, 203, 255, 478, 269, 988, - 409, 675, 628, 719, 399, 990, 549, 338, 753, 450, 564, 633, 171, 155, 19, 646, 727, 452, 501, 427, - 777, 509, 43, 988, 753, 426, 81, 12, 202, 483, 853, 142, 153, 339, 760, 390, 357, 50, 943, 171, - 922, 601, 328, 105, 496, 968, 442, 121, 516, 879, 641, 81, 276, 870, 786, 600, 113, 603, 842, 871, - 907, 887, 275, 610, 237, 404, 32, 234, 784, 745, 565, 526, 357, 275, 803, 441, 819, 226, 751, 752, - 280, 943, 85, 726, 458, 709, 454, 201, 710, 54, 459, 758, 41, 53, 253, 397, 377, 41, 508, 141, - 700, 416, 860, 747, 480, 219, 741, 478, 499, 770, 709, 180, 49, 482, 371, 691, 873, 725, 945, 173, - 992, 186, 526, 914, 721, 1, 435, 963, 232, 247, 497, 464, 697, 362, 30, 521, 348, 233, 250, 120, - 350, 40, 250, 779, 573, 195, 784, 161, 749, 743, 502, 439, 823, 355, 826, 403, 170, 141, 160, 633, - 674, 289, 32, 782, 202, 320, 143, 636, 853, 118, 90, 852, 394, 70, 107, 816, 855, 388, 106, 954, - 157, 36, 6, 16, 765, 698, 204, 695, 194, 677, 574, 598, 218, 883, 526, 824, 177, 746, 239, 462, - 698, 511, 757, 534, 706, 440, 49, 428, 84, 732, 799, 726, 893, 702, 512, 547, 373, 86, 492, 798, - 14, 215, 621, 21, 83, 651, 103, 59, 794, 429, 921, 657, 643, 96, 880, 973, 834, 659, 239, 966, - 462, 524, 114, 62, 561, 625, 529, 303, 10, 714, 997, 409, 904, 55, 387, 728, 407, 305, 105, 436, - 559, 901, 936, 592, 512, 691, 409, 796, 302, 497, 202, 177, 427, 940, 613, 995, 359, 480, 521, 158, - 684, 822, 22, 611, 185, 680, 312, 14, 107, 111, 274, 797, 387, 185, 242, 0, 486, 718, 105, 96, - 698, 749, 899, 739, 770, 814, 644, 435, 80, 326, 161, 37, 407, 33, 946, 605, 30, 935, 768, 27, - 870, 88, 113, 441, 148, 339, 62, 344, 147, 554, 838, 365, 845, 954, 432, 639, 141, 396, 211, 991, - 817, 249, 821, 338, 562, 832, 364, 974, 615, 393, 495, 266, 812, 470, 916, 348, 159, 336, 430, 419, - 803, 249, 180, 215, 544, 542, 840, 903, 458, 636, 786, 729, 872, 581, 795, 820, 806, 671, 758, 979, - 104, 418, 401, 670, 254, 920, 984, 568, 136, 745, 729, 662, 584, 139, 794, 385, 414, 927, 528, 173, - 707, 457, 554, 316, 378, 183, 766, 477, 977, 196, 236, 399, 947, 416, 229, 805, 165, 996, 505, 270, - 105, 735, 704, 696, 796, 825, 140, 528, 303, 50, 795, 623, 635, 537, 560, 87, 119, 294, 8, 867, - 532, 110, 814, 398, 37, 781, 584, 646, 739, 375, 619, 943, 767, 897, 478, 589, 57, 44, 958, 288, - 784, 845, 985, 742, 837, 99, 307, 522, 67, 443, 824, 432, 996, 165, 749, 930, 171, 28, 826, 461, - 621, 323, 155, 272, 826, 376, 43, 340, 694, 898, 80, 158, 236, 168, 747, 443, 744, 193, 265, 631, - 124, 935, 731, 274, 941, 781, 425, 185, 370, 619, 320, 292, 269, 933, 542, 156, 763, 827, 752, 88, - 915, 987, 14, 629, 1, 649, 906, 32, 995, 1, 809, 744, 560, 399, 873, 915, 972, 791, 289, 554, - 509, 984, 558, 530, 970, 600, 405, 401, 579, 683, 293, 540, 251, 903, 849, 120, 129, 995, 452, 521, - 716, 622, 86, 224, 678, 895, 181, 530, 240, 820, 335, 651, 793, 226, 641, 96, 1, 262, 320, 569, - 987, 238, 646, 126, 754, 610, 958, 191, 203, 238, 142, 796, 180, 884, 299, 573, 165, 108, 761, 140, - 974, 789, 646, 852, 559, 23, 619, 704, 422, 890, 260, 480, 565, 52, 542, 372, 492, 201, 991, 546, - 745, 408, 207, 119, 372, 645, 932, 464, 664, 81, 34, 293, 533, 52, 478, 880, 908, 224, 203, 744, - 33, 735, 214, 886, 365, 167, 892, 1, 781, 532, 680, 321, 705, 169, 688, 485, 947, 101, 386, 177, - 50, 42, 101, 708, 474, 654, 399, 915, 679, 625, 330, 242, 952, 822, 471, 795, 477, 641, 725, 252, - 713, 245, 937, 151, 529, 876, 870, 333, 77, 601, 545, 938, 907, 775, 853, 397, 143, 233, 979, 755, - 239, 454, 105, 424, 365, 210, 98, 962, 54, 900, 98, 923, 440, 655, 764, 529, 315, 595, 336, 90, - 697, 464, 774, 685, 726, 70, 324, 754, 282, 32, 536, 494, 622, 25, 594, 389, 890, 488, 75, 37, - 290, 409, 496, 639, 726, 27, 449, 950, 548, 539, 135, 80, 644, 303, 838, 723, 290, 734, 767, 125, - 162, 552, 415, 248, 491, 107, 985, 362, 116, 48, 617, 869, 859, 144, 235, 841, 282, 724, 571, 335, - 913, 470, 560, 263, 194, 343, 242, 809, 782, 677, 985, 339, 728, 336, 344, 410, 430, 465, 613, 56, - 759, 590, 176, 485, 309, 406, 333, 993, 354, 746, 310, 238, 699, 525, 46, 336, 487, 256, 503, 134, - 100, 546, 393, 722, 268, 367, 314, 943, 75, 106, 345, 629, 987, 396, 600, 208, 908, 429, 384, 523, - 92, 130, 545, 355, 277, 990, 668, 673, 351, 991, 853, 719, 863, 449, 312, 84, 100, 616, 532, 211, - 567, 707, 836, 737, 370, 847, 989, 452, 461, 316, 912, 974, 182, 746, 268, 796, 160, 522, 771, 618, - 22, 115, 854, 727, 644, 226, 17, 165, 779, 200, 911, 830, 855, 742, 137, 187, 983, 705, 717, 671, - 565, 785, 719, 886, 253, 962, 785, 657, 154, 293, 196, 620, 253, 144, 447, 173, 899, 796, 5, 72, - 325, 678, 616, 80, 309, 793, 175, 685, 159, 637, 123, 967, 838, 241, 715, 898, 550, 693, 230, 372, - 82, 601, 627, 721, 324, 398, 927, 553, 103, 72, 17, 174, 966, 978, 159, 325, 177, 558, 593, 185, - 372, 505, 393, 859, 599, 651, 745, 573, 377, 321, 865, 349, 591, 400, 553, 890, 440, 844, 345, 885, - 593, 933, 290, 980, 908, 448, 544, 989, 377, 50, 456, 332, 781, 900, 110, 716, 495, 747, 896, 444, - 806, 6, 700, 394, 548, 285, 340, 703, 29, 450, 829, 652, 630, 771, 546, 485, 613, 534, 972, 559, - 116, 481, 313, 507, 904, 434, 971, 343, 607, 42, 794, 784, 169, 865, 896, 421, 507, 415, 916, 871, - 431, 539, 339, 162, 147, 105, 224, 481, 112, 595, 580, 115, 834, 350, 134, 964, 948, 287, 201, 232, - 488, 154, 396, 602, 797, 539, 478, 943, 769, 872, 574, 121, 485, 652, 339, 811, 721, 747, 451, 362, - 821, 340, 744, 910, 0, 206, 594, 572, 277, 505, 120, 973, 680, 961, 757, 354, 555, 627, 847, 849, - 517, 971, 379, 910, 505, 410, 904, 770, 246, 63, 243, 874, 394, 396, 430, 482, 214, 619, 244, 646, - 524, 557, 399, 328, 172, 67, 304, 884, 620, 512, 594, 972, 535, 6, 698, 513, 159, 882, 750, 562, - 809, 764, 454, 366, 75, 506, 93, 786, 167, 831, 16, 382, 853, 638, 494, 452, 324, 72, 78, 83, - 52, 59, 112, 932, 10, 929, 342, 924, 730, 961, 680, 69, 287, 797, 961, 985, 92, 854, 626, 885, - 912, 600, 616, 389, 860, 232, 744, 793, 744, 179, 478, 773, 615, 689, 508, 775, 914, 494, 810, 139, - 288, 234, 974, 431, 129, 780, 581, 371, 548, 22, 868, 653, 981, 741, 270, 815, 623, 428, 653, 139, - 626, 603, 990, 315, 386, 344, 323, 889, 472, 317, 164, 260, 239, 861, 189, 377, 865, 511, 231, 304, - 356, 70, 152, 35, 825, 854, 328, 576, 390, 490, 848, 326, 38, 303, 402, 431, 616, 813, 546, 708, - 206, 388, 2, 962, 783, 967, 890, 442, 815, 49, 831, 831, 665, 251, 410, 321, 94, 741, 246, 179, - 422, 176, 211, 117, 675, 523, 9, 764, 374, 952, 426, 704, 64, 531, 53, 804, 758, 23, 811, 611, - 500, 846, 437, 375, 335, 854, 328, 971, 237, 24, 415, 639, 468, 318, 684, 723, 565, 662, 305, 647, - 449, 281, 597, 158, 136, 294, 882, 885, 383, 734, 938, 866, 268, 471, 115, 296, 908, 673, 50, 472, - 952, 439, 366, 5, 397, 155, 257, 506, 231, 948, 667, 600, 35, 445, 990, 222, 443, 784, 213, 349, - 389, 943, 13, 150, 621, 366, 52, 444, 612, 604, 934, 720, 953, 340, 828, 972, 462, 911, 621, 321, - 812, 435, 522, 50, 672, 78, 57, 761, 313, 950, 352, 238, 55, 27, 972, 226, 753, 201, 416, 176, - 879, 877, 864, 450, 572, 879, 163, 99, 721, 143, 12, 31, 643, 812, 507, 771, 968, 527, 781, 488, - 840, 797, 242, 194, 630, 293, 810, 966, 795, 276, 435, 345, 885, 413, 599, 197, 696, 386, 643, 116, - 93, 322, 710, 680, 785, 538, 112, 553, 581, 960, 12, 874, 923, 48, 615, 506, 652, 898, 359, 539, - 261, 495, 233, 764, 609, 805, 686, 286, 539, 432, 118, 836, 560, 192, 739, 825, 20, 778, 317, 586, - 976, 359, 573, 352, 386, 746, 772, 11, 663, 749, 504, 5, 212, 408, 888, 643, 907, 441, 420, 368, - 737, 97, 516, 169, 25, 359, 219, 527, 797, 672, 716, 69, 452, 880, 692, 298, 683, 300, 459, 327, - 815, 923, 323, 829, 612, 816, 247, 497, 116, 243, 352, 981, 281, 917, 738, 713, 290, 653, 909, 503, - 645, 406, 625, 543, 932, 108, 220, 304, 685, 464, 373, 954, 876, 86, 646, 802, 412, 446, 955, 28, - 664, 539, 850, 655, 783, 28, 392, 470, 707, 735, 422, 941, 523, 610, 682, 451, 37, 672, 156, 237, - 43, 766, 767, 713, 124, 409, 549, 869, 814, 186, 251, 475, 214, 568, 212, 44, 572, 997, 898, 139, - 956, 456, 608, 470, 651, 566, 434, 408, 906, 756, 970, 573, 640, 877, 687, 24, 642, 506, 265, 368, - 271, 399, 972, 950, 814, 109, 824, 595, 121, 856, 465, 516, 468, 473, 631, 793, 281, 736, 416, 708, - 315, 978, 235, 530, 626, 419, 296, 548, 502, 854, 28, 184, 668, 786, 326, 228, 578, 738, 881, 265, - 304, 808, 415, 490, 0, 623, 199, 483, 934, 105, 212, 545, 535, 154, 40, 473, 528, 712, 835, 668, - 349, 235, 338, 307, 230, 334, 872, 522, 374, 225, 143, 746, 996, 144, 385, 136, 848, 545, 487, 434, - 587, 837, 8, 456, 487, 434, 729, 114, 944, 971, 688, 316, 871, 667, 156, 304, 624, 813, 269, 729, - 47, 538, 250, 756, 491, 838, 882, 404, 213, 56, 231, 471, 326, 758, 132, 493, 644, 327, 421, 992, - 327, 435, 57, 651, 676, 352, 519, 199, 776, 354, 235, 648, 647, 3, 95, 842, 260, 345, 713, 912, - 198, 781, 493, 632, 943, 142, 86, 615, 222, 95, 843, 743, 337, 942, 752, 87, 53, 121, 86, 263, - 889, 580, 269, 666, 187, 68, 731, 230, 538, 72, 759, 330, 961, 547, 606, 593, 10, 320, 560, 798, - 122, 32, 957, 646, 288, 450, 604, 161, 128, 880, 109, 220, 175, 818, 590, 425, 413, 217, 346, 205, - 249, 63, 635, 858, 514, 14, 799, 766, 882, 610, 939, 375, 157, 120, 886, 963, 172, 983, 974, 755, - 922, 571, 323, 352, 783, 866, 832, 955, 100, 492, 772, 530, 751, 361, 696, 321, 650, 69, 986, 552, - 192, 55, 798, 91, 39, 563, 654, 564, 761, 544, 892, 167, 801, 122, 277, 25, 451, 829, 967, 781, - 361, 168, 64, 397, 928, 563, 914, 336, 536, 478, 243, 257, 264, 477, 879, 390, 640, 701, 208, 328, - 302, 443, 295, 521, 813, 914, 573, 118, 345, 525, 964, 508, 482, 30, 606, 416, 101, 71, 121, 92, - 435, 284, 453, 161, 20, 361, 70, 414, 23, 804, 255, 839, 276, 586, 890, 36, 427, 246, 542, 865, - 622, 953, 699, 366, 773, 803, 296, 133, 277, 529, 104, 229, 80, 462, 632, 260, 815, 37, 851, 237, - 732, 243, 393, 866, 760, 196, 126, 631, 168, 301, 843, 613, 189, 333, 589, 247, 936, 197, 256, 594, - 232, 956, 75, 306, 190, 329, 424, 153, 751, 690, 757, 805, 876, 539, 48, 122, 857, 473, 770, 388, - 638, 125, 488, 973, 176, 203, 474, 693, 461, 82, 606, 432, 923, 70, 0, 371, 632, 206, 280, 604, - 928, 686, 300, 120, 451, 795, 703, 810, 711, 708, 620, 357, 443, 98, 789, 903, 611, 93, 231, 376, - 530, 299, 791, 1, 732, 298, 289, 131, 726, 834, 806, 249, 172, 709, 898, 123, 456, 5, 942, 462, - 607, 322, 801, 208, 503, 421, 741, 183, 806, 258, 633, 533, 950, 594, 948, 31, 40, 984, 353, 213, - 195, 50, 794, 978, 700, 217, 287, 821, 267, 734, 774, 554, 650, 361, 199, 236, 263, 99, 316, 810, - 946, 984, 940, 891, 603, 180, 834, 333, 639, 286, 522, 33, 256, 202, 418, 467, 266, 716, 918, 126, - 786, 695, 782, 408, 529, 921, 494, 207, 301, 925, 195, 804, 391, 951, 730, 552, 912, 432, 798, 33, - 472, 262, 826, 748, 367, 835, 115, 373, 233, 351, 850, 910, 854, 688, 551, 883, 857, 24, 314, 555, - 822, 986, 422, 917, 175, 172, 470, 354, 830, 208, 311, 834, 206, 653, 144, 823, 106, 126, 638, 689, - 134, 307, 623, 804, 439, 423, 913, 349, 602, 424, 996, 430, 555, 144, 481, 756, 226, 990, 325, 207, - 851, 302, 535, 825, 134, 849, 204, 683, 695, 556, 791, 763, 169, 533, 623, 194, 86, 724, 484, 440, - 92, 870, 471, 86, 538, 47, 303, 819, 777, 652, 702, 900, 530, 522, 459, 321, 913, 559, 963, 963, - 685, 369, 327, 470, 164, 284, 437, 957, 148, 616, 2, 108, 106, 296, 743, 121, 304, 131, 694, 935, - 503, 937, 40, 883, 39, 899, 70, 229, 637, 654, 843, 866, 259, 252, 531, 52, 492, 969, 693, 419, - 278, 777, 970, 442, 546, 456, 503, 69, 955, 129, 697, 623, 842, 359, 325, 515, 223, 527, 84, 469, - 732, 724, 319, 104, 703, 789, 980, 109, 446, 830, 892, 23, 689, 884, 100, 790, 196, 509, 343, 828, - 637, 580, 367, 847, 48, 435, 860, 292, 696, 523, 724, 908, 191, 805, 392, 951, 510, 163, 975, 258, - 569, 922, 723, 232, 692, 328, 49, 654, 48, 35, 88, 450, 900, 854, 485, 700, 424, 515, 759, 543, - 441, 631, 57, 346, 637, 814, 405, 885, 632, 609, 147, 952, 446, 919, 371, 154, 995, 814, 965, 875, - 729, 993, 734, 767, 467, 163, 690, 480, 293, 685, 687, 104, 433, 942, 363, 28, 725, 163, 738, 330, - 370, 129, 741, 952, 444, 241, 309, 380, 279, 336, 337, 607, 503, 132, 517, 368, 882, 87, 539, 687, - 146, 233, 336, 457, 789, 246, 78, 192, 367, 73, 856, 990, 423, 945, 82, 967, 921, 980, 87, 553, - 534, 33, 628, 565, 342, 326, 572, 430, 563, 108, 990, 429, 517, 178, 139, 847, 928, 518, 770, 160, - 291, 75, 224, 297, 564, 234, 704, 948, 382, 163, 596, 163, 675, 420, 231, 70, 604, 366, 722, 886, - 746, 635, 819, 733, 59, 372, 722, 874, 256, 26, 677, 451, 440, 204, 585, 435, 474, 580, 667, 548, - 93, 813, 333, 49, 924, 508, 208, 373, 769, 682, 877, 448, 823, 47, 452, 274, 321, 665, 599, 49, - 866, 570, 286, 442, 690, 385, 101, 478, 215, 713, 539, 238, 659, 344, 146, 142, 454, 289, 340, 764, - 774, 518, 540, 977, 579, 222, 726, 7, 746, 637, 597, 827, 767, 358, 470, 55, 415, 509, 858, 120, - 845, 984, 564, 584, 58, 755, 967, 919, 814, 110, 977, 972, 423, 34, 933, 699, 810, 94, 87, 209, - 362, 393, 526, 620, 121, 994, 676, 983, 367, 698, 236, 500, 684, 97, 500, 185, 617, 155, 47, 89, - 618, 421, 185, 340, 374, 857, 236, 765, 860, 689, 694, 441, 685, 932, 582, 271, 4, 114, 660, 955, - 404, 270, 635, 630, 721, 596, 631, 769, 468, 95, 153, 983, 0, 408, 689, 292, 220, 586, 430, 669, - 524, 188, 965, 910, 334, 575, 996, 506, 189, 133, 273, 525, 542, 881, 75, 916, 663, 610, 461, 956, - 943, 219, 281, 195, 347, 995, 136, 589, 142, 708, 270, 3, 867, 468, 45, 742, 844, 963, 413, 860, - 451, 635, 798, 906, 837, 380, 148, 279, 133, 343, 579, 170, 439, 735, 342, 918, 795, 736, 133, 859, - 650, 486, 856, 63, 431, 677, 686, 670, 198, 123, 512, 572, 878, 888, 346, 340, 606, 826, 844, 375, - 510, 824, 201, 219, 227, 201, 338, 522, 997, 76, 609, 922, 904, 270, 326, 809, 328, 285, 83, 630, - 550, 92, 369, 957, 719, 980, 784, 494, 472, 231, 734, 408, 917, 415, 886, 36, 728, 116, 526, 844, - 659, 493, 959, 395, 112, 758, 154, 664, 744, 156, 99, 767, 668, 620, 51, 747, 239, 97, 737, 399, - 751, 458, 16, 47, 847, 557, 937, 72, 744, 848, 78, 706, 348, 33, 505, 83, 520, 695, 572, 661, - 322, 123, 447, 349, 584, 433, 951, 905, 97, 416, 123, 421, 659, 843, 923, 933, 938, 291, 961, 861, - 145, 367, 714, 153, 66, 697, 744, 657, 477, 511, 602, 445, 950, 553, 278, 96, 937, 555, 368, 415, - 748, 143, 741, 771, 862, 990, 8, 295, 396, 17, 119, 236, 508, 285, 844, 914, 97, 235, 906, 118, - 83, 405, 190, 618, 438, 438, 706, 413, 546, 214, 807, 540, 360, 162, 426, 42, 852, 258, 765, 147, - 550, 13, 547, 704, 227, 733, 678, 587, 623, 795, 309, 538, 920, 372, 971, 929, 590, 466, 749, 42, - 662, 794, 545, 57, 747, 828, 231, 287, 655, 443, 148, 600, 71, 209, 453, 494, 560, 542, 835, 46, - 608, 971, 13, 600, 370, 662, 139, 818, 174, 618, 209, 609, 457, 373, 907, 959, 833, 382, 175, 136, - 374, 157, 417, 761, 312, 710, 389, 746, 155, 238, 941, 567, 450, 717, 282, 408, 997, 194, 918, 799, - 282, 750, 960, 604, 194, 310, 798, 141, 124, 492, 40, 439, 62, 389, 878, 731, 318, 580, 199, 379, - 512, 359, 710, 188, 909, 639, 339, 96, 542, 393, 178, 204, 590, 696, 183, 247, 618, 413, 971, 539, - 702, 430, 715, 949, 425, 760, 971, 207, 956, 373, 144, 106, 921, 591, 16, 774, 796, 179, 924, 709, - 966, 993, 625, 757, 6, 357, 6, 778, 58, 162, 524, 265, 247, 375, 595, 545, 867, 973, 219, 170, - 709, 920, 700, 112, 344, 213, 455, 321, 939, 165, 157, 883, 99, 258, 140, 515, 217, 311, 84, 660, - 715, 504, 149, 198, 566, 341, 521, 474, 351, 951, 546, 183, 603, 876, 538, 901, 754, 363, 893, 973, - 913, 244, 192, 799, 362, 155, 702, 637, 628, 415, 599, 177, 686, 718, 604, 550, 153, 242, 790, 152, - 603, 168, 465, 779, 781, 511, 172, 789, 445, 618, 502, 270, 45, 696, 185, 927, 71, 970, 448, 519, - 201, 918, 190, 958, 174, 835, 941, 916, 255, 575, 693, 976, 150, 665, 612, 452, 227, 259, 784, 568, - 780, 395, 783, 102, 179, 124, 52, 52, 824, 868, 328, 763, 679, 574, 300, 905, 404, 139, 955, 280, - 976, 246, 122, 692, 679, 276, 158, 735, 126, 525, 736, 824, 910, 660, 87, 908, 725, 523, 532, 92, - 473, 876, 886, 500, 715, 258, 458, 28, 768, 219, 382, 504, 883, 10, 716, 783, 241, 519, 576, 892, - 372, 241, 239, 419, 944, 465, 105, 586, 466, 234, 54, 194, 173, 833, 649, 560, 386, 589, 983, 692, - 652, 101, 332, 790, 640, 50, 67, 397, 773, 700, 282, 691, 728, 675, 711, 631, 81, 788, 868, 618, - 635, 265, 892, 617, 11, 764, 624, 990, 609, 58, 615, 781, 480, 939, 461, 611, 163, 184, 465, 314, - 470, 698, 619, 789, 117, 3, 311, 456, 186, 203, 721, 932, 768, 502, 143, 904, 730, 201, 423, 417, - 947, 154, 568, 261, 473, 775, 380, 615, 786, 193, 710, 445, 469, 943, 729, 204, 564, 117, 142, 568, - 342, 854, 790, 984, 824, 297, 982, 834, 21, 944, 482, 759, 312, 2, 512, 659, 599, 860, 803, 4, - 961, 790, 458, 362, 380, 90, 771, 389, 291, 209, 630, 440, 845, 255, 435, 550, 71, 925, 733, 659, - 899, 770, 914, 791, 60, 993, 984, 955, 244, 55, 935, 877, 960, 708, 628, 374, 144, 871, 8, 407, - 438, 591, 590, 124, 164, 402, 195, 757, 242, 435, 238, 136, 675, 569, 455, 48, 984, 938, 717, 381, - 82, 776, 595, 69, 112, 421, 361, 626, 719, 664, 253, 694, 944, 281, 451, 196, 345, 699, 721, 829, - 469, 368, 20, 825, 986, 436, 40, 577, 702, 199, 403, 623, 655, 33, 577, 927, 48, 993, 19, 741, - 107, 221, 193, 932, 70, 832, 172, 355, 396, 210, 191, 54, 477, 861, 755, 198, 434, 199, 481, 52, - 928, 347, 371, 949, 162, 11, 757, 593, 473, 558, 744, 494, 204, 113, 53, 511, 56, 924, 319, 185, - 102, 712, 721, 475, 548, 626, 546, 4, 280, 884, 765, 709, 159, 811, 706, 732, 944, 730, 429, 237, - 956, 924, 75, 24, 985, 357, 143, 86, 440, 209, 838, 576, 813, 81, 262, 809, 761, 310, 483, 447, - 743, 631, 464, 658, 233, 43, 279, 893, 199, 274, 380, 771, 237, 815, 88, 75, 530, 729, 761, 746, - 506, 900, 978, 311, 694, 480, 480, 82, 997, 729, 26, 627, 370, 540, 750, 24, 300, 664, 212, 750, + 41, 454, 833, 335, 564, 1, 187, 989, 749, 365, 350, 572, 132, 64, 949, 153, 584, 216, 805, 140, + 621, 210, 6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961, 12, 110, 883, 116, 750, 296, 646, + 426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, + 539, 647, 569, 509, 203, 88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592, 81, 569, + 267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388, + 195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657, 79, 181, 208, 111, 998, 859, 629, 65, 847, + 288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761, 4, 241, 494, + 478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317, 78, 224, 351, 937, 540, + 288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358, 92, + 584, 989, 62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332, + 778, 684, 598, 740, 143, 446, 33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796, + 648, 357, 952, 891, 287, 666, 19, 514, 49, 557, 86, 870, 95, 853, 441, 440, 587, 61, 614, 678, + 382, 396, 280, 9, 808, 17, 971, 170, 819, 291, 344, 380, 450, 536, 512, 185, 965, 917, 347, 539, + 808, 983, 882, 887, 537, 54, 946, 612, 701, 951, 356, 479, 567, 151, 891, 7, 22, 641, 568, 335, + 665, 730, 423, 95, 434, 728, 158, 280, 2, 395, 84, 688, 247, 911, 49, 476, 435, 815, 792, 729, + 869, 265, 486, 127, 414, 236, 369, 214, 548, 180, 518, 6, 888, 503, 682, 596, 284, 173, 264, 643, + 499, 346, 290, 599, 897, 68, 215, 849, 731, 658, 688, 619, 251, 121, 786, 131, 555, 828, 302, 667, + 528, 433, 544, 487, 322, 753, 947, 125, 287, 626, 824, 14, 304, 10, 788, 403, 733, 106, 959, 703, + 366, 818, 722, 964, 294, 406, 975, 874, 653, 856, 748, 86, 91, 60, 378, 660, 105, 667, 102, 153, + 381, 121, 651, 98, 825, 412, 840, 236, 356, 12, 148, 423, 54, 965, 140, 216, 955, 621, 343, 361, + 533, 921, 757, 715, 521, 647, 837, 299, 592, 886, 13, 682, 173, 36, 63, 493, 121, 551, 133, 537, + 758, 969, 372, 643, 951, 434, 39, 415, 129, 303, 110, 438, 847, 860, 437, 203, 255, 478, 269, 988, + 409, 675, 628, 719, 399, 990, 549, 338, 753, 450, 564, 633, 171, 155, 19, 646, 727, 452, 501, 427, + 777, 509, 43, 988, 753, 426, 81, 12, 202, 483, 853, 142, 153, 339, 760, 390, 357, 50, 943, 171, + 922, 601, 328, 105, 496, 968, 442, 121, 516, 879, 641, 81, 276, 870, 786, 600, 113, 603, 842, 871, + 907, 887, 275, 610, 237, 404, 32, 234, 784, 745, 565, 526, 357, 275, 803, 441, 819, 226, 751, 752, + 280, 943, 85, 726, 458, 709, 454, 201, 710, 54, 459, 758, 41, 53, 253, 397, 377, 41, 508, 141, + 700, 416, 860, 747, 480, 219, 741, 478, 499, 770, 709, 180, 49, 482, 371, 691, 873, 725, 945, 173, + 992, 186, 526, 914, 721, 1, 435, 963, 232, 247, 497, 464, 697, 362, 30, 521, 348, 233, 250, 120, + 350, 40, 250, 779, 573, 195, 784, 161, 749, 743, 502, 439, 823, 355, 826, 403, 170, 141, 160, 633, + 674, 289, 32, 782, 202, 320, 143, 636, 853, 118, 90, 852, 394, 70, 107, 816, 855, 388, 106, 954, + 157, 36, 6, 16, 765, 698, 204, 695, 194, 677, 574, 598, 218, 883, 526, 824, 177, 746, 239, 462, + 698, 511, 757, 534, 706, 440, 49, 428, 84, 732, 799, 726, 893, 702, 512, 547, 373, 86, 492, 798, + 14, 215, 621, 21, 83, 651, 103, 59, 794, 429, 921, 657, 643, 96, 880, 973, 834, 659, 239, 966, + 462, 524, 114, 62, 561, 625, 529, 303, 10, 714, 997, 409, 904, 55, 387, 728, 407, 305, 105, 436, + 559, 901, 936, 592, 512, 691, 409, 796, 302, 497, 202, 177, 427, 940, 613, 995, 359, 480, 521, 158, + 684, 822, 22, 611, 185, 680, 312, 14, 107, 111, 274, 797, 387, 185, 242, 0, 486, 718, 105, 96, + 698, 749, 899, 739, 770, 814, 644, 435, 80, 326, 161, 37, 407, 33, 946, 605, 30, 935, 768, 27, + 870, 88, 113, 441, 148, 339, 62, 344, 147, 554, 838, 365, 845, 954, 432, 639, 141, 396, 211, 991, + 817, 249, 821, 338, 562, 832, 364, 974, 615, 393, 495, 266, 812, 470, 916, 348, 159, 336, 430, 419, + 803, 249, 180, 215, 544, 542, 840, 903, 458, 636, 786, 729, 872, 581, 795, 820, 806, 671, 758, 979, + 104, 418, 401, 670, 254, 920, 984, 568, 136, 745, 729, 662, 584, 139, 794, 385, 414, 927, 528, 173, + 707, 457, 554, 316, 378, 183, 766, 477, 977, 196, 236, 399, 947, 416, 229, 805, 165, 996, 505, 270, + 105, 735, 704, 696, 796, 825, 140, 528, 303, 50, 795, 623, 635, 537, 560, 87, 119, 294, 8, 867, + 532, 110, 814, 398, 37, 781, 584, 646, 739, 375, 619, 943, 767, 897, 478, 589, 57, 44, 958, 288, + 784, 845, 985, 742, 837, 99, 307, 522, 67, 443, 824, 432, 996, 165, 749, 930, 171, 28, 826, 461, + 621, 323, 155, 272, 826, 376, 43, 340, 694, 898, 80, 158, 236, 168, 747, 443, 744, 193, 265, 631, + 124, 935, 731, 274, 941, 781, 425, 185, 370, 619, 320, 292, 269, 933, 542, 156, 763, 827, 752, 88, + 915, 987, 14, 629, 1, 649, 906, 32, 995, 1, 809, 744, 560, 399, 873, 915, 972, 791, 289, 554, + 509, 984, 558, 530, 970, 600, 405, 401, 579, 683, 293, 540, 251, 903, 849, 120, 129, 995, 452, 521, + 716, 622, 86, 224, 678, 895, 181, 530, 240, 820, 335, 651, 793, 226, 641, 96, 1, 262, 320, 569, + 987, 238, 646, 126, 754, 610, 958, 191, 203, 238, 142, 796, 180, 884, 299, 573, 165, 108, 761, 140, + 974, 789, 646, 852, 559, 23, 619, 704, 422, 890, 260, 480, 565, 52, 542, 372, 492, 201, 991, 546, + 745, 408, 207, 119, 372, 645, 932, 464, 664, 81, 34, 293, 533, 52, 478, 880, 908, 224, 203, 744, + 33, 735, 214, 886, 365, 167, 892, 1, 781, 532, 680, 321, 705, 169, 688, 485, 947, 101, 386, 177, + 50, 42, 101, 708, 474, 654, 399, 915, 679, 625, 330, 242, 952, 822, 471, 795, 477, 641, 725, 252, + 713, 245, 937, 151, 529, 876, 870, 333, 77, 601, 545, 938, 907, 775, 853, 397, 143, 233, 979, 755, + 239, 454, 105, 424, 365, 210, 98, 962, 54, 900, 98, 923, 440, 655, 764, 529, 315, 595, 336, 90, + 697, 464, 774, 685, 726, 70, 324, 754, 282, 32, 536, 494, 622, 25, 594, 389, 890, 488, 75, 37, + 290, 409, 496, 639, 726, 27, 449, 950, 548, 539, 135, 80, 644, 303, 838, 723, 290, 734, 767, 125, + 162, 552, 415, 248, 491, 107, 985, 362, 116, 48, 617, 869, 859, 144, 235, 841, 282, 724, 571, 335, + 913, 470, 560, 263, 194, 343, 242, 809, 782, 677, 985, 339, 728, 336, 344, 410, 430, 465, 613, 56, + 759, 590, 176, 485, 309, 406, 333, 993, 354, 746, 310, 238, 699, 525, 46, 336, 487, 256, 503, 134, + 100, 546, 393, 722, 268, 367, 314, 943, 75, 106, 345, 629, 987, 396, 600, 208, 908, 429, 384, 523, + 92, 130, 545, 355, 277, 990, 668, 673, 351, 991, 853, 719, 863, 449, 312, 84, 100, 616, 532, 211, + 567, 707, 836, 737, 370, 847, 989, 452, 461, 316, 912, 974, 182, 746, 268, 796, 160, 522, 771, 618, + 22, 115, 854, 727, 644, 226, 17, 165, 779, 200, 911, 830, 855, 742, 137, 187, 983, 705, 717, 671, + 565, 785, 719, 886, 253, 962, 785, 657, 154, 293, 196, 620, 253, 144, 447, 173, 899, 796, 5, 72, + 325, 678, 616, 80, 309, 793, 175, 685, 159, 637, 123, 967, 838, 241, 715, 898, 550, 693, 230, 372, + 82, 601, 627, 721, 324, 398, 927, 553, 103, 72, 17, 174, 966, 978, 159, 325, 177, 558, 593, 185, + 372, 505, 393, 859, 599, 651, 745, 573, 377, 321, 865, 349, 591, 400, 553, 890, 440, 844, 345, 885, + 593, 933, 290, 980, 908, 448, 544, 989, 377, 50, 456, 332, 781, 900, 110, 716, 495, 747, 896, 444, + 806, 6, 700, 394, 548, 285, 340, 703, 29, 450, 829, 652, 630, 771, 546, 485, 613, 534, 972, 559, + 116, 481, 313, 507, 904, 434, 971, 343, 607, 42, 794, 784, 169, 865, 896, 421, 507, 415, 916, 871, + 431, 539, 339, 162, 147, 105, 224, 481, 112, 595, 580, 115, 834, 350, 134, 964, 948, 287, 201, 232, + 488, 154, 396, 602, 797, 539, 478, 943, 769, 872, 574, 121, 485, 652, 339, 811, 721, 747, 451, 362, + 821, 340, 744, 910, 0, 206, 594, 572, 277, 505, 120, 973, 680, 961, 757, 354, 555, 627, 847, 849, + 517, 971, 379, 910, 505, 410, 904, 770, 246, 63, 243, 874, 394, 396, 430, 482, 214, 619, 244, 646, + 524, 557, 399, 328, 172, 67, 304, 884, 620, 512, 594, 972, 535, 6, 698, 513, 159, 882, 750, 562, + 809, 764, 454, 366, 75, 506, 93, 786, 167, 831, 16, 382, 853, 638, 494, 452, 324, 72, 78, 83, + 52, 59, 112, 932, 10, 929, 342, 924, 730, 961, 680, 69, 287, 797, 961, 985, 92, 854, 626, 885, + 912, 600, 616, 389, 860, 232, 744, 793, 744, 179, 478, 773, 615, 689, 508, 775, 914, 494, 810, 139, + 288, 234, 974, 431, 129, 780, 581, 371, 548, 22, 868, 653, 981, 741, 270, 815, 623, 428, 653, 139, + 626, 603, 990, 315, 386, 344, 323, 889, 472, 317, 164, 260, 239, 861, 189, 377, 865, 511, 231, 304, + 356, 70, 152, 35, 825, 854, 328, 576, 390, 490, 848, 326, 38, 303, 402, 431, 616, 813, 546, 708, + 206, 388, 2, 962, 783, 967, 890, 442, 815, 49, 831, 831, 665, 251, 410, 321, 94, 741, 246, 179, + 422, 176, 211, 117, 675, 523, 9, 764, 374, 952, 426, 704, 64, 531, 53, 804, 758, 23, 811, 611, + 500, 846, 437, 375, 335, 854, 328, 971, 237, 24, 415, 639, 468, 318, 684, 723, 565, 662, 305, 647, + 449, 281, 597, 158, 136, 294, 882, 885, 383, 734, 938, 866, 268, 471, 115, 296, 908, 673, 50, 472, + 952, 439, 366, 5, 397, 155, 257, 506, 231, 948, 667, 600, 35, 445, 990, 222, 443, 784, 213, 349, + 389, 943, 13, 150, 621, 366, 52, 444, 612, 604, 934, 720, 953, 340, 828, 972, 462, 911, 621, 321, + 812, 435, 522, 50, 672, 78, 57, 761, 313, 950, 352, 238, 55, 27, 972, 226, 753, 201, 416, 176, + 879, 877, 864, 450, 572, 879, 163, 99, 721, 143, 12, 31, 643, 812, 507, 771, 968, 527, 781, 488, + 840, 797, 242, 194, 630, 293, 810, 966, 795, 276, 435, 345, 885, 413, 599, 197, 696, 386, 643, 116, + 93, 322, 710, 680, 785, 538, 112, 553, 581, 960, 12, 874, 923, 48, 615, 506, 652, 898, 359, 539, + 261, 495, 233, 764, 609, 805, 686, 286, 539, 432, 118, 836, 560, 192, 739, 825, 20, 778, 317, 586, + 976, 359, 573, 352, 386, 746, 772, 11, 663, 749, 504, 5, 212, 408, 888, 643, 907, 441, 420, 368, + 737, 97, 516, 169, 25, 359, 219, 527, 797, 672, 716, 69, 452, 880, 692, 298, 683, 300, 459, 327, + 815, 923, 323, 829, 612, 816, 247, 497, 116, 243, 352, 981, 281, 917, 738, 713, 290, 653, 909, 503, + 645, 406, 625, 543, 932, 108, 220, 304, 685, 464, 373, 954, 876, 86, 646, 802, 412, 446, 955, 28, + 664, 539, 850, 655, 783, 28, 392, 470, 707, 735, 422, 941, 523, 610, 682, 451, 37, 672, 156, 237, + 43, 766, 767, 713, 124, 409, 549, 869, 814, 186, 251, 475, 214, 568, 212, 44, 572, 997, 898, 139, + 956, 456, 608, 470, 651, 566, 434, 408, 906, 756, 970, 573, 640, 877, 687, 24, 642, 506, 265, 368, + 271, 399, 972, 950, 814, 109, 824, 595, 121, 856, 465, 516, 468, 473, 631, 793, 281, 736, 416, 708, + 315, 978, 235, 530, 626, 419, 296, 548, 502, 854, 28, 184, 668, 786, 326, 228, 578, 738, 881, 265, + 304, 808, 415, 490, 0, 623, 199, 483, 934, 105, 212, 545, 535, 154, 40, 473, 528, 712, 835, 668, + 349, 235, 338, 307, 230, 334, 872, 522, 374, 225, 143, 746, 996, 144, 385, 136, 848, 545, 487, 434, + 587, 837, 8, 456, 487, 434, 729, 114, 944, 971, 688, 316, 871, 667, 156, 304, 624, 813, 269, 729, + 47, 538, 250, 756, 491, 838, 882, 404, 213, 56, 231, 471, 326, 758, 132, 493, 644, 327, 421, 992, + 327, 435, 57, 651, 676, 352, 519, 199, 776, 354, 235, 648, 647, 3, 95, 842, 260, 345, 713, 912, + 198, 781, 493, 632, 943, 142, 86, 615, 222, 95, 843, 743, 337, 942, 752, 87, 53, 121, 86, 263, + 889, 580, 269, 666, 187, 68, 731, 230, 538, 72, 759, 330, 961, 547, 606, 593, 10, 320, 560, 798, + 122, 32, 957, 646, 288, 450, 604, 161, 128, 880, 109, 220, 175, 818, 590, 425, 413, 217, 346, 205, + 249, 63, 635, 858, 514, 14, 799, 766, 882, 610, 939, 375, 157, 120, 886, 963, 172, 983, 974, 755, + 922, 571, 323, 352, 783, 866, 832, 955, 100, 492, 772, 530, 751, 361, 696, 321, 650, 69, 986, 552, + 192, 55, 798, 91, 39, 563, 654, 564, 761, 544, 892, 167, 801, 122, 277, 25, 451, 829, 967, 781, + 361, 168, 64, 397, 928, 563, 914, 336, 536, 478, 243, 257, 264, 477, 879, 390, 640, 701, 208, 328, + 302, 443, 295, 521, 813, 914, 573, 118, 345, 525, 964, 508, 482, 30, 606, 416, 101, 71, 121, 92, + 435, 284, 453, 161, 20, 361, 70, 414, 23, 804, 255, 839, 276, 586, 890, 36, 427, 246, 542, 865, + 622, 953, 699, 366, 773, 803, 296, 133, 277, 529, 104, 229, 80, 462, 632, 260, 815, 37, 851, 237, + 732, 243, 393, 866, 760, 196, 126, 631, 168, 301, 843, 613, 189, 333, 589, 247, 936, 197, 256, 594, + 232, 956, 75, 306, 190, 329, 424, 153, 751, 690, 757, 805, 876, 539, 48, 122, 857, 473, 770, 388, + 638, 125, 488, 973, 176, 203, 474, 693, 461, 82, 606, 432, 923, 70, 0, 371, 632, 206, 280, 604, + 928, 686, 300, 120, 451, 795, 703, 810, 711, 708, 620, 357, 443, 98, 789, 903, 611, 93, 231, 376, + 530, 299, 791, 1, 732, 298, 289, 131, 726, 834, 806, 249, 172, 709, 898, 123, 456, 5, 942, 462, + 607, 322, 801, 208, 503, 421, 741, 183, 806, 258, 633, 533, 950, 594, 948, 31, 40, 984, 353, 213, + 195, 50, 794, 978, 700, 217, 287, 821, 267, 734, 774, 554, 650, 361, 199, 236, 263, 99, 316, 810, + 946, 984, 940, 891, 603, 180, 834, 333, 639, 286, 522, 33, 256, 202, 418, 467, 266, 716, 918, 126, + 786, 695, 782, 408, 529, 921, 494, 207, 301, 925, 195, 804, 391, 951, 730, 552, 912, 432, 798, 33, + 472, 262, 826, 748, 367, 835, 115, 373, 233, 351, 850, 910, 854, 688, 551, 883, 857, 24, 314, 555, + 822, 986, 422, 917, 175, 172, 470, 354, 830, 208, 311, 834, 206, 653, 144, 823, 106, 126, 638, 689, + 134, 307, 623, 804, 439, 423, 913, 349, 602, 424, 996, 430, 555, 144, 481, 756, 226, 990, 325, 207, + 851, 302, 535, 825, 134, 849, 204, 683, 695, 556, 791, 763, 169, 533, 623, 194, 86, 724, 484, 440, + 92, 870, 471, 86, 538, 47, 303, 819, 777, 652, 702, 900, 530, 522, 459, 321, 913, 559, 963, 963, + 685, 369, 327, 470, 164, 284, 437, 957, 148, 616, 2, 108, 106, 296, 743, 121, 304, 131, 694, 935, + 503, 937, 40, 883, 39, 899, 70, 229, 637, 654, 843, 866, 259, 252, 531, 52, 492, 969, 693, 419, + 278, 777, 970, 442, 546, 456, 503, 69, 955, 129, 697, 623, 842, 359, 325, 515, 223, 527, 84, 469, + 732, 724, 319, 104, 703, 789, 980, 109, 446, 830, 892, 23, 689, 884, 100, 790, 196, 509, 343, 828, + 637, 580, 367, 847, 48, 435, 860, 292, 696, 523, 724, 908, 191, 805, 392, 951, 510, 163, 975, 258, + 569, 922, 723, 232, 692, 328, 49, 654, 48, 35, 88, 450, 900, 854, 485, 700, 424, 515, 759, 543, + 441, 631, 57, 346, 637, 814, 405, 885, 632, 609, 147, 952, 446, 919, 371, 154, 995, 814, 965, 875, + 729, 993, 734, 767, 467, 163, 690, 480, 293, 685, 687, 104, 433, 942, 363, 28, 725, 163, 738, 330, + 370, 129, 741, 952, 444, 241, 309, 380, 279, 336, 337, 607, 503, 132, 517, 368, 882, 87, 539, 687, + 146, 233, 336, 457, 789, 246, 78, 192, 367, 73, 856, 990, 423, 945, 82, 967, 921, 980, 87, 553, + 534, 33, 628, 565, 342, 326, 572, 430, 563, 108, 990, 429, 517, 178, 139, 847, 928, 518, 770, 160, + 291, 75, 224, 297, 564, 234, 704, 948, 382, 163, 596, 163, 675, 420, 231, 70, 604, 366, 722, 886, + 746, 635, 819, 733, 59, 372, 722, 874, 256, 26, 677, 451, 440, 204, 585, 435, 474, 580, 667, 548, + 93, 813, 333, 49, 924, 508, 208, 373, 769, 682, 877, 448, 823, 47, 452, 274, 321, 665, 599, 49, + 866, 570, 286, 442, 690, 385, 101, 478, 215, 713, 539, 238, 659, 344, 146, 142, 454, 289, 340, 764, + 774, 518, 540, 977, 579, 222, 726, 7, 746, 637, 597, 827, 767, 358, 470, 55, 415, 509, 858, 120, + 845, 984, 564, 584, 58, 755, 967, 919, 814, 110, 977, 972, 423, 34, 933, 699, 810, 94, 87, 209, + 362, 393, 526, 620, 121, 994, 676, 983, 367, 698, 236, 500, 684, 97, 500, 185, 617, 155, 47, 89, + 618, 421, 185, 340, 374, 857, 236, 765, 860, 689, 694, 441, 685, 932, 582, 271, 4, 114, 660, 955, + 404, 270, 635, 630, 721, 596, 631, 769, 468, 95, 153, 983, 0, 408, 689, 292, 220, 586, 430, 669, + 524, 188, 965, 910, 334, 575, 996, 506, 189, 133, 273, 525, 542, 881, 75, 916, 663, 610, 461, 956, + 943, 219, 281, 195, 347, 995, 136, 589, 142, 708, 270, 3, 867, 468, 45, 742, 844, 963, 413, 860, + 451, 635, 798, 906, 837, 380, 148, 279, 133, 343, 579, 170, 439, 735, 342, 918, 795, 736, 133, 859, + 650, 486, 856, 63, 431, 677, 686, 670, 198, 123, 512, 572, 878, 888, 346, 340, 606, 826, 844, 375, + 510, 824, 201, 219, 227, 201, 338, 522, 997, 76, 609, 922, 904, 270, 326, 809, 328, 285, 83, 630, + 550, 92, 369, 957, 719, 980, 784, 494, 472, 231, 734, 408, 917, 415, 886, 36, 728, 116, 526, 844, + 659, 493, 959, 395, 112, 758, 154, 664, 744, 156, 99, 767, 668, 620, 51, 747, 239, 97, 737, 399, + 751, 458, 16, 47, 847, 557, 937, 72, 744, 848, 78, 706, 348, 33, 505, 83, 520, 695, 572, 661, + 322, 123, 447, 349, 584, 433, 951, 905, 97, 416, 123, 421, 659, 843, 923, 933, 938, 291, 961, 861, + 145, 367, 714, 153, 66, 697, 744, 657, 477, 511, 602, 445, 950, 553, 278, 96, 937, 555, 368, 415, + 748, 143, 741, 771, 862, 990, 8, 295, 396, 17, 119, 236, 508, 285, 844, 914, 97, 235, 906, 118, + 83, 405, 190, 618, 438, 438, 706, 413, 546, 214, 807, 540, 360, 162, 426, 42, 852, 258, 765, 147, + 550, 13, 547, 704, 227, 733, 678, 587, 623, 795, 309, 538, 920, 372, 971, 929, 590, 466, 749, 42, + 662, 794, 545, 57, 747, 828, 231, 287, 655, 443, 148, 600, 71, 209, 453, 494, 560, 542, 835, 46, + 608, 971, 13, 600, 370, 662, 139, 818, 174, 618, 209, 609, 457, 373, 907, 959, 833, 382, 175, 136, + 374, 157, 417, 761, 312, 710, 389, 746, 155, 238, 941, 567, 450, 717, 282, 408, 997, 194, 918, 799, + 282, 750, 960, 604, 194, 310, 798, 141, 124, 492, 40, 439, 62, 389, 878, 731, 318, 580, 199, 379, + 512, 359, 710, 188, 909, 639, 339, 96, 542, 393, 178, 204, 590, 696, 183, 247, 618, 413, 971, 539, + 702, 430, 715, 949, 425, 760, 971, 207, 956, 373, 144, 106, 921, 591, 16, 774, 796, 179, 924, 709, + 966, 993, 625, 757, 6, 357, 6, 778, 58, 162, 524, 265, 247, 375, 595, 545, 867, 973, 219, 170, + 709, 920, 700, 112, 344, 213, 455, 321, 939, 165, 157, 883, 99, 258, 140, 515, 217, 311, 84, 660, + 715, 504, 149, 198, 566, 341, 521, 474, 351, 951, 546, 183, 603, 876, 538, 901, 754, 363, 893, 973, + 913, 244, 192, 799, 362, 155, 702, 637, 628, 415, 599, 177, 686, 718, 604, 550, 153, 242, 790, 152, + 603, 168, 465, 779, 781, 511, 172, 789, 445, 618, 502, 270, 45, 696, 185, 927, 71, 970, 448, 519, + 201, 918, 190, 958, 174, 835, 941, 916, 255, 575, 693, 976, 150, 665, 612, 452, 227, 259, 784, 568, + 780, 395, 783, 102, 179, 124, 52, 52, 824, 868, 328, 763, 679, 574, 300, 905, 404, 139, 955, 280, + 976, 246, 122, 692, 679, 276, 158, 735, 126, 525, 736, 824, 910, 660, 87, 908, 725, 523, 532, 92, + 473, 876, 886, 500, 715, 258, 458, 28, 768, 219, 382, 504, 883, 10, 716, 783, 241, 519, 576, 892, + 372, 241, 239, 419, 944, 465, 105, 586, 466, 234, 54, 194, 173, 833, 649, 560, 386, 589, 983, 692, + 652, 101, 332, 790, 640, 50, 67, 397, 773, 700, 282, 691, 728, 675, 711, 631, 81, 788, 868, 618, + 635, 265, 892, 617, 11, 764, 624, 990, 609, 58, 615, 781, 480, 939, 461, 611, 163, 184, 465, 314, + 470, 698, 619, 789, 117, 3, 311, 456, 186, 203, 721, 932, 768, 502, 143, 904, 730, 201, 423, 417, + 947, 154, 568, 261, 473, 775, 380, 615, 786, 193, 710, 445, 469, 943, 729, 204, 564, 117, 142, 568, + 342, 854, 790, 984, 824, 297, 982, 834, 21, 944, 482, 759, 312, 2, 512, 659, 599, 860, 803, 4, + 961, 790, 458, 362, 380, 90, 771, 389, 291, 209, 630, 440, 845, 255, 435, 550, 71, 925, 733, 659, + 899, 770, 914, 791, 60, 993, 984, 955, 244, 55, 935, 877, 960, 708, 628, 374, 144, 871, 8, 407, + 438, 591, 590, 124, 164, 402, 195, 757, 242, 435, 238, 136, 675, 569, 455, 48, 984, 938, 717, 381, + 82, 776, 595, 69, 112, 421, 361, 626, 719, 664, 253, 694, 944, 281, 451, 196, 345, 699, 721, 829, + 469, 368, 20, 825, 986, 436, 40, 577, 702, 199, 403, 623, 655, 33, 577, 927, 48, 993, 19, 741, + 107, 221, 193, 932, 70, 832, 172, 355, 396, 210, 191, 54, 477, 861, 755, 198, 434, 199, 481, 52, + 928, 347, 371, 949, 162, 11, 757, 593, 473, 558, 744, 494, 204, 113, 53, 511, 56, 924, 319, 185, + 102, 712, 721, 475, 548, 626, 546, 4, 280, 884, 765, 709, 159, 811, 706, 732, 944, 730, 429, 237, + 956, 924, 75, 24, 985, 357, 143, 86, 440, 209, 838, 576, 813, 81, 262, 809, 761, 310, 483, 447, + 743, 631, 464, 658, 233, 43, 279, 893, 199, 274, 380, 771, 237, 815, 88, 75, 530, 729, 761, 746, + 506, 900, 978, 311, 694, 480, 480, 82, 997, 729, 26, 627, 370, 540, 750, 24, 300, 664, 212, 750, 374, 72, 211, 540, 554, 230, 622, 780, 364, 284, 954, 266, 382, 630, 916, 299, 909, 877, 136, 485 }; diff --git a/test/benchmarks/memcpy/memcpy.c b/test/benchmarks/memcpy/memcpy.c index 6960573b7..7ea906baf 100644 --- a/test/benchmarks/memcpy/memcpy.c +++ b/test/benchmarks/memcpy/memcpy.c @@ -9,8 +9,8 @@ // the memcpy_gendata.pl perl script and dumped to a file named // dataset1.h. -#include #include "util.h" +#include //-------------------------------------------------------------------------- // Input/Reference Data @@ -20,21 +20,21 @@ //-------------------------------------------------------------------------- // Main -int main( int argc, char* argv[] ) -{ +int main( int argc, char* argv[] ) { int results_data[DATA_SIZE]; #if PREALLOCATE // If needed we preallocate everything in the caches - memcpy(results_data, input_data, sizeof(int) * DATA_SIZE); + memcpy( results_data, input_data, sizeof( int ) * DATA_SIZE ); #endif // Do the riscv-linux memcpy //setStats(1); - memcpy(results_data, input_data, sizeof(int) * DATA_SIZE); //, DATA_SIZE * sizeof(int)); + memcpy( results_data, input_data, + sizeof( int ) * DATA_SIZE ); //, DATA_SIZE * sizeof(int)); //setStats(0); // Check the results - int v = verify( DATA_SIZE, results_data, input_data ); + int v = verify( DATA_SIZE, results_data, input_data ); return v; } diff --git a/test/benchmarks/memcpy/memcpy_gendata.pl b/test/benchmarks/memcpy/memcpy_gendata.pl index 4efc14579..6c10411d4 100755 --- a/test/benchmarks/memcpy/memcpy_gendata.pl +++ b/test/benchmarks/memcpy/memcpy_gendata.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl #========================================================================== # vvadd_gendata.pl # @@ -129,4 +129,3 @@ () } main(); - diff --git a/test/benchmarks/qsort/Makefile b/test/benchmarks/qsort/Makefile index 946c7d2d2..ab62c1bc0 100644 --- a/test/benchmarks/qsort/Makefile +++ b/test/benchmarks/qsort/Makefile @@ -3,7 +3,7 @@ # # makefile: big_loop.c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/benchmarks/qsort/dataset1.h b/test/benchmarks/qsort/dataset1.h index dd1c6340f..1e4610e83 100644 --- a/test/benchmarks/qsort/dataset1.h +++ b/test/benchmarks/qsort/dataset1.h @@ -1,219 +1,219 @@ // See LICENSE for license details. +// clang-format off +#define DATA_SIZE 2048 -#define DATA_SIZE 2048 - -type input_data[DATA_SIZE] = +type input_data[DATA_SIZE] = { - 89400484, 976015092, 1792756324, 721524505, 1214379246, 3794415, 402845420, 2126940990, 1611680320, 786566648, 754215794, 1231249235, 284658041, 137796456, 2041942843, 329767814, 1255524953, 465119445, 1731949250, 301663421, - 1335861008, 452888789, 14125900, 1231149357, 2002881120, 730845665, 1913581092, 1275331596, 843738737, 1931282005, 1492488573, 490920543, 2066865713, 25885333, 238278880, 1898582764, 250731366, 1612593993, 637659983, 1388759892, - 916073297, 1075762632, 675549432, 937987129, 1417415680, 1508705426, 1663890071, 1746476698, 686797873, 2109530615, 1459500136, 324215873, 1881253854, 1496277718, 810387144, 1212974417, 1020037994, 585169793, 2017191527, 556328195, - 1160036198, 1391095995, 1223583276, 1094283114, 436580096, 190215907, 603159718, 1513255537, 1631935240, 1440145706, 1303736105, 806638567, 1100041120, 1185825535, 1414141069, 2014090929, 419476096, 1273955724, 175753599, 1223475486, - 574236644, 2046759770, 492507266, 1721767511, 726141970, 1256152080, 2029909894, 1382429941, 1939683211, 791188057, 519699747, 1051184301, 1962689485, 706913763, 1776471922, 672906535, 2005817027, 1274190723, 2119425672, 835063788, - 421198539, 1169327477, 2064145552, 1396662140, 1218522465, 2105638337, 754247044, 2143968639, 1395289708, 1750443194, 1412540552, 170281493, 389233190, 448284065, 240618723, 2145930822, 1846605728, 1353999206, 140536987, 1821559709, - 619972089, 1514278798, 750919339, 2143343312, 304427548, 545066288, 1946004194, 1538069400, 1904770864, 924541465, 567779677, 893302687, 1239665569, 1157666831, 2105814934, 1505475223, 1636203720, 9736243, 518073650, 1063743848, - 1029176122, 215018112, 1073871430, 1858933377, 866478506, 1491477359, 477407584, 895562064, 954441852, 638167485, 1550159640, 614612685, 1453397990, 1334857284, 683536723, 168771888, 481561285, 755798022, 2016161810, 1162679490, - 619428858, 1390306889, 256860662, 365275089, 1322281086, 1134185180, 1302724177, 621921213, 837554186, 1711761015, 754896618, 1723143470, 978247260, 1548804416, 598016845, 1631405417, 790929190, 1602517354, 770957259, 198186681, - 1256015513, 2126029304, 135012885, 583112200, 2118203528, 1834388383, 866964848, 1695191950, 745183293, 1143511498, 1112731797, 478721193, 1202162389, 991159735, 1952364329, 519344323, 1667102296, 770412991, 548632788, 714042223, - 1674045273, 1471598258, 1286989824, 1590771096, 308832070, 959354209, 72802865, 670621648, 269167950, 1598436917, 2023498746, 1198213061, 2006856683, 1029832956, 1719009954, 1198254803, 1188748563, 1989240516, 927524181, 1711765426, - 1394929399, 769005536, 2047006719, 1915435344, 618681206, 1431814151, 42021322, 1106678970, 107160610, 1199317660, 185592115, 1870214195, 205008108, 1834318089, 948686793, 946311527, 1262399341, 131405125, 1321897861, 1459138745, - 821481684, 852388468, 603907009, 20643769, 1737931879, 37141933, 2088576982, 366700722, 1761289401, 625991894, 741078359, 817417567, 969305448, 1152416171, 1101933540, 399456957, 2074896270, 1971484382, 747592875, 1160333307, - 1738353358, 2113434968, 1896952705, 1908093581, 1155544307, 117766047, 2034767768, 1316120929, 1507433029, 2045407567, 765386206, 1031625002, 1220915309, 325667019, 1916602098, 16411608, 47463938, 1379995885, 1221108420, 721046824, - 1431492783, 1569479928, 909415369, 204514903, 933673987, 1565700239, 341674967, 602907378, 5309142, 849489374, 180599971, 1480437960, 532467027, 1958396887, 106223060, 1025117441, 935689637, 1752088215, 1704561346, 1568395337, - 1868289345, 569949159, 1045658065, 274746405, 890461390, 507848158, 793505636, 460893030, 1179525294, 388855203, 1113693824, 13887419, 1909681194, 1082499152, 1466632447, 1281443423, 612289854, 373305330, 568652142, 1383640563, - 1073695485, 745777837, 624939139, 1289308008, 1928550562, 148113917, 462743614, 1826880531, 1571598133, 1415390230, 1480273562, 1331593955, 540006359, 261556590, 1690167792, 283430575, 1194709162, 1781233744, 649754857, 1434046375, - 1135793759, 932423857, 1170759710, 1048943084, 692845661, 1620562432, 2036750157, 270410557, 617995659, 1347284277, 1771614266, 30992839, 655445946, 22762734, 1695617313, 867628573, 1577034674, 227870124, 2063408339, 1512163910, - 787913688, 1758748737, 1553547892, 2072440819, 632611704, 873623623, 2097057488, 1879635915, 1404727477, 1840896199, 1609955669, 186112992, 196401930, 130001148, 814302898, 1420810050, 226906236, 1435859758, 221330186, 329049266, - 820933470, 260792255, 1401058771, 210908782, 1774652096, 886978116, 1807085904, 508041515, 767233910, 26687179, 318750634, 910677024, 117260224, 2074840378, 301350822, 464795711, 2053899162, 1335298265, 737518341, 777433215, - 1147341731, 1981481446, 1628389501, 1537459540, 1121432739, 1392162662, 1800522575, 644293952, 1273223611, 1906345724, 28256901, 1467376771, 372465453, 78348530, 135678410, 1061864942, 260267972, 1184561748, 287497702, 1154842325, - 1629914848, 2084953915, 799717076, 1382484003, 2045821218, 933603111, 84924801, 892939912, 279252402, 651750790, 238566180, 942977997, 1822612008, 1849675857, 939497524, 436630343, 549253917, 1028937430, 579174666, 2124749673, - 880456526, 1451442832, 1350653461, 1546104436, 858045289, 2129513521, 1181191604, 727587915, 1619598456, 969076419, 1212628403, 1361078114, 368541415, 333906659, 41714278, 1390274260, 1563717683, 973769771, 1078197595, 918378387, - 1672192305, 1094531762, 92620223, 2125958841, 1620803320, 915948205, 174965839, 27377406, 435236973, 1038830638, 1834161399, 305750851, 330474090, 730422541, 1634445325, 840106059, 767880329, 109526756, 2027814180, 367923081, - 1983379601, 1293091635, 705851791, 226723092, 1067775613, 2082760612, 951663731, 260670135, 1111213862, 1891630185, 1379259015, 176024101, 594814862, 1870859970, 1689946986, 1290969161, 244975305, 1296857499, 1811088032, 1873900475, - 1949896838, 1907793490, 592006699, 1312471120, 509744705, 869853078, 70894786, 503368137, 1686479103, 1602967659, 1214950832, 1131661227, 768185796, 592234826, 1727583308, 949222447, 1760851607, 487888229, 1614780688, 1618378831, - 602368560, 2028116487, 183679578, 1561251584, 986240059, 1525451290, 977907387, 432609664, 1528031307, 116766659, 987761406, 1630293700, 90063199, 114202152, 543952312, 855107605, 812328969, 88823122, 1092881031, 304131252, - 1505022272, 894769708, 1849495275, 1607515830, 1032748996, 472872107, 1593359038, 1027760887, 1074205225, 1657001479, 1524491858, 387061281, 107095939, 1038018856, 798445606, 1486594282, 1878434988, 1558695709, 2033003588, 373226849, - 2133066804, 399991238, 1132597050, 1965358941, 1551661799, 3522194, 935939763, 2070467093, 500734709, 533101409, 1068798385, 998931662, 1500102591, 779093898, 66579049, 1121960111, 749415493, 502323961, 538932155, 259768753, - 753296935, 87897457, 539429964, 1675300017, 1232992084, 420106224, 1685350721, 346598567, 1610244183, 1597506096, 1079859867, 944382193, 1770497338, 764935753, 1776794410, 866854601, 365854486, 304211060, 344860208, 1361012693, - 1450892344, 622170346, 70003859, 1681866717, 435288306, 687941098, 308700094, 1367731096, 1834285819, 255226842, 193873940, 1833603743, 848402819, 152273285, 231181585, 1754447491, 1838218199, 834410115, 229905664, 2052321529, - 338532526, 77482422, 12937811, 35859252, 1645969422, 1501181424, 438711458, 1496078411, 419109342, 1455756978, 1234944834, 1287171290, 470090505, 1900162831, 1130850177, 1772760484, 381571915, 1605369007, 514914429, 994291574, - 1502557594, 1099847920, 1627355806, 1148699143, 1519017268, 946489895, 106595511, 921573402, 181567810, 1575380740, 1719573683, 1561730727, 1920182565, 1510133268, 1102603775, 1175885101, 802730854, 185979744, 1058937717, 1716853034, - 31596852, 462857778, 1335652095, 47036070, 178901145, 1399673078, 222529745, 128036841, 1708126014, 923768127, 1980923963, 1413860940, 1382551511, 208160226, 1892370478, 2091626028, 1793190956, 1417601340, 515811664, 2076612603, - 993525189, 1127173529, 245334962, 134453363, 1206302514, 1344125357, 1139159604, 651536866, 22136821, 1536213818, 2143324534, 879878312, 1944679691, 119285206, 832081018, 1566878909, 876130333, 656954306, 226726100, 937976428, - 1202009920, 1938258683, 2014129292, 1274436639, 1102423908, 1485740112, 879552408, 1712269139, 650513248, 1068587688, 434850545, 382422699, 919736727, 2022291557, 1319798607, 2139976479, 772059719, 1033910502, 1120963974, 340231765, - 1471131758, 1767380006, 47452797, 1313871880, 399114073, 1462921857, 671848647, 31574181, 230340298, 239990424, 590690783, 1714295540, 833019845, 398244682, 522160389, 900852, 1045627895, 1545555937, 226986415, 208433088, - 1502480836, 1611500622, 1933923245, 1588715179, 1655277291, 1749972876, 1386258142, 935490932, 173822937, 702380578, 348131466, 81402251, 875481479, 72939206, 2033828953, 1302272656, 64795664, 2010549018, 1652108025, 58217952, - 1871684562, 190536346, 244709448, 949010757, 320137025, 729474445, 133790520, 740536012, 316479300, 1191513656, 1802197319, 785398708, 1816641611, 2052328978, 930367387, 1374125186, 303845878, 852835634, 454359988, 2131761201, - 1757028186, 536063430, 1765354961, 726869128, 1209784819, 1790557628, 783427298, 2094085507, 1323798820, 846127236, 1065481253, 572240371, 1745543275, 1011417836, 1970797151, 748527394, 343119399, 723323690, 925975225, 901789102, - 1726987516, 535828217, 387611445, 464171383, 1170510314, 1166227930, 1807172811, 1942089394, 985305323, 1368235387, 1691486500, 1568900638, 1876255297, 1249183285, 1710305778, 1763785295, 1733366374, 1444076976, 1629633514, 2105321510, - 225091211, 898893218, 863551327, 1441811554, 546340809, 1977865396, 2116495484, 1221726287, 293109484, 1601617797, 1568176414, 1424797596, 1256372950, 298799048, 1708002892, 829450571, 891710357, 1994402695, 1136264020, 372280769, - 1520667645, 983043723, 1191079043, 680172541, 813511681, 395360213, 1648575360, 1026342885, 2100497812, 422047044, 509116230, 859612092, 2037182006, 895080280, 494367164, 1732028080, 355614494, 2141591317, 1087251698, 580692625, - 225934851, 1581062145, 1515262458, 1497680539, 1711718534, 1774796872, 301673313, 1136356724, 653050943, 109035776, 1709823304, 1340949553, 1365423458, 1155459206, 1203897636, 188016786, 256210446, 633075975, 19227407, 1864952910, - 1143853106, 237020443, 1750197960, 856837002, 80321564, 1679324299, 1257507406, 1390040163, 1590461855, 806384435, 1331383316, 2027828650, 1649392096, 1928309762, 1027758817, 1267173039, 123889599, 95752736, 2060969286, 619461174, - 1686215900, 1817156134, 2118821565, 1596821127, 1800186189, 212821393, 661318748, 1123331233, 146002907, 953877041, 1771924274, 929351822, 2142357746, 356638683, 1610539590, 2001056977, 368889391, 62209567, 1775608361, 992410365, - 1336108161, 696448050, 333820982, 585804640, 1775805177, 809604334, 93191015, 732444124, 1492071476, 1930662128, 174082258, 340442582, 507936866, 362748128, 1607204293, 953383750, 1599876594, 416457166, 571635069, 1356847855, - 267174620, 2011827638, 1572212863, 589049769, 2024853642, 1680251429, 914906004, 398911194, 795915364, 1332467446, 688483428, 628445699, 578787063, 2006320950, 1167207852, 336213879, 1640952769, 1778544166, 1617229086, 190807078, - 1968608155, 2122852959, 31153367, 1353144470, 2196420, 1395155215, 1948121717, 69118708, 2140091269, 2530146, 1740778973, 1601247294, 1205895814, 858150908, 1878253960, 1967705762, 2090543533, 1702425249, 622114437, 1192155877, - 1095403694, 2115445751, 1201124879, 1140728569, 2085323316, 1291025252, 871908043, 863647665, 1245819051, 1468486929, 631022494, 1161580432, 539942311, 1943137808, 1826628136, 259775677, 277497333, 2140756121, 973493986, 1121800211, - 1539560507, 1337406065, 186178768, 482917205, 1459100749, 1924603748, 390743779, 1140008063, 517767440, 1764436465, 722260205, 1400929335, 1706528514, 486165509, 1379460673, 206653795, 3159407, 565150174, 688338919, 1223572435, - 2122262571, 513009937, 1390656632, 271906847, 1622692876, 1313115559, 2061144988, 411864717, 437710825, 513582947, 305489695, 1713188647, 387273799, 1901537567, 644842409, 1231932661, 356672421, 232170581, 1636860706, 302219842, - 2094591332, 1697686200, 1390477985, 1833543700, 1203377492, 50968578, 1332379148, 1514582723, 909273561, 1914809801, 560663378, 1032914339, 1216475831, 113462155, 1165446977, 800591831, 1058677375, 432102601, 2131797509, 1175004233, - 1602827413, 878884686, 446372159, 257728183, 800661980, 1387864976, 2004770236, 999229412, 1428223489, 175843632, 74887898, 630393584, 1147793249, 112648605, 1028529524, 1891904961, 1953919896, 481563348, 436476038, 1601134240, - 72319656, 1581118537, 460420451, 1904576737, 786297537, 359735266, 1918354829, 4031164, 1679777458, 1144017176, 1462192184, 690865719, 1515933932, 363508800, 1480324438, 1044088643, 2036061488, 218671081, 830595166, 381933797, - 108346070, 92271196, 217762975, 1522316172, 1021014457, 1407094080, 857894203, 1968623233, 1459620801, 1345014111, 709651138, 520511102, 2048560397, 1768795266, 1013901419, 1709697877, 1026380990, 1377995642, 1560142576, 542609105, - 1534330971, 528024121, 2015847175, 325324443, 1137511396, 1883999260, 1871060346, 715940689, 167653495, 1292049996, 1172290275, 2018336444, 1951228823, 1666074170, 1834852613, 854475547, 308857120, 502558280, 2105718728, 1624653209, - 514214340, 976063110, 227427283, 912381406, 785989696, 451448729, 212046016, 2068743361, 117280545, 1936668087, 210748671, 1984152603, 945948973, 1409001936, 1644353864, 1139018167, 678475375, 1279061703, 723930558, 195379046, - 1498554338, 999346398, 1665914525, 1473735214, 1561422777, 151416112, 697817760, 1622758049, 607761482, 69889880, 1152335090, 1063657548, 1338090388, 55461678, 1278053582, 837024327, 1914764659, 1049475248, 161502390, 80404202, - 624714335, 879380479, 1066787659, 1375470750, 1561212123, 59384706, 966363087, 2044016080, 1178086274, 1159745061, 291298358, 173062659, 1385675177, 652078020, 1802327778, 1555660285, 623909040, 1579725218, 1649344003, 270814499, - 350182379, 1188076819, 893957771, 534384094, 1057003814, 230634042, 2117880007, 778834747, 250859482, 104637677, 1328272543, 1869264274, 1847908587, 311127477, 506466155, 1808237662, 607471900, 1558244592, 1228817775, 720339756, - 1963053072, 1011473945, 1204992245, 566166447, 419053054, 737377568, 520329478, 1740099311, 1682700783, 1455316979, 2118805956, 729509794, 1565610678, 722347551, 739596391, 882282387, 926200942, 999899279, 1318032594, 122124863, - 1633512617, 1269707634, 380070610, 1043920511, 665601851, 873976891, 717911282, 2135673182, 761851297, 1604330946, 666624765, 513561613, 1504023310, 1128895624, 99511825, 722919148, 1047336724, 550532376, 1082864732, 289686472, - 216557804, 1174587016, 845698678, 1554106660, 577410402, 790256415, 675663963, 2029133999, 161450336, 228960529, 743745539, 1352833750, 2123379476, 852338021, 1291070368, 448708980, 1953450944, 923478775, 827496819, 1126017956, - 197964832, 281317274, 1171925835, 764902582, 595717488, 2129930580, 1437147036, 1447469119, 755554593, 2130879949, 1835203128, 1547662666, 1855359256, 965490116, 672323245, 182598318, 216435361, 1324723894, 1144669754, 454438520, - 1220523503, 1520886946, 1797641070, 1585050246, 797060176, 1821482472, 2128078174, 973367349, 991874801, 679519053, 1961647235, 2094159153, 391321675, 1604357658, 576906032, 1712341869, 344515114, 1122768484, 1659079595, 1328885292, - 48775768, 247448424, 1836119534, 1564061243, 1386366954, 485818381, 37017340, 356546370, 1675494182, 430093707, 1959222232, 1784682542, 1839063567, 1596042792, 295666215, 403378386, 2114587535, 1515528736, 1541546082, 1444048519, - 1215103809, 1687941280, 1546057655, 1905279500, 544899032, 2069178089, 1688652157, 1414160501, 332201519, 631936923, 423299667, 1332937015, 545602285, 310273032, 960982228, 372501343, 1933532372, 1711569347, 11476473, 155845605, - 700725671, 1457464894, 1325083914, 172109594, 664387510, 1705378439, 376781122, 1472567100, 343682568, 1370528050, 265363198, 2079492652, 1803183394, 519194709, 1538391713, 1931493432, 1183464058, 1489699243, 495097609, 801046035, - 177100916, 1292413659, 1348373925, 1550525411, 697685269, 856621012, 1992941115, 1189141368, 221661515, 156760399, 38620214, 375863194, 2078528215, 2103236982, 341987235, 698660475, 381094614, 1201152163, 1275500498, 398211404, - 801610475, 1087556673, 846650758, 1848681194, 1287830283, 1400070607, 1603428054, 1233022905, 810516965, 690710531, 1860435620, 750631050, 1271370220, 860360715, 1189323192, 1913926325, 946425090, 1815408878, 743572345, 1902501708, - 1276205250, 2005653265, 624614472, 2108439398, 1952177514, 964348374, 1171051384, 2126963607, 812288356, 108628319, 980702956, 714456194, 1678967663, 1935271536, 236851791, 1541132933, 1066014062, 1607628402, 1926717418, 954942098, - 1733982669, 14239125, 1506716966, 848141854, 1178260876, 614222093, 731606176, 1512135729, 63244522, 968848252, 1783943137, 1402735006, 1355391150, 1659137391, 1173889730, 1042942541, 1318900244, 1149113346, 2090025563, 1201659316, - 250022739, 1035075488, 674580901, 1090386021, 1943651015, 934048997, 2087660971, 738682048, 1305071296, 91177380, 1708106609, 1685880008, 364589031, 1860839427, 1927367009, 906899219, 1090443335, 892574149, 1969729134, 1874026715, - 927045887, 1159898528, 730296520, 349249331, 317980803, 225908941, 483348027, 1035956563, 241537930, 1279981214, 1247518755, 247447060, 1793747608, 752388169, 288054543, 2073482870, 2039012903, 617768643, 433412593, 499898207, - 1050512245, 331284679, 851322111, 1294873695, 1715379173, 1159675637, 1029338154, 2027445678, 1653332243, 1874855959, 1234157881, 260674360, 1042790263, 1401980800, 730090881, 1745393357, 1550721460, 1607677838, 969500483, 778702716, - 1765830270, 731763278, 1600023202, 1957728250, 690983, 444361278, 1278777407, 1231639101, 597427397, 1087245613, 258177907, 2093472294, 1462778368, 2067100479, 1628387880, 762564955, 1194041213, 1348361229, 1822279764, 1826590258, - 1112056034, 2088786920, 815110420, 1957877704, 1087195269, 881982271, 1945110368, 1656527154, 529233847, 137046551, 522408049, 1880577483, 847255974, 851716534, 925604268, 1037521069, 461527795, 1332620900, 525605961, 1389787451, - 1127911377, 1198857033, 859385989, 706825946, 371790550, 145611377, 655200896, 1900613055, 1333790305, 1101722351, 1278794420, 2089981667, 1150780072, 13180701, 1502266386, 1103013140, 343038558, 1897907456, 1612609979, 1209991461, - 1740783613, 1643991754, 977454680, 787842886, 163362230, 1087742330, 200253206, 1691676526, 360632817, 1787338655, 35595330, 822635252, 1834254978, 1372169786, 1063768444, 973490494, 697866347, 156498369, 169293723, 180549009, - 112035400, 127867199, 241711645, 2004664325, 23288667, 1997381015, 736455241, 1986921372, 1570645300, 2067499753, 1463269859, 148527979, 618168829, 1715279374, 2066440075, 2118433006, 198233440, 1835860030, 1345873587, 1902595458, - 1961619988, 1291438802, 1325008187, 836983022, 1849657867, 500376868, 1599565995, 1705905941, 1600493361, 386733714, 1028820236, 1663100626, 1322696419, 1482983072, 1092382563, 1667679197, 1965855212, 1063839036, 1742032331, 300191208, - 620497725, 503895325, 2094864173, 928179911, 277942057, 1677449797, 1249086623, 799527371, 1180063064, 48311975, 1866094167, 1405763119, 2109851473, 1594621666, 580464203, 1752598186, 1339293088, 922186026, 1403771494, 299505702, - 1345987999, 1298200648, 2128826472, 677220745, 831273447, 741184696, 696188251, 1912065710, 1016469330, 682018288, 353946286, 559509624, 515414188, 1852181952, 407771887, 812094461, 1859683061, 1100089300, 498702377, 653626077, - 765701205, 150878039, 328551896, 77104822, 1775331228, 1835977906, 706357381, 1240287664, 839507573, 1054066034, 1823053058, 701959731, 82879528, 652404808, 866097476, 926939064, 1326017288, 1747861289, 1173840088, 1524006589, - 443704960, 835506582, 5363460, 2068343250, 1683915700, 2080735477, 1913489530, 951256529, 1752318678, 105384223, 1788389051, 1787391786, 1430821640, 540952308, 882484999, 690806365, 202502890, 1593837351, 530093821, 385878401, - 907401151, 378912543, 454746323, 251514112, 1451277631, 1125822965, 21289266, 1642884452, 804368379, 2048205721, 917508270, 1514792012, 139494505, 1143168018, 115016418, 1730333306, 1630776459, 50748643, 1745247524, 1313640711, - 1076198976, 1820281480, 941471466, 806673335, 722162727, 1837280287, 705508794, 2088955494, 510497580, 51692325, 893597382, 1373978529, 1007042224, 685006165, 1471461419, 1555325521, 1215063385, 1424859828, 657251271, 1391827090, - 965562483, 604275115, 1285258674, 341475746, 294191106, 633240394, 1897691227, 1904243956, 823532901, 1577955754, 2016464961, 1862876260, 577384103, 1012611702, 247243083, 636485510, 1952805989, 1447876480, 108021700, 1016615447, - 2047769687, 943871886, 787537653, 12744598, 853545598, 334037304, 553373537, 1089408490, 497867498, 2038925801, 1434633879, 1290629443, 75922980, 957037315, 2130252471, 477317888, 952824381, 1686570783, 459340678, 751885764, - 836307572, 2027909489, 28791588, 322748588, 1335236478, 787106123, 113580144, 954915740, 1317077622, 1299667896, 2009244921, 1548588723, 2049698913, 732388681, 1781891230, 2090684129, 993786972, 1959292396, 1336513734, 691093904, - 1746904676, 935573751, 1123555638, 108413311, 1445352642, 169726789, 123352211, 1635952299, 673775121, 2042861943, 757787251, 512494446, 119656942, 58159196, 2090570016, 486181025, 1619641914, 432990571, 894937325, 379470588, - 1890938638, 1886317932, 1858637614, 969358207, 1230449468, 1890889527, 351741654, 214725897, 1550012286, 308005013, 26292400, 68067591, 1383307838, 1746273091, 1090104632, 1658037573, 2081544705, 1133473813, 1680294422, 1050373352, - 1806061681, 1713475126, 520699193, 417568373, 1355086853, 631399565, 1742434188, 2077667592, 1709019727, 594054971, 937081176, 742185643, 1904514273, 887841601, 1288684086, 424587711, 1497926365, 829844031, 1384314543, 250129297, - 200083737, 693737559, 1527022962, 1462501905, 1687540458, 1156824624, 241481265, 1190890142, 1250360726, 2064308502, 27563032, 1880483834, 1984143440, 104727360, 1324123626, 1089710430, 1403206383, 1930880552, 773197243, 1160186023, - 562994480, 1065136414, 502237764, 1642338733, 1310177444, 1730721241, 1475638246, 615734453, 1160537912, 928836931, 253898558, 1799210492, 1205522527, 413058646, 1589194592, 1774218355, 43955934, 1673314595, 683393460, 1260859787, - 2098829619, 772503535, 1232567659, 758174758, 831270563, 1605294199, 1660678300, 24379565, 1426483935, 1611558740, 1085326591, 12849216, 455856722, 878692218, 1910978116, 1382893830, 1950124297, 950009818, 904287249, 791384486, - 1584408128, 210098472, 1110387095, 364620240, 53868166, 772251062, 472745168, 1133910514, 1715402379, 1445225855, 1541125975, 149171217, 972058766, 1893095488, 1487620835, 640835502, 1470285405, 646688705, 988431201, 703130341, - 1753125385, 1985895474, 696002734, 1783233173, 1317201705, 1755204784, 532132334, 1069450170, 249700039, 524320231, 757959820, 2109052886, 604977130, 1971654864, 1588222158, 1533496974, 623670976, 1405668251, 1955436051, 1082881617, - 1387039848, 874153641, 1345378476, 1168465459, 2005021017, 234039217, 473318229, 654912216, 1473166451, 997649666, 801824335, 2052343947, 1883168929, 185658088, 1389954587, 1725541486, 885873448, 958774566, 2054212564, 60536525, - 1427504270, 1160285859, 1827651881, 1408805003, 1684018729, 61716770, 844057079, 1011596733, 1521350211, 1581801257, 907554175, 2022973269, 1125104871, 1312064004, 1466679625, 970194422, 80900939, 1445279202, 335456148, 510478312, - 92860378, 1646704157, 1650899832, 1533447203, 268087516, 880688023, 1180525723, 1868151949, 1750955971, 401446720, 540093580, 1022861633, 461442838, 1222554291, 456462271, 94760711, 1231111410, 2145073408, 1932108837, 300618464, + 89400484, 976015092, 1792756324, 721524505, 1214379246, 3794415, 402845420, 2126940990, 1611680320, 786566648, 754215794, 1231249235, 284658041, 137796456, 2041942843, 329767814, 1255524953, 465119445, 1731949250, 301663421, + 1335861008, 452888789, 14125900, 1231149357, 2002881120, 730845665, 1913581092, 1275331596, 843738737, 1931282005, 1492488573, 490920543, 2066865713, 25885333, 238278880, 1898582764, 250731366, 1612593993, 637659983, 1388759892, + 916073297, 1075762632, 675549432, 937987129, 1417415680, 1508705426, 1663890071, 1746476698, 686797873, 2109530615, 1459500136, 324215873, 1881253854, 1496277718, 810387144, 1212974417, 1020037994, 585169793, 2017191527, 556328195, + 1160036198, 1391095995, 1223583276, 1094283114, 436580096, 190215907, 603159718, 1513255537, 1631935240, 1440145706, 1303736105, 806638567, 1100041120, 1185825535, 1414141069, 2014090929, 419476096, 1273955724, 175753599, 1223475486, + 574236644, 2046759770, 492507266, 1721767511, 726141970, 1256152080, 2029909894, 1382429941, 1939683211, 791188057, 519699747, 1051184301, 1962689485, 706913763, 1776471922, 672906535, 2005817027, 1274190723, 2119425672, 835063788, + 421198539, 1169327477, 2064145552, 1396662140, 1218522465, 2105638337, 754247044, 2143968639, 1395289708, 1750443194, 1412540552, 170281493, 389233190, 448284065, 240618723, 2145930822, 1846605728, 1353999206, 140536987, 1821559709, + 619972089, 1514278798, 750919339, 2143343312, 304427548, 545066288, 1946004194, 1538069400, 1904770864, 924541465, 567779677, 893302687, 1239665569, 1157666831, 2105814934, 1505475223, 1636203720, 9736243, 518073650, 1063743848, + 1029176122, 215018112, 1073871430, 1858933377, 866478506, 1491477359, 477407584, 895562064, 954441852, 638167485, 1550159640, 614612685, 1453397990, 1334857284, 683536723, 168771888, 481561285, 755798022, 2016161810, 1162679490, + 619428858, 1390306889, 256860662, 365275089, 1322281086, 1134185180, 1302724177, 621921213, 837554186, 1711761015, 754896618, 1723143470, 978247260, 1548804416, 598016845, 1631405417, 790929190, 1602517354, 770957259, 198186681, + 1256015513, 2126029304, 135012885, 583112200, 2118203528, 1834388383, 866964848, 1695191950, 745183293, 1143511498, 1112731797, 478721193, 1202162389, 991159735, 1952364329, 519344323, 1667102296, 770412991, 548632788, 714042223, + 1674045273, 1471598258, 1286989824, 1590771096, 308832070, 959354209, 72802865, 670621648, 269167950, 1598436917, 2023498746, 1198213061, 2006856683, 1029832956, 1719009954, 1198254803, 1188748563, 1989240516, 927524181, 1711765426, + 1394929399, 769005536, 2047006719, 1915435344, 618681206, 1431814151, 42021322, 1106678970, 107160610, 1199317660, 185592115, 1870214195, 205008108, 1834318089, 948686793, 946311527, 1262399341, 131405125, 1321897861, 1459138745, + 821481684, 852388468, 603907009, 20643769, 1737931879, 37141933, 2088576982, 366700722, 1761289401, 625991894, 741078359, 817417567, 969305448, 1152416171, 1101933540, 399456957, 2074896270, 1971484382, 747592875, 1160333307, + 1738353358, 2113434968, 1896952705, 1908093581, 1155544307, 117766047, 2034767768, 1316120929, 1507433029, 2045407567, 765386206, 1031625002, 1220915309, 325667019, 1916602098, 16411608, 47463938, 1379995885, 1221108420, 721046824, + 1431492783, 1569479928, 909415369, 204514903, 933673987, 1565700239, 341674967, 602907378, 5309142, 849489374, 180599971, 1480437960, 532467027, 1958396887, 106223060, 1025117441, 935689637, 1752088215, 1704561346, 1568395337, + 1868289345, 569949159, 1045658065, 274746405, 890461390, 507848158, 793505636, 460893030, 1179525294, 388855203, 1113693824, 13887419, 1909681194, 1082499152, 1466632447, 1281443423, 612289854, 373305330, 568652142, 1383640563, + 1073695485, 745777837, 624939139, 1289308008, 1928550562, 148113917, 462743614, 1826880531, 1571598133, 1415390230, 1480273562, 1331593955, 540006359, 261556590, 1690167792, 283430575, 1194709162, 1781233744, 649754857, 1434046375, + 1135793759, 932423857, 1170759710, 1048943084, 692845661, 1620562432, 2036750157, 270410557, 617995659, 1347284277, 1771614266, 30992839, 655445946, 22762734, 1695617313, 867628573, 1577034674, 227870124, 2063408339, 1512163910, + 787913688, 1758748737, 1553547892, 2072440819, 632611704, 873623623, 2097057488, 1879635915, 1404727477, 1840896199, 1609955669, 186112992, 196401930, 130001148, 814302898, 1420810050, 226906236, 1435859758, 221330186, 329049266, + 820933470, 260792255, 1401058771, 210908782, 1774652096, 886978116, 1807085904, 508041515, 767233910, 26687179, 318750634, 910677024, 117260224, 2074840378, 301350822, 464795711, 2053899162, 1335298265, 737518341, 777433215, + 1147341731, 1981481446, 1628389501, 1537459540, 1121432739, 1392162662, 1800522575, 644293952, 1273223611, 1906345724, 28256901, 1467376771, 372465453, 78348530, 135678410, 1061864942, 260267972, 1184561748, 287497702, 1154842325, + 1629914848, 2084953915, 799717076, 1382484003, 2045821218, 933603111, 84924801, 892939912, 279252402, 651750790, 238566180, 942977997, 1822612008, 1849675857, 939497524, 436630343, 549253917, 1028937430, 579174666, 2124749673, + 880456526, 1451442832, 1350653461, 1546104436, 858045289, 2129513521, 1181191604, 727587915, 1619598456, 969076419, 1212628403, 1361078114, 368541415, 333906659, 41714278, 1390274260, 1563717683, 973769771, 1078197595, 918378387, + 1672192305, 1094531762, 92620223, 2125958841, 1620803320, 915948205, 174965839, 27377406, 435236973, 1038830638, 1834161399, 305750851, 330474090, 730422541, 1634445325, 840106059, 767880329, 109526756, 2027814180, 367923081, + 1983379601, 1293091635, 705851791, 226723092, 1067775613, 2082760612, 951663731, 260670135, 1111213862, 1891630185, 1379259015, 176024101, 594814862, 1870859970, 1689946986, 1290969161, 244975305, 1296857499, 1811088032, 1873900475, + 1949896838, 1907793490, 592006699, 1312471120, 509744705, 869853078, 70894786, 503368137, 1686479103, 1602967659, 1214950832, 1131661227, 768185796, 592234826, 1727583308, 949222447, 1760851607, 487888229, 1614780688, 1618378831, + 602368560, 2028116487, 183679578, 1561251584, 986240059, 1525451290, 977907387, 432609664, 1528031307, 116766659, 987761406, 1630293700, 90063199, 114202152, 543952312, 855107605, 812328969, 88823122, 1092881031, 304131252, + 1505022272, 894769708, 1849495275, 1607515830, 1032748996, 472872107, 1593359038, 1027760887, 1074205225, 1657001479, 1524491858, 387061281, 107095939, 1038018856, 798445606, 1486594282, 1878434988, 1558695709, 2033003588, 373226849, + 2133066804, 399991238, 1132597050, 1965358941, 1551661799, 3522194, 935939763, 2070467093, 500734709, 533101409, 1068798385, 998931662, 1500102591, 779093898, 66579049, 1121960111, 749415493, 502323961, 538932155, 259768753, + 753296935, 87897457, 539429964, 1675300017, 1232992084, 420106224, 1685350721, 346598567, 1610244183, 1597506096, 1079859867, 944382193, 1770497338, 764935753, 1776794410, 866854601, 365854486, 304211060, 344860208, 1361012693, + 1450892344, 622170346, 70003859, 1681866717, 435288306, 687941098, 308700094, 1367731096, 1834285819, 255226842, 193873940, 1833603743, 848402819, 152273285, 231181585, 1754447491, 1838218199, 834410115, 229905664, 2052321529, + 338532526, 77482422, 12937811, 35859252, 1645969422, 1501181424, 438711458, 1496078411, 419109342, 1455756978, 1234944834, 1287171290, 470090505, 1900162831, 1130850177, 1772760484, 381571915, 1605369007, 514914429, 994291574, + 1502557594, 1099847920, 1627355806, 1148699143, 1519017268, 946489895, 106595511, 921573402, 181567810, 1575380740, 1719573683, 1561730727, 1920182565, 1510133268, 1102603775, 1175885101, 802730854, 185979744, 1058937717, 1716853034, + 31596852, 462857778, 1335652095, 47036070, 178901145, 1399673078, 222529745, 128036841, 1708126014, 923768127, 1980923963, 1413860940, 1382551511, 208160226, 1892370478, 2091626028, 1793190956, 1417601340, 515811664, 2076612603, + 993525189, 1127173529, 245334962, 134453363, 1206302514, 1344125357, 1139159604, 651536866, 22136821, 1536213818, 2143324534, 879878312, 1944679691, 119285206, 832081018, 1566878909, 876130333, 656954306, 226726100, 937976428, + 1202009920, 1938258683, 2014129292, 1274436639, 1102423908, 1485740112, 879552408, 1712269139, 650513248, 1068587688, 434850545, 382422699, 919736727, 2022291557, 1319798607, 2139976479, 772059719, 1033910502, 1120963974, 340231765, + 1471131758, 1767380006, 47452797, 1313871880, 399114073, 1462921857, 671848647, 31574181, 230340298, 239990424, 590690783, 1714295540, 833019845, 398244682, 522160389, 900852, 1045627895, 1545555937, 226986415, 208433088, + 1502480836, 1611500622, 1933923245, 1588715179, 1655277291, 1749972876, 1386258142, 935490932, 173822937, 702380578, 348131466, 81402251, 875481479, 72939206, 2033828953, 1302272656, 64795664, 2010549018, 1652108025, 58217952, + 1871684562, 190536346, 244709448, 949010757, 320137025, 729474445, 133790520, 740536012, 316479300, 1191513656, 1802197319, 785398708, 1816641611, 2052328978, 930367387, 1374125186, 303845878, 852835634, 454359988, 2131761201, + 1757028186, 536063430, 1765354961, 726869128, 1209784819, 1790557628, 783427298, 2094085507, 1323798820, 846127236, 1065481253, 572240371, 1745543275, 1011417836, 1970797151, 748527394, 343119399, 723323690, 925975225, 901789102, + 1726987516, 535828217, 387611445, 464171383, 1170510314, 1166227930, 1807172811, 1942089394, 985305323, 1368235387, 1691486500, 1568900638, 1876255297, 1249183285, 1710305778, 1763785295, 1733366374, 1444076976, 1629633514, 2105321510, + 225091211, 898893218, 863551327, 1441811554, 546340809, 1977865396, 2116495484, 1221726287, 293109484, 1601617797, 1568176414, 1424797596, 1256372950, 298799048, 1708002892, 829450571, 891710357, 1994402695, 1136264020, 372280769, + 1520667645, 983043723, 1191079043, 680172541, 813511681, 395360213, 1648575360, 1026342885, 2100497812, 422047044, 509116230, 859612092, 2037182006, 895080280, 494367164, 1732028080, 355614494, 2141591317, 1087251698, 580692625, + 225934851, 1581062145, 1515262458, 1497680539, 1711718534, 1774796872, 301673313, 1136356724, 653050943, 109035776, 1709823304, 1340949553, 1365423458, 1155459206, 1203897636, 188016786, 256210446, 633075975, 19227407, 1864952910, + 1143853106, 237020443, 1750197960, 856837002, 80321564, 1679324299, 1257507406, 1390040163, 1590461855, 806384435, 1331383316, 2027828650, 1649392096, 1928309762, 1027758817, 1267173039, 123889599, 95752736, 2060969286, 619461174, + 1686215900, 1817156134, 2118821565, 1596821127, 1800186189, 212821393, 661318748, 1123331233, 146002907, 953877041, 1771924274, 929351822, 2142357746, 356638683, 1610539590, 2001056977, 368889391, 62209567, 1775608361, 992410365, + 1336108161, 696448050, 333820982, 585804640, 1775805177, 809604334, 93191015, 732444124, 1492071476, 1930662128, 174082258, 340442582, 507936866, 362748128, 1607204293, 953383750, 1599876594, 416457166, 571635069, 1356847855, + 267174620, 2011827638, 1572212863, 589049769, 2024853642, 1680251429, 914906004, 398911194, 795915364, 1332467446, 688483428, 628445699, 578787063, 2006320950, 1167207852, 336213879, 1640952769, 1778544166, 1617229086, 190807078, + 1968608155, 2122852959, 31153367, 1353144470, 2196420, 1395155215, 1948121717, 69118708, 2140091269, 2530146, 1740778973, 1601247294, 1205895814, 858150908, 1878253960, 1967705762, 2090543533, 1702425249, 622114437, 1192155877, + 1095403694, 2115445751, 1201124879, 1140728569, 2085323316, 1291025252, 871908043, 863647665, 1245819051, 1468486929, 631022494, 1161580432, 539942311, 1943137808, 1826628136, 259775677, 277497333, 2140756121, 973493986, 1121800211, + 1539560507, 1337406065, 186178768, 482917205, 1459100749, 1924603748, 390743779, 1140008063, 517767440, 1764436465, 722260205, 1400929335, 1706528514, 486165509, 1379460673, 206653795, 3159407, 565150174, 688338919, 1223572435, + 2122262571, 513009937, 1390656632, 271906847, 1622692876, 1313115559, 2061144988, 411864717, 437710825, 513582947, 305489695, 1713188647, 387273799, 1901537567, 644842409, 1231932661, 356672421, 232170581, 1636860706, 302219842, + 2094591332, 1697686200, 1390477985, 1833543700, 1203377492, 50968578, 1332379148, 1514582723, 909273561, 1914809801, 560663378, 1032914339, 1216475831, 113462155, 1165446977, 800591831, 1058677375, 432102601, 2131797509, 1175004233, + 1602827413, 878884686, 446372159, 257728183, 800661980, 1387864976, 2004770236, 999229412, 1428223489, 175843632, 74887898, 630393584, 1147793249, 112648605, 1028529524, 1891904961, 1953919896, 481563348, 436476038, 1601134240, + 72319656, 1581118537, 460420451, 1904576737, 786297537, 359735266, 1918354829, 4031164, 1679777458, 1144017176, 1462192184, 690865719, 1515933932, 363508800, 1480324438, 1044088643, 2036061488, 218671081, 830595166, 381933797, + 108346070, 92271196, 217762975, 1522316172, 1021014457, 1407094080, 857894203, 1968623233, 1459620801, 1345014111, 709651138, 520511102, 2048560397, 1768795266, 1013901419, 1709697877, 1026380990, 1377995642, 1560142576, 542609105, + 1534330971, 528024121, 2015847175, 325324443, 1137511396, 1883999260, 1871060346, 715940689, 167653495, 1292049996, 1172290275, 2018336444, 1951228823, 1666074170, 1834852613, 854475547, 308857120, 502558280, 2105718728, 1624653209, + 514214340, 976063110, 227427283, 912381406, 785989696, 451448729, 212046016, 2068743361, 117280545, 1936668087, 210748671, 1984152603, 945948973, 1409001936, 1644353864, 1139018167, 678475375, 1279061703, 723930558, 195379046, + 1498554338, 999346398, 1665914525, 1473735214, 1561422777, 151416112, 697817760, 1622758049, 607761482, 69889880, 1152335090, 1063657548, 1338090388, 55461678, 1278053582, 837024327, 1914764659, 1049475248, 161502390, 80404202, + 624714335, 879380479, 1066787659, 1375470750, 1561212123, 59384706, 966363087, 2044016080, 1178086274, 1159745061, 291298358, 173062659, 1385675177, 652078020, 1802327778, 1555660285, 623909040, 1579725218, 1649344003, 270814499, + 350182379, 1188076819, 893957771, 534384094, 1057003814, 230634042, 2117880007, 778834747, 250859482, 104637677, 1328272543, 1869264274, 1847908587, 311127477, 506466155, 1808237662, 607471900, 1558244592, 1228817775, 720339756, + 1963053072, 1011473945, 1204992245, 566166447, 419053054, 737377568, 520329478, 1740099311, 1682700783, 1455316979, 2118805956, 729509794, 1565610678, 722347551, 739596391, 882282387, 926200942, 999899279, 1318032594, 122124863, + 1633512617, 1269707634, 380070610, 1043920511, 665601851, 873976891, 717911282, 2135673182, 761851297, 1604330946, 666624765, 513561613, 1504023310, 1128895624, 99511825, 722919148, 1047336724, 550532376, 1082864732, 289686472, + 216557804, 1174587016, 845698678, 1554106660, 577410402, 790256415, 675663963, 2029133999, 161450336, 228960529, 743745539, 1352833750, 2123379476, 852338021, 1291070368, 448708980, 1953450944, 923478775, 827496819, 1126017956, + 197964832, 281317274, 1171925835, 764902582, 595717488, 2129930580, 1437147036, 1447469119, 755554593, 2130879949, 1835203128, 1547662666, 1855359256, 965490116, 672323245, 182598318, 216435361, 1324723894, 1144669754, 454438520, + 1220523503, 1520886946, 1797641070, 1585050246, 797060176, 1821482472, 2128078174, 973367349, 991874801, 679519053, 1961647235, 2094159153, 391321675, 1604357658, 576906032, 1712341869, 344515114, 1122768484, 1659079595, 1328885292, + 48775768, 247448424, 1836119534, 1564061243, 1386366954, 485818381, 37017340, 356546370, 1675494182, 430093707, 1959222232, 1784682542, 1839063567, 1596042792, 295666215, 403378386, 2114587535, 1515528736, 1541546082, 1444048519, + 1215103809, 1687941280, 1546057655, 1905279500, 544899032, 2069178089, 1688652157, 1414160501, 332201519, 631936923, 423299667, 1332937015, 545602285, 310273032, 960982228, 372501343, 1933532372, 1711569347, 11476473, 155845605, + 700725671, 1457464894, 1325083914, 172109594, 664387510, 1705378439, 376781122, 1472567100, 343682568, 1370528050, 265363198, 2079492652, 1803183394, 519194709, 1538391713, 1931493432, 1183464058, 1489699243, 495097609, 801046035, + 177100916, 1292413659, 1348373925, 1550525411, 697685269, 856621012, 1992941115, 1189141368, 221661515, 156760399, 38620214, 375863194, 2078528215, 2103236982, 341987235, 698660475, 381094614, 1201152163, 1275500498, 398211404, + 801610475, 1087556673, 846650758, 1848681194, 1287830283, 1400070607, 1603428054, 1233022905, 810516965, 690710531, 1860435620, 750631050, 1271370220, 860360715, 1189323192, 1913926325, 946425090, 1815408878, 743572345, 1902501708, + 1276205250, 2005653265, 624614472, 2108439398, 1952177514, 964348374, 1171051384, 2126963607, 812288356, 108628319, 980702956, 714456194, 1678967663, 1935271536, 236851791, 1541132933, 1066014062, 1607628402, 1926717418, 954942098, + 1733982669, 14239125, 1506716966, 848141854, 1178260876, 614222093, 731606176, 1512135729, 63244522, 968848252, 1783943137, 1402735006, 1355391150, 1659137391, 1173889730, 1042942541, 1318900244, 1149113346, 2090025563, 1201659316, + 250022739, 1035075488, 674580901, 1090386021, 1943651015, 934048997, 2087660971, 738682048, 1305071296, 91177380, 1708106609, 1685880008, 364589031, 1860839427, 1927367009, 906899219, 1090443335, 892574149, 1969729134, 1874026715, + 927045887, 1159898528, 730296520, 349249331, 317980803, 225908941, 483348027, 1035956563, 241537930, 1279981214, 1247518755, 247447060, 1793747608, 752388169, 288054543, 2073482870, 2039012903, 617768643, 433412593, 499898207, + 1050512245, 331284679, 851322111, 1294873695, 1715379173, 1159675637, 1029338154, 2027445678, 1653332243, 1874855959, 1234157881, 260674360, 1042790263, 1401980800, 730090881, 1745393357, 1550721460, 1607677838, 969500483, 778702716, + 1765830270, 731763278, 1600023202, 1957728250, 690983, 444361278, 1278777407, 1231639101, 597427397, 1087245613, 258177907, 2093472294, 1462778368, 2067100479, 1628387880, 762564955, 1194041213, 1348361229, 1822279764, 1826590258, + 1112056034, 2088786920, 815110420, 1957877704, 1087195269, 881982271, 1945110368, 1656527154, 529233847, 137046551, 522408049, 1880577483, 847255974, 851716534, 925604268, 1037521069, 461527795, 1332620900, 525605961, 1389787451, + 1127911377, 1198857033, 859385989, 706825946, 371790550, 145611377, 655200896, 1900613055, 1333790305, 1101722351, 1278794420, 2089981667, 1150780072, 13180701, 1502266386, 1103013140, 343038558, 1897907456, 1612609979, 1209991461, + 1740783613, 1643991754, 977454680, 787842886, 163362230, 1087742330, 200253206, 1691676526, 360632817, 1787338655, 35595330, 822635252, 1834254978, 1372169786, 1063768444, 973490494, 697866347, 156498369, 169293723, 180549009, + 112035400, 127867199, 241711645, 2004664325, 23288667, 1997381015, 736455241, 1986921372, 1570645300, 2067499753, 1463269859, 148527979, 618168829, 1715279374, 2066440075, 2118433006, 198233440, 1835860030, 1345873587, 1902595458, + 1961619988, 1291438802, 1325008187, 836983022, 1849657867, 500376868, 1599565995, 1705905941, 1600493361, 386733714, 1028820236, 1663100626, 1322696419, 1482983072, 1092382563, 1667679197, 1965855212, 1063839036, 1742032331, 300191208, + 620497725, 503895325, 2094864173, 928179911, 277942057, 1677449797, 1249086623, 799527371, 1180063064, 48311975, 1866094167, 1405763119, 2109851473, 1594621666, 580464203, 1752598186, 1339293088, 922186026, 1403771494, 299505702, + 1345987999, 1298200648, 2128826472, 677220745, 831273447, 741184696, 696188251, 1912065710, 1016469330, 682018288, 353946286, 559509624, 515414188, 1852181952, 407771887, 812094461, 1859683061, 1100089300, 498702377, 653626077, + 765701205, 150878039, 328551896, 77104822, 1775331228, 1835977906, 706357381, 1240287664, 839507573, 1054066034, 1823053058, 701959731, 82879528, 652404808, 866097476, 926939064, 1326017288, 1747861289, 1173840088, 1524006589, + 443704960, 835506582, 5363460, 2068343250, 1683915700, 2080735477, 1913489530, 951256529, 1752318678, 105384223, 1788389051, 1787391786, 1430821640, 540952308, 882484999, 690806365, 202502890, 1593837351, 530093821, 385878401, + 907401151, 378912543, 454746323, 251514112, 1451277631, 1125822965, 21289266, 1642884452, 804368379, 2048205721, 917508270, 1514792012, 139494505, 1143168018, 115016418, 1730333306, 1630776459, 50748643, 1745247524, 1313640711, + 1076198976, 1820281480, 941471466, 806673335, 722162727, 1837280287, 705508794, 2088955494, 510497580, 51692325, 893597382, 1373978529, 1007042224, 685006165, 1471461419, 1555325521, 1215063385, 1424859828, 657251271, 1391827090, + 965562483, 604275115, 1285258674, 341475746, 294191106, 633240394, 1897691227, 1904243956, 823532901, 1577955754, 2016464961, 1862876260, 577384103, 1012611702, 247243083, 636485510, 1952805989, 1447876480, 108021700, 1016615447, + 2047769687, 943871886, 787537653, 12744598, 853545598, 334037304, 553373537, 1089408490, 497867498, 2038925801, 1434633879, 1290629443, 75922980, 957037315, 2130252471, 477317888, 952824381, 1686570783, 459340678, 751885764, + 836307572, 2027909489, 28791588, 322748588, 1335236478, 787106123, 113580144, 954915740, 1317077622, 1299667896, 2009244921, 1548588723, 2049698913, 732388681, 1781891230, 2090684129, 993786972, 1959292396, 1336513734, 691093904, + 1746904676, 935573751, 1123555638, 108413311, 1445352642, 169726789, 123352211, 1635952299, 673775121, 2042861943, 757787251, 512494446, 119656942, 58159196, 2090570016, 486181025, 1619641914, 432990571, 894937325, 379470588, + 1890938638, 1886317932, 1858637614, 969358207, 1230449468, 1890889527, 351741654, 214725897, 1550012286, 308005013, 26292400, 68067591, 1383307838, 1746273091, 1090104632, 1658037573, 2081544705, 1133473813, 1680294422, 1050373352, + 1806061681, 1713475126, 520699193, 417568373, 1355086853, 631399565, 1742434188, 2077667592, 1709019727, 594054971, 937081176, 742185643, 1904514273, 887841601, 1288684086, 424587711, 1497926365, 829844031, 1384314543, 250129297, + 200083737, 693737559, 1527022962, 1462501905, 1687540458, 1156824624, 241481265, 1190890142, 1250360726, 2064308502, 27563032, 1880483834, 1984143440, 104727360, 1324123626, 1089710430, 1403206383, 1930880552, 773197243, 1160186023, + 562994480, 1065136414, 502237764, 1642338733, 1310177444, 1730721241, 1475638246, 615734453, 1160537912, 928836931, 253898558, 1799210492, 1205522527, 413058646, 1589194592, 1774218355, 43955934, 1673314595, 683393460, 1260859787, + 2098829619, 772503535, 1232567659, 758174758, 831270563, 1605294199, 1660678300, 24379565, 1426483935, 1611558740, 1085326591, 12849216, 455856722, 878692218, 1910978116, 1382893830, 1950124297, 950009818, 904287249, 791384486, + 1584408128, 210098472, 1110387095, 364620240, 53868166, 772251062, 472745168, 1133910514, 1715402379, 1445225855, 1541125975, 149171217, 972058766, 1893095488, 1487620835, 640835502, 1470285405, 646688705, 988431201, 703130341, + 1753125385, 1985895474, 696002734, 1783233173, 1317201705, 1755204784, 532132334, 1069450170, 249700039, 524320231, 757959820, 2109052886, 604977130, 1971654864, 1588222158, 1533496974, 623670976, 1405668251, 1955436051, 1082881617, + 1387039848, 874153641, 1345378476, 1168465459, 2005021017, 234039217, 473318229, 654912216, 1473166451, 997649666, 801824335, 2052343947, 1883168929, 185658088, 1389954587, 1725541486, 885873448, 958774566, 2054212564, 60536525, + 1427504270, 1160285859, 1827651881, 1408805003, 1684018729, 61716770, 844057079, 1011596733, 1521350211, 1581801257, 907554175, 2022973269, 1125104871, 1312064004, 1466679625, 970194422, 80900939, 1445279202, 335456148, 510478312, + 92860378, 1646704157, 1650899832, 1533447203, 268087516, 880688023, 1180525723, 1868151949, 1750955971, 401446720, 540093580, 1022861633, 461442838, 1222554291, 456462271, 94760711, 1231111410, 2145073408, 1932108837, 300618464, 2055783490, 980863365, 1308872551, 1010427073, 1399854717, 1217804021, 934700736, 878744414 }; -type verify_data[DATA_SIZE] = +type verify_data[DATA_SIZE] = { - 690983, 900852, 2196420, 2530146, 3159407, 3522194, 3794415, 4031164, 5309142, 5363460, 9736243, 11476473, 12744598, 12849216, 12937811, 13180701, 13887419, 14125900, 14239125, 16411608, - 19227407, 20643769, 21289266, 22136821, 22762734, 23288667, 24379565, 25885333, 26292400, 26687179, 27377406, 27563032, 28256901, 28791588, 30992839, 31153367, 31574181, 31596852, 35595330, 35859252, - 37017340, 37141933, 38620214, 41714278, 42021322, 43955934, 47036070, 47452797, 47463938, 48311975, 48775768, 50748643, 50968578, 51692325, 53868166, 55461678, 58159196, 58217952, 59384706, 60536525, - 61716770, 62209567, 63244522, 64795664, 66579049, 68067591, 69118708, 69889880, 70003859, 70894786, 72319656, 72802865, 72939206, 74887898, 75922980, 77104822, 77482422, 78348530, 80321564, 80404202, - 80900939, 81402251, 82879528, 84924801, 87897457, 88823122, 89400484, 90063199, 91177380, 92271196, 92620223, 92860378, 93191015, 94760711, 95752736, 99511825, 104637677, 104727360, 105384223, 106223060, - 106595511, 107095939, 107160610, 108021700, 108346070, 108413311, 108628319, 109035776, 109526756, 112035400, 112648605, 113462155, 113580144, 114202152, 115016418, 116766659, 117260224, 117280545, 117766047, 119285206, - 119656942, 122124863, 123352211, 123889599, 127867199, 128036841, 130001148, 131405125, 133790520, 134453363, 135012885, 135678410, 137046551, 137796456, 139494505, 140536987, 145611377, 146002907, 148113917, 148527979, - 149171217, 150878039, 151416112, 152273285, 155845605, 156498369, 156760399, 161450336, 161502390, 163362230, 167653495, 168771888, 169293723, 169726789, 170281493, 172109594, 173062659, 173822937, 174082258, 174965839, - 175753599, 175843632, 176024101, 177100916, 178901145, 180549009, 180599971, 181567810, 182598318, 183679578, 185592115, 185658088, 185979744, 186112992, 186178768, 188016786, 190215907, 190536346, 190807078, 193873940, - 195379046, 196401930, 197964832, 198186681, 198233440, 200083737, 200253206, 202502890, 204514903, 205008108, 206653795, 208160226, 208433088, 210098472, 210748671, 210908782, 212046016, 212821393, 214725897, 215018112, - 216435361, 216557804, 217762975, 218671081, 221330186, 221661515, 222529745, 225091211, 225908941, 225934851, 226723092, 226726100, 226906236, 226986415, 227427283, 227870124, 228960529, 229905664, 230340298, 230634042, - 231181585, 232170581, 234039217, 236851791, 237020443, 238278880, 238566180, 239990424, 240618723, 241481265, 241537930, 241711645, 244709448, 244975305, 245334962, 247243083, 247447060, 247448424, 249700039, 250022739, - 250129297, 250731366, 250859482, 251514112, 253898558, 255226842, 256210446, 256860662, 257728183, 258177907, 259768753, 259775677, 260267972, 260670135, 260674360, 260792255, 261556590, 265363198, 267174620, 268087516, - 269167950, 270410557, 270814499, 271906847, 274746405, 277497333, 277942057, 279252402, 281317274, 283430575, 284658041, 287497702, 288054543, 289686472, 291298358, 293109484, 294191106, 295666215, 298799048, 299505702, - 300191208, 300618464, 301350822, 301663421, 301673313, 302219842, 303845878, 304131252, 304211060, 304427548, 305489695, 305750851, 308005013, 308700094, 308832070, 308857120, 310273032, 311127477, 316479300, 317980803, - 318750634, 320137025, 322748588, 324215873, 325324443, 325667019, 328551896, 329049266, 329767814, 330474090, 331284679, 332201519, 333820982, 333906659, 334037304, 335456148, 336213879, 338532526, 340231765, 340442582, - 341475746, 341674967, 341987235, 343038558, 343119399, 343682568, 344515114, 344860208, 346598567, 348131466, 349249331, 350182379, 351741654, 353946286, 355614494, 356546370, 356638683, 356672421, 359735266, 360632817, - 362748128, 363508800, 364589031, 364620240, 365275089, 365854486, 366700722, 367923081, 368541415, 368889391, 371790550, 372280769, 372465453, 372501343, 373226849, 373305330, 375863194, 376781122, 378912543, 379470588, - 380070610, 381094614, 381571915, 381933797, 382422699, 385878401, 386733714, 387061281, 387273799, 387611445, 388855203, 389233190, 390743779, 391321675, 395360213, 398211404, 398244682, 398911194, 399114073, 399456957, - 399991238, 401446720, 402845420, 403378386, 407771887, 411864717, 413058646, 416457166, 417568373, 419053054, 419109342, 419476096, 420106224, 421198539, 422047044, 423299667, 424587711, 430093707, 432102601, 432609664, - 432990571, 433412593, 434850545, 435236973, 435288306, 436476038, 436580096, 436630343, 437710825, 438711458, 443704960, 444361278, 446372159, 448284065, 448708980, 451448729, 452888789, 454359988, 454438520, 454746323, - 455856722, 456462271, 459340678, 460420451, 460893030, 461442838, 461527795, 462743614, 462857778, 464171383, 464795711, 465119445, 470090505, 472745168, 472872107, 473318229, 477317888, 477407584, 478721193, 481561285, - 481563348, 482917205, 483348027, 485818381, 486165509, 486181025, 487888229, 490920543, 492507266, 494367164, 495097609, 497867498, 498702377, 499898207, 500376868, 500734709, 502237764, 502323961, 502558280, 503368137, - 503895325, 506466155, 507848158, 507936866, 508041515, 509116230, 509744705, 510478312, 510497580, 512494446, 513009937, 513561613, 513582947, 514214340, 514914429, 515414188, 515811664, 517767440, 518073650, 519194709, - 519344323, 519699747, 520329478, 520511102, 520699193, 522160389, 522408049, 524320231, 525605961, 528024121, 529233847, 530093821, 532132334, 532467027, 533101409, 534384094, 535828217, 536063430, 538932155, 539429964, - 539942311, 540006359, 540093580, 540952308, 542609105, 543952312, 544899032, 545066288, 545602285, 546340809, 548632788, 549253917, 550532376, 553373537, 556328195, 559509624, 560663378, 562994480, 565150174, 566166447, - 567779677, 568652142, 569949159, 571635069, 572240371, 574236644, 576906032, 577384103, 577410402, 578787063, 579174666, 580464203, 580692625, 583112200, 585169793, 585804640, 589049769, 590690783, 592006699, 592234826, - 594054971, 594814862, 595717488, 597427397, 598016845, 602368560, 602907378, 603159718, 603907009, 604275115, 604977130, 607471900, 607761482, 612289854, 614222093, 614612685, 615734453, 617768643, 617995659, 618168829, - 618681206, 619428858, 619461174, 619972089, 620497725, 621921213, 622114437, 622170346, 623670976, 623909040, 624614472, 624714335, 624939139, 625991894, 628445699, 630393584, 631022494, 631399565, 631936923, 632611704, - 633075975, 633240394, 636485510, 637659983, 638167485, 640835502, 644293952, 644842409, 646688705, 649754857, 650513248, 651536866, 651750790, 652078020, 652404808, 653050943, 653626077, 654912216, 655200896, 655445946, - 656954306, 657251271, 661318748, 664387510, 665601851, 666624765, 670621648, 671848647, 672323245, 672906535, 673775121, 674580901, 675549432, 675663963, 677220745, 678475375, 679519053, 680172541, 682018288, 683393460, - 683536723, 685006165, 686797873, 687941098, 688338919, 688483428, 690710531, 690806365, 690865719, 691093904, 692845661, 693737559, 696002734, 696188251, 696448050, 697685269, 697817760, 697866347, 698660475, 700725671, - 701959731, 702380578, 703130341, 705508794, 705851791, 706357381, 706825946, 706913763, 709651138, 714042223, 714456194, 715940689, 717911282, 720339756, 721046824, 721524505, 722162727, 722260205, 722347551, 722919148, - 723323690, 723930558, 726141970, 726869128, 727587915, 729474445, 729509794, 730090881, 730296520, 730422541, 730845665, 731606176, 731763278, 732388681, 732444124, 736455241, 737377568, 737518341, 738682048, 739596391, - 740536012, 741078359, 741184696, 742185643, 743572345, 743745539, 745183293, 745777837, 747592875, 748527394, 749415493, 750631050, 750919339, 751885764, 752388169, 753296935, 754215794, 754247044, 754896618, 755554593, - 755798022, 757787251, 757959820, 758174758, 761851297, 762564955, 764902582, 764935753, 765386206, 765701205, 767233910, 767880329, 768185796, 769005536, 770412991, 770957259, 772059719, 772251062, 772503535, 773197243, - 777433215, 778702716, 778834747, 779093898, 783427298, 785398708, 785989696, 786297537, 786566648, 787106123, 787537653, 787842886, 787913688, 790256415, 790929190, 791188057, 791384486, 793505636, 795915364, 797060176, - 798445606, 799527371, 799717076, 800591831, 800661980, 801046035, 801610475, 801824335, 802730854, 804368379, 806384435, 806638567, 806673335, 809604334, 810387144, 810516965, 812094461, 812288356, 812328969, 813511681, - 814302898, 815110420, 817417567, 820933470, 821481684, 822635252, 823532901, 827496819, 829450571, 829844031, 830595166, 831270563, 831273447, 832081018, 833019845, 834410115, 835063788, 835506582, 836307572, 836983022, - 837024327, 837554186, 839507573, 840106059, 843738737, 844057079, 845698678, 846127236, 846650758, 847255974, 848141854, 848402819, 849489374, 851322111, 851716534, 852338021, 852388468, 852835634, 853545598, 854475547, - 855107605, 856621012, 856837002, 857894203, 858045289, 858150908, 859385989, 859612092, 860360715, 863551327, 863647665, 866097476, 866478506, 866854601, 866964848, 867628573, 869853078, 871908043, 873623623, 873976891, - 874153641, 875481479, 876130333, 878692218, 878744414, 878884686, 879380479, 879552408, 879878312, 880456526, 880688023, 881982271, 882282387, 882484999, 885873448, 886978116, 887841601, 890461390, 891710357, 892574149, - 892939912, 893302687, 893597382, 893957771, 894769708, 894937325, 895080280, 895562064, 898893218, 901789102, 904287249, 906899219, 907401151, 907554175, 909273561, 909415369, 910677024, 912381406, 914906004, 915948205, - 916073297, 917508270, 918378387, 919736727, 921573402, 922186026, 923478775, 923768127, 924541465, 925604268, 925975225, 926200942, 926939064, 927045887, 927524181, 928179911, 928836931, 929351822, 930367387, 932423857, - 933603111, 933673987, 934048997, 934700736, 935490932, 935573751, 935689637, 935939763, 937081176, 937976428, 937987129, 939497524, 941471466, 942977997, 943871886, 944382193, 945948973, 946311527, 946425090, 946489895, - 948686793, 949010757, 949222447, 950009818, 951256529, 951663731, 952824381, 953383750, 953877041, 954441852, 954915740, 954942098, 957037315, 958774566, 959354209, 960982228, 964348374, 965490116, 965562483, 966363087, - 968848252, 969076419, 969305448, 969358207, 969500483, 970194422, 972058766, 973367349, 973490494, 973493986, 973769771, 976015092, 976063110, 977454680, 977907387, 978247260, 980702956, 980863365, 983043723, 985305323, - 986240059, 987761406, 988431201, 991159735, 991874801, 992410365, 993525189, 993786972, 994291574, 997649666, 998931662, 999229412, 999346398, 999899279, 1007042224, 1010427073, 1011417836, 1011473945, 1011596733, 1012611702, - 1013901419, 1016469330, 1016615447, 1020037994, 1021014457, 1022861633, 1025117441, 1026342885, 1026380990, 1027758817, 1027760887, 1028529524, 1028820236, 1028937430, 1029176122, 1029338154, 1029832956, 1031625002, 1032748996, 1032914339, - 1033910502, 1035075488, 1035956563, 1037521069, 1038018856, 1038830638, 1042790263, 1042942541, 1043920511, 1044088643, 1045627895, 1045658065, 1047336724, 1048943084, 1049475248, 1050373352, 1050512245, 1051184301, 1054066034, 1057003814, - 1058677375, 1058937717, 1061864942, 1063657548, 1063743848, 1063768444, 1063839036, 1065136414, 1065481253, 1066014062, 1066787659, 1067775613, 1068587688, 1068798385, 1069450170, 1073695485, 1073871430, 1074205225, 1075762632, 1076198976, - 1078197595, 1079859867, 1082499152, 1082864732, 1082881617, 1085326591, 1087195269, 1087245613, 1087251698, 1087556673, 1087742330, 1089408490, 1089710430, 1090104632, 1090386021, 1090443335, 1092382563, 1092881031, 1094283114, 1094531762, - 1095403694, 1099847920, 1100041120, 1100089300, 1101722351, 1101933540, 1102423908, 1102603775, 1103013140, 1106678970, 1110387095, 1111213862, 1112056034, 1112731797, 1113693824, 1120963974, 1121432739, 1121800211, 1121960111, 1122768484, - 1123331233, 1123555638, 1125104871, 1125822965, 1126017956, 1127173529, 1127911377, 1128895624, 1130850177, 1131661227, 1132597050, 1133473813, 1133910514, 1134185180, 1135793759, 1136264020, 1136356724, 1137511396, 1139018167, 1139159604, - 1140008063, 1140728569, 1143168018, 1143511498, 1143853106, 1144017176, 1144669754, 1147341731, 1147793249, 1148699143, 1149113346, 1150780072, 1152335090, 1152416171, 1154842325, 1155459206, 1155544307, 1156824624, 1157666831, 1159675637, - 1159745061, 1159898528, 1160036198, 1160186023, 1160285859, 1160333307, 1160537912, 1161580432, 1162679490, 1165446977, 1166227930, 1167207852, 1168465459, 1169327477, 1170510314, 1170759710, 1171051384, 1171925835, 1172290275, 1173840088, - 1173889730, 1174587016, 1175004233, 1175885101, 1178086274, 1178260876, 1179525294, 1180063064, 1180525723, 1181191604, 1183464058, 1184561748, 1185825535, 1188076819, 1188748563, 1189141368, 1189323192, 1190890142, 1191079043, 1191513656, - 1192155877, 1194041213, 1194709162, 1198213061, 1198254803, 1198857033, 1199317660, 1201124879, 1201152163, 1201659316, 1202009920, 1202162389, 1203377492, 1203897636, 1204992245, 1205522527, 1205895814, 1206302514, 1209784819, 1209991461, - 1212628403, 1212974417, 1214379246, 1214950832, 1215063385, 1215103809, 1216475831, 1217804021, 1218522465, 1220523503, 1220915309, 1221108420, 1221726287, 1222554291, 1223475486, 1223572435, 1223583276, 1228817775, 1230449468, 1231111410, - 1231149357, 1231249235, 1231639101, 1231932661, 1232567659, 1232992084, 1233022905, 1234157881, 1234944834, 1239665569, 1240287664, 1245819051, 1247518755, 1249086623, 1249183285, 1250360726, 1255524953, 1256015513, 1256152080, 1256372950, - 1257507406, 1260859787, 1262399341, 1267173039, 1269707634, 1271370220, 1273223611, 1273955724, 1274190723, 1274436639, 1275331596, 1275500498, 1276205250, 1278053582, 1278777407, 1278794420, 1279061703, 1279981214, 1281443423, 1285258674, - 1286989824, 1287171290, 1287830283, 1288684086, 1289308008, 1290629443, 1290969161, 1291025252, 1291070368, 1291438802, 1292049996, 1292413659, 1293091635, 1294873695, 1296857499, 1298200648, 1299667896, 1302272656, 1302724177, 1303736105, - 1305071296, 1308872551, 1310177444, 1312064004, 1312471120, 1313115559, 1313640711, 1313871880, 1316120929, 1317077622, 1317201705, 1318032594, 1318900244, 1319798607, 1321897861, 1322281086, 1322696419, 1323798820, 1324123626, 1324723894, - 1325008187, 1325083914, 1326017288, 1328272543, 1328885292, 1331383316, 1331593955, 1332379148, 1332467446, 1332620900, 1332937015, 1333790305, 1334857284, 1335236478, 1335298265, 1335652095, 1335861008, 1336108161, 1336513734, 1337406065, - 1338090388, 1339293088, 1340949553, 1344125357, 1345014111, 1345378476, 1345873587, 1345987999, 1347284277, 1348361229, 1348373925, 1350653461, 1352833750, 1353144470, 1353999206, 1355086853, 1355391150, 1356847855, 1361012693, 1361078114, - 1365423458, 1367731096, 1368235387, 1370528050, 1372169786, 1373978529, 1374125186, 1375470750, 1377995642, 1379259015, 1379460673, 1379995885, 1382429941, 1382484003, 1382551511, 1382893830, 1383307838, 1383640563, 1384314543, 1385675177, - 1386258142, 1386366954, 1387039848, 1387864976, 1388759892, 1389787451, 1389954587, 1390040163, 1390274260, 1390306889, 1390477985, 1390656632, 1391095995, 1391827090, 1392162662, 1394929399, 1395155215, 1395289708, 1396662140, 1399673078, - 1399854717, 1400070607, 1400929335, 1401058771, 1401980800, 1402735006, 1403206383, 1403771494, 1404727477, 1405668251, 1405763119, 1407094080, 1408805003, 1409001936, 1412540552, 1413860940, 1414141069, 1414160501, 1415390230, 1417415680, - 1417601340, 1420810050, 1424797596, 1424859828, 1426483935, 1427504270, 1428223489, 1430821640, 1431492783, 1431814151, 1434046375, 1434633879, 1435859758, 1437147036, 1440145706, 1441811554, 1444048519, 1444076976, 1445225855, 1445279202, - 1445352642, 1447469119, 1447876480, 1450892344, 1451277631, 1451442832, 1453397990, 1455316979, 1455756978, 1457464894, 1459100749, 1459138745, 1459500136, 1459620801, 1462192184, 1462501905, 1462778368, 1462921857, 1463269859, 1466632447, - 1466679625, 1467376771, 1468486929, 1470285405, 1471131758, 1471461419, 1471598258, 1472567100, 1473166451, 1473735214, 1475638246, 1480273562, 1480324438, 1480437960, 1482983072, 1485740112, 1486594282, 1487620835, 1489699243, 1491477359, - 1492071476, 1492488573, 1496078411, 1496277718, 1497680539, 1497926365, 1498554338, 1500102591, 1501181424, 1502266386, 1502480836, 1502557594, 1504023310, 1505022272, 1505475223, 1506716966, 1507433029, 1508705426, 1510133268, 1512135729, - 1512163910, 1513255537, 1514278798, 1514582723, 1514792012, 1515262458, 1515528736, 1515933932, 1519017268, 1520667645, 1520886946, 1521350211, 1522316172, 1524006589, 1524491858, 1525451290, 1527022962, 1528031307, 1533447203, 1533496974, - 1534330971, 1536213818, 1537459540, 1538069400, 1538391713, 1539560507, 1541125975, 1541132933, 1541546082, 1545555937, 1546057655, 1546104436, 1547662666, 1548588723, 1548804416, 1550012286, 1550159640, 1550525411, 1550721460, 1551661799, - 1553547892, 1554106660, 1555325521, 1555660285, 1558244592, 1558695709, 1560142576, 1561212123, 1561251584, 1561422777, 1561730727, 1563717683, 1564061243, 1565610678, 1565700239, 1566878909, 1568176414, 1568395337, 1568900638, 1569479928, - 1570645300, 1571598133, 1572212863, 1575380740, 1577034674, 1577955754, 1579725218, 1581062145, 1581118537, 1581801257, 1584408128, 1585050246, 1588222158, 1588715179, 1589194592, 1590461855, 1590771096, 1593359038, 1593837351, 1594621666, - 1596042792, 1596821127, 1597506096, 1598436917, 1599565995, 1599876594, 1600023202, 1600493361, 1601134240, 1601247294, 1601617797, 1602517354, 1602827413, 1602967659, 1603428054, 1604330946, 1604357658, 1605294199, 1605369007, 1607204293, - 1607515830, 1607628402, 1607677838, 1609955669, 1610244183, 1610539590, 1611500622, 1611558740, 1611680320, 1612593993, 1612609979, 1614780688, 1617229086, 1618378831, 1619598456, 1619641914, 1620562432, 1620803320, 1622692876, 1622758049, - 1624653209, 1627355806, 1628387880, 1628389501, 1629633514, 1629914848, 1630293700, 1630776459, 1631405417, 1631935240, 1633512617, 1634445325, 1635952299, 1636203720, 1636860706, 1640952769, 1642338733, 1642884452, 1643991754, 1644353864, - 1645969422, 1646704157, 1648575360, 1649344003, 1649392096, 1650899832, 1652108025, 1653332243, 1655277291, 1656527154, 1657001479, 1658037573, 1659079595, 1659137391, 1660678300, 1663100626, 1663890071, 1665914525, 1666074170, 1667102296, - 1667679197, 1672192305, 1673314595, 1674045273, 1675300017, 1675494182, 1677449797, 1678967663, 1679324299, 1679777458, 1680251429, 1680294422, 1681866717, 1682700783, 1683915700, 1684018729, 1685350721, 1685880008, 1686215900, 1686479103, - 1686570783, 1687540458, 1687941280, 1688652157, 1689946986, 1690167792, 1691486500, 1691676526, 1695191950, 1695617313, 1697686200, 1702425249, 1704561346, 1705378439, 1705905941, 1706528514, 1708002892, 1708106609, 1708126014, 1709019727, - 1709697877, 1709823304, 1710305778, 1711569347, 1711718534, 1711761015, 1711765426, 1712269139, 1712341869, 1713188647, 1713475126, 1714295540, 1715279374, 1715379173, 1715402379, 1716853034, 1719009954, 1719573683, 1721767511, 1723143470, - 1725541486, 1726987516, 1727583308, 1730333306, 1730721241, 1731949250, 1732028080, 1733366374, 1733982669, 1737931879, 1738353358, 1740099311, 1740778973, 1740783613, 1742032331, 1742434188, 1745247524, 1745393357, 1745543275, 1746273091, - 1746476698, 1746904676, 1747861289, 1749972876, 1750197960, 1750443194, 1750955971, 1752088215, 1752318678, 1752598186, 1753125385, 1754447491, 1755204784, 1757028186, 1758748737, 1760851607, 1761289401, 1763785295, 1764436465, 1765354961, - 1765830270, 1767380006, 1768795266, 1770497338, 1771614266, 1771924274, 1772760484, 1774218355, 1774652096, 1774796872, 1775331228, 1775608361, 1775805177, 1776471922, 1776794410, 1778544166, 1781233744, 1781891230, 1783233173, 1783943137, - 1784682542, 1787338655, 1787391786, 1788389051, 1790557628, 1792756324, 1793190956, 1793747608, 1797641070, 1799210492, 1800186189, 1800522575, 1802197319, 1802327778, 1803183394, 1806061681, 1807085904, 1807172811, 1808237662, 1811088032, - 1815408878, 1816641611, 1817156134, 1820281480, 1821482472, 1821559709, 1822279764, 1822612008, 1823053058, 1826590258, 1826628136, 1826880531, 1827651881, 1833543700, 1833603743, 1834161399, 1834254978, 1834285819, 1834318089, 1834388383, - 1834852613, 1835203128, 1835860030, 1835977906, 1836119534, 1837280287, 1838218199, 1839063567, 1840896199, 1846605728, 1847908587, 1848681194, 1849495275, 1849657867, 1849675857, 1852181952, 1855359256, 1858637614, 1858933377, 1859683061, - 1860435620, 1860839427, 1862876260, 1864952910, 1866094167, 1868151949, 1868289345, 1869264274, 1870214195, 1870859970, 1871060346, 1871684562, 1873900475, 1874026715, 1874855959, 1876255297, 1878253960, 1878434988, 1879635915, 1880483834, - 1880577483, 1881253854, 1883168929, 1883999260, 1886317932, 1890889527, 1890938638, 1891630185, 1891904961, 1892370478, 1893095488, 1896952705, 1897691227, 1897907456, 1898582764, 1900162831, 1900613055, 1901537567, 1902501708, 1902595458, - 1904243956, 1904514273, 1904576737, 1904770864, 1905279500, 1906345724, 1907793490, 1908093581, 1909681194, 1910978116, 1912065710, 1913489530, 1913581092, 1913926325, 1914764659, 1914809801, 1915435344, 1916602098, 1918354829, 1920182565, - 1924603748, 1926717418, 1927367009, 1928309762, 1928550562, 1930662128, 1930880552, 1931282005, 1931493432, 1932108837, 1933532372, 1933923245, 1935271536, 1936668087, 1938258683, 1939683211, 1942089394, 1943137808, 1943651015, 1944679691, - 1945110368, 1946004194, 1948121717, 1949896838, 1950124297, 1951228823, 1952177514, 1952364329, 1952805989, 1953450944, 1953919896, 1955436051, 1957728250, 1957877704, 1958396887, 1959222232, 1959292396, 1961619988, 1961647235, 1962689485, - 1963053072, 1965358941, 1965855212, 1967705762, 1968608155, 1968623233, 1969729134, 1970797151, 1971484382, 1971654864, 1977865396, 1980923963, 1981481446, 1983379601, 1984143440, 1984152603, 1985895474, 1986921372, 1989240516, 1992941115, - 1994402695, 1997381015, 2001056977, 2002881120, 2004664325, 2004770236, 2005021017, 2005653265, 2005817027, 2006320950, 2006856683, 2009244921, 2010549018, 2011827638, 2014090929, 2014129292, 2015847175, 2016161810, 2016464961, 2017191527, - 2018336444, 2022291557, 2022973269, 2023498746, 2024853642, 2027445678, 2027814180, 2027828650, 2027909489, 2028116487, 2029133999, 2029909894, 2033003588, 2033828953, 2034767768, 2036061488, 2036750157, 2037182006, 2038925801, 2039012903, - 2041942843, 2042861943, 2044016080, 2045407567, 2045821218, 2046759770, 2047006719, 2047769687, 2048205721, 2048560397, 2049698913, 2052321529, 2052328978, 2052343947, 2053899162, 2054212564, 2055783490, 2060969286, 2061144988, 2063408339, - 2064145552, 2064308502, 2066440075, 2066865713, 2067100479, 2067499753, 2068343250, 2068743361, 2069178089, 2070467093, 2072440819, 2073482870, 2074840378, 2074896270, 2076612603, 2077667592, 2078528215, 2079492652, 2080735477, 2081544705, - 2082760612, 2084953915, 2085323316, 2087660971, 2088576982, 2088786920, 2088955494, 2089981667, 2090025563, 2090543533, 2090570016, 2090684129, 2091626028, 2093472294, 2094085507, 2094159153, 2094591332, 2094864173, 2097057488, 2098829619, - 2100497812, 2103236982, 2105321510, 2105638337, 2105718728, 2105814934, 2108439398, 2109052886, 2109530615, 2109851473, 2113434968, 2114587535, 2115445751, 2116495484, 2117880007, 2118203528, 2118433006, 2118805956, 2118821565, 2119425672, - 2122262571, 2122852959, 2123379476, 2124749673, 2125958841, 2126029304, 2126940990, 2126963607, 2128078174, 2128826472, 2129513521, 2129930580, 2130252471, 2130879949, 2131761201, 2131797509, 2133066804, 2135673182, 2139976479, 2140091269, + 690983, 900852, 2196420, 2530146, 3159407, 3522194, 3794415, 4031164, 5309142, 5363460, 9736243, 11476473, 12744598, 12849216, 12937811, 13180701, 13887419, 14125900, 14239125, 16411608, + 19227407, 20643769, 21289266, 22136821, 22762734, 23288667, 24379565, 25885333, 26292400, 26687179, 27377406, 27563032, 28256901, 28791588, 30992839, 31153367, 31574181, 31596852, 35595330, 35859252, + 37017340, 37141933, 38620214, 41714278, 42021322, 43955934, 47036070, 47452797, 47463938, 48311975, 48775768, 50748643, 50968578, 51692325, 53868166, 55461678, 58159196, 58217952, 59384706, 60536525, + 61716770, 62209567, 63244522, 64795664, 66579049, 68067591, 69118708, 69889880, 70003859, 70894786, 72319656, 72802865, 72939206, 74887898, 75922980, 77104822, 77482422, 78348530, 80321564, 80404202, + 80900939, 81402251, 82879528, 84924801, 87897457, 88823122, 89400484, 90063199, 91177380, 92271196, 92620223, 92860378, 93191015, 94760711, 95752736, 99511825, 104637677, 104727360, 105384223, 106223060, + 106595511, 107095939, 107160610, 108021700, 108346070, 108413311, 108628319, 109035776, 109526756, 112035400, 112648605, 113462155, 113580144, 114202152, 115016418, 116766659, 117260224, 117280545, 117766047, 119285206, + 119656942, 122124863, 123352211, 123889599, 127867199, 128036841, 130001148, 131405125, 133790520, 134453363, 135012885, 135678410, 137046551, 137796456, 139494505, 140536987, 145611377, 146002907, 148113917, 148527979, + 149171217, 150878039, 151416112, 152273285, 155845605, 156498369, 156760399, 161450336, 161502390, 163362230, 167653495, 168771888, 169293723, 169726789, 170281493, 172109594, 173062659, 173822937, 174082258, 174965839, + 175753599, 175843632, 176024101, 177100916, 178901145, 180549009, 180599971, 181567810, 182598318, 183679578, 185592115, 185658088, 185979744, 186112992, 186178768, 188016786, 190215907, 190536346, 190807078, 193873940, + 195379046, 196401930, 197964832, 198186681, 198233440, 200083737, 200253206, 202502890, 204514903, 205008108, 206653795, 208160226, 208433088, 210098472, 210748671, 210908782, 212046016, 212821393, 214725897, 215018112, + 216435361, 216557804, 217762975, 218671081, 221330186, 221661515, 222529745, 225091211, 225908941, 225934851, 226723092, 226726100, 226906236, 226986415, 227427283, 227870124, 228960529, 229905664, 230340298, 230634042, + 231181585, 232170581, 234039217, 236851791, 237020443, 238278880, 238566180, 239990424, 240618723, 241481265, 241537930, 241711645, 244709448, 244975305, 245334962, 247243083, 247447060, 247448424, 249700039, 250022739, + 250129297, 250731366, 250859482, 251514112, 253898558, 255226842, 256210446, 256860662, 257728183, 258177907, 259768753, 259775677, 260267972, 260670135, 260674360, 260792255, 261556590, 265363198, 267174620, 268087516, + 269167950, 270410557, 270814499, 271906847, 274746405, 277497333, 277942057, 279252402, 281317274, 283430575, 284658041, 287497702, 288054543, 289686472, 291298358, 293109484, 294191106, 295666215, 298799048, 299505702, + 300191208, 300618464, 301350822, 301663421, 301673313, 302219842, 303845878, 304131252, 304211060, 304427548, 305489695, 305750851, 308005013, 308700094, 308832070, 308857120, 310273032, 311127477, 316479300, 317980803, + 318750634, 320137025, 322748588, 324215873, 325324443, 325667019, 328551896, 329049266, 329767814, 330474090, 331284679, 332201519, 333820982, 333906659, 334037304, 335456148, 336213879, 338532526, 340231765, 340442582, + 341475746, 341674967, 341987235, 343038558, 343119399, 343682568, 344515114, 344860208, 346598567, 348131466, 349249331, 350182379, 351741654, 353946286, 355614494, 356546370, 356638683, 356672421, 359735266, 360632817, + 362748128, 363508800, 364589031, 364620240, 365275089, 365854486, 366700722, 367923081, 368541415, 368889391, 371790550, 372280769, 372465453, 372501343, 373226849, 373305330, 375863194, 376781122, 378912543, 379470588, + 380070610, 381094614, 381571915, 381933797, 382422699, 385878401, 386733714, 387061281, 387273799, 387611445, 388855203, 389233190, 390743779, 391321675, 395360213, 398211404, 398244682, 398911194, 399114073, 399456957, + 399991238, 401446720, 402845420, 403378386, 407771887, 411864717, 413058646, 416457166, 417568373, 419053054, 419109342, 419476096, 420106224, 421198539, 422047044, 423299667, 424587711, 430093707, 432102601, 432609664, + 432990571, 433412593, 434850545, 435236973, 435288306, 436476038, 436580096, 436630343, 437710825, 438711458, 443704960, 444361278, 446372159, 448284065, 448708980, 451448729, 452888789, 454359988, 454438520, 454746323, + 455856722, 456462271, 459340678, 460420451, 460893030, 461442838, 461527795, 462743614, 462857778, 464171383, 464795711, 465119445, 470090505, 472745168, 472872107, 473318229, 477317888, 477407584, 478721193, 481561285, + 481563348, 482917205, 483348027, 485818381, 486165509, 486181025, 487888229, 490920543, 492507266, 494367164, 495097609, 497867498, 498702377, 499898207, 500376868, 500734709, 502237764, 502323961, 502558280, 503368137, + 503895325, 506466155, 507848158, 507936866, 508041515, 509116230, 509744705, 510478312, 510497580, 512494446, 513009937, 513561613, 513582947, 514214340, 514914429, 515414188, 515811664, 517767440, 518073650, 519194709, + 519344323, 519699747, 520329478, 520511102, 520699193, 522160389, 522408049, 524320231, 525605961, 528024121, 529233847, 530093821, 532132334, 532467027, 533101409, 534384094, 535828217, 536063430, 538932155, 539429964, + 539942311, 540006359, 540093580, 540952308, 542609105, 543952312, 544899032, 545066288, 545602285, 546340809, 548632788, 549253917, 550532376, 553373537, 556328195, 559509624, 560663378, 562994480, 565150174, 566166447, + 567779677, 568652142, 569949159, 571635069, 572240371, 574236644, 576906032, 577384103, 577410402, 578787063, 579174666, 580464203, 580692625, 583112200, 585169793, 585804640, 589049769, 590690783, 592006699, 592234826, + 594054971, 594814862, 595717488, 597427397, 598016845, 602368560, 602907378, 603159718, 603907009, 604275115, 604977130, 607471900, 607761482, 612289854, 614222093, 614612685, 615734453, 617768643, 617995659, 618168829, + 618681206, 619428858, 619461174, 619972089, 620497725, 621921213, 622114437, 622170346, 623670976, 623909040, 624614472, 624714335, 624939139, 625991894, 628445699, 630393584, 631022494, 631399565, 631936923, 632611704, + 633075975, 633240394, 636485510, 637659983, 638167485, 640835502, 644293952, 644842409, 646688705, 649754857, 650513248, 651536866, 651750790, 652078020, 652404808, 653050943, 653626077, 654912216, 655200896, 655445946, + 656954306, 657251271, 661318748, 664387510, 665601851, 666624765, 670621648, 671848647, 672323245, 672906535, 673775121, 674580901, 675549432, 675663963, 677220745, 678475375, 679519053, 680172541, 682018288, 683393460, + 683536723, 685006165, 686797873, 687941098, 688338919, 688483428, 690710531, 690806365, 690865719, 691093904, 692845661, 693737559, 696002734, 696188251, 696448050, 697685269, 697817760, 697866347, 698660475, 700725671, + 701959731, 702380578, 703130341, 705508794, 705851791, 706357381, 706825946, 706913763, 709651138, 714042223, 714456194, 715940689, 717911282, 720339756, 721046824, 721524505, 722162727, 722260205, 722347551, 722919148, + 723323690, 723930558, 726141970, 726869128, 727587915, 729474445, 729509794, 730090881, 730296520, 730422541, 730845665, 731606176, 731763278, 732388681, 732444124, 736455241, 737377568, 737518341, 738682048, 739596391, + 740536012, 741078359, 741184696, 742185643, 743572345, 743745539, 745183293, 745777837, 747592875, 748527394, 749415493, 750631050, 750919339, 751885764, 752388169, 753296935, 754215794, 754247044, 754896618, 755554593, + 755798022, 757787251, 757959820, 758174758, 761851297, 762564955, 764902582, 764935753, 765386206, 765701205, 767233910, 767880329, 768185796, 769005536, 770412991, 770957259, 772059719, 772251062, 772503535, 773197243, + 777433215, 778702716, 778834747, 779093898, 783427298, 785398708, 785989696, 786297537, 786566648, 787106123, 787537653, 787842886, 787913688, 790256415, 790929190, 791188057, 791384486, 793505636, 795915364, 797060176, + 798445606, 799527371, 799717076, 800591831, 800661980, 801046035, 801610475, 801824335, 802730854, 804368379, 806384435, 806638567, 806673335, 809604334, 810387144, 810516965, 812094461, 812288356, 812328969, 813511681, + 814302898, 815110420, 817417567, 820933470, 821481684, 822635252, 823532901, 827496819, 829450571, 829844031, 830595166, 831270563, 831273447, 832081018, 833019845, 834410115, 835063788, 835506582, 836307572, 836983022, + 837024327, 837554186, 839507573, 840106059, 843738737, 844057079, 845698678, 846127236, 846650758, 847255974, 848141854, 848402819, 849489374, 851322111, 851716534, 852338021, 852388468, 852835634, 853545598, 854475547, + 855107605, 856621012, 856837002, 857894203, 858045289, 858150908, 859385989, 859612092, 860360715, 863551327, 863647665, 866097476, 866478506, 866854601, 866964848, 867628573, 869853078, 871908043, 873623623, 873976891, + 874153641, 875481479, 876130333, 878692218, 878744414, 878884686, 879380479, 879552408, 879878312, 880456526, 880688023, 881982271, 882282387, 882484999, 885873448, 886978116, 887841601, 890461390, 891710357, 892574149, + 892939912, 893302687, 893597382, 893957771, 894769708, 894937325, 895080280, 895562064, 898893218, 901789102, 904287249, 906899219, 907401151, 907554175, 909273561, 909415369, 910677024, 912381406, 914906004, 915948205, + 916073297, 917508270, 918378387, 919736727, 921573402, 922186026, 923478775, 923768127, 924541465, 925604268, 925975225, 926200942, 926939064, 927045887, 927524181, 928179911, 928836931, 929351822, 930367387, 932423857, + 933603111, 933673987, 934048997, 934700736, 935490932, 935573751, 935689637, 935939763, 937081176, 937976428, 937987129, 939497524, 941471466, 942977997, 943871886, 944382193, 945948973, 946311527, 946425090, 946489895, + 948686793, 949010757, 949222447, 950009818, 951256529, 951663731, 952824381, 953383750, 953877041, 954441852, 954915740, 954942098, 957037315, 958774566, 959354209, 960982228, 964348374, 965490116, 965562483, 966363087, + 968848252, 969076419, 969305448, 969358207, 969500483, 970194422, 972058766, 973367349, 973490494, 973493986, 973769771, 976015092, 976063110, 977454680, 977907387, 978247260, 980702956, 980863365, 983043723, 985305323, + 986240059, 987761406, 988431201, 991159735, 991874801, 992410365, 993525189, 993786972, 994291574, 997649666, 998931662, 999229412, 999346398, 999899279, 1007042224, 1010427073, 1011417836, 1011473945, 1011596733, 1012611702, + 1013901419, 1016469330, 1016615447, 1020037994, 1021014457, 1022861633, 1025117441, 1026342885, 1026380990, 1027758817, 1027760887, 1028529524, 1028820236, 1028937430, 1029176122, 1029338154, 1029832956, 1031625002, 1032748996, 1032914339, + 1033910502, 1035075488, 1035956563, 1037521069, 1038018856, 1038830638, 1042790263, 1042942541, 1043920511, 1044088643, 1045627895, 1045658065, 1047336724, 1048943084, 1049475248, 1050373352, 1050512245, 1051184301, 1054066034, 1057003814, + 1058677375, 1058937717, 1061864942, 1063657548, 1063743848, 1063768444, 1063839036, 1065136414, 1065481253, 1066014062, 1066787659, 1067775613, 1068587688, 1068798385, 1069450170, 1073695485, 1073871430, 1074205225, 1075762632, 1076198976, + 1078197595, 1079859867, 1082499152, 1082864732, 1082881617, 1085326591, 1087195269, 1087245613, 1087251698, 1087556673, 1087742330, 1089408490, 1089710430, 1090104632, 1090386021, 1090443335, 1092382563, 1092881031, 1094283114, 1094531762, + 1095403694, 1099847920, 1100041120, 1100089300, 1101722351, 1101933540, 1102423908, 1102603775, 1103013140, 1106678970, 1110387095, 1111213862, 1112056034, 1112731797, 1113693824, 1120963974, 1121432739, 1121800211, 1121960111, 1122768484, + 1123331233, 1123555638, 1125104871, 1125822965, 1126017956, 1127173529, 1127911377, 1128895624, 1130850177, 1131661227, 1132597050, 1133473813, 1133910514, 1134185180, 1135793759, 1136264020, 1136356724, 1137511396, 1139018167, 1139159604, + 1140008063, 1140728569, 1143168018, 1143511498, 1143853106, 1144017176, 1144669754, 1147341731, 1147793249, 1148699143, 1149113346, 1150780072, 1152335090, 1152416171, 1154842325, 1155459206, 1155544307, 1156824624, 1157666831, 1159675637, + 1159745061, 1159898528, 1160036198, 1160186023, 1160285859, 1160333307, 1160537912, 1161580432, 1162679490, 1165446977, 1166227930, 1167207852, 1168465459, 1169327477, 1170510314, 1170759710, 1171051384, 1171925835, 1172290275, 1173840088, + 1173889730, 1174587016, 1175004233, 1175885101, 1178086274, 1178260876, 1179525294, 1180063064, 1180525723, 1181191604, 1183464058, 1184561748, 1185825535, 1188076819, 1188748563, 1189141368, 1189323192, 1190890142, 1191079043, 1191513656, + 1192155877, 1194041213, 1194709162, 1198213061, 1198254803, 1198857033, 1199317660, 1201124879, 1201152163, 1201659316, 1202009920, 1202162389, 1203377492, 1203897636, 1204992245, 1205522527, 1205895814, 1206302514, 1209784819, 1209991461, + 1212628403, 1212974417, 1214379246, 1214950832, 1215063385, 1215103809, 1216475831, 1217804021, 1218522465, 1220523503, 1220915309, 1221108420, 1221726287, 1222554291, 1223475486, 1223572435, 1223583276, 1228817775, 1230449468, 1231111410, + 1231149357, 1231249235, 1231639101, 1231932661, 1232567659, 1232992084, 1233022905, 1234157881, 1234944834, 1239665569, 1240287664, 1245819051, 1247518755, 1249086623, 1249183285, 1250360726, 1255524953, 1256015513, 1256152080, 1256372950, + 1257507406, 1260859787, 1262399341, 1267173039, 1269707634, 1271370220, 1273223611, 1273955724, 1274190723, 1274436639, 1275331596, 1275500498, 1276205250, 1278053582, 1278777407, 1278794420, 1279061703, 1279981214, 1281443423, 1285258674, + 1286989824, 1287171290, 1287830283, 1288684086, 1289308008, 1290629443, 1290969161, 1291025252, 1291070368, 1291438802, 1292049996, 1292413659, 1293091635, 1294873695, 1296857499, 1298200648, 1299667896, 1302272656, 1302724177, 1303736105, + 1305071296, 1308872551, 1310177444, 1312064004, 1312471120, 1313115559, 1313640711, 1313871880, 1316120929, 1317077622, 1317201705, 1318032594, 1318900244, 1319798607, 1321897861, 1322281086, 1322696419, 1323798820, 1324123626, 1324723894, + 1325008187, 1325083914, 1326017288, 1328272543, 1328885292, 1331383316, 1331593955, 1332379148, 1332467446, 1332620900, 1332937015, 1333790305, 1334857284, 1335236478, 1335298265, 1335652095, 1335861008, 1336108161, 1336513734, 1337406065, + 1338090388, 1339293088, 1340949553, 1344125357, 1345014111, 1345378476, 1345873587, 1345987999, 1347284277, 1348361229, 1348373925, 1350653461, 1352833750, 1353144470, 1353999206, 1355086853, 1355391150, 1356847855, 1361012693, 1361078114, + 1365423458, 1367731096, 1368235387, 1370528050, 1372169786, 1373978529, 1374125186, 1375470750, 1377995642, 1379259015, 1379460673, 1379995885, 1382429941, 1382484003, 1382551511, 1382893830, 1383307838, 1383640563, 1384314543, 1385675177, + 1386258142, 1386366954, 1387039848, 1387864976, 1388759892, 1389787451, 1389954587, 1390040163, 1390274260, 1390306889, 1390477985, 1390656632, 1391095995, 1391827090, 1392162662, 1394929399, 1395155215, 1395289708, 1396662140, 1399673078, + 1399854717, 1400070607, 1400929335, 1401058771, 1401980800, 1402735006, 1403206383, 1403771494, 1404727477, 1405668251, 1405763119, 1407094080, 1408805003, 1409001936, 1412540552, 1413860940, 1414141069, 1414160501, 1415390230, 1417415680, + 1417601340, 1420810050, 1424797596, 1424859828, 1426483935, 1427504270, 1428223489, 1430821640, 1431492783, 1431814151, 1434046375, 1434633879, 1435859758, 1437147036, 1440145706, 1441811554, 1444048519, 1444076976, 1445225855, 1445279202, + 1445352642, 1447469119, 1447876480, 1450892344, 1451277631, 1451442832, 1453397990, 1455316979, 1455756978, 1457464894, 1459100749, 1459138745, 1459500136, 1459620801, 1462192184, 1462501905, 1462778368, 1462921857, 1463269859, 1466632447, + 1466679625, 1467376771, 1468486929, 1470285405, 1471131758, 1471461419, 1471598258, 1472567100, 1473166451, 1473735214, 1475638246, 1480273562, 1480324438, 1480437960, 1482983072, 1485740112, 1486594282, 1487620835, 1489699243, 1491477359, + 1492071476, 1492488573, 1496078411, 1496277718, 1497680539, 1497926365, 1498554338, 1500102591, 1501181424, 1502266386, 1502480836, 1502557594, 1504023310, 1505022272, 1505475223, 1506716966, 1507433029, 1508705426, 1510133268, 1512135729, + 1512163910, 1513255537, 1514278798, 1514582723, 1514792012, 1515262458, 1515528736, 1515933932, 1519017268, 1520667645, 1520886946, 1521350211, 1522316172, 1524006589, 1524491858, 1525451290, 1527022962, 1528031307, 1533447203, 1533496974, + 1534330971, 1536213818, 1537459540, 1538069400, 1538391713, 1539560507, 1541125975, 1541132933, 1541546082, 1545555937, 1546057655, 1546104436, 1547662666, 1548588723, 1548804416, 1550012286, 1550159640, 1550525411, 1550721460, 1551661799, + 1553547892, 1554106660, 1555325521, 1555660285, 1558244592, 1558695709, 1560142576, 1561212123, 1561251584, 1561422777, 1561730727, 1563717683, 1564061243, 1565610678, 1565700239, 1566878909, 1568176414, 1568395337, 1568900638, 1569479928, + 1570645300, 1571598133, 1572212863, 1575380740, 1577034674, 1577955754, 1579725218, 1581062145, 1581118537, 1581801257, 1584408128, 1585050246, 1588222158, 1588715179, 1589194592, 1590461855, 1590771096, 1593359038, 1593837351, 1594621666, + 1596042792, 1596821127, 1597506096, 1598436917, 1599565995, 1599876594, 1600023202, 1600493361, 1601134240, 1601247294, 1601617797, 1602517354, 1602827413, 1602967659, 1603428054, 1604330946, 1604357658, 1605294199, 1605369007, 1607204293, + 1607515830, 1607628402, 1607677838, 1609955669, 1610244183, 1610539590, 1611500622, 1611558740, 1611680320, 1612593993, 1612609979, 1614780688, 1617229086, 1618378831, 1619598456, 1619641914, 1620562432, 1620803320, 1622692876, 1622758049, + 1624653209, 1627355806, 1628387880, 1628389501, 1629633514, 1629914848, 1630293700, 1630776459, 1631405417, 1631935240, 1633512617, 1634445325, 1635952299, 1636203720, 1636860706, 1640952769, 1642338733, 1642884452, 1643991754, 1644353864, + 1645969422, 1646704157, 1648575360, 1649344003, 1649392096, 1650899832, 1652108025, 1653332243, 1655277291, 1656527154, 1657001479, 1658037573, 1659079595, 1659137391, 1660678300, 1663100626, 1663890071, 1665914525, 1666074170, 1667102296, + 1667679197, 1672192305, 1673314595, 1674045273, 1675300017, 1675494182, 1677449797, 1678967663, 1679324299, 1679777458, 1680251429, 1680294422, 1681866717, 1682700783, 1683915700, 1684018729, 1685350721, 1685880008, 1686215900, 1686479103, + 1686570783, 1687540458, 1687941280, 1688652157, 1689946986, 1690167792, 1691486500, 1691676526, 1695191950, 1695617313, 1697686200, 1702425249, 1704561346, 1705378439, 1705905941, 1706528514, 1708002892, 1708106609, 1708126014, 1709019727, + 1709697877, 1709823304, 1710305778, 1711569347, 1711718534, 1711761015, 1711765426, 1712269139, 1712341869, 1713188647, 1713475126, 1714295540, 1715279374, 1715379173, 1715402379, 1716853034, 1719009954, 1719573683, 1721767511, 1723143470, + 1725541486, 1726987516, 1727583308, 1730333306, 1730721241, 1731949250, 1732028080, 1733366374, 1733982669, 1737931879, 1738353358, 1740099311, 1740778973, 1740783613, 1742032331, 1742434188, 1745247524, 1745393357, 1745543275, 1746273091, + 1746476698, 1746904676, 1747861289, 1749972876, 1750197960, 1750443194, 1750955971, 1752088215, 1752318678, 1752598186, 1753125385, 1754447491, 1755204784, 1757028186, 1758748737, 1760851607, 1761289401, 1763785295, 1764436465, 1765354961, + 1765830270, 1767380006, 1768795266, 1770497338, 1771614266, 1771924274, 1772760484, 1774218355, 1774652096, 1774796872, 1775331228, 1775608361, 1775805177, 1776471922, 1776794410, 1778544166, 1781233744, 1781891230, 1783233173, 1783943137, + 1784682542, 1787338655, 1787391786, 1788389051, 1790557628, 1792756324, 1793190956, 1793747608, 1797641070, 1799210492, 1800186189, 1800522575, 1802197319, 1802327778, 1803183394, 1806061681, 1807085904, 1807172811, 1808237662, 1811088032, + 1815408878, 1816641611, 1817156134, 1820281480, 1821482472, 1821559709, 1822279764, 1822612008, 1823053058, 1826590258, 1826628136, 1826880531, 1827651881, 1833543700, 1833603743, 1834161399, 1834254978, 1834285819, 1834318089, 1834388383, + 1834852613, 1835203128, 1835860030, 1835977906, 1836119534, 1837280287, 1838218199, 1839063567, 1840896199, 1846605728, 1847908587, 1848681194, 1849495275, 1849657867, 1849675857, 1852181952, 1855359256, 1858637614, 1858933377, 1859683061, + 1860435620, 1860839427, 1862876260, 1864952910, 1866094167, 1868151949, 1868289345, 1869264274, 1870214195, 1870859970, 1871060346, 1871684562, 1873900475, 1874026715, 1874855959, 1876255297, 1878253960, 1878434988, 1879635915, 1880483834, + 1880577483, 1881253854, 1883168929, 1883999260, 1886317932, 1890889527, 1890938638, 1891630185, 1891904961, 1892370478, 1893095488, 1896952705, 1897691227, 1897907456, 1898582764, 1900162831, 1900613055, 1901537567, 1902501708, 1902595458, + 1904243956, 1904514273, 1904576737, 1904770864, 1905279500, 1906345724, 1907793490, 1908093581, 1909681194, 1910978116, 1912065710, 1913489530, 1913581092, 1913926325, 1914764659, 1914809801, 1915435344, 1916602098, 1918354829, 1920182565, + 1924603748, 1926717418, 1927367009, 1928309762, 1928550562, 1930662128, 1930880552, 1931282005, 1931493432, 1932108837, 1933532372, 1933923245, 1935271536, 1936668087, 1938258683, 1939683211, 1942089394, 1943137808, 1943651015, 1944679691, + 1945110368, 1946004194, 1948121717, 1949896838, 1950124297, 1951228823, 1952177514, 1952364329, 1952805989, 1953450944, 1953919896, 1955436051, 1957728250, 1957877704, 1958396887, 1959222232, 1959292396, 1961619988, 1961647235, 1962689485, + 1963053072, 1965358941, 1965855212, 1967705762, 1968608155, 1968623233, 1969729134, 1970797151, 1971484382, 1971654864, 1977865396, 1980923963, 1981481446, 1983379601, 1984143440, 1984152603, 1985895474, 1986921372, 1989240516, 1992941115, + 1994402695, 1997381015, 2001056977, 2002881120, 2004664325, 2004770236, 2005021017, 2005653265, 2005817027, 2006320950, 2006856683, 2009244921, 2010549018, 2011827638, 2014090929, 2014129292, 2015847175, 2016161810, 2016464961, 2017191527, + 2018336444, 2022291557, 2022973269, 2023498746, 2024853642, 2027445678, 2027814180, 2027828650, 2027909489, 2028116487, 2029133999, 2029909894, 2033003588, 2033828953, 2034767768, 2036061488, 2036750157, 2037182006, 2038925801, 2039012903, + 2041942843, 2042861943, 2044016080, 2045407567, 2045821218, 2046759770, 2047006719, 2047769687, 2048205721, 2048560397, 2049698913, 2052321529, 2052328978, 2052343947, 2053899162, 2054212564, 2055783490, 2060969286, 2061144988, 2063408339, + 2064145552, 2064308502, 2066440075, 2066865713, 2067100479, 2067499753, 2068343250, 2068743361, 2069178089, 2070467093, 2072440819, 2073482870, 2074840378, 2074896270, 2076612603, 2077667592, 2078528215, 2079492652, 2080735477, 2081544705, + 2082760612, 2084953915, 2085323316, 2087660971, 2088576982, 2088786920, 2088955494, 2089981667, 2090025563, 2090543533, 2090570016, 2090684129, 2091626028, 2093472294, 2094085507, 2094159153, 2094591332, 2094864173, 2097057488, 2098829619, + 2100497812, 2103236982, 2105321510, 2105638337, 2105718728, 2105814934, 2108439398, 2109052886, 2109530615, 2109851473, 2113434968, 2114587535, 2115445751, 2116495484, 2117880007, 2118203528, 2118433006, 2118805956, 2118821565, 2119425672, + 2122262571, 2122852959, 2123379476, 2124749673, 2125958841, 2126029304, 2126940990, 2126963607, 2128078174, 2128826472, 2129513521, 2129930580, 2130252471, 2130879949, 2131761201, 2131797509, 2133066804, 2135673182, 2139976479, 2140091269, 2140756121, 2141591317, 2142357746, 2143324534, 2143343312, 2143968639, 2145073408, 2145930822 }; diff --git a/test/benchmarks/qsort/qsort.c b/test/benchmarks/qsort/qsort.c index a76ec5c7b..ef3981b8a 100644 --- a/test/benchmarks/qsort/qsort.c +++ b/test/benchmarks/qsort/qsort.c @@ -13,8 +13,8 @@ #include "util.h" #include //#include -#include #include +#include // The INSERTION_THRESHOLD is the size of the subarray when the // algorithm switches to using an insertion sort instead of @@ -25,109 +25,110 @@ // NSTACK is the required auxiliary storage. // It must be at least 2*lg(DATA_SIZE) -#define NSTACK 50 +#define NSTACK 50 //-------------------------------------------------------------------------- // Input/Reference Data -#define type int +#define type int #include "dataset1.h" // Swap macro for swapping two values. -#define SWAP(a,b) do { typeof(a) temp=(a);(a)=(b);(b)=temp; } while (0) -#define SWAP_IF_GREATER(a, b) do { if ((a) > (b)) SWAP(a, b); } while (0) +#define SWAP( a, b ) \ + do { \ + typeof( a ) temp = ( a ); \ + ( a ) = ( b ); \ + ( b ) = temp; \ + } while( 0 ) +#define SWAP_IF_GREATER( a, b ) \ + do { \ + if( ( a ) > ( b ) ) \ + SWAP( a, b ); \ + } while( 0 ) //-------------------------------------------------------------------------- // Quicksort function -static void insertion_sort(size_t n, type arr[]) -{ +static void insertion_sort( size_t n, type arr[] ) { type *i, *j; - type value; - for (i = arr+1; i < arr+n; i++) - { + type value; + for( i = arr + 1; i < arr + n; i++ ) { value = *i; - j = i; - while (value < *(j-1)) - { - *j = *(j-1); - if (--j == arr) + j = i; + while( value < *( j - 1 ) ) { + *j = *( j - 1 ); + if( --j == arr ) break; } *j = value; } } -static void selection_sort(size_t n, type arr[]) -{ - for (type* i = arr; i < arr+n-1; i++) - for (type* j = i+1; j < arr+n; j++) - SWAP_IF_GREATER(*i, *j); +static void selection_sort( size_t n, type arr[] ) { + for( type* i = arr; i < arr + n - 1; i++ ) + for( type* j = i + 1; j < arr + n; j++ ) + SWAP_IF_GREATER( *i, *j ); } -void sort(size_t n, type arr[]) -{ - type* ir = arr+n; - type* l = arr+1; - type* stack[NSTACK]; +void sort( size_t n, type arr[] ) { + type* ir = arr + n; + type* l = arr + 1; + type* stack[NSTACK]; type** stackp = stack; - for (;;) - { + for( ;; ) { // Insertion sort when subarray small enough. - if ( ir-l < INSERTION_THRESHOLD ) - { - insertion_sort(ir - l + 1, l - 1); + if( ir - l < INSERTION_THRESHOLD ) { + insertion_sort( ir - l + 1, l - 1 ); - if ( stackp == stack ) break; + if( stackp == stack ) + break; // Pop stack and begin a new round of partitioning. ir = *stackp--; - l = *stackp--; - } - else - { + l = *stackp--; + } else { // Choose median of left, center, and right elements as // partitioning element a. Also rearrange so that a[l-1] <= a[l] <= a[ir-]. - SWAP(arr[((l-arr) + (ir-arr))/2-1], l[0]); - SWAP_IF_GREATER(l[-1], ir[-1]); - SWAP_IF_GREATER(l[0], ir[-1]); - SWAP_IF_GREATER(l[-1], l[0]); + SWAP( arr[( ( l - arr ) + ( ir - arr ) ) / 2 - 1], l[0] ); + SWAP_IF_GREATER( l[-1], ir[-1] ); + SWAP_IF_GREATER( l[0], ir[-1] ); + SWAP_IF_GREATER( l[-1], l[0] ); // Initialize pointers for partitioning. - type* i = l+1; + type* i = l + 1; type* j = ir; // Partitioning element. - type a = l[0]; - - for (;;) { // Beginning of innermost loop. - while (*i++ < a); // Scan up to find element > a. - while (*(j-- - 2) > a); // Scan down to find element < a. - if (j < i) break; // Pointers crossed. Partitioning complete. - SWAP(i[-1], j[-1]); // Exchange elements. - } // End of innermost loop. + type a = l[0]; + + for( ;; ) { // Beginning of innermost loop. + while( *i++ < a ) + ; // Scan up to find element > a. + while( *( j-- - 2 ) > a ) + ; // Scan down to find element < a. + if( j < i ) + break; // Pointers crossed. Partitioning complete. + SWAP( i[-1], j[-1] ); // Exchange elements. + } // End of innermost loop. // Insert partitioning element. - l[0] = j[-1]; + l[0] = j[-1]; j[-1] = a; stackp += 2; // Push pointers to larger subarray on stack, // process smaller subarray immediately. - if ( ir-i+1 >= j-l ) - { - stackp[0] = ir; + if( ir - i + 1 >= j - l ) { + stackp[0] = ir; stackp[-1] = i; - ir = j-1; - } - else - { - stackp[0] = j-1; + ir = j - 1; + } else { + stackp[0] = j - 1; stackp[-1] = l; - l = i; + l = i; } } } @@ -136,13 +137,12 @@ void sort(size_t n, type arr[]) //-------------------------------------------------------------------------- // Main -int main( int argc, char* argv[] ) -{ +int main( int argc, char* argv[] ) { #if PREALLOCATE // If needed we preallocate everything in the caches - sort(DATA_SIZE, verify_data); - if (verify(DATA_SIZE, input_data, input_data)){ - assert(0); + sort( DATA_SIZE, verify_data ); + if( verify( DATA_SIZE, input_data, input_data ) ) { + assert( 0 ); return 1; } #endif @@ -155,6 +155,6 @@ int main( int argc, char* argv[] ) // Check the results int v = verify( DATA_SIZE, input_data, verify_data ); - assert(0 == v); + assert( 0 == v ); return v; } diff --git a/test/benchmarks/qsort/qsort_gendata.pl b/test/benchmarks/qsort/qsort_gendata.pl index 92fc8fa00..0b2554292 100755 --- a/test/benchmarks/qsort/qsort_gendata.pl +++ b/test/benchmarks/qsort/qsort_gendata.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl #========================================================================== # qsort_gendata.pl # @@ -129,4 +129,3 @@ () } main(); - diff --git a/test/benchmarks/towers/Makefile b/test/benchmarks/towers/Makefile index 8f9802e3f..8b5eaf39b 100644 --- a/test/benchmarks/towers/Makefile +++ b/test/benchmarks/towers/Makefile @@ -3,7 +3,7 @@ # # makefile: big_loop.c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/benchmarks/towers/towers.c b/test/benchmarks/towers/towers.c index 14f8853c8..56702dba4 100644 --- a/test/benchmarks/towers/towers.c +++ b/test/benchmarks/towers/towers.c @@ -19,71 +19,64 @@ // This is the number of discs in the puzzle. -#define NUM_DISCS 7 +#define NUM_DISCS 7 //-------------------------------------------------------------------------- // List data structure and functions -struct Node -{ - int val; +struct Node { + int val; struct Node* next; }; -struct List -{ - int size; +struct List { + int size; struct Node* head; }; struct List g_nodeFreeList; struct Node g_nodePool[NUM_DISCS]; -int list_getSize( struct List* list ) -{ +int list_getSize( struct List* list ) { return list->size; } -void list_init( struct List* list ) -{ +void list_init( struct List* list ) { list->size = 0; list->head = 0; } -void list_push( struct List* list, int val ) -{ +void list_push( struct List* list, int val ) { struct Node* newNode; // Pop the next free node off the free list - newNode = g_nodeFreeList.head; + newNode = g_nodeFreeList.head; g_nodeFreeList.head = g_nodeFreeList.head->next; // Push the new node onto the given list - newNode->next = list->head; - list->head = newNode; + newNode->next = list->head; + list->head = newNode; // Assign the value - list->head->val = val; + list->head->val = val; // Increment size list->size++; - } -int list_pop( struct List* list ) -{ +int list_pop( struct List* list ) { struct Node* freedNode; - int val; + int val; // Get the value from the->head of given list - val = list->head->val; + val = list->head->val; // Pop the head node off the given list - freedNode = list->head; - list->head = list->head->next; + freedNode = list->head; + list->head = list->head->next; // Push the freed node onto the free list - freedNode->next = g_nodeFreeList.head; + freedNode->next = g_nodeFreeList.head; g_nodeFreeList.head = freedNode; // Decrement size @@ -92,101 +85,87 @@ int list_pop( struct List* list ) return val; } -void list_clear( struct List* list ) -{ - while ( list_getSize(list) > 0 ) - list_pop(list); +void list_clear( struct List* list ) { + while( list_getSize( list ) > 0 ) + list_pop( list ); } //-------------------------------------------------------------------------- // Tower data structure and functions -struct Towers -{ - int numDiscs; - int numMoves; +struct Towers { + int numDiscs; + int numMoves; struct List pegA; struct List pegB; struct List pegC; }; -void towers_init( struct Towers* this, int n ) -{ +void towers_init( struct Towers* this, int n ) { int i; this->numDiscs = n; this->numMoves = 0; - list_init( &(this->pegA) ); - list_init( &(this->pegB) ); - list_init( &(this->pegC) ); - - for ( i = 0; i < n; i++ ) - list_push( &(this->pegA), n-i ); + list_init( &( this->pegA ) ); + list_init( &( this->pegB ) ); + list_init( &( this->pegC ) ); + for( i = 0; i < n; i++ ) + list_push( &( this->pegA ), n - i ); } -void towers_clear( struct Towers* this ) -{ +void towers_clear( struct Towers* this ) { - list_clear( &(this->pegA) ); - list_clear( &(this->pegB) ); - list_clear( &(this->pegC) ); + list_clear( &( this->pegA ) ); + list_clear( &( this->pegB ) ); + list_clear( &( this->pegC ) ); towers_init( this, this->numDiscs ); - } -void towers_solve_h( struct Towers* this, int n, - struct List* startPeg, - struct List* tempPeg, - struct List* destPeg ) -{ +void towers_solve_h( struct Towers* this, int n, struct List* startPeg, struct List* tempPeg, struct List* destPeg ) { int val; - if ( n == 1 ) { - val = list_pop(startPeg); - list_push(destPeg,val); + if( n == 1 ) { + val = list_pop( startPeg ); + list_push( destPeg, val ); this->numMoves++; + } else { + towers_solve_h( this, n - 1, startPeg, destPeg, tempPeg ); + towers_solve_h( this, 1, startPeg, tempPeg, destPeg ); + towers_solve_h( this, n - 1, tempPeg, startPeg, destPeg ); } - else { - towers_solve_h( this, n-1, startPeg, destPeg, tempPeg ); - towers_solve_h( this, 1, startPeg, tempPeg, destPeg ); - towers_solve_h( this, n-1, tempPeg, startPeg, destPeg ); - } - } -void towers_solve( struct Towers* this ) -{ - towers_solve_h( this, this->numDiscs, &(this->pegA), &(this->pegB), &(this->pegC) ); +void towers_solve( struct Towers* this ) { + towers_solve_h( this, this->numDiscs, &( this->pegA ), &( this->pegB ), &( this->pegC ) ); } -int towers_verify( struct Towers* this ) -{ +int towers_verify( struct Towers* this ) { struct Node* ptr; - int numDiscs = 0; + int numDiscs = 0; - if ( list_getSize(&this->pegA) != 0 ) { + if( list_getSize( &this->pegA ) != 0 ) { return 2; } - if ( list_getSize(&this->pegB) != 0 ) { + if( list_getSize( &this->pegB ) != 0 ) { return 3; } - if ( list_getSize(&this->pegC) != this->numDiscs ) { + if( list_getSize( &this->pegC ) != this->numDiscs ) { return 4; } - for ( ptr = this->pegC.head; ptr != 0; ptr = ptr->next ) { + for( ptr = this->pegC.head; ptr != 0; ptr = ptr->next ) { numDiscs++; - if ( ptr->val != numDiscs ) { + if( ptr->val != numDiscs ) { return 5; } } - if ( this->numMoves != ((1 << this->numDiscs) - 1) ) { + if( this->numMoves != ( ( 1 << this->numDiscs ) - 1 ) ) { return 6; } @@ -196,21 +175,20 @@ int towers_verify( struct Towers* this ) //-------------------------------------------------------------------------- // Main -int main( int argc, char* argv[] ) -{ +int main( int argc, char* argv[] ) { struct Towers towers; - int i; + int i; // Initialize free list list_init( &g_nodeFreeList ); - g_nodeFreeList.head = &(g_nodePool[0]); - g_nodeFreeList.size = NUM_DISCS; - g_nodePool[NUM_DISCS-1].next = 0; - g_nodePool[NUM_DISCS-1].val = 99; - for ( i = 0; i < (NUM_DISCS-1); i++ ) { - g_nodePool[i].next = &(g_nodePool[i+1]); - g_nodePool[i].val = i; + g_nodeFreeList.head = &( g_nodePool[0] ); + g_nodeFreeList.size = NUM_DISCS; + g_nodePool[NUM_DISCS - 1].next = 0; + g_nodePool[NUM_DISCS - 1].val = 99; + for( i = 0; i < ( NUM_DISCS - 1 ); i++ ) { + g_nodePool[i].next = &( g_nodePool[i + 1] ); + g_nodePool[i].val = i; } towers_init( &towers, NUM_DISCS ); @@ -224,13 +202,12 @@ int main( int argc, char* argv[] ) // Solve it towers_clear( &towers ); -// setStats(1); //DDD: These set CSR counters which are not 100% supported in Rev yet + // setStats(1); //DDD: These set CSR counters which are not 100% supported in Rev yet towers_solve( &towers ); -// setStats(0); + // setStats(0); // Check the results int result = towers_verify( &towers ); - assert(result == 0); + assert( result == 0 ); return result; } - diff --git a/test/bge_ble/Makefile b/test/bge_ble/Makefile index 48bc014b0..bf10b880b 100644 --- a/test/bge_ble/Makefile +++ b/test/bge_ble/Makefile @@ -3,7 +3,7 @@ # # makefile: bge_ble # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/bge_ble/bge_ble.c b/test/bge_ble/bge_ble.c index 9828499ab..75a115f0b 100644 --- a/test/bge_ble/bge_ble.c +++ b/test/bge_ble/bge_ble.c @@ -1,6 +1,8 @@ int main() { - asm("li a2, 2; li a3, 2; bge a2, a3, 0x8; .byte 0x00; .byte 0x00; .byte 0x00; .byte 0x00;"); - asm("li a2, 2; li a3, 2; ble a2, a3, 0x8; .byte 0x00; .byte 0x00; .byte 0x00; .byte 0x00;"); + asm( "li a2, 2; li a3, 2; bge a2, a3, 0x8; .byte 0x00; .byte 0x00; .byte " + "0x00; .byte 0x00;" ); + asm( "li a2, 2; li a3, 2; ble a2, a3, 0x8; .byte 0x00; .byte 0x00; .byte " + "0x00; .byte 0x00;" ); - return 0; + return 0; } diff --git a/test/bge_ble/rev-bge-ble.py b/test/bge_ble/rev-bge-ble.py old mode 100644 new mode 100755 index 6d5c98fd1..022df7cec --- a/test/bge_ble/rev-bge-ble.py +++ b/test/bge_ble/rev-bge-ble.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "bge_ble.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "bge_ble.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/bge_ble/run_bge_ble.sh b/test/bge_ble/run_bge_ble.sh index 12a9d2fa8..7385b4829 100755 --- a/test/bge_ble/run_bge_ble.sh +++ b/test/bge_ble/run_bge_ble.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x bge_ble.exe ]; then +if [[ -x bge_ble.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-bge-ble.py else echo "Test BGE_BLE: bge_ble.exe not Found - likely build failed" diff --git a/test/big_loop/Makefile b/test/big_loop/Makefile index 1c1bffe4e..a1bf3a6d0 100644 --- a/test/big_loop/Makefile +++ b/test/big_loop/Makefile @@ -3,7 +3,7 @@ # # makefile: big_loop.c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/big_loop/big_loop.c b/test/big_loop/big_loop.c index 96c2a1f01..0b7fc9f69 100644 --- a/test/big_loop/big_loop.c +++ b/test/big_loop/big_loop.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,22 +11,22 @@ * */ -#include #include +#include uint64_t A[1024]; uint64_t B[1024]; uint64_t R[1024]; -int main(int argc, char **argv){ +int main( int argc, char** argv ) { uint64_t i = 0; uint64_t j = 0; - int r = 0; + int r = 0; - for( i=0; i<512; i++ ){ - for( unsigned j=0; j<512; j++ ){ + for( i = 0; i < 512; i++ ) { + for( unsigned j = 0; j < 512; j++ ) { R[j] = A[j] + B[j] * i; - if( (R[j]%2) == 0 ){ + if( ( R[j] % 2 ) == 0 ) { r++; } } diff --git a/test/big_loop/run_big_loop.sh b/test/big_loop/run_big_loop.sh old mode 100644 new mode 100755 index bad7b1bf8..0d14a4dc6 --- a/test/big_loop/run_big_loop.sh +++ b/test/big_loop/run_big_loop.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x big_loop.exe ]; then +if [[ -x big_loop.exe ]]; then sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program="big_loop.exe" --numHarts=1 --numCores=1 else echo "Test BIG_LOOP: big_loop.exe not Found - likely build failed" diff --git a/test/cache_1/Makefile b/test/cache_1/Makefile index c67319ee2..2d8febd25 100644 --- a/test/cache_1/Makefile +++ b/test/cache_1/Makefile @@ -3,7 +3,7 @@ # # makefile: large_bss # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/cache_1/cache_1.c b/test/cache_1/cache_1.c index fbe87844d..686535150 100644 --- a/test/cache_1/cache_1.c +++ b/test/cache_1/cache_1.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,13 +13,13 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; int j = 0; - i = i + argc; - for( i=0; i<1024; i++ ){ - if( (j/3) == 0 ){ - j+= i*12; + i = i + argc; + for( i = 0; i < 1024; i++ ) { + if( ( j / 3 ) == 0 ) { + j += i * 12; } } return i; diff --git a/test/cache_1/rev-test-cache1.py b/test/cache_1/rev-test-cache1.py old mode 100644 new mode 100755 index 1725aa25d..74b556c85 --- a/test/cache_1/rev-test-cache1.py +++ b/test/cache_1/rev-test-cache1.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -15,22 +16,22 @@ DEBUG_MEM = 10 DEBUG_LEVEL = 10 VERBOSE = 10 -MEM_SIZE = 1024 * 1024 * 1024 - 1 +memSize = 1024 * 1024 * 1024 - 1 # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams( { - "verbose": 6, # Verbosity - "numCores": 1, # Number of cores - "clock": "2.0GHz", # Clock - "memSize": MEM_SIZE, # Memory size in bytes - "machine": "[0:RV32I]", # Core:Config; RV32I for core 0 - "startAddr": "[0:0x00000000]", # Starting address for core 0 - "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "2.0GHz", # Clock + "memSize": memSize, # Memory size in bytes + "machine": "[0:RV32I]", # Core:Config; RV32I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles "program": os.getenv("REV_EXE", "cache_1.exe"), # Target executable - "enable_memH": 1, # Enable memHierarchy support - "splash": 1, # Display the splash message + "enableMemH": 1, # Enable memHierarchy support + "splash": 1, # Display the splash message } ) comp_cpu.enableAllStatistics() @@ -82,7 +83,7 @@ "clock": "2GHz", "verbose": VERBOSE, "addr_range_start": 0, - "addr_range_end": MEM_SIZE, + "addr_range_end": memSize, "backing": "malloc", } ) diff --git a/test/cache_1/run_cache_1.sh b/test/cache_1/run_cache_1.sh index f780cb630..65b8679dc 100755 --- a/test/cache_1/run_cache_1.sh +++ b/test/cache_1/run_cache_1.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x cache_1.exe ]; then +if [[ -x cache_1.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-test-cache1.py else echo "Test CACHE-TEST1: cache_test1.exe not Found - likely build failed" diff --git a/test/cache_2/Makefile b/test/cache_2/Makefile index d6560497e..1adda5792 100644 --- a/test/cache_2/Makefile +++ b/test/cache_2/Makefile @@ -3,7 +3,7 @@ # # makefile: cache_test2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/cache_2/cache_2.c b/test/cache_2/cache_2.c index 45cddfe94..f87936924 100644 --- a/test/cache_2/cache_2.c +++ b/test/cache_2/cache_2.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,9 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; - } diff --git a/test/cache_2/rev-test-cache2.py b/test/cache_2/rev-test-cache2.py old mode 100644 new mode 100755 index 1e9155e33..a49e38d22 --- a/test/cache_2/rev-test-cache2.py +++ b/test/cache_2/rev-test-cache2.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -15,85 +16,85 @@ DEBUG_MEM = 10 DEBUG_LEVEL = 10 VERBOSE = 10 -MEM_SIZE = 1024*1024*1024-1 +memSize = 1024*1024*1024-1 # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 10, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "2.0GHz", # Clock - "memSize" : MEM_SIZE, # Memory size in bytes - "machine" : "[0:RV64GC]", # Core:Config; RV64G for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "cache_2.exe"), # Target executable - "enable_memH" : 1, # Enable memHierarchy support - "splash" : 1 # Display the splash message + "verbose": 10, # Verbosity + "numCores": 1, # Number of cores + "clock": "2.0GHz", # Clock + "memSize": memSize, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64G for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "cache_2.exe"), # Target executable + "enableMemH": 1, # Enable memHierarchy support + "splash": 1 # Display the splash message }) comp_cpu.enableAllStatistics() # Create the RevMemCtrl subcomponent -comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl"); +comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl") comp_lsq.addParams({ - "verbose" : "10", - "clock" : "2.0Ghz", - "max_loads" : 64, - "max_stores" : 64, - "max_flush" : 64, - "max_llsc" : 64, - "max_readlock" : 64, - "max_writeunlock" : 64, - "max_custom" : 64, - "ops_per_cycle" : 64 + "verbose": "10", + "clock": "2.0Ghz", + "max_loads": 64, + "max_stores": 64, + "max_flush": 64, + "max_llsc": 64, + "max_readlock": 64, + "max_writeunlock": 64, + "max_custom": 64, + "ops_per_cycle": 64 }) -comp_lsq.enableAllStatistics({"type":"sst.AccumulatorStatistic"}) +comp_lsq.enableAllStatistics({"type": "sst.AccumulatorStatistic"}) iface = comp_lsq.setSubComponent("memIface", "memHierarchy.standardInterface") iface.addParams({ - "verbose" : VERBOSE + "verbose": VERBOSE }) l1cache = sst.Component("l1cache", "memHierarchy.Cache") l1cache.addParams({ - "access_latency_cycles" : "4", - "cache_frequency" : "2 Ghz", - "replacement_policy" : "lru", - "coherence_protocol" : "MESI", - "associativity" : "4", - "cache_line_size" : "64", - "debug" : 1, - "debug_level" : DEBUG_LEVEL, - "verbose" : VERBOSE, - "L1" : "1", - "cache_size" : "16KiB" + "access_latency_cycles": "4", + "cache_frequency": "2 Ghz", + "replacement_policy": "lru", + "coherence_protocol": "MESI", + "associativity": "4", + "cache_line_size": "64", + "debug": 1, + "debug_level": DEBUG_LEVEL, + "verbose": VERBOSE, + "L1": "1", + "cache_size": "16KiB" }) memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams({ - "debug" : DEBUG_MEM, - "debug_level" : DEBUG_LEVEL, - "clock" : "2GHz", - "verbose" : VERBOSE, - "addr_range_start" : 0, - "addr_range_end" : MEM_SIZE, - "backing" : "malloc" + "debug": DEBUG_MEM, + "debug_level": DEBUG_LEVEL, + "clock": "2GHz", + "verbose": VERBOSE, + "addr_range_start": 0, + "addr_range_end": memSize, + "backing": "malloc" }) memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams({ - "access_time" : "100ns", - "mem_size" : "8GB" + "access_time": "100ns", + "mem_size": "8GB" }) -#sst.setStatisticLoadLevel(7) -#sst.setStatisticOutput("sst.statOutputConsole") -#sst.enableAllStatisticsForAllComponents() +# sst.setStatisticLoadLevel(7) +# sst.setStatisticOutput("sst.statOutputConsole") +# sst.enableAllStatisticsForAllComponents() link1 = sst.Link("link1") -link1.connect( (iface, "port", "1ns"), (l1cache, "high_network_0", "1ns") ) +link1.connect((iface, "port", "1ns"), (l1cache, "high_network_0", "1ns")) link2 = sst.Link("link2") -link2.connect( (l1cache, "low_network_0", "1ns"), (memctrl, "direct_link", "1ns") ) +link2.connect((l1cache, "low_network_0", "1ns"), (memctrl, "direct_link", "1ns")) # EOF diff --git a/test/cache_2/run_cache_2.sh b/test/cache_2/run_cache_2.sh index 727bf1077..7dd1cf056 100755 --- a/test/cache_2/run_cache_2.sh +++ b/test/cache_2/run_cache_2.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x cache_2.exe ]; then +if [[ -x cache_2.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-test-cache2.py else echo "Test TEST_CACHE2: cache_test2.exe not Found - likely build failed" diff --git a/test/coproc_ex/Makefile b/test/coproc_ex/Makefile index e81ff6d5f..598bb8001 100644 --- a/test/coproc_ex/Makefile +++ b/test/coproc_ex/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -14,7 +14,7 @@ EXAMPLE=coproc_ex CC="${RVCC}" -ARCH=rv64imafd +ARCH=rv64gc #ABI=lp64 all: $(EXAMPLE).exe diff --git a/test/coproc_ex/coproc_ex.c b/test/coproc_ex/coproc_ex.c index db26e2d15..765437509 100644 --- a/test/coproc_ex/coproc_ex.c +++ b/test/coproc_ex/coproc_ex.c @@ -1,22 +1,22 @@ -/* - * ex1.c - * - * RISC-V ISA: RV32I - * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC - * All Rights Reserved - * contact@tactcomplabs.com - * - * See LICENSE in the top level directory for licensing details - * - */ - -#include - -int main(int argc, char **argv){ - int i = 9; - i = i + argc; - asm volatile("ADDIW a0, a0, 0"); - asm volatile("ADDIW a0, a0, 0"); - return i; -} +/* + * ex1.c + * + * RISC-V ISA: RV32I + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include + +int main( int argc, char** argv ) { + int i = 9; + i = i + argc; + asm volatile( "ADDIW a0, a0, 0" ); + asm volatile( "ADDIW a0, a0, 0" ); + return i; +} diff --git a/test/coproc_ex/rev-test-coproc_ex.py b/test/coproc_ex/rev-test-coproc_ex.py old mode 100644 new mode 100755 index 0b6cc82fd..312c263a2 --- a/test/coproc_ex/rev-test-coproc_ex.py +++ b/test/coproc_ex/rev-test-coproc_ex.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,23 +23,23 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GC]", # Core:Config; RV64GC for core 0 - "enableCoProc" : 1, - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "coproc_ex.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64GC for core 0 + "enableCoProc": 1, + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "coproc_ex.exe"), # Target executable + "splash": 1 # Display the splash message }) comp_cpu.enableAllStatistics() comp_coProc = comp_cpu.setSubComponent("co_proc", "revcpu.RevSimpleCoProc") comp_coProc.addParams({ - "clock" : "1.0GHz", - "verbose" : 6 + "clock": "1.0GHz", + "verbose": 6 }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/coproc_ex/run_coproc_ex.sh b/test/coproc_ex/run_coproc_ex.sh index 78e6b37b4..4e380a572 100755 --- a/test/coproc_ex/run_coproc_ex.sh +++ b/test/coproc_ex/run_coproc_ex.sh @@ -4,7 +4,7 @@ make # Check that the exec was built... -if [ -x coproc_ex.exe ]; then +if [[ -x coproc_ex.exe ]]; then sst-info revcpu sst --add-lib-path=../../build/src/ ./rev-test-coproc_ex.py else diff --git a/test/csr/Makefile b/test/csr/Makefile new file mode 100644 index 000000000..de4509d32 --- /dev/null +++ b/test/csr/Makefile @@ -0,0 +1,26 @@ +# +# Makefile +# +# makefile: csr +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +EXAMPLE=csr +CXX="${RVCXX}" +ARCH=rv64gc +ABI=lp64d + +CFLAGS=-I ../../common/syscalls -O1 + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) $(CFLAGS) -march=$(ARCH) -mabi=$(ABI) -static -o $(EXAMPLE).exe $(EXAMPLE).cc +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/csr/csr.cc b/test/csr/csr.cc new file mode 100644 index 000000000..b2eee160e --- /dev/null +++ b/test/csr/csr.cc @@ -0,0 +1,259 @@ +/* + * csr.cc + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include "syscalls.h" +#include +#include +#include +#include + +#define assert( x ) \ + do { \ + if( !x ) \ + asm( " .word 0" ); \ + } while( 0 ) + +enum class CSROp { Write, Set, Clear }; + +enum class OpKind { Imm, Reg }; + +template +struct CSRInst; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + if constexpr( ARG == 0 ) { + asm volatile( "csrrw zero, %0, zero" ::"I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrw zero, %0, %1" ::"I"( CSR ), "r"( arg ) ); + } + } else { + if constexpr( ARG == 0 ) { + asm volatile( "csrrw %0, %1, zero" : "=r"( old ) : "I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrw %0, %1, %2" : "=r"( old ) : "I"( CSR ), "r"( arg ) ); + } + } + return old; + } +}; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + if constexpr( ARG == 0 ) { + asm volatile( "csrrs zero, %0, zero" ::"I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrs zero, %0, %1" ::"I"( CSR ), "r"( arg ) ); + } + return old; + } else { + if constexpr( ARG == 0 ) { + asm volatile( "csrrs %0, %1, zero" : "=r"( old ) : "I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrs %0, %1, %2" : "=r"( old ) : "I"( CSR ), "r"( arg ) ); + } + return old; + } + } +}; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + if constexpr( ARG == 0 ) { + asm volatile( "csrrc zero, %0, zero" ::"I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrc zero, %0, %1" ::"I"( CSR ), "r"( arg ) ); + } + } else { + if constexpr( ARG == 0 ) { + asm volatile( "csrrc %0, %1, zero" : "=r"( old ) : "I"( CSR ) ); + } else { + size_t arg = ARG; + asm volatile( "csrrc %0, %1, %2" : "=r"( old ) : "I"( CSR ), "r"( arg ) ); + } + } + return old; + } +}; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + asm volatile( "csrrwi zero, %0, %1" ::"I"( CSR ), "K"( ARG ) ); + } else { + asm volatile( "csrrwi %0, %1, %2" : "=r"( old ) : "I"( CSR ), "K"( ARG ) ); + } + return old; + } +}; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + asm volatile( "csrrsi zero, %0, %1" ::"I"( CSR ), "K"( ARG ) ); + } else { + asm volatile( "csrrsi %0, %1, %2" : "=r"( old ) : "I"( CSR ), "K"( ARG ) ); + } + return old; + } +}; + +template +struct CSRInst { + size_t operator()() { + size_t old = 0; + if constexpr( RD0 ) { + asm volatile( "csrrci zero, %0, %1" ::"I"( CSR ), "K"( ARG ) ); + } else { + asm volatile( "csrrci %0, %1, %2" : "=r"( old ) : "I"( CSR ), "K"( ARG ) ); + } + return old; + } +}; + +template +size_t ReadCSR() { + size_t old; + asm volatile( "csrr %0, %1" : "=r"( old ) : "I"( CSR ) ); + return old; +} + +size_t testnum = 0; + +template +void CSRTest1() { + ++testnum; + +#if 0 + char test[128]; + snprintf( test, sizeof( test ), " Test %zu:\n", testnum ); + rev_write( 1, test, strlen( test ) ); +#endif + + // Initialize the CSR register to INIT + CSRInst{}(); + + // Perform the CSR operation with the argument + size_t oldval = CSRInst{}(); + + // Read the new value of the CSR + size_t newval = ReadCSR(); + + // Old value must be initial value or zero + if constexpr( RD0 ) { + assert( oldval == 0 ); + } else { + assert( oldval == INIT ); + } + + // New value according to operation + switch( OP ) { + case CSROp::Write: assert( newval == ARG ); break; + case CSROp::Set: assert( newval == ( INIT | ARG ) ); break; + case CSROp::Clear: assert( newval == ( INIT & ~ARG ) ); break; + } +} + +template +void CSRTest2() { + CSRTest1(); + CSRTest1(); + CSRTest1(); +} + +template +void CSRTest3() { + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + + if constexpr( KIND == OpKind::Reg ) { + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + CSRTest2(); + } +} + +template +void CSRTest4() { + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + + if constexpr( KIND == OpKind::Reg ) { + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + CSRTest3(); + } +} + +template +void CSRTest5() { + CSRTest4(); + CSRTest4(); + CSRTest4(); + CSRTest4(); +} + +int main( int argc, char** argv ) { + + CSRTest5<1>(); // fflags + CSRTest5<2>(); // frm + CSRTest5<3>(); // fcsr + CSRTest5<0xff>(); // A random unprivileged read-write CSR + return 0; +} diff --git a/test/cxx/CMakeLists.txt b/test/cxx/CMakeLists.txt new file mode 100644 index 000000000..6ba679d13 --- /dev/null +++ b/test/cxx/CMakeLists.txt @@ -0,0 +1,11 @@ +# RevCPU test/cxx/CMakeLists.txt +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +add_rev_test(SIMPLE_STRUCT simple_struct 30 "test_level=2;rv64;memh;c++") +add_subdirectory(stl) diff --git a/test/cxx/simple_struct/Makefile b/test/cxx/simple_struct/Makefile index 784e9e73d..a3f95b635 100644 --- a/test/cxx/simple_struct/Makefile +++ b/test/cxx/simple_struct/Makefile @@ -3,7 +3,7 @@ # # makefile: simple_struct # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -13,13 +13,12 @@ .PHONY: src EXAMPLE=simple_struct -CC=riscv64-unknown-elf-g++ -#ARCH=rv64g -ARCH=rv64imafd +CXX=${RVCXX} +ARCH=rv64gc all: $(EXAMPLE).exe $(EXAMPLE).exe: $(EXAMPLE).cc - $(CC) -march=$(ARCH) -I../../../common/syscalls -o $(EXAMPLE).exe $(EXAMPLE).cc -static + $(CXX) -march=$(ARCH) -I../../../common/syscalls -o $(EXAMPLE).exe $(EXAMPLE).cc -static clean: rm -Rf $(EXAMPLE).exe diff --git a/test/cxx/simple_struct/rev-test-simple-struct.py b/test/cxx/simple_struct/rev-test-simple-struct.py old mode 100644 new mode 100755 index 28d46a876..8f0b99487 --- a/test/cxx/simple_struct/rev-test-simple-struct.py +++ b/test/cxx/simple_struct/rev-test-simple-struct.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,17 +23,17 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # - # "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "startSymbol" : "[0:_start]", - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "simple_struct.exe"), # Target executable - "trcStartCycle" : 1, - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # + # "startAddr": "[0:0x00000000]", # Starting address for core 0 + "startSymbol": "[0:_start]", + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "simple_struct.exe"), # Target executable + "trcStartCycle": 1, + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/cxx/simple_struct/run_simple_struct.sh b/test/cxx/simple_struct/run_simple_struct.sh index ce6858781..d5f1270fd 100755 --- a/test/cxx/simple_struct/run_simple_struct.sh +++ b/test/cxx/simple_struct/run_simple_struct.sh @@ -1,10 +1,17 @@ #!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# #Build the test make clean && make # Check that the exec was built... -if [ -x simple_struct.exe ]; then +if [[ -x simple_struct.exe ]]; then sst --add-lib-path=../../../build/src/ ./rev-test-simple-struct.py else echo "Test SIMPLE_STRUCT: simple_struct.exe not Found - likely build failed" diff --git a/test/cxx/simple_struct/simple_struct.cc b/test/cxx/simple_struct/simple_struct.cc index a6ee64339..b50d8a3e1 100644 --- a/test/cxx/simple_struct/simple_struct.cc +++ b/test/cxx/simple_struct/simple_struct.cc @@ -1,51 +1,51 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + #include "syscalls.h" #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) - +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) //Fine to overload new at global scope, could also be done per class -void* operator new(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; +void* operator new( std::size_t t ) { + void* p = reinterpret_cast( rev_mmap( 0, t, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 ) ); + return p; } //Not necessary to do this as a template, but this makes it easy to overload per class - template - void revDel(void* p){ - std::size_t addr = reinterpret_cast(p); - rev_munmap(addr, sizeof(T)); - } - +template +void revDel( void* p ) { + std::size_t addr = reinterpret_cast( p ); + rev_munmap( addr, sizeof( T ) ); +} class rec { - public: +public: unsigned c; - rec(unsigned a, unsigned b) { - c = a + b; - } + + rec( unsigned a, unsigned b ) { c = a + b; } //Must overload delete per class as we need to know how big the thing is we are freeing unless someone has // a better idea w/ some c++ magic? - void operator delete(void* p){ revDel(p); } + void operator delete( void* p ) { revDel( p ); } }; int main() { - rec testrec(1,2); - assert(testrec.c==3); + rec testrec( 1, 2 ); + assert( testrec.c == 3 ); - #if 1 - rec* pRec = new rec(2,3); - assert(pRec->c==5); +#if 1 + rec* pRec = new rec( 2, 3 ); + assert( pRec->c == 5 ); delete pRec; - #endif +#endif } diff --git a/test/cxx/stl/CMakeLists.txt b/test/cxx/stl/CMakeLists.txt new file mode 100644 index 000000000..c6d7e3542 --- /dev/null +++ b/test/cxx/stl/CMakeLists.txt @@ -0,0 +1,23 @@ +# RevCPU test/cxx/stl CMakeLists.txt +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#add_rev_test(array array 30 "memh;rv64;c++" SCRIPT "run_array.sh") +add_rev_test(map map 30 "test_level=2;memh;rv64;c++" SCRIPT "run_map.sh") +add_rev_test(map_obj map_obj 30 "test_level=2;memh;rv64;c++" SCRIPT "run_map_obj.sh") +add_rev_test(multimap multimap 30 "test_level=2;memh;rv64;c++" SCRIPT "run_multimap.sh") +add_rev_test(multimap_obj multimap_obj 30 "test_level=2;memh;rv64;c++" SCRIPT "run_multimap_obj.sh") +add_rev_test(vector vector 30 "test_level=2;memh;rv64;c++" SCRIPT "run_vector.sh") +#add_rev_test(vector_edge vector_edge 30 "memh;rv64;c++" SCRIPT "run_vector_edge.sh") +#add_rev_test(vector_int64_t vector_int64_t 30 "memh;rv64;c++" SCRIPT "run_vector_int64_t.sh") +add_rev_test(vector_obj vector_obj 30 "test_level=2;memh;rv64;c++" SCRIPT "run_vector_obj.sh") +add_rev_test(vector_pair vector_pair 30 "test_level=2;memh;rv64;c++" SCRIPT "run_vector_pair.sh") +#add_rev_test(vector_vector_int64_t vector_vector_int64_t 30 "memh;rv64;c++" SCRIPT "run_vector_vector_int64_t.sh") +add_rev_test(unordered_map unordered_map 30 "test_level=2;memh;rv64;c++" SCRIPT "run_unordered_map.sh") +add_rev_test(unordered_map_obj unordered_map_obj 30 "test_level=2;memh;rv64;c++" SCRIPT "run_unordered_map_obj.sh") + diff --git a/test/cxx/stl/array/Makefile b/test/cxx/stl/array/Makefile new file mode 100644 index 000000000..3a54a04ae --- /dev/null +++ b/test/cxx/stl/array/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: array +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=array +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/array/array.cc b/test/cxx/stl/array/array.cc new file mode 100644 index 000000000..094e0accf --- /dev/null +++ b/test/cxx/stl/array/array.cc @@ -0,0 +1,65 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include +#include + +#include "rev-macros.h" +#include "revalloc.h" + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +#define DIM 450 // Large array test +#define N 10 + +typedef std::basic_string, Allocator> revString; + +void testAlloc() { + std::array arr; + + for( int i = 0; i < DIM; i++ ) { + arr[i] = i; + } + + int expected_sum = DIM * ( DIM - 1 ) / 2; + int sum = 0; + for( int i = 0; i < DIM; i++ ) { + sum += arr[i]; + } + + assert( sum == expected_sum ); +} + +void testBoundsCheck() { + std::array arr; + + try { + arr.at( DIM ) = DIM; // accessing DIM using at should throw an exception + assert( false ); + } catch( const std::out_of_range& e ) { + // success + } +} + +int main() { + + //When constructing the map the correct method is to use the default constructor and then + // insert each element as shown (using std::pair + std::array arr; + + testAlloc(); + testBoundsCheck(); + + return 0; +} diff --git a/test/cxx/stl/array/rev-test.py b/test/cxx/stl/array/rev-test.py new file mode 100755 index 000000000..19526fd5d --- /dev/null +++ b/test/cxx/stl/array/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "array.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/array/run_array.sh b/test/cxx/stl/array/run_array.sh new file mode 100755 index 000000000..17cb5b00c --- /dev/null +++ b/test/cxx/stl/array/run_array.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x array.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX array.c: array.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/map/Makefile b/test/cxx/stl/map/Makefile index 64f39f229..80011234e 100644 --- a/test/cxx/stl/map/Makefile +++ b/test/cxx/stl/map/Makefile @@ -1,9 +1,9 @@ # # Makefile # -# makefile: vector +# makefile: map # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -13,14 +13,12 @@ .PHONY: src EXAMPLE=map -CC=riscv64-unknown-elf-g++ -#CC="${RVCC}" -#ARCH=rv64g -ARCH=rv64imafdc +CXX=${RVCXX} +ARCH=rv64gc all: $(EXAMPLE).exe -$(EXAMPLE).exe: $(EXAMPLE).c - $(CC) -march=$(ARCH) -O0 -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).c -static +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static clean: rm -Rf $(EXAMPLE).exe diff --git a/test/cxx/stl/map/map.c b/test/cxx/stl/map/map.c deleted file mode 100644 index 42cbf7a16..000000000 --- a/test/cxx/stl/map/map.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "revalloc.hpp" -#include -#include -#include "rev-macros.h" - -#define assert(x) if (!(x)) { asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); } - -typedef std::basic_string, Allocator > revString; - -int main() { - - //When constructing the map the correct method is to use the default constructor and then - // insert each element as shown (using std::pair) - - std::map< revString, - int, - std::less, - Allocator> > m; - - - m.insert(std::pair{"CPU", 10}); - m.insert(std::pair{"GPU", 11}); - m.insert(std::pair{"RAM", 12}); - assert(m.size() == 3); - - m["CPU"] = 15; - m["GPU"] = 17; - m["RAM"] = 20; - - assert(m["CPU"] == 15); - assert(m["GPU"] == 17); - assert(m["RAM"] == 20); - - assert(m.count("RAM") == 1); - assert(m.count("Nope") == 0); - - m.extract("RAM"); //Use extract instead of erase - assert(m.size () == 2); - assert(m["CPU"] == 15); - assert(m.count("RAM") == 0); - - m.extract("GPU"); - assert(m.size () == 1); - - return 0; -} diff --git a/test/cxx/stl/map/map.cc b/test/cxx/stl/map/map.cc new file mode 100644 index 000000000..93650e7e8 --- /dev/null +++ b/test/cxx/stl/map/map.cc @@ -0,0 +1,56 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +typedef std::basic_string, Allocator> revString; + +int main() { + + //When constructing the map the correct method is to use the default constructor and then + // insert each element as shown (using std::pair) + + std::map, Allocator>> m; + + m.insert( std::pair{ "CPU", 10 } ); + m.insert( std::pair{ "GPU", 11 } ); + m.insert( std::pair{ "RAM", 12 } ); + assert( m.size() == 3 ); + + m["CPU"] = 15; + m["GPU"] = 17; + m["RAM"] = 20; + + assert( m["CPU"] == 15 ); + assert( m["GPU"] == 17 ); + assert( m["RAM"] == 20 ); + + assert( m.count( "RAM" ) == 1 ); + assert( m.count( "Nope" ) == 0 ); + + m.extract( "RAM" ); //Use extract instead of erase + assert( m.size() == 2 ); + assert( m["CPU"] == 15 ); + assert( m.count( "RAM" ) == 0 ); + + m.extract( "GPU" ); + assert( m.size() == 1 ); + + return 0; +} diff --git a/test/cxx/stl/map/rev-test.py b/test/cxx/stl/map/rev-test.py old mode 100644 new mode 100755 index d03a32d9f..b5e85c880 --- a/test/cxx/stl/map/rev-test.py +++ b/test/cxx/stl/map/rev-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # rev-test.py # -import os import sst # Define SST core options @@ -22,15 +22,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 20, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "map.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "map.exe", # Target executable + "splash": 1 # Display the splash message }) # sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/cxx/stl/map/revalloc.hpp b/test/cxx/stl/map/revalloc.hpp deleted file mode 100644 index 82647fe63..000000000 --- a/test/cxx/stl/map/revalloc.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include "syscalls.h" -#include "unistd.h" - -#ifndef __REV_REVALLOC__ -#define __REV_REVALLOC__ - -/*void* operator new(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -}*/ - -void* mynew(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -} - -template -class StandardAllocPolicy { -public : - // typedefs - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - -public : - // convert an StandardAllocPolicy to StandardAllocPolicy - template - struct rebind { - typedef StandardAllocPolicy other; - }; - -public : - inline explicit StandardAllocPolicy() {} - inline ~StandardAllocPolicy() {} - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - template - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - - // memory allocation - inline pointer allocate(size_type cnt, - typename std::allocator::const_pointer = 0) { - return reinterpret_cast( - rev_mmap(0, // Let rev choose the address - cnt * sizeof(T), - PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions - MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous - -1, // No file descriptor because it's an anonymous mapping - 0)); // No offset, irrelevant for anonymous mappings - - } - inline void deallocate(pointer p, size_type n) { - // void* t = reinterpret_cast (p); - std::size_t addr = reinterpret_cast(p); - rev_munmap(addr, n); - } - - // size - inline size_type max_size() const { - return std::numeric_limits::max(); - } - - // construction/destruction - //inline void construct(pointer p, const T& t) { pointer z = new(sizeof(T); new(z) T(t); p = z; } - template - inline void construct(U* p, Args&&... args){ new(p) U(std::forward(args)...); }; - //template - //inline void construct(U* p, Args&&... args){ pointer z = reinterpret_cast(mynew(sizeof(U))); new(z) U(std::forward(args)...); p = z;} - inline void destroy(pointer p) { p->~T(); } -}; // end of class StandardAllocPolicy - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(StandardAllocPolicy const&, - StandardAllocPolicy const&) { - return true; -} -template -inline bool operator==(StandardAllocPolicy const&, - OtherAllocator const&) { - return false; -} - -template > -class Allocator : public Policy { -private : - typedef Policy AllocationPolicy; - -public : - typedef typename AllocationPolicy::size_type size_type; - typedef typename AllocationPolicy::difference_type difference_type; - typedef typename AllocationPolicy::pointer pointer; - typedef typename AllocationPolicy::const_pointer const_pointer; - typedef typename AllocationPolicy::reference reference; - typedef typename AllocationPolicy::const_reference const_reference; - typedef typename AllocationPolicy::value_type value_type; - -public : - template - struct rebind { - typedef Allocator::other> other; - }; - -public : - inline explicit Allocator() {} - inline ~Allocator() {} - inline Allocator(Allocator const& rhs): Policy(rhs) {} - template - inline Allocator(Allocator const&) {} - template - inline Allocator(Allocator const& rhs): Policy(rhs) {} -}; // end of class Allocator - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} - -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} -template -inline bool operator==(Allocator const& lhs, OtherAllocator const& rhs) { - return operator==(static_cast(lhs), rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - OtherAllocator const& rhs) { - return !operator==(lhs, rhs); -} - -#endif \ No newline at end of file diff --git a/test/cxx/stl/map/run_map.sh b/test/cxx/stl/map/run_map.sh new file mode 100755 index 000000000..609b4378f --- /dev/null +++ b/test/cxx/stl/map/run_map.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x map.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX map: map.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/map_obj/Makefile b/test/cxx/stl/map_obj/Makefile new file mode 100644 index 000000000..517f3ae8c --- /dev/null +++ b/test/cxx/stl/map_obj/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: map_obj +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=map_obj +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/map_obj/map_obj.cc b/test/cxx/stl/map_obj/map_obj.cc new file mode 100644 index 000000000..7cc242ffa --- /dev/null +++ b/test/cxx/stl/map_obj/map_obj.cc @@ -0,0 +1,108 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include +#include +#include + +#include "rev-macros.h" +#include "revalloc.h" + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } +#define DIM 450 + +typedef std::basic_string, Allocator> revString; + +class EntityEmbedding { +public: + uint64_t id; + std::array vals; + + EntityEmbedding( uint64_t id ) : id( id ) {} + + EntityEmbedding() {} +}; + +using TestMap = std::map, Allocator>>; + +void testInsertion() { + TestMap m; + + m.insert( { 0, EntityEmbedding( 0 ) } ); + m.insert( { 1, EntityEmbedding( 1 ) } ); + m.insert( { 0, EntityEmbedding( 2 ) } ); + + assert( m.size() == 2 ); // make sure that only two entries exist here + assert( m[0].id == 0 ); // the original value (0) should be returned +} + +void testFind() { + TestMap m; + + m.insert( { 0, EntityEmbedding( 0 ) } ); + m.insert( { 1, EntityEmbedding( 1 ) } ); + m.insert( { 0, EntityEmbedding( 2 ) } ); + m.insert( { 2, EntityEmbedding( 3 ) } ); + + assert( m.size() == 3 ); + + auto it1 = m.find( 1 ); // find key1 + assert( it1 != m.end() && it1->second.id == 1 ); + + auto it2 = m.find( 4 ); // find key that does not exist + assert( it2 == m.end() ); +} + +void testIteration() { + TestMap m; + + m.insert( { 1, EntityEmbedding( 0 ) } ); + m.insert( { 2, EntityEmbedding( 1 ) } ); + m.insert( { 3, EntityEmbedding( 2 ) } ); + m.insert( { 4, EntityEmbedding( 3 ) } ); + + assert( m.size() == 4 ); + + // ensure that the map is iterated in the intended order + int num = 1; + for( auto it = m.begin(); it != m.end(); it++ ) { + assert( it->first == num ); + num++; + } +} + +void testDeletion() { + TestMap m; + + m.insert( { 1, EntityEmbedding( 0 ) } ); + m.insert( { 2, EntityEmbedding( 1 ) } ); + m.insert( { 3, EntityEmbedding( 2 ) } ); + m.insert( { 4, EntityEmbedding( 3 ) } ); + + assert( m.size() == 4 ); + + auto check = m.extract( 1 ); // remove key 1 + assert( check.key() == 1 ); + assert( m.size() == 3 ); +} + +int main() { + + testInsertion(); + testFind(); + testIteration(); + testDeletion(); + + return 0; +} diff --git a/test/cxx/stl/map_obj/rev-test.py b/test/cxx/stl/map_obj/rev-test.py new file mode 100755 index 000000000..e5a37ff11 --- /dev/null +++ b/test/cxx/stl/map_obj/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "map_obj.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/map_obj/run_map_obj.sh b/test/cxx/stl/map_obj/run_map_obj.sh new file mode 100755 index 000000000..947532c01 --- /dev/null +++ b/test/cxx/stl/map_obj/run_map_obj.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x map_obj.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX map_pbj: map_obj.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/multimap/Makefile b/test/cxx/stl/multimap/Makefile new file mode 100644 index 000000000..322264630 --- /dev/null +++ b/test/cxx/stl/multimap/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: multimap +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=multimap +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/multimap/multimap.cc b/test/cxx/stl/multimap/multimap.cc new file mode 100644 index 000000000..86a424d26 --- /dev/null +++ b/test/cxx/stl/multimap/multimap.cc @@ -0,0 +1,119 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +typedef std::basic_string, Allocator> revString; + +using TestMultiMap = std::multimap< + uint64_t, // key + std::pair, // value + std::less, // sorting method + Allocator>>>; // revalloc Allocator + +void testInsertion() { + TestMultiMap m; + + m.insert( { + 1, {2, 3.0f} + } ); + m.insert( { + 2, {3, 4.0f} + } ); + assert( m.size() == 2 ); + + m.insert( { + 1, {4, 5.0f} + } ); + m.insert( { + 1, {6, 7.0f} + } ); + assert( m.size() == 4 ); +} + +void testDuplicateKeyInsertion() { + TestMultiMap m; + m.insert( { + 1, {2, 3.0f} + } ); + m.insert( { + 1, {4, 5.0f} + } ); + m.insert( { + 1, {6, 7.0f} + } ); + + assert( m.size() == 3 ); + + auto range = m.equal_range( 1 ); // all values for key 1 + int count = 0; + for( auto it = range.first; it != range.second; it++ ) { + count++; + } + assert( count == 3 ); // should be able to count 3 values for key 1 +} + +void testOrderPreservation() { + TestMultiMap m; + m.insert( { + 1, {2, 3.0f} + } ); + m.insert( { + 1, {4, 5.0f} + } ); + m.insert( { + 1, {6, 7.0f} + } ); + + auto it = m.begin(); + assert( it->second.first == 2 ); + it++; + assert( it->second.first == 4 ); +} + +void testDeletion() { + TestMultiMap m; + m.insert( { + 1, {2, 3.0f} + } ); + m.insert( { + 1, {4, 5.0f} + } ); + m.insert( { + 1, {6, 7.0f} + } ); + m.insert( { + 2, {7, 8.0f} + } ); + + assert( m.size() == 4 ); + + // delete all entries with key 2 + m.extract( 2 ); + + assert( m.size() == 3 ); +} + +int main() { + testInsertion(); + testDuplicateKeyInsertion(); + testOrderPreservation(); + testDeletion(); + return 0; +} diff --git a/test/cxx/stl/multimap/rev-test.py b/test/cxx/stl/multimap/rev-test.py new file mode 100755 index 000000000..d7c5551ed --- /dev/null +++ b/test/cxx/stl/multimap/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "multimap.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/multimap/run_multimap.sh b/test/cxx/stl/multimap/run_multimap.sh new file mode 100755 index 000000000..a99e51965 --- /dev/null +++ b/test/cxx/stl/multimap/run_multimap.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x multimap.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX multimap: multimap.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/multimap_obj/Makefile b/test/cxx/stl/multimap_obj/Makefile new file mode 100644 index 000000000..2c249eb30 --- /dev/null +++ b/test/cxx/stl/multimap_obj/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: multimap_obj +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=multimap_obj +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/multimap_obj/multimap_obj.cc b/test/cxx/stl/multimap_obj/multimap_obj.cc new file mode 100644 index 000000000..ce0b6b301 --- /dev/null +++ b/test/cxx/stl/multimap_obj/multimap_obj.cc @@ -0,0 +1,102 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +typedef std::basic_string, Allocator> revString; + +class WikiDataEdge { +public: + uint64_t src; + uint64_t dst; + uint64_t type; + + WikiDataEdge( uint64_t s, uint64_t d, uint64_t t ) : src( s ), dst( d ), type( t ) {} + + WikiDataEdge() {} +}; + +using TestMultiMap = std::multimap< + uint64_t, // key + WikiDataEdge, // value + std::less, // sorting method + Allocator>>; // revalloc Allocator + +void testInsertion() { + TestMultiMap m; + + m.insert( { 0, WikiDataEdge( 1, 2, 0 ) } ); + m.insert( { 1, WikiDataEdge( 1, 4, 1 ) } ); + m.insert( { 0, WikiDataEdge( 2, 1, 0 ) } ); + + assert( m.size() == 3 ); +} + +void testDuplicateKeyInsertion() { + TestMultiMap m; + m.insert( { 0, WikiDataEdge( 1, 2, 0 ) } ); + m.insert( { 1, WikiDataEdge( 1, 4, 1 ) } ); + m.insert( { 0, WikiDataEdge( 2, 1, 0 ) } ); + + assert( m.size() == 3 ); + + auto range = m.equal_range( 0 ); // all values for key 0 + int count = 0; + for( auto it = range.first; it != range.second; it++ ) { + count++; + } + assert( count == 2 ); // should be able to count 3 values for key 1 +} + +void testOrderPreservation() { + TestMultiMap m; + m.insert( { 0, WikiDataEdge( 1, 2, 0 ) } ); + m.insert( { 0, WikiDataEdge( 1, 4, 1 ) } ); + m.insert( { 0, WikiDataEdge( 2, 1, 0 ) } ); + + // note the order of insertion and checks is not the same + auto it = m.begin(); + assert( it->second.src == 1 && it->second.dst == 2 ); + it++; + assert( it->second.src == 1 && it->second.dst == 4 ); + it++; + assert( it->second.src == 2 && it->second.dst == 1 ); +} + +void testDeletion() { + TestMultiMap m; + m.insert( { 0, WikiDataEdge( 1, 2, 0 ) } ); + m.insert( { 1, WikiDataEdge( 1, 4, 1 ) } ); + m.insert( { 0, WikiDataEdge( 2, 1, 0 ) } ); + + assert( m.size() == 3 ); + + // delete all entries with key 1 + m.extract( 1 ); + + assert( m.size() == 2 ); +} + +int main() { + testInsertion(); + testDuplicateKeyInsertion(); + testOrderPreservation(); + testDeletion(); + return 0; +} diff --git a/test/cxx/stl/multimap_obj/rev-test.py b/test/cxx/stl/multimap_obj/rev-test.py new file mode 100755 index 000000000..c578f348f --- /dev/null +++ b/test/cxx/stl/multimap_obj/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "multimap_obj.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/multimap_obj/run_multimap_obj.sh b/test/cxx/stl/multimap_obj/run_multimap_obj.sh new file mode 100755 index 000000000..ef7d07cb0 --- /dev/null +++ b/test/cxx/stl/multimap_obj/run_multimap_obj.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x multimap_obj.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX multimap_obj: multimap_obj.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/unordered_map/Makefile b/test/cxx/stl/unordered_map/Makefile new file mode 100644 index 000000000..ff825f067 --- /dev/null +++ b/test/cxx/stl/unordered_map/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: unordered_map +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=unordered_map +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/unordered_map/rev-test.py b/test/cxx/stl/unordered_map/rev-test.py new file mode 100755 index 000000000..582f3f80a --- /dev/null +++ b/test/cxx/stl/unordered_map/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "unordered_map.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/unordered_map/run_unordered_map.sh b/test/cxx/stl/unordered_map/run_unordered_map.sh new file mode 100755 index 000000000..9b865268c --- /dev/null +++ b/test/cxx/stl/unordered_map/run_unordered_map.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x unordered_map.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX unordered_map: unordered_map.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/unordered_map/unordered_map.cc b/test/cxx/stl/unordered_map/unordered_map.cc new file mode 100644 index 000000000..beb77c681 --- /dev/null +++ b/test/cxx/stl/unordered_map/unordered_map.cc @@ -0,0 +1,88 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +typedef std::basic_string, Allocator> revString; + +using TestMap = + std::unordered_map, std::equal_to, Allocator>>; + +// using TestMap = std::unordered_map, Allocator> >; + +void testInsertion() { + TestMap m; + + m.insert( { 0, 1 } ); + m.insert( { 1, 2 } ); + m.insert( { 2, 3 } ); + assert( m.size() == 3 ); + + m.insert( { 0, 2 } ); + assert( m[0] == 1 ); // the orignal value of key 0 = 1 should be returned +} + +void testElementAccess() { + TestMap m; + m.insert( { 0, 1 } ); + m.insert( { 1, 2 } ); + m.insert( { 2, 3 } ); + + assert( m.find( 0 ) != m.end() && m[0] == 1 ); + + // key 4 should not exist in the map + assert( m.find( 4 ) == m.end() ); +} + +void testDeletion() { + TestMap m; + m.insert( { 0, 1 } ); + m.insert( { 1, 2 } ); + m.insert( { 2, 3 } ); + + assert( m.size() == 3 ); + + auto check = m.extract( 0 ); + + // removed element 0, check size, removed key and make sure key=0 does not exist in map + assert( m.find( 0 ) == m.end() && m.size() == 2 && check.key() == 0 ); +} + +void testIteration() { + TestMap m; + m.insert( { 0, 1 } ); + m.insert( { 1, 2 } ); + m.insert( { 2, 3 } ); + + // assert( m.begin()->first == 0 ); + + for( auto it = m.begin(); it != m.end(); it++ ) { + assert( it->first >= 0 && it->first <= 2 && it->second >= 1 && it->second <= 3 ); + } +} + +int main() { + + testInsertion(); + testElementAccess(); + testDeletion(); + testIteration(); + + return 0; +} diff --git a/test/cxx/stl/unordered_map_obj/Makefile b/test/cxx/stl/unordered_map_obj/Makefile new file mode 100644 index 000000000..88e6f9f97 --- /dev/null +++ b/test/cxx/stl/unordered_map_obj/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: unordered_map_obj +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=unordered_map_obj +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/unordered_map_obj/rev-test.py b/test/cxx/stl/unordered_map_obj/rev-test.py new file mode 100755 index 000000000..634eea6ff --- /dev/null +++ b/test/cxx/stl/unordered_map_obj/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "unordered_map_obj.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/unordered_map_obj/run_unordered_map_obj.sh b/test/cxx/stl/unordered_map_obj/run_unordered_map_obj.sh new file mode 100755 index 000000000..b4f432dab --- /dev/null +++ b/test/cxx/stl/unordered_map_obj/run_unordered_map_obj.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x unordered_map_obj.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX unordered_map_obj: unordered_map_obj.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/unordered_map_obj/unordered_map_obj.cc b/test/cxx/stl/unordered_map_obj/unordered_map_obj.cc new file mode 100644 index 000000000..c5359d94d --- /dev/null +++ b/test/cxx/stl/unordered_map_obj/unordered_map_obj.cc @@ -0,0 +1,120 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include +#include +#include + +#include "rev-macros.h" +#include "revalloc.h" + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } +#define DIM 450 + +typedef std::basic_string, Allocator> revString; + +class ContigSet { +public: + uint64_t id; + uint8_t val1; + uint64_t val2; + int val3; + + ContigSet() {} + + ContigSet( uint64_t id ) : id( id ) {} + + ContigSet( uint64_t id, uint8_t v1, uint64_t v2, uint64_t v3 ) : id( id ), val1( v1 ), val2( v2 ), val3( v3 ) {} +}; + +using TestMap = std:: + unordered_map, std::equal_to, Allocator>>; + +void testInsertion() { + TestMap m; + + m.insert( { 0, ContigSet( 0 ) } ); + m.insert( { 1, ContigSet( 1 ) } ); + m.insert( { 0, ContigSet( 2 ) } ); + + assert( m.size() == 2 ); // make sure that only two entries exist here + assert( m[0].id == 0 ); // the original value (0) should be returned + + // check for value update + m[0].id = 42; + assert( m[0].id == 42 ); +} + +void testFind() { + TestMap m; + + m.insert( { 0, ContigSet( 0 ) } ); + m.insert( { 1, ContigSet( 1 ) } ); + m.insert( { 0, ContigSet( 2 ) } ); + m.insert( { 2, ContigSet( 3 ) } ); + + assert( m.size() == 3 ); + + auto it1 = m.find( 1 ); // find key1 + assert( it1 != m.end() && it1->second.id == 1 ); + + auto it2 = m.find( 4 ); // find key that does not exist + assert( it2 == m.end() ); +} + +void testIteration() { + TestMap m; + + m.insert( { 1, ContigSet( 0 ) } ); + m.insert( { 2, ContigSet( 1 ) } ); + m.insert( { 3, ContigSet( 2 ) } ); + m.insert( { 4, ContigSet( 3 ) } ); + + assert( m.size() == 4 ); + + int count = 0; + + // ensure all objects are iterated over with range check on expected values + for( auto it = m.begin(); it != m.end(); it++ ) { + assert( it->first >= 1 && it->first <= 4 && it->second.id >= 0 && it->second.id <= 3 ); + count++; + } + + assert( count == m.size() ); +} + +void testDeletion() { + TestMap m; + + m.insert( { 1, ContigSet( 0 ) } ); + m.insert( { 2, ContigSet( 1 ) } ); + m.insert( { 3, ContigSet( 2 ) } ); + m.insert( { 4, ContigSet( 3 ) } ); + + assert( m.size() == 4 ); + + auto check = m.extract( 1 ); // remove key 1 + assert( check.key() == 1 ); + assert( m.size() == 3 ); +} + +int main() { + + testInsertion(); + testFind(); + testIteration(); + testDeletion(); + + return 0; +} diff --git a/test/cxx/stl/vector/Makefile b/test/cxx/stl/vector/Makefile index 433f85d09..ec961d683 100644 --- a/test/cxx/stl/vector/Makefile +++ b/test/cxx/stl/vector/Makefile @@ -3,7 +3,7 @@ # # makefile: vector # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -13,14 +13,12 @@ .PHONY: src EXAMPLE=vector -CC=riscv64-unknown-elf-g++ -#CC="${RVCC}" -#ARCH=rv64g -ARCH=rv64imafdc +CXX=${RVCXX} +ARCH=rv64gc all: $(EXAMPLE).exe -$(EXAMPLE).exe: $(EXAMPLE).c - $(CC) -march=$(ARCH) -O0 -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).c -static +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static clean: rm -Rf $(EXAMPLE).exe diff --git a/test/cxx/stl/vector/rev-test.py b/test/cxx/stl/vector/rev-test.py old mode 100644 new mode 100755 index ea53494a3..a31c53650 --- a/test/cxx/stl/vector/rev-test.py +++ b/test/cxx/stl/vector/rev-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # rev-test.py # -import os import sst # Define SST core options @@ -22,15 +22,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 20, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "vector.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector.exe", # Target executable + "splash": 1 # Display the splash message }) # sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/cxx/stl/vector/revalloc.hpp b/test/cxx/stl/vector/revalloc.hpp deleted file mode 100644 index d49f49b74..000000000 --- a/test/cxx/stl/vector/revalloc.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include "syscalls.h" -#include "unistd.h" - -#ifndef __REV_REVALLOC__ -#define __REV_REVALLOC__ - -/*void* operator new(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -}*/ - -void* mynew(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -} - -template -class StandardAllocPolicy { -public : - // typedefs - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - -public : - // convert an StandardAllocPolicy to StandardAllocPolicy - template - struct rebind { - typedef StandardAllocPolicy other; - }; - -public : - inline explicit StandardAllocPolicy() {} - inline ~StandardAllocPolicy() {} - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - template - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - - // memory allocation - inline pointer allocate(size_type cnt, - typename std::allocator::const_pointer = 0) { - return reinterpret_cast( - rev_mmap(0, // Let rev choose the address - cnt * sizeof(T), - PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions - MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous - -1, // No file descriptor because it's an anonymous mapping - 0)); // No offset, irrelevant for anonymous mappings - - } - inline void deallocate(pointer p, size_type n) - { std::size_t addr = reinterpret_cast(p); - rev_munmap(addr, n); } - //inline void deallocate(pointer p, size_type n) - // { rev_munmap(*p, n); } - - // size - inline size_type max_size() const { - return std::numeric_limits::max(); - } - - // construction/destruction - //inline void construct(pointer p, const T& t) { pointer z = new(sizeof(T); new(z) T(t); p = z; } - template - inline void construct(U* p, Args&&... args){ new(p) U(std::forward(args)...); }; - //template - //inline void construct(U* p, Args&&... args){ pointer z = reinterpret_cast(mynew(sizeof(U))); new(z) U(std::forward(args)...); p = z;} - inline void destroy(pointer p) { p->~T(); } -}; // end of class StandardAllocPolicy - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(StandardAllocPolicy const&, - StandardAllocPolicy const&) { - return true; -} -template -inline bool operator==(StandardAllocPolicy const&, - OtherAllocator const&) { - return false; -} - -template > -class Allocator : public Policy { -private : - typedef Policy AllocationPolicy; - -public : - typedef typename AllocationPolicy::size_type size_type; - typedef typename AllocationPolicy::difference_type difference_type; - typedef typename AllocationPolicy::pointer pointer; - typedef typename AllocationPolicy::const_pointer const_pointer; - typedef typename AllocationPolicy::reference reference; - typedef typename AllocationPolicy::const_reference const_reference; - typedef typename AllocationPolicy::value_type value_type; - -public : - template - struct rebind { - typedef Allocator::other> other; - }; - -public : - inline explicit Allocator() {} - inline ~Allocator() {} - inline Allocator(Allocator const& rhs): Policy(rhs) {} - template - inline Allocator(Allocator const&) {} - template - inline Allocator(Allocator const& rhs): Policy(rhs) {} -}; // end of class Allocator - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} - -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} -template -inline bool operator==(Allocator const& lhs, OtherAllocator const& rhs) { - return operator==(static_cast(lhs), rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - OtherAllocator const& rhs) { - return !operator==(lhs, rhs); -} - -#endif \ No newline at end of file diff --git a/test/cxx/stl/vector/run_vector.sh b/test/cxx/stl/vector/run_vector.sh new file mode 100755 index 000000000..effd46476 --- /dev/null +++ b/test/cxx/stl/vector/run_vector.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector: vector.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector/vector.c b/test/cxx/stl/vector/vector.c deleted file mode 100644 index 9450dc709..000000000 --- a/test/cxx/stl/vector/vector.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "revalloc.hpp" -#include -#include "rev-macros.h" - -#define assert(x) if (!(x)) { asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); } - -int main() { - std::vector > v; - v.push_back(0xbeef); - int a = v.back(); - assert(a == 0xbeef); - assert(v[0] == 0xbeef); - v.push_back(0xdead); - a = v.back(); - assert(a == 0xdead); - assert(v[0] == 0xbeef); - assert(v[1] == 0xdead); - assert(v.size() == 2); - v.pop_back(); - assert(v.size() == 1); - assert(v[0] == 0xbeef); - v.clear(); - for(int i = 0; i < 100; i++){ - v.push_back(i); - } - assert(v.size() == 100); - for(int i = 0; i < 100; i++){ - assert(v[i] == i); - } - return 0; -} diff --git a/test/cxx/stl/vector/vector.cc b/test/cxx/stl/vector/vector.cc new file mode 100644 index 000000000..b8beb0f68 --- /dev/null +++ b/test/cxx/stl/vector/vector.cc @@ -0,0 +1,45 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +int main() { + std::vector> v; + v.push_back( 0xbeef ); + int a = v.back(); + assert( a == 0xbeef ); + assert( v[0] == 0xbeef ); + v.push_back( 0xdead ); + a = v.back(); + assert( a == 0xdead ); + assert( v[0] == 0xbeef ); + assert( v[1] == 0xdead ); + assert( v.size() == 2 ); + v.pop_back(); + assert( v.size() == 1 ); + assert( v[0] == 0xbeef ); + v.clear(); + for( int i = 0; i < 100; i++ ) { + v.push_back( i ); + } + assert( v.size() == 100 ); + for( int i = 0; i < 100; i++ ) { + assert( v[i] == i ); + } + return 0; +} diff --git a/test/cxx/stl/vector_edge/Makefile b/test/cxx/stl/vector_edge/Makefile new file mode 100644 index 000000000..50ce997f5 --- /dev/null +++ b/test/cxx/stl/vector_edge/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: vector_edge +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=vector_edge +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/vector_edge/rev-test.py b/test/cxx/stl/vector_edge/rev-test.py new file mode 100755 index 000000000..db7af8f34 --- /dev/null +++ b/test/cxx/stl/vector_edge/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector_edge.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/vector_edge/run_vector_edge.sh b/test/cxx/stl/vector_edge/run_vector_edge.sh new file mode 100755 index 000000000..4d876e05e --- /dev/null +++ b/test/cxx/stl/vector_edge/run_vector_edge.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector_edge.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector_edge: vector_edge.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector_edge/vector_edge.cc b/test/cxx/stl/vector_edge/vector_edge.cc new file mode 100644 index 000000000..efb812e5e --- /dev/null +++ b/test/cxx/stl/vector_edge/vector_edge.cc @@ -0,0 +1,193 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "revalloc.h" +#include + +#include "rev-macros.h" + +#include +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +#define N 10 +#define M 20 + +typedef struct { + int src; + int dst; +} edge_t; + +class Edge { +public: + int src; + int dst; + + Edge() {} + + Edge( int src, int dst ) : src( src ), dst( dst ) {} + + Edge( const Edge& e ) : src( e.src ), dst( e.dst ) {} +}; + +void test_struct_edge_push_back() { + std::vector> v; + v.push_back( { 1, 1 } ); + v.push_back( { 2, 2 } ); + assert( v.size() == 2 && v[0].src == 1 && v[0].dst == 1 && v[1].src == 2 && v[1].dst == 2 ); +} + +void test_struct_edge_reserve() { + std::vector> v; + v.reserve( N ); + + auto initial_address = v.data(); + bool reserve_failed = false; + + // add N elements, the vector should not resize + for( int i = 0; i < N; i++ ) { + v.push_back( { i, i } ); + if( initial_address != v.data() ) { + reserve_failed = true; + break; + } + } + + assert( !reserve_failed && v.size() == N ); +} + +void test_struct_edge_resize() { + // assert(false); + std::vector> v; + v.resize( N ); + assert( v.size() == N ); + + // fill using the access operator + for( int i = 0; i < N; i++ ) { + v[i] = { i, i }; + } + + assert( v.size() == N && v[0].src == 0 && v[0].dst == 0 && ( v[N / 2].src = N / 2 ) && ( v[N / 2].dst = N / 2 ) ); +} + +void test_struct_edge_begin_and_end() { + std::vector> v; + for( int i = 0; i < N; i++ ) { + v.push_back( { i, i } ); + } + + // use an iterator to check if the vector contains the correct edges + int i = 0; + for( auto it = v.begin(); it != v.end(); it++, i++ ) { + assert( it->src == i && it->dst == i ); + } +} + +void test_struct_edge_at() { + std::vector> v; + for( int i = 0; i < N; i++ ) { + v.push_back( { i, i } ); + } + + for( int i = 0; i < N; i++ ) { + assert( v.at( i ).src == i && v.at( i ).dst == i ); + } + + try { + edge_t check = v.at( N + 1 ); + assert( false ); // this should never run + } catch( const std::out_of_range& e ) { + } +} + +void test_class_edge_reserve() { + std::vector> v; + v.reserve( N ); + + auto initial_address = v.data(); + bool reserve_failed = false; + + // add N elements, the vector should not resize + for( int i = 0; i < N; i++ ) { + v.push_back( Edge( i, i ) ); + if( initial_address != v.data() ) { + reserve_failed = true; + break; + } + } + + assert( !reserve_failed && v.size() == N ); +} + +void test_class_edge_resize() { + std::vector> v; + v.resize( N ); + assert( v.size() == N ); + + // fill using the access operator + for( int i = 0; i < N; i++ ) { + v[i] = Edge( i, i ); + } + + assert( v.size() == N && v[0].src == 0 && v[0].dst == 0 && ( v[N / 2].src = N / 2 ) && ( v[N / 2].dst = N / 2 ) ); +} + +void test_class_edge_begin_and_end() { + std::vector> v; + for( int i = 0; i < N; i++ ) { + v.push_back( Edge( i, i ) ); + } + + // use an iterator to check if the vector contains the correct edges + int i = 0; + for( auto it = v.begin(); it != v.end(); it++, i++ ) { + assert( it->src == i && it->dst == i ); + } +} + +void test_class_edge_at() { + std::vector> v; + for( int i = 0; i < N; i++ ) { + v.push_back( Edge( i, i ) ); + } + + for( int i = 0; i < N; i++ ) { + assert( v.at( i ).src == i && v.at( i ).dst == i ); + } + + try { + Edge check = v.at( N + 1 ); + assert( false ); // this should never execute + } catch( const std::out_of_range& e ) { + } +} + +int main() { + // edge struct tests + test_struct_edge_push_back(); + test_struct_edge_reserve(); + test_struct_edge_resize(); + test_struct_edge_begin_and_end(); + test_struct_edge_at(); + + // edge class tests + test_class_edge_reserve(); + test_class_edge_resize(); + test_class_edge_begin_and_end(); + test_class_edge_at(); + + return 0; +} diff --git a/test/cxx/stl/vector_int64_t/Makefile b/test/cxx/stl/vector_int64_t/Makefile new file mode 100644 index 000000000..18d03caa9 --- /dev/null +++ b/test/cxx/stl/vector_int64_t/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: vector_int64_t +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=vector_int64_t +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -I ../../../syscalls -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/vector_int64_t/rev-test.py b/test/cxx/stl/vector_int64_t/rev-test.py new file mode 100755 index 000000000..c79db3be6 --- /dev/null +++ b/test/cxx/stl/vector_int64_t/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector_int64_t.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/vector_int64_t/run_vector_int64_t.sh b/test/cxx/stl/vector_int64_t/run_vector_int64_t.sh new file mode 100755 index 000000000..db066ab5d --- /dev/null +++ b/test/cxx/stl/vector_int64_t/run_vector_int64_t.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector_int64_t.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector_int64_t: vector_int64_t.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector_int64_t/vector_int64_t.cc b/test/cxx/stl/vector_int64_t/vector_int64_t.cc new file mode 100644 index 000000000..ad002b05a --- /dev/null +++ b/test/cxx/stl/vector_int64_t/vector_int64_t.cc @@ -0,0 +1,136 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "revalloc.h" +#include + +#include "rev-macros.h" + +#include +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +#define N 10 +#define M 20 + +// fill in pre-sized std vector -- tests out the [] access operator +static inline void fill_vector( std::vector>& v, int start_pos, int count ) { + int end_pos = start_pos + count; + for( int i = start_pos; i < end_pos; i++ ) { + v[i] = i; + } +} + +// fill a vector using push_back +static inline void fill_push_back_vector( std::vector>& v, int start_num, int count ) { + int end_num = start_num + count; + for( int i = start_num; i < end_num; i++ ) { + v.push_back( i ); + } +} + +void test_reserve() { + std::vector> v; + v.reserve( N ); + + assert( v.capacity() == N ); + assert( v.size() == 0 ); + + auto initial_address = v.data(); + bool reserve_failed = false; + for( int64_t i = 0; i < N; i++ ) { + v.push_back( i ); + if( v.data() != initial_address ) { + reserve_failed = true; + break; + } + } + assert( v.size() == N && !reserve_failed && ( v[N / 2] == N / 2 ) ) + + // Now check if the reallocation works when the vector grows larger than capacity + v.push_back( N ); + assert( v.data() != initial_address && v.size() == ( N + 1 ) && v.capacity() >= ( N + 1 ) ); +} + +void test_resize() { + std::vector> v; + v.resize( N ); + + assert( v.size() == N ); + fill_vector( v, 0, N ); + assert( v.size() == N ); // ensure that vector::size has not increased + + fill_push_back_vector( v, N, N ); + assert( v.size() == ( 2 * N ) ); // ensure that vector::size is now 2*N + + // Resize to 4*N and check + v.resize( 4 * N ); + assert( v.size() == 4 * N ); + fill_vector( v, 2 * N, 2 * N ); + + assert( v.size() == 4 * N ); +} + +void test_begin_and_end() { + std::vector> v; + fill_push_back_vector( v, 0, N ); + + int64_t i = 0; + for( auto iter = v.begin(); iter < v.end(); iter++, i++ ) { + assert( *iter == i ); + } +} + +void test_erase() { + std::vector> v; + fill_push_back_vector( v, 0, N ); + assert( v.size() == N ); + + // erase the first N / 2 elements one at a time + for( int i = 0; i < ( N / 2 ); i++ ) { + v.erase( v.begin() ); + } + assert( v.size() == ( N / 2 ) ); + assert( v[0] == ( N / 2 ) ); + + // test erase via iterator range + v.erase( v.begin(), v.end() ); + assert( v.size() == 0 ); +} + +void test_at() { + std::vector> v; + fill_push_back_vector( v, 0, N ); + + int check = -1; + try { + v.at( N + 1 ) = N + 1; + check = 0; // this should not run + } catch( const std::out_of_range& e ) { + assert( check == -1 ); + } +} + +int main() { + + test_reserve(); + test_resize(); + test_begin_and_end(); + test_erase(); + test_at(); + + return 0; +} diff --git a/test/cxx/stl/vector_obj/Makefile b/test/cxx/stl/vector_obj/Makefile index 95397d4d6..7555164d2 100644 --- a/test/cxx/stl/vector_obj/Makefile +++ b/test/cxx/stl/vector_obj/Makefile @@ -1,9 +1,9 @@ # # Makefile # -# makefile: vector +# makefile: vector_obj # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -13,14 +13,13 @@ .PHONY: src EXAMPLE=vector_obj -CC=riscv64-unknown-elf-g++ -#CC="${RVCC}" +CXX=${RVCXX} #ARCH=rv64g -ARCH=rv64imafdc +ARCH=rv64gc all: $(EXAMPLE).exe -$(EXAMPLE).exe: $(EXAMPLE).c - $(CC) -march=$(ARCH) -O0 -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).c -static +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static clean: rm -Rf $(EXAMPLE).exe diff --git a/test/cxx/stl/vector_obj/rev-test.py b/test/cxx/stl/vector_obj/rev-test.py old mode 100644 new mode 100755 index 748fd5626..a9d79a53d --- a/test/cxx/stl/vector_obj/rev-test.py +++ b/test/cxx/stl/vector_obj/rev-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # rev-test.py # -import os import sst # Define SST core options @@ -22,15 +22,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 20, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "vector_obj.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector_obj.exe", # Target executable + "splash": 1 # Display the splash message }) # sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/cxx/stl/vector_obj/revalloc.hpp b/test/cxx/stl/vector_obj/revalloc.hpp deleted file mode 100644 index 3749d8db8..000000000 --- a/test/cxx/stl/vector_obj/revalloc.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include "syscalls.h" -#include "unistd.h" - -#ifndef __REV_REVALLOC__ -#define __REV_REVALLOC__ - -/*void* operator new(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -}*/ - -void* mynew(std::size_t t){ - void* p = reinterpret_cast(rev_mmap(0, - t, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0)); - return p; -} - -template -class StandardAllocPolicy { -public : - // typedefs - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - -public : - // convert an StandardAllocPolicy to StandardAllocPolicy - template - struct rebind { - typedef StandardAllocPolicy other; - }; - -public : - inline explicit StandardAllocPolicy() {} - inline ~StandardAllocPolicy() {} - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - template - inline explicit StandardAllocPolicy(StandardAllocPolicy const&) {} - - // memory allocation - inline pointer allocate(size_type cnt, - typename std::allocator::const_pointer = 0) { - return reinterpret_cast( - rev_mmap(0, // Let rev choose the address - cnt * sizeof(T), - PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions - MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous - -1, // No file descriptor because it's an anonymous mapping - 0)); // No offset, irrelevant for anonymous mappings - - } - inline void deallocate(pointer p, size_type n) - { std::size_t addr = reinterpret_cast(p); - rev_munmap(addr, n); } - - // size - inline size_type max_size() const { - return std::numeric_limits::max(); - } - - // construction/destruction - //inline void construct(pointer p, const T& t) { pointer z = new(sizeof(T); new(z) T(t); p = z; } - template - inline void construct(U* p, Args&&... args){ new(p) U(std::forward(args)...); }; - //template - //inline void construct(U* p, Args&&... args){ pointer z = reinterpret_cast(mynew(sizeof(U))); new(z) U(std::forward(args)...); p = z;} - inline void destroy(pointer p) { p->~T(); } -}; // end of class StandardAllocPolicy - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(StandardAllocPolicy const&, - StandardAllocPolicy const&) { - return true; -} -template -inline bool operator==(StandardAllocPolicy const&, - OtherAllocator const&) { - return false; -} - -template > -class Allocator : public Policy { -private : - typedef Policy AllocationPolicy; - -public : - typedef typename AllocationPolicy::size_type size_type; - typedef typename AllocationPolicy::difference_type difference_type; - typedef typename AllocationPolicy::pointer pointer; - typedef typename AllocationPolicy::const_pointer const_pointer; - typedef typename AllocationPolicy::reference reference; - typedef typename AllocationPolicy::const_reference const_reference; - typedef typename AllocationPolicy::value_type value_type; - -public : - template - struct rebind { - typedef Allocator::other> other; - }; - -public : - inline explicit Allocator() {} - inline ~Allocator() {} - inline Allocator(Allocator const& rhs): Policy(rhs) {} - template - inline Allocator(Allocator const&) {} - template - inline Allocator(Allocator const& rhs): Policy(rhs) {} -}; // end of class Allocator - -// determines if memory from another -// allocator can be deallocated from this one -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} - -template -inline bool operator==(Allocator const& lhs, - Allocator const& rhs) { - return operator==(static_cast(lhs), - static_cast(rhs)); -} -template -inline bool operator==(Allocator const& lhs, OtherAllocator const& rhs) { - return operator==(static_cast(lhs), rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - Allocator const& rhs) { - return !operator==(lhs, rhs); -} -template -inline bool operator!=(Allocator const& lhs, - OtherAllocator const& rhs) { - return !operator==(lhs, rhs); -} - -#endif \ No newline at end of file diff --git a/test/cxx/stl/vector_obj/run_vector_obj.sh b/test/cxx/stl/vector_obj/run_vector_obj.sh new file mode 100755 index 000000000..5faff7488 --- /dev/null +++ b/test/cxx/stl/vector_obj/run_vector_obj.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector_obj.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector_obj: vector_obj.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector_obj/vector_obj.c b/test/cxx/stl/vector_obj/vector_obj.c deleted file mode 100644 index d518c2cb0..000000000 --- a/test/cxx/stl/vector_obj/vector_obj.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "revalloc.hpp" -#include -#include "rev-macros.h" - -#define assert(x) if (!(x)) { asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); } - -int main() { - - class TestObj { - public: - TestObj(int m1, int m2){mem1 = m1; mem2 = m2;} - TestObj(){mem1 = 0; mem2 = 0;} - ~TestObj(){}; - - int GetM1(){return mem1;} - int GetM2(){return mem2;} - void SetM1(int m){mem1 = m;} - void SetM2(int m){mem2 = m;} - private: - int mem1; - int mem2; - }; - - std::vector > v; - - TestObj c; - v.push_back(c); - v[0].SetM1(0xbeef); - assert(v[0].GetM1() == 0xbeef) - - return 0; -} diff --git a/test/cxx/stl/vector_obj/vector_obj.cc b/test/cxx/stl/vector_obj/vector_obj.cc new file mode 100644 index 000000000..be387b6d2 --- /dev/null +++ b/test/cxx/stl/vector_obj/vector_obj.cc @@ -0,0 +1,58 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +int main() { + + class TestObj { + public: + TestObj( int m1, int m2 ) { + mem1 = m1; + mem2 = m2; + } + + TestObj() { + mem1 = 0; + mem2 = 0; + } + + ~TestObj(){}; + + int GetM1() { return mem1; } + + int GetM2() { return mem2; } + + void SetM1( int m ) { mem1 = m; } + + void SetM2( int m ) { mem2 = m; } + + private: + int mem1; + int mem2; + }; + + std::vector> v; + + TestObj c; + v.push_back( c ); + v[0].SetM1( 0xbeef ); + assert( v[0].GetM1() == 0xbeef ) + + return 0; +} diff --git a/test/cxx/stl/vector_pair/Makefile b/test/cxx/stl/vector_pair/Makefile new file mode 100644 index 000000000..bf8cc0ea4 --- /dev/null +++ b/test/cxx/stl/vector_pair/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: vector_pair +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=vector_pair +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/vector_pair/rev-test.py b/test/cxx/stl/vector_pair/rev-test.py new file mode 100755 index 000000000..14252c593 --- /dev/null +++ b/test/cxx/stl/vector_pair/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector_pair.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/vector_pair/run_vector_pair.sh b/test/cxx/stl/vector_pair/run_vector_pair.sh new file mode 100755 index 000000000..c6bc8f907 --- /dev/null +++ b/test/cxx/stl/vector_pair/run_vector_pair.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector_pair.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector_pair: vector_pair.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector_pair/vector_pair.cc b/test/cxx/stl/vector_pair/vector_pair.cc new file mode 100644 index 000000000..51273f918 --- /dev/null +++ b/test/cxx/stl/vector_pair/vector_pair.cc @@ -0,0 +1,109 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include + +#include +#include // For std::pair + +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +#define N 10 +#define M 20 + +bool testSize() { + std::vector, Allocator>> vec = { + {1, 2}, + {3, 4} + }; + if( vec.size() != 2 ) + return false; + + vec.push_back( { 5, 6 } ); + return vec.size() == 3; +} + +bool testReserve() { + std::vector, Allocator>> vec; + vec.reserve( N ); + if( vec.capacity() != N ) { + return false; + } + + auto initial_address = vec.data(); + bool reserve_failed = false; + for( int i = 0; i < N; i++ ) { + vec.push_back( std::pair( i, i ) ); + + // the vector backing store address should not change + if( vec.data() != initial_address ) { + reserve_failed = true; + break; + } + } + + return !reserve_failed && ( vec.size() == N ); +} + +bool testResize() { + std::vector, Allocator>> vec( 2 ); + vec.resize( 4 ); + if( vec.size() != 4 ) + return false; + + // Newly added pairs should be initialized to (0, 0) + return vec[2].first == 0 && vec[2].second == 0 && vec[3].first == 0 && vec[3].second == 0; +} + +bool testPushBack() { + std::vector, Allocator>> vec; + vec.push_back( { 1, 2 } ); + vec.push_back( { 3, 4 } ); + + return vec.size() == 2 && vec[1].first == 3 && vec[1].second == 4; +} + +bool testBeginEnd() { + std::vector, Allocator>> vec = { + {1, 1}, + {2, 2}, + {3, 3} + }; + auto it = vec.begin(); + if( it == vec.end() || it->first != 1 || it->second != 1 ) + return false; + + int64_t sumFirst = 0, sumSecond = 0; + for( auto it = vec.begin(); it != vec.end(); ++it ) { + sumFirst += it->first; + sumSecond += it->second; + } + return sumFirst == 6 && sumSecond == 6; +} + +int main() { + + assert( testSize() ); + assert( testPushBack() ); + assert( testReserve() ); + assert( testResize() ); + assert( testBeginEnd() ); + + return 0; +} diff --git a/test/cxx/stl/vector_vector_int64_t/Makefile b/test/cxx/stl/vector_vector_int64_t/Makefile new file mode 100644 index 000000000..f900d2fcf --- /dev/null +++ b/test/cxx/stl/vector_vector_int64_t/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: vector_vector_int64_t +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=vector_vector_int64_t +CXX=${RVCXX} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -O0 -I../../../../common/include -I../../../../common/syscalls -I../../../include -o $(EXAMPLE).exe $(EXAMPLE).cc -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/cxx/stl/vector_vector_int64_t/rev-test.py b/test/cxx/stl/vector_vector_int64_t/rev-test.py new file mode 100755 index 000000000..243ca9d2d --- /dev/null +++ b/test/cxx/stl/vector_vector_int64_t/rev-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-test.py +# + +import sst + +# Define SST core options +sst.setProgramOption("timebase", "1ps") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(8) + +max_addr_gb = 1 + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams({ + "verbose": 20, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector_vector_int64_t.exe", # Target executable + "splash": 1 # Display the splash message +}) + +# sst.setStatisticOutput("sst.statOutputCSV") +sst.enableAllStatisticsForAllComponents() + +# EOF diff --git a/test/cxx/stl/vector_vector_int64_t/run_vector_vector_int64_t.sh b/test/cxx/stl/vector_vector_int64_t/run_vector_vector_int64_t.sh new file mode 100755 index 000000000..7e8b9a92f --- /dev/null +++ b/test/cxx/stl/vector_vector_int64_t/run_vector_vector_int64_t.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x vector_vector_int64_t.exe ]]; then + sst --add-lib-path=../../../../build/src/ ./rev-test.py +else + echo "Test STL CXX vector_vector_int64_t: vector_vector_int64_t.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/cxx/stl/vector_vector_int64_t/vector_vector_int64_t.cc b/test/cxx/stl/vector_vector_int64_t/vector_vector_int64_t.cc new file mode 100644 index 000000000..735b60c8c --- /dev/null +++ b/test/cxx/stl/vector_vector_int64_t/vector_vector_int64_t.cc @@ -0,0 +1,120 @@ +// +// Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +// All Rights Reserved +// contact@tactcomplabs.com +// +// See LICENSE in the top level directory for licensing details +// + +#include "rev-macros.h" +#include "revalloc.h" +#include + +#include +#include // For std::pair + +#include +#include + +#define assert( x ) \ + if( !( x ) ) { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } + +#define N 20 +#define M 40 + +bool testSize() { + std::vector>, Allocator>>> vec = { + {1, 2}, + {3, 4} + }; + if( vec.size() != 2 ) + return false; + + vec.push_back( { 5, 6, 7 } ); + return vec.size() == 3; +} + +bool testResize() { + std::vector>, Allocator>>> vec( 2 ); + vec.resize( 3 ); + if( vec.size() != 3 ) + return false; + + vec[2].resize( 2, 42 ); + return vec[2].size() == 2 && vec[2][1] == 42; +} + +bool testReserve() { + std::vector>, Allocator>>> vec; + vec.reserve( N ); + assert( vec.capacity() == N ); + + auto initial_address = vec.data(); + bool reserve_failed = false; + bool realloc_failed = false; + for( int i = 0; i < N; i++ ) { + vec.push_back( std::vector>{ i, i } ); + if( vec.data() != initial_address ) { // the data address must not change for N pushes + reserve_failed = true; + break; + } + } + + return !reserve_failed && ( vec.size() == N ); +} + +bool testPushBack() { + std::vector>, Allocator>>> vec; + vec.push_back( { 1, 2 } ); + vec.push_back( { 3 } ); + + return vec.size() == 2 && vec[1].size() == 1 && vec[1][0] == 3; +} + +bool testBeginEnd() { + std::vector>, Allocator>>> vec = { + { 1 }, { 2 }, { 3 } }; + auto it = vec.begin(); + if( it == vec.end() || ( *it )[0] != 1 ) + return false; + + int sum = 0; + for( auto it = vec.begin(); it != vec.end(); ++it ) { + sum += ( *it )[0]; + } + return sum == 6; +} + +bool testAt() { + std::vector>, Allocator>>> vec = { + { 1 }, { 2 }, { 3 }, { 4 } }; + if( vec.at( 0 )[0] != 1 && vec.at( 3 )[0] != 4 ) { + return false; + } + + try { + auto check = vec.at( 5 ); + return false; // this line should never execute + } catch( std::out_of_range& e ) { + return true; + } + + // return false; +} + +int main() { + + assert( testReserve() ); + assert( testSize() ); + assert( testResize() ); + assert( testPushBack() ); + assert( testBeginEnd() ); + assert( testAt() ); + + return 0; +} diff --git a/test/dcmp/Makefile b/test/dcmp/Makefile index b860b2491..16068ca79 100644 --- a/test/dcmp/Makefile +++ b/test/dcmp/Makefile @@ -3,7 +3,7 @@ # # makefile: dcmp # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/dcmp/dcmp.c b/test/dcmp/dcmp.c index e877151f5..f8ad976b0 100644 --- a/test/dcmp/dcmp.c +++ b/test/dcmp/dcmp.c @@ -1,18 +1,18 @@ -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { volatile double da = 0.199; volatile double db = 0.25; - assert(da < db); - assert(da <= db); - assert(db > da); - assert(db >= da); + assert( da < db ); + assert( da <= db ); + assert( db > da ); + assert( db >= da ); da = 0.25; - assert(da == db); + assert( da == db ); } diff --git a/test/dcmp/rev-dcmp.py b/test/dcmp/rev-dcmp.py index 213f47fda..0531ebb67 100755 --- a/test/dcmp/rev-dcmp.py +++ b/test/dcmp/rev-dcmp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/dcmp/run_dcmp.sh b/test/dcmp/run_dcmp.sh index ac1f73be1..5cd1b75a5 100755 --- a/test/dcmp/run_dcmp.sh +++ b/test/dcmp/run_dcmp.sh @@ -4,7 +4,7 @@ make # Check that the exec was built... -if [ -x dcmp.exe ]; then +if [[ -x dcmp.exe ]]; then sst --add-lib-path=../../src/ ./rev-dcmp.py else echo "Test DCMP: dcmp.exe not Found - likely build failed" diff --git a/test/dep_check/Makefile b/test/dep_check/Makefile index ea1cf7a34..77f18fcb4 100644 --- a/test/dep_check/Makefile +++ b/test/dep_check/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/dep_check/dep_check.c b/test/dep_check/dep_check.c index 715246967..c1f8079d1 100644 --- a/test/dep_check/dep_check.c +++ b/test/dep_check/dep_check.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,11 +13,10 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int o; - -/* The assembly sequence below should produce a + /* The assembly sequence below should produce a * cascade of dependent instructions * The cost of "add" in the RV32I instruction * table MUST be set to a value larger than 1 @@ -32,29 +31,29 @@ int main(int argc, char **argv){ //ADD a0, a0, a0 //ADD a0, a0, a0 - asm volatile("ADDI a0, zero, %1" : "=r"(o) : "I"(42)); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0"); - asm volatile("ADD a0, a0, a0" : "=r"(o)); + asm volatile( "ADDI a0, zero, %1" : "=r"( o ) : "I"( 42 ) ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" ); + asm volatile( "ADD a0, a0, a0" : "=r"( o ) ); return o; } diff --git a/test/divw/Makefile b/test/divw/Makefile index b045e2964..f81a68484 100644 --- a/test/divw/Makefile +++ b/test/divw/Makefile @@ -3,7 +3,7 @@ # # makefile: divw # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/divw/divw.c b/test/divw/divw.c index 119b59c42..00493aff3 100644 --- a/test/divw/divw.c +++ b/test/divw/divw.c @@ -1,21 +1,21 @@ -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { // test for infinite loops - for (int i = 0; i < 2; i++) { - int zz = (i + 1) / i; + for( int i = 0; i < 2; i++ ) { + int zz = ( i + 1 ) / i; } // test the corner cases - int _zero = 0x00l; + int _zero = 0x00l; int divisor = 7; - int zzx = divisor / _zero; - assert(zzx == 0xFFFFFFFFFFFFFFFF); + int zzx = divisor / _zero; + assert( zzx == 0xFFFFFFFFFFFFFFFF ); return 0; } diff --git a/test/divw2/Makefile b/test/divw2/Makefile index 62379021b..d615f67cd 100644 --- a/test/divw2/Makefile +++ b/test/divw2/Makefile @@ -3,7 +3,7 @@ # # makefile: divw2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/divw2/divw2.c b/test/divw2/divw2.c index 76bf7126e..f1803608b 100644 --- a/test/divw2/divw2.c +++ b/test/divw2/divw2.c @@ -1,14 +1,14 @@ -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { - int d = -20; - int x = -3; + int d = -20; + int x = -3; int div = d / x; - assert(div == 6); + assert( div == 6 ); return 0; } diff --git a/test/dot_double/Makefile b/test/dot_double/Makefile index 8c43cf3ca..98e75b9c6 100644 --- a/test/dot_double/Makefile +++ b/test/dot_double/Makefile @@ -3,7 +3,7 @@ # # makefile: dot_double # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/dot_double/dot_double.c b/test/dot_double/dot_double.c index 46bd894ee..741f0a36c 100644 --- a/test/dot_double/dot_double.c +++ b/test/dot_double/dot_double.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64IMAFDC * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ -#include #include "cblas.h" +#include double x[1024]; double y[1024]; -int main(int argc, char **argv){ +int main( int argc, char** argv ) { float result; - int inc_x=1; - int inc_y=1; - int m=0; - int i=0; - int l=0; + int inc_x = 1; + int inc_y = 1; + int m = 0; + int i = 0; + int l = 0; - for( l=0; l<1024; l++ ){ - x[l] = (double)(l); - y[l] = (double)(l)*(double)(l); + for( l = 0; l < 1024; l++ ) { + x[l] = (double) ( l ); + y[l] = (double) ( l ) * (double) ( l ); } - for( l=0; l<1024; l++ ){ - result = cblas_ddot(m, &x[0], inc_x, &y[0], inc_y); + for( l = 0; l < 1024; l++ ) { + result = cblas_ddot( m, &x[0], inc_x, &y[0], inc_y ); } return 0; diff --git a/test/dot_double/rev-test-do_double.py b/test/dot_double/rev-test-do_double.py old mode 100644 new mode 100755 index 2fe1c9745..efca7aab5 --- a/test/dot_double/rev-test-do_double.py +++ b/test/dot_double/rev-test-do_double.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "dot_double.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "dot_double.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/dot_double/run_dot_double.sh b/test/dot_double/run_dot_double.sh index 6a5a3be0b..c974d6805 100755 --- a/test/dot_double/run_dot_double.sh +++ b/test/dot_double/run_dot_double.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x dot_double.exe ]; then +if [[ -x dot_double.exe ]]; then sst --add-lib-path=../../build/src/ ./dot_double.py else echo "Test DOT_DOUBLE: dot_double.exe not Found - likely build failed" diff --git a/test/dot_single/Makefile b/test/dot_single/Makefile index c25d3a5f9..271cc4c22 100644 --- a/test/dot_single/Makefile +++ b/test/dot_single/Makefile @@ -3,7 +3,7 @@ # # makefile: dot_single # -# Copyright (C) 2017-2020 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/dot_single/dot_single.c b/test/dot_single/dot_single.c index 697744711..666511044 100644 --- a/test/dot_single/dot_single.c +++ b/test/dot_single/dot_single.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64IMAFDC * - * Copyright (C) 2017-2020 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ -#include #include "cblas.h" +#include float x[1024]; float y[1024]; -int main(int argc, char **argv){ +int main( int argc, char** argv ) { float result; - int inc_x=1; - int inc_y=1; - int m=0; - int i=0; - int l=0; + int inc_x = 1; + int inc_y = 1; + int m = 0; + int i = 0; + int l = 0; - for( l=0; l<1024; l++ ){ - x[l] = (float)(l); - y[l] = (float)(l)*(float)(l); + for( l = 0; l < 1024; l++ ) { + x[l] = (float) ( l ); + y[l] = (float) ( l ) * (float) ( l ); } - for( l=0; l<1024; l++ ){ - result = cblas_sdot(m, &x[0], inc_x, &y[0], inc_y); + for( l = 0; l < 1024; l++ ) { + result = cblas_sdot( m, &x[0], inc_x, &y[0], inc_y ); } return 0; diff --git a/test/dot_single/rev-test-do_single.py b/test/dot_single/rev-test-do_single.py old mode 100644 new mode 100755 index f562dc075..1eb4276dd --- a/test/dot_single/rev-test-do_single.py +++ b/test/dot_single/rev-test-do_single.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2020 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "dot_single.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "dot_single.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/dot_single/run_dot_single.sh b/test/dot_single/run_dot_single.sh index 748ffda17..35dcaed99 100755 --- a/test/dot_single/run_dot_single.sh +++ b/test/dot_single/run_dot_single.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x dot_single.exe ]; then +if [[ -x dot_single.exe ]]; then sst --add-lib-path=../../build/src/ ./dot_single.py else echo "Test DOT_SINGLE: dot_single.exe not Found - likely build failed" diff --git a/test/ex1/Makefile b/test/ex1/Makefile index f48cca340..969acad30 100644 --- a/test/ex1/Makefile +++ b/test/ex1/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex1/ex1.c b/test/ex1/ex1.c index a8ac4ee67..7d63b7799 100644 --- a/test/ex1/ex1.c +++ b/test/ex1/ex1.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex2/Makefile b/test/ex2/Makefile index 132a2c416..bcf7137b8 100644 --- a/test/ex2/Makefile +++ b/test/ex2/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex2/ex2.c b/test/ex2/ex2.c index 35ee561e9..f87936924 100644 --- a/test/ex2/ex2.c +++ b/test/ex2/ex2.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex3/Makefile b/test/ex3/Makefile index 7aaf2a1ff..48e845ce8 100644 --- a/test/ex3/Makefile +++ b/test/ex3/Makefile @@ -3,7 +3,7 @@ # # makefile: ex3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex3/ex3.c b/test/ex3/ex3.c index a8ac4ee67..7d63b7799 100644 --- a/test/ex3/ex3.c +++ b/test/ex3/ex3.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex4/Makefile b/test/ex4/Makefile index 57cd2b707..6e015d08c 100644 --- a/test/ex4/Makefile +++ b/test/ex4/Makefile @@ -3,7 +3,7 @@ # # makefile: ex4 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex4/ex4.c b/test/ex4/ex4.c index 35ee561e9..f87936924 100644 --- a/test/ex4/ex4.c +++ b/test/ex4/ex4.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex5/Makefile b/test/ex5/Makefile index 1a0f3d14d..c8ecaea04 100644 --- a/test/ex5/Makefile +++ b/test/ex5/Makefile @@ -3,7 +3,7 @@ # # makefile: ex5 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex5/ex5.c b/test/ex5/ex5.c index 35ee561e9..f87936924 100644 --- a/test/ex5/ex5.c +++ b/test/ex5/ex5.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex6/Makefile b/test/ex6/Makefile index c942d438e..049279fcd 100644 --- a/test/ex6/Makefile +++ b/test/ex6/Makefile @@ -3,7 +3,7 @@ # # makefile: ex6 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex6/ex6.c b/test/ex6/ex6.c index d0f85ab8a..49a5b8cdc 100644 --- a/test/ex6/ex6.c +++ b/test/ex6/ex6.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64IMAFDC * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/ex7/Makefile b/test/ex7/Makefile index d3444e080..bda346536 100644 --- a/test/ex7/Makefile +++ b/test/ex7/Makefile @@ -3,7 +3,7 @@ # # makefile: ex7 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/ex7/ex7.c b/test/ex7/ex7.c index 6c7bdb9b4..0445430ac 100644 --- a/test/ex7/ex7.c +++ b/test/ex7/ex7.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,19 +11,17 @@ * */ -__attribute__((naked)) int main() { - asm( - " add sp, sp, -16\n" - " sw zero, 0(sp)\n" - " lw a0, 0(sp)\n" - " fcvt.s.w fa0, a0\n" - " fmv.w.x fa1, zero\n" - " feq.s a0, fa0, fa1\n" - " bnez a0, 1f\n" - " .word 0\n" - "1:\n" - " add sp, sp, 16\n" - " li a0, 0\n" - " ret\n" - ); +__attribute__( ( naked ) ) int main() { + asm( " add sp, sp, -16\n" + " sw zero, 0(sp)\n" + " lw a0, 0(sp)\n" + " fcvt.s.w fa0, a0\n" + " fmv.w.x fa1, zero\n" + " feq.s a0, fa0, fa1\n" + " bnez a0, 1f\n" + " .word 0\n" + "1:\n" + " add sp, sp, 16\n" + " li a0, 0\n" + " ret\n" ); } diff --git a/test/ext_version/Makefile b/test/ext_version/Makefile new file mode 100644 index 000000000..fdbedc692 --- /dev/null +++ b/test/ext_version/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: ext_version +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=ext_version +CC=${RVCC} +ARCH=rv64imafdc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -O3 -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/ext_version/ext_version.c b/test/ext_version/ext_version.c new file mode 100644 index 000000000..0f7268b7c --- /dev/null +++ b/test/ext_version/ext_version.c @@ -0,0 +1,3 @@ +int main( void ) { + return 0; +} diff --git a/test/ext_version/run_ext_version.sh b/test/ext_version/run_ext_version.sh new file mode 100755 index 000000000..dc330aa51 --- /dev/null +++ b/test/ext_version/run_ext_version.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e + +make clean +make + +# Unknown extension +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:RV64XGC]" 2>&1 | grep -q 'Error: failed to parse the machine model: RV64XGC' + +# Out of order extension +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:RV64GVC]" 2>&1 | grep -q 'Error: failed to parse the machine model: RV64GVC' + +# Incomplete version string +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:RV64XGC2P]" 2>&1 | grep -q 'Error: failed to parse the machine model: RV64XGC2P' + +# Unsupported version +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:RV64GCV0p7]" 2>&1 | grep -q 'Error: Version 0.7 of V extension is not supported' + +# Supported version +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:rv64i2p0m2a2p0fd2p0c]" 2>&1 | grep -q 'Simulation is complete' + +# Supported version +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "ext_version.exe" --args "one" --enableMemH=0 --machine="[CORES:rv64i2p0m2a2p0fd2p0c2_p]" 2>&1 | grep -q 'Simulation is complete' + +echo 'Simulation is complete' diff --git a/test/fault/Makefile b/test/fault/Makefile index 48ce009af..86997eaef 100644 --- a/test/fault/Makefile +++ b/test/fault/Makefile @@ -3,7 +3,7 @@ # # makefile: fault1 # -# Copyright (C) 2017-2020 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/fault/fault-test-1.py b/test/fault/fault-test-1.py old mode 100644 new mode 100755 index bc3332979..7aa9b63e7 --- a/test/fault/fault-test-1.py +++ b/test/fault/fault-test-1.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-1.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "decode", # Enable the decode faults - "fault_width" : "single", # single bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "decode", # Enable the decode faults + "fault_width": "single", # single bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-2.py b/test/fault/fault-test-2.py old mode 100644 new mode 100755 index 71880d8f2..a2ec591db --- a/test/fault/fault-test-2.py +++ b/test/fault/fault-test-2.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-2.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "mem", # Enable the decode faults - "fault_width" : "single", # single bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "mem", # Enable the decode faults + "fault_width": "single", # single bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-3.py b/test/fault/fault-test-3.py old mode 100644 new mode 100755 index 9a0bdf582..4df731478 --- a/test/fault/fault-test-3.py +++ b/test/fault/fault-test-3.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-3.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "reg", # Enable the decode faults - "fault_width" : "single", # single bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "reg", # Enable the decode faults + "fault_width": "single", # single bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-4.py b/test/fault/fault-test-4.py old mode 100644 new mode 100755 index 736bd2f35..f02a15b80 --- a/test/fault/fault-test-4.py +++ b/test/fault/fault-test-4.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-4.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "alu", # Enable the decode faults - "fault_width" : "single", # single bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "alu", # Enable the decode faults + "fault_width": "single", # single bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-5.py b/test/fault/fault-test-5.py old mode 100644 new mode 100755 index c8f230a45..5dde053fa --- a/test/fault/fault-test-5.py +++ b/test/fault/fault-test-5.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-5.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "alu", # Enable the decode faults - "fault_width" : "word", # word flips flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "alu", # Enable the decode faults + "fault_width": "word", # word flips flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-6.py b/test/fault/fault-test-6.py old mode 100644 new mode 100755 index 10ea0c5ad..eb057d83e --- a/test/fault/fault-test-6.py +++ b/test/fault/fault-test-6.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-6.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "alu", # Enable the decode faults - "fault_width" : "3", # 3 bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "alu", # Enable the decode faults + "fault_width": "3", # 3 bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-7.py b/test/fault/fault-test-7.py old mode 100644 new mode 100755 index e13b2ba1e..adc935cc5 --- a/test/fault/fault-test-7.py +++ b/test/fault/fault-test-7.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-7.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "[reg,alu]", # Enable reg and alu faults - "fault_width" : "3", # 3 bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "[reg,alu]", # Enable reg and alu faults + "fault_width": "3", # 3 bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-8.py b/test/fault/fault-test-8.py old mode 100644 new mode 100755 index 3397e48c4..65b7d7940 --- a/test/fault/fault-test-8.py +++ b/test/fault/fault-test-8.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-8.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "[reg,alu,crack,mem]", # Enable all faults - "fault_width" : "3", # 3 bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "[reg,alu,crack,mem]", # Enable all faults + "fault_width": "3", # 3 bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault-test-9.py b/test/fault/fault-test-9.py old mode 100644 new mode 100755 index 22f0e12c3..80f90d9d5 --- a/test/fault/fault-test-9.py +++ b/test/fault/fault-test-9.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # fault-test-9.py # -import os import sst # Define SST core options @@ -22,21 +22,21 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "fault1.exe", # Target executable - - "enable_faults" : 1, # Enable the fault interfaces - "faults" : "all", # Enable all faults - "fault_width" : "1", # 3 bit flips - "fault_range" : 65536, # clocks between faults - - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "fault1.exe", # Target executable + + "enable_faults": 1, # Enable the fault interfaces + "faults": "all", # Enable all faults + "fault_width": "1", # 3 bit flips + "fault_range": 65536, # clocks between faults + + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/fault/fault1.c b/test/fault/fault1.c index 46f3af0eb..a9d2689b7 100644 --- a/test/fault/fault1.c +++ b/test/fault/fault1.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,8 +11,8 @@ * */ -#include #include +#include #define WIDTH 32768 @@ -20,17 +20,17 @@ uint64_t VECT_A[WIDTH]; uint64_t VECT_B[WIDTH]; uint64_t RESULT[WIDTH]; -int run_this(){ +int run_this() { uint64_t i = 0x00ull; uint64_t r = 0x00ull; - for( i=0; i fenv_test.makefile + ./fenv_gentests TONEAREST >> fenv_test.makefile + ./fenv_gentests UPWARD >> fenv_test.makefile + ./fenv_gentests DOWNWARD >> fenv_test.makefile + ./fenv_gentests TOWARDZERO >> fenv_test.makefile + +# build test generator on local host +fenv_gentests: fenv_test.h fenv_gentests.cc + g++ $(CXX_OPTS) fenv_gentests.cc -o $@ + +clean: + rm -Rf *.asm *.exe *.csv fenv_test.makefile TONEAREST_*.cc UPWARD_*.cc DOWNWARD_*.cc TOWARDZERO_*.cc fenv_gentests + +.PHONY: buildtests runtests clean TONEAREST UPWARD DOWNWARD TOWARDZERO + +#-- EOF diff --git a/test/fenv/fenv_gentests.cc b/test/fenv/fenv_gentests.cc new file mode 100644 index 000000000..a9a1749e1 --- /dev/null +++ b/test/fenv/fenv_gentests.cc @@ -0,0 +1,334 @@ +/* + * fenv_gentests.cc + * + * RISC-V ISA: RV32F, RV32D, RV64F, RV64D + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include "fenv_test.h" + +constexpr unsigned maxtests_per_file = 500; + +const char* file_prefix; +size_t testnum; +size_t testcount; +unsigned filenum; +int rounding; +std::ofstream out; +size_t failures = 0; + +void openfile() { + ++filenum; + char filename[256]; + char filenum_s[32]; + snprintf( filenum_s, sizeof( filenum_s ), "%u", filenum ); + strcat( strcat( strcpy( filename, file_prefix ), "_" ), filenum_s ); + std::cout << " " << filename << ".exe"; + strcat( filename, ".cc" ); + out.open( filename, std::ios::out | std::ios::trunc ); + if( !out.is_open() ) { + std::cerr << "Error: Could not open " << filename << std::endl; + exit( 1 ); + } + + out << R"( +#include "fenv_test.h" + +size_t failures = 0; + +constexpr char file_prefix[] = ")" + << file_prefix << R"("; + +void (*fenv_tests[])() = { +)"; +} + +void closefile() { + if( out.is_open() ) { + out << R"( +}; + +size_t num_fenv_tests = sizeof( fenv_tests ) / sizeof( *fenv_tests ); + +int main() { + for( size_t i = 0; i < num_fenv_tests; ++i ) + fenv_tests[i](); + +#if 0 // TODO: This code causes seg faults + char fail[128], nfail[64]; + strcpy( fail, "\nfenv " ); + strcat( fail, file_prefix ); + snprintf( nfail, sizeof( nfail ), ": %zu / )" + << testcount << R"( test failures\n", failures ); + strcat( fail, nfail ); + fenv_write( 2, fail ); +#endif + +#ifdef __riscv + if(failures) + asm(" .word 0"); +#endif + + return !!failures; +} +)"; + out.close(); + } +} + +template +void generate_test( const std::pair& oper_pair, Ts... ops ) { + if( !out.is_open() ) { + openfile(); + } + + ++testnum; + auto& [func, func_src] = oper_pair; + fenv_t fenv; + std::fesetround( rounding ); + std::feholdexcept( &fenv ); + + volatile T result = func( ops... ); + int excepts = std::fetestexcept( FE_ALL_EXCEPT ); + + out << " []{\n"; + out << " // Test " << testnum << "\n"; + out << " using namespace std;\n"; + out << " auto func =" << func_src << ";\n"; + out << " auto func_src = R\"(" << func_src << ")\";\n"; + out << " fenv_t fenv;\n"; + + switch( rounding ) { + case FE_TONEAREST: out << " fesetround( FE_TONEAREST );\n"; break; + case FE_TOWARDZERO: out << " fesetround( FE_TOWARDZERO );\n"; break; + case FE_UPWARD: out << " fesetround( FE_UPWARD );\n"; break; + case FE_DOWNWARD: out << " fesetround( FE_DOWNWARD );\n"; break; + } + + out << " feholdexcept( &fenv );\n"; + out << " " << type << " result{ func( " << args_string( ops... ) << " ) };\n"; + out << " int exceptions = fetestexcept( FE_ALL_EXCEPT );\n"; + out << " " << type << " result_expected{ " << repr( result ) << " };\n"; + out << " int exceptions_expected = " << exception_string( excepts ) << ";\n"; + out << " bool result_passed = test_result( \"" << testnum << "\", file_prefix, func_src, result, result_expected, " + << args_string( ops... ) << " );\n"; + out << " bool exceptions_passed = test_exceptions( \"" << testnum + << "\", file_prefix, func_src, exceptions, exceptions_expected, result_passed, " << args_string( ops... ) << ");\n"; + out << " failures += !(result_passed && exceptions_passed);\n"; + out << " fesetenv( &fenv );\n"; + out << " },\n"; + std::fesetenv( &fenv ); + + if( ++testcount >= maxtests_per_file ) { + closefile(); + testcount = 0; + } +} + +template +static const FP special_fp_values[]{ + FP( 0.0f ), + FP( -0.0f ), + FP( 1.0f ), + FP( -1.0f ), + FP( 1.5f ), + FP( -1.5f ), + std::numeric_limits::quiet_NaN(), + std::numeric_limits::signaling_NaN(), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + std::numeric_limits::lowest(), + std::numeric_limits::max(), +}; + +// clang-format off +template +static const FP special_fcvt_values[]{ + FP( std::numeric_limits::max() ), + FP( std::numeric_limits::max() ) + FP( 0.75f ), + FP( std::numeric_limits::max() ) - FP( 0.75f ), + FP( std::numeric_limits::max() ) + FP( 0.25f ), + FP( std::numeric_limits::max() ) - FP( 0.25f ), + FP( std::numeric_limits::max() ) + FP( 0.5f ), + FP( std::numeric_limits::max() ) - FP( 0.5f ), + FP( std::numeric_limits::max() ) + FP( 1.0f ), + FP( std::numeric_limits::max() ) - FP( 1.0f ), + FP( std::numeric_limits::min() ), + FP( std::numeric_limits::min() ) + FP( 0.75f ), + FP( std::numeric_limits::min() ) - FP( 0.75f ), + FP( std::numeric_limits::min() ) + FP( 0.25f ), + FP( std::numeric_limits::min() ) - FP( 0.25f ), + FP( std::numeric_limits::min() ) + FP( 0.5f ), + FP( std::numeric_limits::min() ) - FP( 0.5f ), + FP( std::numeric_limits::min() ) + FP( 1.0f ), + FP( std::numeric_limits::min() ) - FP( 1.0f ), + FP( 0.0f ), + FP( -0.0f ), + FP( 0.25f ), + FP( -0.25f ), + FP( 0.5f ), + FP( -0.5f ), + FP( 0.75f ), + FP( -0.75f ), + std::numeric_limits::quiet_NaN(), + std::numeric_limits::signaling_NaN(), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + fpmax, + fpmin, + std::nextafter( fpmax, std::numeric_limits::infinity() ), + std::nextafter( fpmin, -std::numeric_limits::infinity() ), +}; +// clang-format on + +#define OPER_PAIR( lambda ) \ + { lambda, #lambda } + +template +const char fcvt_instruction[] = ""; +template<> +const char fcvt_instruction[] = "fcvt.w.s"; +template<> +const char fcvt_instruction[] = "fcvt.wu.s"; +template<> +const char fcvt_instruction[] = "fcvt.w.d"; +template<> +const char fcvt_instruction[] = "fcvt.wu.d"; + +#if __riscv_xlen >= 64 +template<> +const char fcvt_instruction[] = "fcvt.l.s"; +template<> +const char fcvt_instruction[] = "fcvt.lu.s"; +template<> +const char fcvt_instruction[] = "fcvt.l.d"; +template<> +const char fcvt_instruction[] = "fcvt.lu.d"; +#endif + +template +void generate_fcvt_tests() { + char test_src[256]; + test_src[0] = 0; + strcat( test_src, "[]( volatile auto x ) { " ); + strcat( test_src, type ); + strcat( test_src, " res; asm volatile( \"" ); + strcat( test_src, fcvt_instruction ); + strcat( test_src, R"( %0, %1" : "=r"(res) : "f"(x) ); return res; })" ); + + using INT_FUNC1 = std::pair[]; + for( auto oper_pair : INT_FUNC1{ + {[]( volatile auto x ) { return to_int( x ); }, test_src}, + } ) { + for( auto x : special_fcvt_values ) { + generate_test( oper_pair, x ); + } + } +} + +template +const char fma_instruction[] = ""; +template<> +const char fma_instruction[] = "fmadd.s"; +template<> +const char fma_instruction[] = "fmadd.d"; + +template +void generate_tests() { + using FUNC1 = std::pair[]; + for( auto oper_pair : FUNC1{ + OPER_PAIR( []( volatile auto x ) { return -x; } ), + OPER_PAIR( []( volatile auto x ) { return std::fabs( x ); } ), + } ) { + for( auto x : special_fp_values ) { + generate_test( oper_pair, x ); + } + } + + generate_fcvt_tests(); + generate_fcvt_tests(); + +#if __riscv_xlen >= 64 + generate_fcvt_tests(); + generate_fcvt_tests(); +#endif + + using FUNC2 = std::pair[]; + for( auto oper_pair : FUNC2{ + OPER_PAIR( []( volatile auto x, volatile auto y ) { return x + y; } ), + OPER_PAIR( []( volatile auto x, volatile auto y ) { return x - y; } ), + OPER_PAIR( []( volatile auto x, volatile auto y ) { return x * y; } ), + OPER_PAIR( []( volatile auto x, volatile auto y ) { return x / y; } ), + } ) { + for( auto x : special_fp_values ) { + for( auto y : special_fp_values ) { + generate_test( oper_pair, x, y ); + } + } + } + + using FUNC3 = std::pair[]; + char test_src[256]; + test_src[0] = 0; + strcat( test_src, R"( []( volatile auto x, volatile auto y, volatile auto z ) { )" ); + strcat( test_src, type ); + strcat( test_src, R"( res; asm volatile( " )" ); + strcat( test_src, fma_instruction ); + strcat( test_src, R"( %0, %1, %2, %3 " : "=f"(res) : "f"(x), "f"(y), "f"(z) ); return res; } )" ); + + for( auto oper_pair : FUNC3{ + {[]( volatile auto x, volatile auto y, volatile auto z ) + -> std::common_type_t { + using namespace std; + using T = common_type_t; + return revFMA( T( x ), T( y ), T( z ) ); + }, test_src}, + } ) { + for( auto x : special_fp_values ) { + for( auto y : special_fp_values ) { + for( auto z : special_fp_values ) { + generate_test( oper_pair, x, y, z ); + } + } + } + } +} + +[[noreturn]] void usage( const char* prog ) { + std::cerr << "Usage: " << prog << "{ TONEAREST | UPWARD | DOWNWARD | TOWARDZERO }" << std::endl; + exit( 1 ); +} + +int main( int argc, char** argv ) { + if( argc < 2 ) + usage( *argv ); + else if( !strcmp( argv[1], "TONEAREST" ) ) + rounding = FE_TONEAREST; + else if( !strcmp( argv[1], "UPWARD" ) ) + rounding = FE_UPWARD; + else if( !strcmp( argv[1], "DOWNWARD" ) ) + rounding = FE_DOWNWARD; + else if( !strcmp( argv[1], "TOWARDZERO" ) ) + rounding = FE_TOWARDZERO; + else + usage( *argv ); + + file_prefix = argv[1]; + + std::cout << file_prefix << "_EXES ="; + generate_tests(); + generate_tests(); + std::cout << "\n" + << file_prefix << ": $(" << file_prefix << "_EXES)\nRUN_" << file_prefix << ": $(" << file_prefix + << "_EXES)\n\t$(foreach exe,$^,./run_fenv_test.sh $(exe) &&) true\n.PHONY: " << file_prefix << " RUN_" << file_prefix + << std::endl; + closefile(); + + return 0; +} diff --git a/test/fenv/fenv_test.h b/test/fenv/fenv_test.h new file mode 100644 index 000000000..9ac988f1a --- /dev/null +++ b/test/fenv/fenv_test.h @@ -0,0 +1,322 @@ +#ifndef __FENV_TEST_H +#define __FENV_TEST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __riscv +#include "syscalls.h" +#else +#include +#include +#endif + +//#pragma STDC FENV_ACCESS ON + +#define FP_SIGNAN 100 // A random value not returned by fpclassify() + +template +int float_class( T x ) { + static_assert( std::numeric_limits::is_iec559, "Environment does not support IEEE 754" ); + int c = std::fpclassify( x ); + if( c == FP_NAN ) { + std::conditional_t, uint32_t, uint64_t> ix; + std::memcpy( &ix, &x, sizeof( ix ) ); + if( !( ix & decltype( ix ){ 1 } << ( std::is_same_v ? 22 : 51 ) ) ) { + c = FP_SIGNAN; + } + } + return c; +} + +inline void fenv_write( int fd, const char* str ) { + size_t len = 0; + while( str[len] ) + len++; +#ifdef __riscv + rev_write( fd, str, len ); +#else + write( fd, str, len ); +#endif +} + +// Limits when converting from floating-point to integer +template +inline constexpr FP fpmax = FP( 0 ); +template +inline constexpr FP fpmin = FP( 0 ); +template<> +inline constexpr float fpmax = 0x1.fffffep+30f; +template<> +inline constexpr float fpmin = -0x1p+31f; +template<> +inline constexpr float fpmax = 0x1.fffffep+31f; +template<> +inline constexpr float fpmin = 0x0p+0f; +template<> +inline constexpr float fpmax = 0x1.fffffep+62f; +template<> +inline constexpr float fpmin = -0x1p+63f; +template<> +inline constexpr float fpmax = 0x1.fffffep+63f; +template<> +inline constexpr float fpmin = 0x0p+0f; +template<> +inline constexpr double fpmax = 0x1.fffffffcp+30; +template<> +inline constexpr double fpmin = -0x1p+31; +template<> +inline constexpr double fpmax = 0x1.fffffffep+31; +template<> +inline constexpr double fpmin = 0x0p+0; +template<> +inline constexpr double fpmax = 0x1.fffffffffffffp+62; +template<> +inline constexpr double fpmin = -0x1p+63; +template<> +inline constexpr double fpmax = 0x1.fffffffffffffp+63; +template<> +inline constexpr double fpmin = 0x0p+0; + +/// Converts FP to Integer +template +INT to_int( T x ) { + using namespace std; + + if constexpr( std::is_same_v ) { + x = rintf( x ); + } else { + x = rint( x ); + } + + if( isnan( x ) || x > fpmax ) { + feraiseexcept( FE_INVALID ); + return numeric_limits::max(); + } else if( x < fpmin ) { + feraiseexcept( FE_INVALID ); + return numeric_limits::min(); + } else { + return static_cast( x ); + } +} + +/// returns a type string +template +inline constexpr char type[] = "(INVALID)"; +template<> +inline constexpr char type[] = "float"; +template<> +inline constexpr char type[] = "double"; +template<> +inline constexpr char type[] = "int32_t"; +template<> +inline constexpr char type[] = "uint32_t"; +template<> +inline constexpr char type[] = "int64_t"; +template<> +inline constexpr char type[] = "uint64_t"; + +/// Prints a value as a portable C++ exact constant +/// Handles +/- 0, +/- Inf, qNaN, sNaN +template +const char* repr( T x ) { + static char s[128]; + if constexpr( std::is_floating_point_v ) { + *s = 0; + switch( float_class( x ) ) { + case FP_NAN: + strcat( s, "std::numeric_limits<" ); + strcat( s, type ); + strcat( s, ">::quiet_NaN()" ); + break; + case FP_SIGNAN: + strcat( s, "std::numeric_limits<" ); + strcat( s, type ); + strcat( s, ">::signaling_NaN()" ); + break; + case FP_INFINITE: + if( std::signbit( x ) ) + strcat( s, "-" ); + strcat( s, "std::numeric_limits<" ); + strcat( s, type ); + strcat( s, ">::infinity()" ); + break; + default: { + static char fps[64]; + snprintf( fps, sizeof( fps ), "%a", (double) x ); + strcat( s, fps ); + strcat( s, std::is_same_v ? "f" : "" ); + } + } + } else if constexpr( std::is_same_v ) { + if( x == std::numeric_limits::min() ) { + snprintf( s, sizeof( s ), "-%" PRIi32 "-1", std::numeric_limits::max() ); + } else { + snprintf( s, sizeof( s ), "%" PRIi32, x ); + } + } else if constexpr( std::is_same_v ) { + static_assert( sizeof( long long ) == sizeof( int64_t ) ); + if( x == std::numeric_limits::min() ) { + snprintf( s, sizeof( s ), "-%" PRIi64 "ll-1", std::numeric_limits::max() ); + } else { + snprintf( s, sizeof( s ), "%" PRIi64 "ll", x ); + } + } else if constexpr( std::is_same_v ) { + snprintf( s, sizeof( s ), "%" PRIu32 "u", x ); + } else if constexpr( std::is_same_v ) { + static_assert( sizeof( unsigned long long ) == sizeof( uint64_t ) ); + snprintf( s, sizeof( s ), "%" PRIu64 "llu", x ); + } else { + static_assert( ( (void) sizeof( T ), false ), "Error: Unknown data type\n" ); + } + + return s; +} + +/// Formats a comma-separated list of values +template +const char* args_string( Ts... args ) { + static char s[1024]; + const char* sep = ""; + s[0] = 0; + (void) ( ..., ( strcat( strcat( s, sep ), repr( args ) ), sep = ", " ) ); + return s; +} + +/// Prints a logical-OR of exception names in an exception value +inline const char* exception_string( int exceptions ) { + static char s[128]; + s[0] = 0; + if( exceptions ) { + static constexpr std::pair etable[] = { + {FE_DIVBYZERO, "FE_DIVBYZERO"}, + { FE_INEXACT, "FE_INEXACT"}, + { FE_INVALID, "FE_INVALID"}, + { FE_OVERFLOW, "FE_OVERFLOW"}, + {FE_UNDERFLOW, "FE_UNDERFLOW"}, + }; + const char* sep = ""; + for( auto& e : etable ) { + if( exceptions & e.first ) { + strcat( s, sep ); + strcat( s, e.second ); + sep = " | "; + } + } + } else { + strcat( s, "0" ); + } + return s; +} + +template +bool test_result( const char* test, const char* file_prefix, const char* test_src, T result, T result_expected, Ts... args ) { + if constexpr( std::is_floating_point_v ) { + // Remove payloads from any NaNs + for( T& x : { std::ref( result ), std::ref( result_expected ) } ) { + switch( float_class( x ) ) { + case FP_NAN: x = std::numeric_limits::quiet_NaN(); break; + case FP_SIGNAN: x = std::numeric_limits::signaling_NaN(); break; + } + } + } + + // Compare for exact bit representation equality + if( memcmp( &result, &result_expected, sizeof( T ) ) ) { + char s[1024]; + *s = 0; + + strcat( s, "\nResult error in fenv " ); + strcat( s, file_prefix ); + strcat( s, " Test " ); + strcat( s, test ); + strcat( s, ":\n" ); + strcat( s, test_src ); + strcat( s, "\n ( " ); + strcat( s, args_string( args... ) ); + strcat( s, " )\n" ); + strcat( s, "Expected result: " ); + strcat( s, repr( result_expected ) ); + strcat( s, "\n" ); + strcat( s, "Actual result: " ); + strcat( s, repr( result ) ); + strcat( s, "\n" ); + fenv_write( 2, s ); + return false; + } else { + return true; + } +} + +template +bool test_exceptions( + const char* test, + const char* file_prefix, + const char* test_src, + int exceptions, + int exceptions_expected, + bool result_passed, + Ts... args +) { + char s[1024]; + *s = 0; + if( ( exceptions ^ exceptions_expected ) & FE_ALL_EXCEPT ) { + if( result_passed ) { + strcat( s, "\nExceptions error in fenv " ); + strcat( s, file_prefix ); + strcat( s, " Test " ); + strcat( s, test ); + strcat( s, ":\n" ); + strcat( s, test_src ); + strcat( s, "\n ( " ); + strcat( s, args_string( args... ) ); + strcat( s, " )\n" ); + } + strcat( s, "Expected exceptions: " ); + strcat( s, exception_string( exceptions_expected ) ); + strcat( s, "\n" ); + strcat( s, "Actual exceptions: " ); + strcat( s, exception_string( exceptions ) ); + strcat( s, "\n" ); + fenv_write( 2, s ); + return false; + } else { + if( result_passed ) { + strcat( s, "\nfenv " ); + strcat( s, file_prefix ); + strcat( s, " Test " ); + strcat( s, test ); + strcat( s, " Passed\n" ); + fenv_write( 2, s ); + } + return true; + } +} + +/// Rev FMA template which handles 0.0 * NAN and NAN * 0.0 correctly +// RISC-V requires INVALID exception when x * y is INVALID even when z = qNaN +template +inline auto revFMA( T x, T y, T z ) { + using namespace std; + if( ( y == 0 && isinf( x ) ) || ( x == 0 && isinf( y ) ) ) { + feraiseexcept( FE_INVALID ); + } + if constexpr( is_same_v ) { + return fmaf( x, y, z ); + } else { + return fma( x, y, z ); + } +} + +#endif diff --git a/test/fenv/run_fenv.sh b/test/fenv/run_fenv.sh new file mode 100755 index 000000000..970cac2d1 --- /dev/null +++ b/test/fenv/run_fenv.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make runtests diff --git a/test/fenv/run_fenv_test.sh b/test/fenv/run_fenv_test.sh new file mode 100755 index 000000000..501d29ae3 --- /dev/null +++ b/test/fenv/run_fenv_test.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program="$1" --verbose=0 | awk 'BEGIN {pass=0} /Simulation is complete/ {pass=1;next} {print} END {exit !pass}' diff --git a/test/include/rev-macros.h b/test/include/rev-macros.h index 8184590f4..b7fb9e002 100644 --- a/test/include/rev-macros.h +++ b/test/include/rev-macros.h @@ -1,20 +1,22 @@ +// clang-format off + #ifndef __REV_MACROS_H__ #define __REV_MACROS_H__ // Supported values for TRC_OP: slti sltiu slli srli srai #ifndef NO_REV_MACROS -#define TRACE_OFF asm volatile("slli x0,x0,0"); -#define TRACE_ON asm volatile("slli x0,x0,1"); -#define TRACE_PUSH_OFF asm volatile("slli x0,x0,2"); -#define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); +#define TRACE_OFF asm volatile("slli x0,x0,0"); +#define TRACE_ON asm volatile("slli x0,x0,1"); +#define TRACE_PUSH_OFF asm volatile("slli x0,x0,2"); +#define TRACE_PUSH_ON asm volatile("slli x0,x0,3"); #define TRACE_POP asm volatile("slli x0,x0,4"); -#define TRACE_ASSERT(x) { TRACE_PUSH_ON; \ +#define TRACE_ASSERT(x) do { TRACE_PUSH_ON; \ if (!(x)) { asm volatile(".word 0x0"); }; \ - TRACE_PUSH_OFF } + TRACE_POP } while (0) #else #define TRACE_OFF -#define TRACE_ON +#define TRACE_ON #define TRACE_PUSH_OFF #define TRACE_PUSH_ON #define TRACE_POP diff --git a/test/isa/CMakeLists.txt b/test/isa/CMakeLists.txt index 413d0b4d7..96c1650be 100644 --- a/test/isa/CMakeLists.txt +++ b/test/isa/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -7,36 +7,37 @@ file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c) -if(BUILD_ASM_TESTING) - #project(asm_tst C) +#project(asm_tst C) - #set(CMAKE_C_COMPILER "${RISCV_ENV}/bin/riscv64-unknown-elf-gcc") - #set(CMAKE_ASM_COMPILER "${RISCV_ENV}/bin/riscv64-unknown-elf-gcc") - #set(CMAKE_C_FLAGS "-O0 -march=rv64imafdc -static") - #set(CMAKE_OSX_DEPLOYMENT_TARGET "") +#set(CMAKE_C_COMPILER "${RISCV_ENV}/bin/riscv64-unknown-elf-gcc") +#set(CMAKE_ASM_COMPILER "${RISCV_ENV}/bin/riscv64-unknown-elf-gcc") +#set(CMAKE_C_FLAGS "-O0 -march=rv64imafdc -static") +#set(CMAKE_OSX_DEPLOYMENT_TARGET "") - set (passRegex "Simulation is complete") +set (passRegex "Simulation is complete") - add_test( - NAME BUILD_CLEAN - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND make clean +add_test( + NAME BUILD_CLEAN + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND make clean ) - foreach(testSrc ${TEST_SRCS}) - # Extract the file name - get_filename_component(testName ${testSrc} NAME_WE) +foreach(testSrc ${TEST_SRCS}) + # Extract the file name + get_filename_component(testName ${testSrc} NAME_WE) - #COMMAND sst --model-options=${CMAKE_CURRENT_SOURCE_DIR}/${testName} ./rev-isa-test.py) - # Add the tests for execution - add_test(NAME ${testName} + #COMMAND sst --model-options=${CMAKE_CURRENT_SOURCE_DIR}/${testName} ./rev-isa-test.py) + # Add the tests for execution + add_test(NAME ${testName} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ./run_asm_test.sh) - set_tests_properties( ${testName} - PROPERTIES - ENVIRONMENT "RVASM=${testName}; RVCC=${RVCC}" - TIMEOUT 30 - LABELS "all;rv64;isa" - PASS_REGULAR_EXPRESSION "${passRegex}") - endforeach(testSrc) -endif() + set_tests_properties( ${testName} + PROPERTIES + ENVIRONMENT "RVASM=${testName}; RVCC=${RVCC}" + TIMEOUT 30 + LABELS "rv64;isa" + PASS_REGULAR_EXPRESSION "${passRegex}") + if(TEST_LEVEL LESS 2) + set_tests_properties(${testName} PROPERTIES DISABLED TRUE) + endif() +endforeach(testSrc) diff --git a/test/isa/Makefile b/test/isa/Makefile index 39bd823a2..aad36e59b 100644 --- a/test/isa/Makefile +++ b/test/isa/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -18,7 +18,7 @@ ARCH=rv64imafdc ISA_SOURCES := $(wildcard *.c) ISA_HEADERS := $(wildcard *.h) ISA_EXES=$(ISA_SOURCES:.c=.exe) -RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O0 -ffast-math -fno-common -fno-builtin-printf -march=$(ARCH) -mabi=lp64d +RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu17 -O0 -ffast-math -fno-common -fno-builtin-printf -march=$(ARCH) -mabi=lp64d -fsignaling-nans -frounding-math -fno-associative-math ifeq "$(RVCC)" "riscv64-unknown-elf-gcc" RISCV_GCC_OPTS += -fno-tree-loop-distribute-patterns diff --git a/test/isa/add.c b/test/isa/add.c index dbe26b31f..c28a9b78b 100644 --- a/test/isa/add.c +++ b/test/isa/add.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,26 +11,26 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, add, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, add, 0x00000002, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, add, 0x0000000a, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, add, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, add, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, add, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 2, add, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, add, 0x00000002, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, add, 0x0000000a, 0x00000003, 0x00000007 ); + TEST_RR_OP( 5, add, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, add, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, add, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP( 8, add, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff ); - TEST_RR_OP( 9, add, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); + TEST_RR_OP( 8, add, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff ); + TEST_RR_OP( 9, add, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); TEST_RR_OP( 10, add, 0x0000000080007ffe, 0x000000007fffffff, 0x0000000000007fff ); TEST_RR_OP( 11, add, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff ); @@ -49,17 +49,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 18, add, 25, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 19, add, 26, 13 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); + asm volatile( "fail:" ); + assert( false ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/addi.c b/test/isa/addi.c index eed065022..be97a6ec5 100644 --- a/test/isa/addi.c +++ b/test/isa/addi.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, addi, 0x00000000, 0x00000000, 0x000 ); - TEST_IMM_OP( 3, addi, 0x00000002, 0x00000001, 0x001 ); - TEST_IMM_OP( 4, addi, 0x0000000a, 0x00000003, 0x007 ); + TEST_IMM_OP( 2, addi, 0x00000000, 0x00000000, 0x000 ); + TEST_IMM_OP( 3, addi, 0x00000002, 0x00000001, 0x001 ); + TEST_IMM_OP( 4, addi, 0x0000000a, 0x00000003, 0x007 ); - TEST_IMM_OP( 5, addi, 0xfffffffffffff800, 0x0000000000000000, 0x800 ); - TEST_IMM_OP( 6, addi, 0xffffffff80000000, 0xffffffff80000000, 0x000 ); - TEST_IMM_OP( 7, addi, 0xffffffff7ffff800, 0xffffffff80000000, 0x800 ); + TEST_IMM_OP( 5, addi, 0xfffffffffffff800, 0x0000000000000000, 0x800 ); + TEST_IMM_OP( 6, addi, 0xffffffff80000000, 0xffffffff80000000, 0x000 ); + TEST_IMM_OP( 7, addi, 0xffffffff7ffff800, 0xffffffff80000000, 0x800 ); - TEST_IMM_OP( 8, addi, 0x00000000000007ff, 0x00000000, 0x7ff ); - TEST_IMM_OP( 9, addi, 0x000000007fffffff, 0x7fffffff, 0x000 ); + TEST_IMM_OP( 8, addi, 0x00000000000007ff, 0x00000000, 0x7ff ); + TEST_IMM_OP( 9, addi, 0x000000007fffffff, 0x7fffffff, 0x000 ); TEST_IMM_OP( 10, addi, 0x00000000800007fe, 0x7fffffff, 0x7ff ); TEST_IMM_OP( 11, addi, 0xffffffff800007ff, 0xffffffff80000000, 0x7ff ); @@ -47,18 +47,17 @@ int main(int argc, char **argv){ // Source/Destination tests //------------------------------------------------------------- - //TEST_IMM_SRC1_EQ_DEST( 17, addi, 24, 13, 11 ); - + //TEST_IMM_SRC1_EQ_DEST( 17, addi, 24, 13, 11 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/addiw.c b/test/isa/addiw.c index 49111ec4e..ab6cf3a7a 100644 --- a/test/isa/addiw.c +++ b/test/isa/addiw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,26 +11,26 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_IMM_OP( 2, addiw, 0x00000000, 0x00000000, 0x000 ); - TEST_IMM_OP( 3, addiw, 0x00000002, 0x00000001, 0x001 ); - TEST_IMM_OP( 4, addiw, 0x0000000a, 0x00000003, 0x007 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_IMM_OP( 2, addiw, 0x00000000, 0x00000000, 0x000 ); + TEST_IMM_OP( 3, addiw, 0x00000002, 0x00000001, 0x001 ); + TEST_IMM_OP( 4, addiw, 0x0000000a, 0x00000003, 0x007 ); - TEST_IMM_OP( 5, addiw, 0xfffffffffffff800, 0x0000000000000000, 0x800 ); - TEST_IMM_OP( 6, addiw, 0xffffffff80000000, 0xffffffff80000000, 0x000 ); - TEST_IMM_OP( 7, addiw, 0x000000007ffff800, 0xffffffff80000000, 0x800 ); + TEST_IMM_OP( 5, addiw, 0xfffffffffffff800, 0x0000000000000000, 0x800 ); + TEST_IMM_OP( 6, addiw, 0xffffffff80000000, 0xffffffff80000000, 0x000 ); + TEST_IMM_OP( 7, addiw, 0x000000007ffff800, 0xffffffff80000000, 0x800 ); - TEST_IMM_OP( 8, addiw, 0x00000000000007ff, 0x00000000, 0x7ff ); - TEST_IMM_OP( 9, addiw, 0x000000007fffffff, 0x7fffffff, 0x000 ); + TEST_IMM_OP( 8, addiw, 0x00000000000007ff, 0x00000000, 0x7ff ); + TEST_IMM_OP( 9, addiw, 0x000000007fffffff, 0x7fffffff, 0x000 ); TEST_IMM_OP( 10, addiw, 0xffffffff800007fe, 0x7fffffff, 0x7ff ); TEST_IMM_OP( 11, addiw, 0xffffffff800007ff, 0xffffffff80000000, 0x7ff ); @@ -48,17 +48,15 @@ int main(int argc, char **argv){ //TEST_IMM_SRC1_EQ_DEST( 17, addiw, 24, 13, 11 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); - + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/addw.c b/test/isa/addw.c index 7d2b62f55..833fc6cc7 100644 --- a/test/isa/addw.c +++ b/test/isa/addw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, addw, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, addw, 0x00000002, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, addw, 0x0000000a, 0x00000003, 0x00000007 ); + TEST_RR_OP( 2, addw, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, addw, 0x00000002, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, addw, 0x0000000a, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, addw, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, addw, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, addw, 0x000000007fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, addw, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, addw, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, addw, 0x000000007fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP( 8, addw, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff ); - TEST_RR_OP( 9, addw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); + TEST_RR_OP( 8, addw, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff ); + TEST_RR_OP( 9, addw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); TEST_RR_OP( 10, addw, 0xffffffff80007ffe, 0x000000007fffffff, 0x0000000000007fff ); TEST_RR_OP( 11, addw, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff ); @@ -51,15 +51,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 18, addw, 25, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 19, addw, 26, 13 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/and.c b/test/isa/and.c index 83c56071e..8d7ac59cf 100644 --- a/test/isa/and.c +++ b/test/isa/and.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_RR_OP( 2, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); TEST_RR_OP( 3, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); @@ -35,15 +35,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 7, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); TEST_RR_SRC12_EQ_DEST( 8, and, 0xff00ff00, 0xff00ff00 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/andi.c b/test/isa/andi.c index e9aac1457..b8860aca0 100644 --- a/test/isa/andi.c +++ b/test/isa/andi.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,36 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_IMM_OP( 2, andi, 0xff00ff00, 0xff00ff00, 0xf0f ); TEST_IMM_OP( 3, andi, 0x000000f0, 0x0ff00ff0, 0x0f0 ); TEST_IMM_OP( 4, andi, 0x0000000f, 0x00ff00ff, 0x70f ); TEST_IMM_OP( 5, andi, 0x00000000, 0xf00ff00f, 0x0f0 ); - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- TEST_IMM_SRC1_EQ_DEST( 6, andi, 0x00000000, 0xff00ff00, 0x0f0 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); + asm volatile( "fail:" ); + assert( false ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/div.c b/test/isa/div.c index 1a423825d..12c21cb50 100644 --- a/test/isa/div.c +++ b/test/isa/div.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,39 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- +int main( int argc, char** argv ) { - TEST_RR_OP( 2, div, 3, 20, 6 ); - TEST_RR_OP( 3, div, -3, -20, 6 ); - TEST_RR_OP( 4, div, -3, 20, -6 ); - TEST_RR_OP( 5, div, 3, -20, -6 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 6, div, -1<<63, -1<<63, 1 ); - TEST_RR_OP( 7, div, -1<<63, -1<<63, -1 ); + TEST_RR_OP( 2, div, 3, 20, 6 ); + TEST_RR_OP( 3, div, -3, -20, 6 ); + TEST_RR_OP( 4, div, -3, 20, -6 ); + TEST_RR_OP( 5, div, 3, -20, -6 ); - TEST_RR_OP( 8, div, -1, -1<<63, 0 ); - TEST_RR_OP( 9, div, -1, 1, 0 ); - TEST_RR_OP(10, div, -1, 0, 0 ); + TEST_RR_OP( 6, div, -1 << 63, -1 << 63, 1 ); + TEST_RR_OP( 7, div, -1 << 63, -1 << 63, -1 ); + TEST_RR_OP( 8, div, -1, -1 << 63, 0 ); + TEST_RR_OP( 9, div, -1, 1, 0 ); + TEST_RR_OP( 10, div, -1, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/divu.c b/test/isa/divu.c index 31b4218ff..0cb3427fc 100644 --- a/test/isa/divu.c +++ b/test/isa/divu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, divu, 3, 20, 6 ); - TEST_RR_OP( 3, divu, 3074457345618258599, -20, 6 ); - TEST_RR_OP( 4, divu, 0, 20, -6 ); - TEST_RR_OP( 5, divu, 0, -20, -6 ); + TEST_RR_OP( 2, divu, 3, 20, 6 ); + TEST_RR_OP( 3, divu, 3074457345618258599, -20, 6 ); + TEST_RR_OP( 4, divu, 0, 20, -6 ); + TEST_RR_OP( 5, divu, 0, -20, -6 ); - TEST_RR_OP( 6, divu, -1<<63, -1<<63, 1 ); - TEST_RR_OP( 7, divu, 0, -1<<63, -1 ); + TEST_RR_OP( 6, divu, -1 << 63, -1 << 63, 1 ); + TEST_RR_OP( 7, divu, 0, -1 << 63, -1 ); - TEST_RR_OP( 8, divu, -1, -1<<63, 0 ); - TEST_RR_OP( 9, divu, -1, 1, 0 ); - TEST_RR_OP(10, divu, -1, 0, 0 ); + TEST_RR_OP( 8, divu, -1, -1 << 63, 0 ); + TEST_RR_OP( 9, divu, -1, 1, 0 ); + TEST_RR_OP( 10, divu, -1, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/divuw.c b/test/isa/divuw.c index 691928c22..f06e9f180 100644 --- a/test/isa/divuw.c +++ b/test/isa/divuw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,39 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, divuw, 3, 20, 6 ); - TEST_RR_OP( 3, divuw, 715827879, -20 << 32 >> 32, 6 ); - TEST_RR_OP( 4, divuw, 0, 20, -6 ); - TEST_RR_OP( 5, divuw, 0, -20, -6 ); + TEST_RR_OP( 2, divuw, 3, 20, 6 ); + TEST_RR_OP( 3, divuw, 715827879, -20 << 32 >> 32, 6 ); + TEST_RR_OP( 4, divuw, 0, 20, -6 ); + TEST_RR_OP( 5, divuw, 0, -20, -6 ); - TEST_RR_OP( 6, divuw, -1<<31, -1<<31, 1 ); - TEST_RR_OP( 7, divuw, 0, -1<<31, -1 ); + TEST_RR_OP( 6, divuw, -1 << 31, -1 << 31, 1 ); + TEST_RR_OP( 7, divuw, 0, -1 << 31, -1 ); - TEST_RR_OP( 8, divuw, -1, -1<<31, 0 ); - TEST_RR_OP( 9, divuw, -1, 1, 0 ); - TEST_RR_OP(10, divuw, -1, 0, 0 ); + TEST_RR_OP( 8, divuw, -1, -1 << 31, 0 ); + TEST_RR_OP( 9, divuw, -1, 1, 0 ); + TEST_RR_OP( 10, divuw, -1, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/divw.c b/test/isa/divw.c index 4cf1a0ac4..bd0adf794 100644 --- a/test/isa/divw.c +++ b/test/isa/divw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, divw, 3, 20, 6 ); - TEST_RR_OP( 3, divw, -3, -20, 6 ); - TEST_RR_OP( 4, divw, -3, 20, -6 ); - TEST_RR_OP( 5, divw, 3, -20, -6 ); + TEST_RR_OP( 2, divw, 3, 20, 6 ); + TEST_RR_OP( 3, divw, -3, -20, 6 ); + TEST_RR_OP( 4, divw, -3, 20, -6 ); + TEST_RR_OP( 5, divw, 3, -20, -6 ); - TEST_RR_OP( 6, divw, -1<<31, -1<<31, 1 ); - TEST_RR_OP( 7, divw, -1<<31, -1<<31, -1 ); + TEST_RR_OP( 6, divw, -1 << 31, -1 << 31, 1 ); + TEST_RR_OP( 7, divw, -1 << 31, -1 << 31, -1 ); - TEST_RR_OP( 8, divw, -1, -1<<31, 0 ); - TEST_RR_OP( 9, divw, -1, 1, 0 ); - TEST_RR_OP(10, divw, -1, 0, 0 ); + TEST_RR_OP( 8, divw, -1, -1 << 31, 0 ); + TEST_RR_OP( 9, divw, -1, 1, 0 ); + TEST_RR_OP( 10, divw, -1, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/f_ldst.c b/test/isa/f_ldst.c index 4fd6c30e8..28951ac56 100644 --- a/test/isa/f_ldst.c +++ b/test/isa/f_ldst.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,55 +11,46 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Basic tests of flw, fld, fsw, and fsd - // #------------------------------------------------------------- - // + // #------------------------------------------------------------- + // # Basic tests of flw, fld, fsw, and fsd + // #------------------------------------------------------------- + // - TEST_CASE(2, a0, 0x40000000deadbeef, \ - ASM_GEN(la a1, tdat); \ - ASM_GEN(flw f1, 4(a1)); \ - ASM_GEN(fsw f1, 20(a1)); \ - ASM_GEN(ld a0, 16(a1)); - ); + TEST_CASE( 2, a0, 0x40000000deadbeef, ASM_GEN( la a1, tdat ); ASM_GEN( flw f1, 4( a1 ) ); ASM_GEN( fsw f1, 20( a1 ) ); + ASM_GEN( ld a0, 16( a1 ) ); ); - TEST_CASE(3, a0, 0x1337d00dbf800000, \ - ASM_GEN(la a1, tdat); \ - ASM_GEN(flw f1, 0(a1)); \ - ASM_GEN(fsw f1, 24(a1)); \ - ASM_GEN(ld a0, 24(a1)) - ); + TEST_CASE( 3, a0, 0x1337d00dbf800000, ASM_GEN( la a1, tdat ); ASM_GEN( flw f1, 0( a1 ) ); ASM_GEN( fsw f1, 24( a1 ) ); + ASM_GEN( ld a0, 24( a1 ) ) ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm (".word 0xbf800000"); - asm (".word 0x40000000"); - asm (".word 0x40400000"); - asm (".word 0xc0800000"); - asm (".word 0xdeadbeef"); - asm (".word 0xcafebabe"); - asm (".word 0xabad1dea"); - asm (".word 0x1337d00d"); +asm( "tdat:" ); +asm( ".word 0xbf800000" ); +asm( ".word 0x40000000" ); +asm( ".word 0x40400000" ); +asm( ".word 0xc0800000" ); +asm( ".word 0xdeadbeef" ); +asm( ".word 0xcafebabe" ); +asm( ".word 0xabad1dea" ); +asm( ".word 0x1337d00d" ); RVTEST_DATA_END diff --git a/test/isa/fadd.c b/test/isa/fadd.c index a569da395..ce886790c 100644 --- a/test/isa/fadd.c +++ b/test/isa/fadd.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,26 +11,25 @@ * */ +#include "isa_test_macros.h" #include #include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- - float a = 0.0f; float b = 0.0f; float q = 0.0f; float x = 0.0f; - a = 2.5f; - b = 1.0f; - q = a + b; - x = 3.5f; + a = 2.5f; + b = 1.0f; + q = a + b; + x = 3.5f; assert( x == q ); a = 2.5f; diff --git a/test/isa/fclass.c b/test/isa/fclass.c index fd6b17504..02518d17b 100644 --- a/test/isa/fclass.c +++ b/test/isa/fclass.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,12 +11,12 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests @@ -30,18 +30,18 @@ int main(int argc, char **argv){ TEST_FCLASS_S( 7, 1 << 5, 0x007fffff ) TEST_FCLASS_S( 8, 1 << 6, 0x3f800000 ) TEST_FCLASS_S( 9, 1 << 7, 0x7f800000 ) - TEST_FCLASS_S(10, 1 << 8, 0x7f800001 ) + TEST_FCLASS_S( 10, 1 << 8, 0x7f800001 ) //TEST_FCLASS_S(11, 1 << 9, 0x7fc00000 ) // All NaNs classified as signaling - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(0); + asm volatile( "fail:" ); + assert( 0 ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/fcmp.c b/test/isa/fcmp.c index 973e2fe19..531f2c8b0 100644 --- a/test/isa/fcmp.c +++ b/test/isa/fcmp.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,45 +11,45 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- - TEST_FP_CMP_OP_S( 2, feq.s, 0x00, 1, -1.36, -1.36); - TEST_FP_CMP_OP_S( 3, fle.s, 0x00, 1, -1.36, -1.36); - TEST_FP_CMP_OP_S( 4, flt.s, 0x00, 0, -1.36, -1.36); + TEST_FP_CMP_OP_S( 2, feq.s, 0x00, 1, -1.36, -1.36 ); + TEST_FP_CMP_OP_S( 3, fle.s, 0x00, 1, -1.36, -1.36 ); + TEST_FP_CMP_OP_S( 4, flt.s, 0x00, 0, -1.36, -1.36 ); - TEST_FP_CMP_OP_S( 5, feq.s, 0x00, 0, -1.37, -1.36); - TEST_FP_CMP_OP_S( 6, fle.s, 0x00, 1, -1.37, -1.36); - TEST_FP_CMP_OP_S( 7, flt.s, 0x00, 1, -1.37, -1.36); + TEST_FP_CMP_OP_S( 5, feq.s, 0x00, 0, -1.37, -1.36 ); + TEST_FP_CMP_OP_S( 6, fle.s, 0x00, 1, -1.37, -1.36 ); + TEST_FP_CMP_OP_S( 7, flt.s, 0x00, 1, -1.37, -1.36 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(0); + asm volatile( "fail:" ); + assert( 0 ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - TEST_FP_OP_DATA2_CMP( 2, 1, -1.36, -1.36); - TEST_FP_OP_DATA2_CMP( 3, 1, -1.36, -1.36); - TEST_FP_OP_DATA2_CMP( 4, 0, -1.36, -1.36); +TEST_FP_OP_DATA2_CMP( 2, 1, -1.36, -1.36 ); +TEST_FP_OP_DATA2_CMP( 3, 1, -1.36, -1.36 ); +TEST_FP_OP_DATA2_CMP( 4, 0, -1.36, -1.36 ); - TEST_FP_OP_DATA2_CMP( 5, 0, -1.37, -1.36); - TEST_FP_OP_DATA2_CMP( 6, 1, -1.37, -1.36); - TEST_FP_OP_DATA2_CMP( 7, 1, -1.37, -1.36); +TEST_FP_OP_DATA2_CMP( 5, 0, -1.37, -1.36 ); +TEST_FP_OP_DATA2_CMP( 6, 1, -1.37, -1.36 ); +TEST_FP_OP_DATA2_CMP( 7, 1, -1.37, -1.36 ); RVTEST_DATA_END diff --git a/test/isa/fcvt_sd.c b/test/isa/fcvt_sd.c index 9bda57e04..de172d025 100644 --- a/test/isa/fcvt_sd.c +++ b/test/isa/fcvt_sd.c @@ -3,39 +3,40 @@ * * RISC-V ISA: RV32F, RV32D, RV64F, RV64D * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * * See LICENSE in the top level directory for licensing details * */ -#include #include +#include #pragma GCC diagnostic error "-Wdouble-promotion" #pragma GCC diagnostic error "-Wconversion" -#define FCVT_TEST(test, to_t, from_t, inst, result, input, rm) do { \ - to_t res = (to_t) 0xE0E0E0E0; \ - asm volatile( #inst " %0, %1" rm : "=f"(res) : "f"(input) ); \ - if (res != (result)) \ - asm volatile(" .word 0; .word " #test); \ - } while(0) +#define FCVT_TEST( test, to_t, from_t, inst, result, input, rm ) \ + do { \ + to_t res = (to_t) 0xE0E0E0E0; \ + asm volatile( #inst " %0, %1" rm : "=f"( res ) : "f"( input ) ); \ + if( res != ( result ) ) \ + asm volatile( " .word 0; .word " #test ); \ + } while( 0 ) -int main(int argc, char **argv){ +int main( int argc, char** argv ) { #if __riscv_flen >= 64 - asm volatile("slli x0,x0,1"); // Enable tracing + asm volatile( "slli x0,x0,1" ); // Enable tracing - FCVT_TEST( 1, float, double, fcvt.s.d, -1.125f, -1.125, ", rne" ); - FCVT_TEST( 2, float, double, fcvt.s.d, -1.f, -1.0, ", rne" ); - FCVT_TEST( 3, double, float, fcvt.d.s, -1.125, -1.125f, "" ); - FCVT_TEST( 4, double, float, fcvt.d.s, -1.0, -1.0f, "" ); - FCVT_TEST( 5, double, float, fcvt.d.s, (double) INFINITY, INFINITY, "" ); - FCVT_TEST( 6, double, float, fcvt.d.s, (double) -INFINITY, -INFINITY, "" ); + FCVT_TEST( 1, float, double, fcvt.s.d, -1.125f, -1.125, ", rne" ); + FCVT_TEST( 2, float, double, fcvt.s.d, -1.f, -1.0, ", rne" ); + FCVT_TEST( 3, double, float, fcvt.d.s, -1.125, -1.125f, "" ); + FCVT_TEST( 4, double, float, fcvt.d.s, -1.0, -1.0f, "" ); + FCVT_TEST( 5, double, float, fcvt.d.s, (double) INFINITY, INFINITY, "" ); + FCVT_TEST( 6, double, float, fcvt.d.s, (double) -INFINITY, -INFINITY, "" ); -#endif // __riscv_flen >= 64 +#endif // __riscv_flen >= 64 - return 0; + return 0; } diff --git a/test/isa/fcvt_sw.c b/test/isa/fcvt_sw.c index 4e71af65f..b843e99d6 100644 --- a/test/isa/fcvt_sw.c +++ b/test/isa/fcvt_sw.c @@ -3,59 +3,60 @@ * * RISC-V ISA: RV32F, RV32D, RV64F, RV64D * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * * See LICENSE in the top level directory for licensing details * */ -#include #include +#include #pragma GCC diagnostic error "-Wdouble-promotion" #pragma GCC diagnostic error "-Wconversion" -#define FCVT_TEST(test, to_t, from_t, inst, result, input, rm) do { \ +#define FCVT_TEST( test, to_t, from_t, inst, result, input, rm ) \ + do { \ to_t res = (to_t) 0xE0E0E0E0; \ - asm volatile( #inst " %0, %1, " #rm : "=f"(res) : "r"(input) ); \ - if (res != (result)) \ - asm(" .word 0; .word " #test); \ - } while(0) + asm volatile( #inst " %0, %1, " #rm : "=f"( res ) : "r"( input ) ); \ + if( res != ( result ) ) \ + asm( " .word 0; .word " #test ); \ + } while( 0 ) -int main(int argc, char **argv){ - asm volatile("slli x0,x0,1"); // Enable tracing +int main( int argc, char** argv ) { + asm volatile( "slli x0,x0,1" ); // Enable tracing #if __riscv_flen >= 32 - FCVT_TEST( 1, float, int32_t, fcvt.s.w, 1.f, (int32_t)1, rne ); - FCVT_TEST( 2, float, int32_t, fcvt.s.w, -1.f, -(int32_t)1, rne ); - FCVT_TEST( 3, float, int32_t, fcvt.s.w, -0.0f, (int32_t)0, rne ); - FCVT_TEST( 4, float, uint32_t, fcvt.s.wu, 1.0f, (uint32_t)1, rne ); - FCVT_TEST( 5, float, uint32_t, fcvt.s.wu, 0x1p+32f, -(uint32_t)1, rne ); - FCVT_TEST( 6, float, uint32_t, fcvt.s.wu, 0.0f, (uint32_t)0, rne ); + FCVT_TEST( 1, float, int32_t, fcvt.s.w, 1.f, (int32_t) 1, rne ); + FCVT_TEST( 2, float, int32_t, fcvt.s.w, -1.f, -(int32_t) 1, rne ); + FCVT_TEST( 3, float, int32_t, fcvt.s.w, -0.0f, (int32_t) 0, rne ); + FCVT_TEST( 4, float, uint32_t, fcvt.s.wu, 1.0f, (uint32_t) 1, rne ); + FCVT_TEST( 5, float, uint32_t, fcvt.s.wu, 0x1p+32f, -(uint32_t) 1, rne ); + FCVT_TEST( 6, float, uint32_t, fcvt.s.wu, 0.0f, (uint32_t) 0, rne ); #if __riscv_xlen >= 64 - FCVT_TEST( 7, float, int64_t, fcvt.s.l, 1.0f, (int64_t)1, rne ); - FCVT_TEST( 8, float, int64_t, fcvt.s.l, -1.0f, -(int64_t)1, rne ); - FCVT_TEST( 9, float, int64_t, fcvt.s.l, 0.0f, (int64_t)0, rne ); - FCVT_TEST( 10, float, uint64_t, fcvt.s.lu, 1.0f, (uint64_t)1, rne ); - FCVT_TEST( 11, float, uint64_t, fcvt.s.lu, 0x1p+64f, -(uint64_t)1, rne ); - FCVT_TEST( 12, float, uint64_t, fcvt.s.lu, 0.0f, (uint64_t)0, rne ); + FCVT_TEST( 7, float, int64_t, fcvt.s.l, 1.0f, (int64_t) 1, rne ); + FCVT_TEST( 8, float, int64_t, fcvt.s.l, -1.0f, -(int64_t) 1, rne ); + FCVT_TEST( 9, float, int64_t, fcvt.s.l, 0.0f, (int64_t) 0, rne ); + FCVT_TEST( 10, float, uint64_t, fcvt.s.lu, 1.0f, (uint64_t) 1, rne ); + FCVT_TEST( 11, float, uint64_t, fcvt.s.lu, 0x1p+64f, -(uint64_t) 1, rne ); + FCVT_TEST( 12, float, uint64_t, fcvt.s.lu, 0.0f, (uint64_t) 0, rne ); #if __riscv_flen >= 64 - FCVT_TEST( 13, double, int64_t, fcvt.d.l, 1.0, (int64_t)1, rne ); - FCVT_TEST( 14, double, int64_t, fcvt.d.l, -1.0, -(int64_t)1, rne ); - FCVT_TEST( 15, double, int64_t, fcvt.d.l, 0.0, (int64_t)0, rne ); - FCVT_TEST( 16, double, uint64_t, fcvt.d.lu, 1.0, (uint64_t)1, rne ); - FCVT_TEST( 17, double, uint64_t, fcvt.d.lu, 0x1p+64, -(uint64_t)1, rne ); - FCVT_TEST( 18, double, uint64_t, fcvt.d.lu, 0.0, (uint64_t)0, rne ); + FCVT_TEST( 13, double, int64_t, fcvt.d.l, 1.0, (int64_t) 1, rne ); + FCVT_TEST( 14, double, int64_t, fcvt.d.l, -1.0, -(int64_t) 1, rne ); + FCVT_TEST( 15, double, int64_t, fcvt.d.l, 0.0, (int64_t) 0, rne ); + FCVT_TEST( 16, double, uint64_t, fcvt.d.lu, 1.0, (uint64_t) 1, rne ); + FCVT_TEST( 17, double, uint64_t, fcvt.d.lu, 0x1p+64, -(uint64_t) 1, rne ); + FCVT_TEST( 18, double, uint64_t, fcvt.d.lu, 0.0, (uint64_t) 0, rne ); -#endif // __riscv_flen >= 64 -#endif // __riscv_xlen >= 64 -#endif // __riscv_flen >= 32 +#endif // __riscv_flen >= 64 +#endif // __riscv_xlen >= 64 +#endif // __riscv_flen >= 32 - return 0; + return 0; } diff --git a/test/isa/fcvt_w.c b/test/isa/fcvt_w.c index 5964c8802..d437d808a 100644 --- a/test/isa/fcvt_w.c +++ b/test/isa/fcvt_w.c @@ -3,132 +3,133 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * * See LICENSE in the top level directory for licensing details * */ -#include #include +#include #pragma GCC diagnostic error "-Wdouble-promotion" #pragma GCC diagnostic error "-Wconversion" -#define FCVT_TEST(test, to_t, from_t, inst, result, input, rm) do { \ +#define FCVT_TEST( test, to_t, from_t, inst, result, input, rm ) \ + do { \ to_t res = (to_t) 0xE0E0E0E0; \ - asm volatile(#inst " %0, %1, " #rm : "=r"(res) : "f"(input)); \ - if (res != (result)) \ - asm volatile(" .word 0; .word " #test); \ - } while(0) + asm volatile( #inst " %0, %1, " #rm : "=r"( res ) : "f"( input ) ); \ + if( res != ( result ) ) \ + asm volatile( " .word 0; .word " #test ); \ + } while( 0 ) -int main(int argc, char **argv){ - asm volatile("slli x0,x0,1"); // Enable tracing +int main( int argc, char** argv ) { + asm volatile( "slli x0,x0,1" ); // Enable tracing #if __riscv_flen >= 32 -FCVT_TEST( 2, int32_t, float, fcvt.w.s, -1, -1.1f, rtz ); -FCVT_TEST( 3, int32_t, float, fcvt.w.s, -1, -1.0f, rtz ); -FCVT_TEST( 4, int32_t, float, fcvt.w.s, 0, -0.9f, rtz ); -FCVT_TEST( 5, int32_t, float, fcvt.w.s, 0, 0.9f, rtz ); -FCVT_TEST( 6, int32_t, float, fcvt.w.s, 1, 1.0f, rtz ); -FCVT_TEST( 7, int32_t, float, fcvt.w.s, 1, 1.1f, rtz ); -// FCVT_TEST( 8, int32_t, float, fcvt.w.s, 0x7fffff80, 0x1.fffffep+30, rtz ); -// FCVT_TEST( 9, int32_t, float, fcvt.w.s, INT32_MAX, 0x1.ffffffp+30f, rtz ); -FCVT_TEST( 10, int32_t, float, fcvt.w.s, 0x80000080, -0x1.fffffep+30f, rtz ); -FCVT_TEST( 11, int32_t, float, fcvt.w.s, INT32_MIN, -0x1.ffffffp+30f, rtz ); -FCVT_TEST( 12, uint32_t, float, fcvt.wu.s, 0, -1.1f, rtz ); -FCVT_TEST( 13, uint32_t, float, fcvt.wu.s, 0, -1.0f, rtz ); -FCVT_TEST( 14, uint32_t, float, fcvt.wu.s, 0, -3.0f, rtz ); -FCVT_TEST( 15, uint32_t, float, fcvt.wu.s, 0, -1.0f, rtz ); -FCVT_TEST( 16, uint32_t, float, fcvt.wu.s, 0, -0.9f, rtz ); -FCVT_TEST( 17, uint32_t, float, fcvt.wu.s, 0, 0.9f, rtz ); -FCVT_TEST( 18, uint32_t, float, fcvt.wu.s, 1, 1.0f, rtz ); -FCVT_TEST( 19, uint32_t, float, fcvt.wu.s, 1, 1.1f, rtz ); -FCVT_TEST( 20, uint32_t, float, fcvt.wu.s, 0, -3e9f, rtz ); -FCVT_TEST( 21, uint32_t, float, fcvt.wu.s, 0xffffff00, 0x1.fffffep+31f, rtz ); -// FCVT_TEST( 22, uint32_t, float, fcvt.wu.s, UINT32_MAX, 0x1.ffffffp+31f, rtz ); + FCVT_TEST( 2, int32_t, float, fcvt.w.s, -1, -1.1f, rtz ); + FCVT_TEST( 3, int32_t, float, fcvt.w.s, -1, -1.0f, rtz ); + FCVT_TEST( 4, int32_t, float, fcvt.w.s, 0, -0.9f, rtz ); + FCVT_TEST( 5, int32_t, float, fcvt.w.s, 0, 0.9f, rtz ); + FCVT_TEST( 6, int32_t, float, fcvt.w.s, 1, 1.0f, rtz ); + FCVT_TEST( 7, int32_t, float, fcvt.w.s, 1, 1.1f, rtz ); + // FCVT_TEST( 8, int32_t, float, fcvt.w.s, 0x7fffff80, 0x1.fffffep+30, rtz ); + // FCVT_TEST( 9, int32_t, float, fcvt.w.s, INT32_MAX, 0x1.ffffffp+30f, rtz ); + FCVT_TEST( 10, int32_t, float, fcvt.w.s, 0x80000080, -0x1.fffffep+30f, rtz ); + FCVT_TEST( 11, int32_t, float, fcvt.w.s, INT32_MIN, -0x1.ffffffp+30f, rtz ); + FCVT_TEST( 12, uint32_t, float, fcvt.wu.s, 0, -1.1f, rtz ); + FCVT_TEST( 13, uint32_t, float, fcvt.wu.s, 0, -1.0f, rtz ); + FCVT_TEST( 14, uint32_t, float, fcvt.wu.s, 0, -3.0f, rtz ); + FCVT_TEST( 15, uint32_t, float, fcvt.wu.s, 0, -1.0f, rtz ); + FCVT_TEST( 16, uint32_t, float, fcvt.wu.s, 0, -0.9f, rtz ); + FCVT_TEST( 17, uint32_t, float, fcvt.wu.s, 0, 0.9f, rtz ); + FCVT_TEST( 18, uint32_t, float, fcvt.wu.s, 1, 1.0f, rtz ); + FCVT_TEST( 19, uint32_t, float, fcvt.wu.s, 1, 1.1f, rtz ); + FCVT_TEST( 20, uint32_t, float, fcvt.wu.s, 0, -3e9f, rtz ); + FCVT_TEST( 21, uint32_t, float, fcvt.wu.s, 0xffffff00, 0x1.fffffep+31f, rtz ); + // FCVT_TEST( 22, uint32_t, float, fcvt.wu.s, UINT32_MAX, 0x1.ffffffp+31f, rtz ); #if __riscv_xlen >= 64 -FCVT_TEST( 23, int64_t, float, fcvt.l.s, -1, -1.1f, rtz ); -FCVT_TEST( 24, int64_t, float, fcvt.l.s, -1, -1.0f, rtz ); -FCVT_TEST( 25, int64_t, float, fcvt.l.s, 0, -0.9f, rtz ); -FCVT_TEST( 26, int64_t, float, fcvt.l.s, 0, 0.9f, rtz ); -FCVT_TEST( 27, int64_t, float, fcvt.l.s, 1, 1.0f, rtz ); -FCVT_TEST( 28, int64_t, float, fcvt.l.s, 1, 1.1f, rtz ); -FCVT_TEST( 29, int64_t, float, fcvt.l.s, 0x7fffff8000000000, 0x1.fffffep+62f, rtz ); -// FCVT_TEST( 30, int64_t, float, fcvt.l.s, INT64_MAX, 0x1.ffffffp+62f, rtz ); -FCVT_TEST( 31, int64_t, float, fcvt.l.s, 0x8000010000000000, -0x1.fffffdp+62f, rtz ); -FCVT_TEST( 32, int64_t, float, fcvt.l.s, 0x8000008000000000, -0x1.fffffep+62f, rtz ); -FCVT_TEST( 33, int64_t, float, fcvt.l.s, INT64_MIN, -0x1.ffffffp+62f, rtz ); -FCVT_TEST( 34, uint64_t, float, fcvt.lu.s, 0, -3.0f, rtz ); -FCVT_TEST( 35, uint64_t, float, fcvt.lu.s, 0, -1.0f, rtz ); -FCVT_TEST( 36, uint64_t, float, fcvt.lu.s, 0, -0.9f, rtz ); -FCVT_TEST( 37, uint64_t, float, fcvt.lu.s, 0, 0.9f, rtz ); -FCVT_TEST( 38, uint64_t, float, fcvt.lu.s, 1, 1.0f, rtz ); -FCVT_TEST( 39, uint64_t, float, fcvt.lu.s, 1, 1.1f, rtz ); -FCVT_TEST( 40, uint64_t, float, fcvt.lu.s, 0, -3e9f, rtz ); -FCVT_TEST( 41, uint64_t, float, fcvt.lu.s, 0xffffff0000000000, 0x1.fffffep+63f, rtz ); -// FCVT_TEST( 42, uint64_t, float, fcvt.lu.s, UINT64_MAX, 0x1.ffffffp+63f, rtz ); -FCVT_TEST( 43, uint64_t, float, fcvt.lu.s, 0, -0x1.fffffdp+63f, rtz ); -FCVT_TEST( 44, uint64_t, float, fcvt.lu.s, 0, -0x1.fffffep+63f, rtz ); -FCVT_TEST( 45, uint64_t, float, fcvt.lu.s, 0, -0x1.ffffffp+63f, rtz ); + FCVT_TEST( 23, int64_t, float, fcvt.l.s, -1, -1.1f, rtz ); + FCVT_TEST( 24, int64_t, float, fcvt.l.s, -1, -1.0f, rtz ); + FCVT_TEST( 25, int64_t, float, fcvt.l.s, 0, -0.9f, rtz ); + FCVT_TEST( 26, int64_t, float, fcvt.l.s, 0, 0.9f, rtz ); + FCVT_TEST( 27, int64_t, float, fcvt.l.s, 1, 1.0f, rtz ); + FCVT_TEST( 28, int64_t, float, fcvt.l.s, 1, 1.1f, rtz ); + FCVT_TEST( 29, int64_t, float, fcvt.l.s, 0x7fffff8000000000, 0x1.fffffep+62f, rtz ); + // FCVT_TEST( 30, int64_t, float, fcvt.l.s, INT64_MAX, 0x1.ffffffp+62f, rtz ); + FCVT_TEST( 31, int64_t, float, fcvt.l.s, 0x8000010000000000, -0x1.fffffdp+62f, rtz ); + FCVT_TEST( 32, int64_t, float, fcvt.l.s, 0x8000008000000000, -0x1.fffffep+62f, rtz ); + FCVT_TEST( 33, int64_t, float, fcvt.l.s, INT64_MIN, -0x1.ffffffp+62f, rtz ); + FCVT_TEST( 34, uint64_t, float, fcvt.lu.s, 0, -3.0f, rtz ); + FCVT_TEST( 35, uint64_t, float, fcvt.lu.s, 0, -1.0f, rtz ); + FCVT_TEST( 36, uint64_t, float, fcvt.lu.s, 0, -0.9f, rtz ); + FCVT_TEST( 37, uint64_t, float, fcvt.lu.s, 0, 0.9f, rtz ); + FCVT_TEST( 38, uint64_t, float, fcvt.lu.s, 1, 1.0f, rtz ); + FCVT_TEST( 39, uint64_t, float, fcvt.lu.s, 1, 1.1f, rtz ); + FCVT_TEST( 40, uint64_t, float, fcvt.lu.s, 0, -3e9f, rtz ); + FCVT_TEST( 41, uint64_t, float, fcvt.lu.s, 0xffffff0000000000, 0x1.fffffep+63f, rtz ); + // FCVT_TEST( 42, uint64_t, float, fcvt.lu.s, UINT64_MAX, 0x1.ffffffp+63f, rtz ); + FCVT_TEST( 43, uint64_t, float, fcvt.lu.s, 0, -0x1.fffffdp+63f, rtz ); + FCVT_TEST( 44, uint64_t, float, fcvt.lu.s, 0, -0x1.fffffep+63f, rtz ); + FCVT_TEST( 45, uint64_t, float, fcvt.lu.s, 0, -0x1.ffffffp+63f, rtz ); -#endif // __riscv_xlen >= 64 +#endif // __riscv_xlen >= 64 -#endif // __riscv_flen >= 32 +#endif // __riscv_flen >= 32 #if __riscv_flen >= 64 -FCVT_TEST( 46, int32_t, double, fcvt.w.d, -1, -1.1, rtz ); -FCVT_TEST( 47, int32_t, double, fcvt.w.d, -1, -1.0, rtz ); -FCVT_TEST( 48, int32_t, double, fcvt.w.d, 0, -0.9, rtz ); -FCVT_TEST( 49, int32_t, double, fcvt.w.d, 0, 0.9, rtz ); -FCVT_TEST( 50, int32_t, double, fcvt.w.d, 1, 1.0, rtz ); -FCVT_TEST( 51, int32_t, double, fcvt.w.d, 1, 1.1, rtz ); -FCVT_TEST( 52, int32_t, double, fcvt.w.d, 2147483647, 0x1.fffffffffffffp+30, rtz ); -FCVT_TEST( 53, int32_t, double, fcvt.w.d, INT32_MAX, 0x1.0p+31, rtz ); -FCVT_TEST( 54, int32_t, double, fcvt.w.d, -2147483647, -0x1.fffffffffffffp+30, rtz ); -FCVT_TEST( 55, int32_t, double, fcvt.w.d, INT32_MIN, -0x1.0p+31, rtz ); -FCVT_TEST( 56, uint32_t, double, fcvt.wu.d, 0, -1.1, rtz ); -FCVT_TEST( 57, uint32_t, double, fcvt.wu.d, 0, -1.0, rtz ); -FCVT_TEST( 58, uint32_t, double, fcvt.wu.d, 0, -3.0, rtz ); -FCVT_TEST( 59, uint32_t, double, fcvt.wu.d, 0, -1.0, rtz ); -FCVT_TEST( 60, uint32_t, double, fcvt.wu.d, 0, -0.9, rtz ); -FCVT_TEST( 61, uint32_t, double, fcvt.wu.d, 0, 0.9, rtz ); -FCVT_TEST( 62, uint32_t, double, fcvt.wu.d, 1, 1.0, rtz ); -FCVT_TEST( 63, uint32_t, double, fcvt.wu.d, 1, 1.1, rtz ); -FCVT_TEST( 64, uint32_t, double, fcvt.wu.d, 0, -3e9, rtz ); -FCVT_TEST( 65, uint32_t, double, fcvt.wu.d, UINT32_MAX, 0x1.fffffffffffffp+31, rtz ); -FCVT_TEST( 66, uint32_t, double, fcvt.wu.d, -2, 0x1.fffffffcp+31, rtz ); -FCVT_TEST( 67, uint32_t, double, fcvt.wu.d, UINT32_MAX, 0x1.0p+32, rtz ); + FCVT_TEST( 46, int32_t, double, fcvt.w.d, -1, -1.1, rtz ); + FCVT_TEST( 47, int32_t, double, fcvt.w.d, -1, -1.0, rtz ); + FCVT_TEST( 48, int32_t, double, fcvt.w.d, 0, -0.9, rtz ); + FCVT_TEST( 49, int32_t, double, fcvt.w.d, 0, 0.9, rtz ); + FCVT_TEST( 50, int32_t, double, fcvt.w.d, 1, 1.0, rtz ); + FCVT_TEST( 51, int32_t, double, fcvt.w.d, 1, 1.1, rtz ); + FCVT_TEST( 52, int32_t, double, fcvt.w.d, 2147483647, 0x1.fffffffffffffp+30, rtz ); + FCVT_TEST( 53, int32_t, double, fcvt.w.d, INT32_MAX, 0x1.0p+31, rtz ); + FCVT_TEST( 54, int32_t, double, fcvt.w.d, -2147483647, -0x1.fffffffffffffp+30, rtz ); + FCVT_TEST( 55, int32_t, double, fcvt.w.d, INT32_MIN, -0x1.0p+31, rtz ); + FCVT_TEST( 56, uint32_t, double, fcvt.wu.d, 0, -1.1, rtz ); + FCVT_TEST( 57, uint32_t, double, fcvt.wu.d, 0, -1.0, rtz ); + FCVT_TEST( 58, uint32_t, double, fcvt.wu.d, 0, -3.0, rtz ); + FCVT_TEST( 59, uint32_t, double, fcvt.wu.d, 0, -1.0, rtz ); + FCVT_TEST( 60, uint32_t, double, fcvt.wu.d, 0, -0.9, rtz ); + FCVT_TEST( 61, uint32_t, double, fcvt.wu.d, 0, 0.9, rtz ); + FCVT_TEST( 62, uint32_t, double, fcvt.wu.d, 1, 1.0, rtz ); + FCVT_TEST( 63, uint32_t, double, fcvt.wu.d, 1, 1.1, rtz ); + FCVT_TEST( 64, uint32_t, double, fcvt.wu.d, 0, -3e9, rtz ); + FCVT_TEST( 65, uint32_t, double, fcvt.wu.d, UINT32_MAX, 0x1.fffffffffffffp+31, rtz ); + FCVT_TEST( 66, uint32_t, double, fcvt.wu.d, -2, 0x1.fffffffcp+31, rtz ); + FCVT_TEST( 67, uint32_t, double, fcvt.wu.d, UINT32_MAX, 0x1.0p+32, rtz ); #if __riscv_xlen >= 64 -FCVT_TEST( 68, int64_t, double, fcvt.l.d, -1, -1.1, rtz ); -FCVT_TEST( 69, int64_t, double, fcvt.l.d, -1, -1.0, rtz ); -FCVT_TEST( 70, int64_t, double, fcvt.l.d, 0, -0.9, rtz ); -FCVT_TEST( 71, int64_t, double, fcvt.l.d, 0, 0.9, rtz ); -FCVT_TEST( 72, int64_t, double, fcvt.l.d, 1, 1.0, rtz ); -FCVT_TEST( 73, int64_t, double, fcvt.l.d, 1, 1.1, rtz ); -// FCVT_TEST( 74, int64_t, double, fcvt.l.d, 0x7ffffffffffffc00, 0x1.fffffffffffffp+62, rtz ); -// FCVT_TEST( 75, int64_t, double, fcvt.l.d, INT64_MAX, 0x1.0p+63, rtz ); -FCVT_TEST( 76, int64_t, double, fcvt.l.d, 0x8000000000000400, -0x1.fffffffffffffp+62, rtz ); -FCVT_TEST( 77, int64_t, double, fcvt.l.d, INT64_MIN, -0x1.0p+63, rtz ); -FCVT_TEST( 78, uint64_t, double, fcvt.lu.d, 0, -3.0, rtz ); -FCVT_TEST( 79, uint64_t, double, fcvt.lu.d, 0, -1.0, rtz ); -FCVT_TEST( 80, uint64_t, double, fcvt.lu.d, 0, -0.9, rtz ); -FCVT_TEST( 81, uint64_t, double, fcvt.lu.d, 0, 0.9, rtz ); -FCVT_TEST( 82, uint64_t, double, fcvt.lu.d, 1, 1.0, rtz ); -FCVT_TEST( 83, uint64_t, double, fcvt.lu.d, 1, 1.1, rtz ); -FCVT_TEST( 84, uint64_t, double, fcvt.lu.d, 0, -3e9, rtz ); -FCVT_TEST( 85, uint64_t, double, fcvt.lu.d, 0xfffffffffffff800, 0x1.fffffffffffffp+63, rtz ); -FCVT_TEST( 86, uint64_t, double, fcvt.lu.d, 0, -0x1.fffffffffffffp+63, rtz ); -FCVT_TEST( 87, uint64_t, double, fcvt.lu.d, 0, -0x1.0p+64, rtz ); -// FCVT_TEST( 88, uint64_t, double, fcvt.lu.d, UINT64_MAX, 0x1.0p+64, rtz ); + FCVT_TEST( 68, int64_t, double, fcvt.l.d, -1, -1.1, rtz ); + FCVT_TEST( 69, int64_t, double, fcvt.l.d, -1, -1.0, rtz ); + FCVT_TEST( 70, int64_t, double, fcvt.l.d, 0, -0.9, rtz ); + FCVT_TEST( 71, int64_t, double, fcvt.l.d, 0, 0.9, rtz ); + FCVT_TEST( 72, int64_t, double, fcvt.l.d, 1, 1.0, rtz ); + FCVT_TEST( 73, int64_t, double, fcvt.l.d, 1, 1.1, rtz ); + // FCVT_TEST( 74, int64_t, double, fcvt.l.d, 0x7ffffffffffffc00, 0x1.fffffffffffffp+62, rtz ); + // FCVT_TEST( 75, int64_t, double, fcvt.l.d, INT64_MAX, 0x1.0p+63, rtz ); + FCVT_TEST( 76, int64_t, double, fcvt.l.d, 0x8000000000000400, -0x1.fffffffffffffp+62, rtz ); + FCVT_TEST( 77, int64_t, double, fcvt.l.d, INT64_MIN, -0x1.0p+63, rtz ); + FCVT_TEST( 78, uint64_t, double, fcvt.lu.d, 0, -3.0, rtz ); + FCVT_TEST( 79, uint64_t, double, fcvt.lu.d, 0, -1.0, rtz ); + FCVT_TEST( 80, uint64_t, double, fcvt.lu.d, 0, -0.9, rtz ); + FCVT_TEST( 81, uint64_t, double, fcvt.lu.d, 0, 0.9, rtz ); + FCVT_TEST( 82, uint64_t, double, fcvt.lu.d, 1, 1.0, rtz ); + FCVT_TEST( 83, uint64_t, double, fcvt.lu.d, 1, 1.1, rtz ); + FCVT_TEST( 84, uint64_t, double, fcvt.lu.d, 0, -3e9, rtz ); + FCVT_TEST( 85, uint64_t, double, fcvt.lu.d, 0xfffffffffffff800, 0x1.fffffffffffffp+63, rtz ); + FCVT_TEST( 86, uint64_t, double, fcvt.lu.d, 0, -0x1.fffffffffffffp+63, rtz ); + FCVT_TEST( 87, uint64_t, double, fcvt.lu.d, 0, -0x1.0p+64, rtz ); + // FCVT_TEST( 88, uint64_t, double, fcvt.lu.d, UINT64_MAX, 0x1.0p+64, rtz ); -#endif // __riscv_xlen >= 64 +#endif // __riscv_xlen >= 64 -#endif // __riscv_flen >= 64 +#endif // __riscv_flen >= 64 } diff --git a/test/isa/fdiv.c b/test/isa/fdiv.c index bed278e7a..4650d9eaa 100644 --- a/test/isa/fdiv.c +++ b/test/isa/fdiv.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,28 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- - float a = 0.0; float b = 0.0; float q = 0.0; float x = 0.0; - /* TEST_FP_OP2_S(2, fdiv.s, 1, 1.1557273520668288, 3.14159265, 2.71828182 );*/ - a = 3.14159265; - b = 2.71828182; - q = a / b; - x = 1.1557273520668288; + /* TEST_FP_OP2_S(2, fdiv.s, 1, 1.1557273520668288, 3.14159265, 2.71828182 );*/ + a = 3.14159265; + b = 2.71828182; + q = a / b; + x = 1.1557273520668288; assert( x == q ); @@ -50,31 +49,31 @@ int main(int argc, char **argv){ x = 3.14159265; assert( x == q ); - TEST_FP_OP2_S(4, fdiv.s, 0, 3.14159265, 3.14159265, 1.0 ); - TEST_FP_OP2_S(5, fdiv.s, 0, 1.1557273520668288, 3.14159265, 2.71828182 ); + TEST_FP_OP2_S( 4, fdiv.s, 0, 3.14159265, 3.14159265, 1.0 ); + TEST_FP_OP2_S( 5, fdiv.s, 0, 1.1557273520668288, 3.14159265, 2.71828182 ); - TEST_FP_OP1_S(6, fsqrt.s, 1, 1.7724538498928541, 3.14159265 ); - TEST_FP_OP1_S(7, fsqrt.s, 0, 100, 10000 ); - TEST_FP_OP1_S(8, fsqrt.s, 1, 13.076696, 171.0); + TEST_FP_OP1_S( 6, fsqrt.s, 1, 1.7724538498928541, 3.14159265 ); + TEST_FP_OP1_S( 7, fsqrt.s, 0, 100, 10000 ); + TEST_FP_OP1_S( 8, fsqrt.s, 1, 13.076696, 171.0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(0); + asm volatile( "fail:" ); + assert( 0 ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN -TEST_FP_OP_DATA2(4, 3.14159265, 3.14159265, 1.0); -TEST_FP_OP_DATA2(5, 1.1557273520668288, 3.14159265, 2.71828182); -TEST_FP_OP_DATA1(6, 1.7724538498928541, 3.14159265 ); -TEST_FP_OP_DATA1(7, 100, 10000 ); -TEST_FP_OP_DATA1(8, 13.076696, 171.0); +TEST_FP_OP_DATA2( 4, 3.14159265, 3.14159265, 1.0 ); +TEST_FP_OP_DATA2( 5, 1.1557273520668288, 3.14159265, 2.71828182 ); +TEST_FP_OP_DATA1( 6, 1.7724538498928541, 3.14159265 ); +TEST_FP_OP_DATA1( 7, 100, 10000 ); +TEST_FP_OP_DATA1( 8, 13.076696, 171.0 ); RVTEST_DATA_END diff --git a/test/isa/fma.c b/test/isa/fma.c index bdc9bf191..a884fdb18 100644 --- a/test/isa/fma.c +++ b/test/isa/fma.c @@ -1,25 +1,23 @@ -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".word 0x00"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".word 0x00" ); \ + } \ + while( 0 ) -#define FMA_TEST(T, INST) \ - do { \ - volatile T ad = 2.0; \ - volatile T bd = 3.0; \ - volatile T cd = 5.0; \ - volatile T rd; \ - asm volatile(INST " %0, %1, %2, %3" \ - : "=f"(rd) \ - : "f"(ad), "f"(bd), "f"(cd)); \ - assert(rd >= 10.99); \ - assert(rd <= 11.01); \ - } while (0) +#define FMA_TEST( T, INST ) \ + do { \ + volatile T ad = 2.0; \ + volatile T bd = 3.0; \ + volatile T cd = 5.0; \ + volatile T rd; \ + asm volatile( INST " %0, %1, %2, %3" : "=f"( rd ) : "f"( ad ), "f"( bd ), "f"( cd ) ); \ + assert( rd >= 10.99 ); \ + assert( rd <= 11.01 ); \ + } while( 0 ) int main() { - FMA_TEST(float, "fmadd.s"); - FMA_TEST(double, "fmadd.d"); + FMA_TEST( float, "fmadd.s" ); + FMA_TEST( double, "fmadd.d" ); return 0; } diff --git a/test/isa/fmadd.c b/test/isa/fmadd.c index 0cf3949a4..de3918d0e 100644 --- a/test/isa/fmadd.c +++ b/test/isa/fmadd.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,63 +11,59 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- - TEST_FP_OP3_S( 2, fmadd.s, 0, 3.5, 1.0, 2.5, 1.0 ); - TEST_FP_OP3_S( 3, fmadd.s, 1, 1236.2, -1.0, -1235.1, 1.1 ); - TEST_FP_OP3_S( 4, fmadd.s, 0, -12.0, 2.0, -5.0, -2.0 ); - - TEST_FP_OP3_S( 5, fnmadd.s, 0, -3.5, 1.0, 2.5, 1.0 ); - TEST_FP_OP3_S( 6, fnmadd.s, 1, -1236.2, -1.0, -1235.1, 1.1 ); - TEST_FP_OP3_S( 7, fnmadd.s, 0, 12.0, 2.0, -5.0, -2.0 ); + TEST_FP_OP3_S( 2, fmadd.s, 0, 3.5, 1.0, 2.5, 1.0 ); + TEST_FP_OP3_S( 3, fmadd.s, 1, 1236.2, -1.0, -1235.1, 1.1 ); + TEST_FP_OP3_S( 4, fmadd.s, 0, -12.0, 2.0, -5.0, -2.0 ); - TEST_FP_OP3_S( 8, fmsub.s, 0, 1.5, 1.0, 2.5, 1.0 ); - TEST_FP_OP3_S( 9, fmsub.s, 1, 1234, -1.0, -1235.1, 1.1 ); - TEST_FP_OP3_S(10, fmsub.s, 0, -8.0, 2.0, -5.0, -2.0 ); + TEST_FP_OP3_S( 5, fnmadd.s, 0, -3.5, 1.0, 2.5, 1.0 ); + TEST_FP_OP3_S( 6, fnmadd.s, 1, -1236.2, -1.0, -1235.1, 1.1 ); + TEST_FP_OP3_S( 7, fnmadd.s, 0, 12.0, 2.0, -5.0, -2.0 ); - TEST_FP_OP3_S(11, fnmsub.s, 0, -1.5, 1.0, 2.5, 1.0 ); - TEST_FP_OP3_S(12, fnmsub.s, 1, -1234, -1.0, -1235.1, 1.1 ); - TEST_FP_OP3_S(13, fnmsub.s, 0, 8.0, 2.0, -5.0, -2.0 ); - - - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(0); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + TEST_FP_OP3_S( 8, fmsub.s, 0, 1.5, 1.0, 2.5, 1.0 ); + TEST_FP_OP3_S( 9, fmsub.s, 1, 1234, -1.0, -1235.1, 1.1 ); + TEST_FP_OP3_S( 10, fmsub.s, 0, -8.0, 2.0, -5.0, -2.0 ); + TEST_FP_OP3_S( 11, fnmsub.s, 0, -1.5, 1.0, 2.5, 1.0 ); + TEST_FP_OP3_S( 12, fnmsub.s, 1, -1234, -1.0, -1235.1, 1.1 ); + TEST_FP_OP3_S( 13, fnmsub.s, 0, 8.0, 2.0, -5.0, -2.0 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); + asm volatile( "fail:" ); + assert( 0 ); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); + +asm( ".data" ); RVTEST_DATA_BEGIN -TEST_FP_OP_DATA3( 2, 3.5, 1.0, 2.5, 1.0 ); -TEST_FP_OP_DATA3( 3, 1236.2, -1.0, -1235.1, 1.1 ); -TEST_FP_OP_DATA3( 4, -12.0, 2.0, -5.0, -2.0 ); -TEST_FP_OP_DATA3( 5, -3.5, 1.0, 2.5, 1.0 ); -TEST_FP_OP_DATA3( 6, -1236.2, -1.0, -1235.1, 1.1 ); -TEST_FP_OP_DATA3( 7, 12.0, 2.0, -5.0, -2.0 ); -TEST_FP_OP_DATA3( 8, 1.5, 1.0, 2.5, 1.0 ); -TEST_FP_OP_DATA3( 9, 1234, -1.0, -1235.1, 1.1 ); -TEST_FP_OP_DATA3(10, -8.0, 2.0, -5.0, -2.0 ); -TEST_FP_OP_DATA3(11, -1.5, 1.0, 2.5, 1.0 ); -TEST_FP_OP_DATA3(12, -1234, -1.0, -1235.1, 1.1 ); -TEST_FP_OP_DATA3(13, 8.0, 2.0, -5.0, -2.0 ); +TEST_FP_OP_DATA3( 2, 3.5, 1.0, 2.5, 1.0 ); +TEST_FP_OP_DATA3( 3, 1236.2, -1.0, -1235.1, 1.1 ); +TEST_FP_OP_DATA3( 4, -12.0, 2.0, -5.0, -2.0 ); +TEST_FP_OP_DATA3( 5, -3.5, 1.0, 2.5, 1.0 ); +TEST_FP_OP_DATA3( 6, -1236.2, -1.0, -1235.1, 1.1 ); +TEST_FP_OP_DATA3( 7, 12.0, 2.0, -5.0, -2.0 ); +TEST_FP_OP_DATA3( 8, 1.5, 1.0, 2.5, 1.0 ); +TEST_FP_OP_DATA3( 9, 1234, -1.0, -1235.1, 1.1 ); +TEST_FP_OP_DATA3( 10, -8.0, 2.0, -5.0, -2.0 ); +TEST_FP_OP_DATA3( 11, -1.5, 1.0, 2.5, 1.0 ); +TEST_FP_OP_DATA3( 12, -1234, -1.0, -1235.1, 1.1 ); +TEST_FP_OP_DATA3( 13, 8.0, 2.0, -5.0, -2.0 ); RVTEST_DATA_END diff --git a/test/isa/fmin.c b/test/isa/fmin.c index febb89ddb..3962d06b9 100644 --- a/test/isa/fmin.c +++ b/test/isa/fmin.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,69 +11,69 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- - TEST_FP_OP2_S( 2, fmin.s, 0, 1.0, 2.5, 1.0 ); - TEST_FP_OP2_S( 3, fmin.s, 0, -1235.1, -1235.1, 1.1 ); - TEST_FP_OP2_S( 4, fmin.s, 0, -1235.1, 1.1, -1235.1 ); - TEST_FP_OP2_S( 5, fmin.s, 0, -1235.1, NaN, -1235.1 ); - TEST_FP_OP2_S( 6, fmin.s, 0, 0.00000001, 3.14159265, 0.00000001 ); - TEST_FP_OP2_S( 7, fmin.s, 0, -2.0, -1.0, -2.0 ); + TEST_FP_OP2_S( 2, fmin.s, 0, 1.0, 2.5, 1.0 ); + TEST_FP_OP2_S( 3, fmin.s, 0, -1235.1, -1235.1, 1.1 ); + TEST_FP_OP2_S( 4, fmin.s, 0, -1235.1, 1.1, -1235.1 ); + TEST_FP_OP2_S( 5, fmin.s, 0, -1235.1, NaN, -1235.1 ); + TEST_FP_OP2_S( 6, fmin.s, 0, 0.00000001, 3.14159265, 0.00000001 ); + TEST_FP_OP2_S( 7, fmin.s, 0, -2.0, -1.0, -2.0 ); - TEST_FP_OP2_S(12, fmax.s, 0, 2.5, 2.5, 1.0 ); - TEST_FP_OP2_S(13, fmax.s, 0, 1.1, -1235.1, 1.1 ); - TEST_FP_OP2_S(14, fmax.s, 0, 1.1, 1.1, -1235.1 ); - TEST_FP_OP2_S(15, fmax.s, 0, -1235.1, NaN, -1235.1 ); - TEST_FP_OP2_S(16, fmax.s, 0, 3.14159265, 3.14159265, 0.00000001 ); - TEST_FP_OP2_S(17, fmax.s, 0, -1.0, -1.0, -2.0 ); + TEST_FP_OP2_S( 12, fmax.s, 0, 2.5, 2.5, 1.0 ); + TEST_FP_OP2_S( 13, fmax.s, 0, 1.1, -1235.1, 1.1 ); + TEST_FP_OP2_S( 14, fmax.s, 0, 1.1, 1.1, -1235.1 ); + TEST_FP_OP2_S( 15, fmax.s, 0, -1235.1, NaN, -1235.1 ); + TEST_FP_OP2_S( 16, fmax.s, 0, 3.14159265, 3.14159265, 0.00000001 ); + TEST_FP_OP2_S( 17, fmax.s, 0, -1.0, -1.0, -2.0 ); - // # -0.0 < +0.0 + // # -0.0 < +0.0 //TEST_FP_OP2_S(30, fmin.s, 0, -0.0, -0.0, 0.0 ); // -0 < 0 not recognized by c++, so Rev treats these as identical values //TEST_FP_OP2_S(31, fmin.s, 0, -0.0, 0.0, -0.0 ); //TEST_FP_OP2_S(32, fmax.s, 0, 0.0, -0.0, 0.0 ); //TEST_FP_OP2_S(33, fmax.s, 0, 0.0, 0.0, -0.0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(0); + asm volatile( "fail:" ); + assert( 0 ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - TEST_FP_OP_DATA2( 2, 1.0, 2.5, 1.0 ); - TEST_FP_OP_DATA2( 3, -1235.1, -1235.1, 1.1 ); - TEST_FP_OP_DATA2( 4, -1235.1, 1.1, -1235.1 ); - TEST_FP_OP_DATA2( 5, -1235.1, NaN, -1235.1 ); - TEST_FP_OP_DATA2( 6, 0.00000001, 3.14159265, 0.00000001 ); - TEST_FP_OP_DATA2( 7, -2.0, -1.0, -2.0 ); +TEST_FP_OP_DATA2( 2, 1.0, 2.5, 1.0 ); +TEST_FP_OP_DATA2( 3, -1235.1, -1235.1, 1.1 ); +TEST_FP_OP_DATA2( 4, -1235.1, 1.1, -1235.1 ); +TEST_FP_OP_DATA2( 5, -1235.1, NaN, -1235.1 ); +TEST_FP_OP_DATA2( 6, 0.00000001, 3.14159265, 0.00000001 ); +TEST_FP_OP_DATA2( 7, -2.0, -1.0, -2.0 ); - TEST_FP_OP_DATA2(12, 2.5, 2.5, 1.0 ); - TEST_FP_OP_DATA2(13, 1.1, -1235.1, 1.1 ); - TEST_FP_OP_DATA2(14, 1.1, 1.1, -1235.1 ); - TEST_FP_OP_DATA2(15, -1235.1, NaN, -1235.1 ); - TEST_FP_OP_DATA2(16, 3.14159265, 3.14159265, 0.00000001 ); - TEST_FP_OP_DATA2(17, -1.0, -1.0, -2.0 ); +TEST_FP_OP_DATA2( 12, 2.5, 2.5, 1.0 ); +TEST_FP_OP_DATA2( 13, 1.1, -1235.1, 1.1 ); +TEST_FP_OP_DATA2( 14, 1.1, 1.1, -1235.1 ); +TEST_FP_OP_DATA2( 15, -1235.1, NaN, -1235.1 ); +TEST_FP_OP_DATA2( 16, 3.14159265, 3.14159265, 0.00000001 ); +TEST_FP_OP_DATA2( 17, -1.0, -1.0, -2.0 ); - // # -0.0 < +0.0 - TEST_FP_OP_DATA2(30, -0.0, -0.0, 0.0 ); - TEST_FP_OP_DATA2(31, -0.0, 0.0, -0.0 ); - TEST_FP_OP_DATA2(32, 0.0, -0.0, 0.0 ); - TEST_FP_OP_DATA2(33, 0.0, 0.0, -0.0 ); +// # -0.0 < +0.0 +TEST_FP_OP_DATA2( 30, -0.0, -0.0, 0.0 ); +TEST_FP_OP_DATA2( 31, -0.0, 0.0, -0.0 ); +TEST_FP_OP_DATA2( 32, 0.0, -0.0, 0.0 ); +TEST_FP_OP_DATA2( 33, 0.0, 0.0, -0.0 ); RVTEST_DATA_END diff --git a/test/isa/fmove.c b/test/isa/fmove.c index 8a160c484..25309847c 100644 --- a/test/isa/fmove.c +++ b/test/isa/fmove.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,51 +11,48 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { // #------------------------------------------------------------- // # Arithmetic tests // #------------------------------------------------------------- -#define TEST_FSGNJS(n, insn, new_sign, rs1_sign, rs2_sign) \ - TEST_CASE(n, a0, 0x12345678 | (-(new_sign) << 31), \ - ASM_GEN( li a1, ((rs1_sign) << 31) | 0x12345678); \ - ASM_GEN(li a2, -(rs2_sign)); \ - ASM_GEN(fmv.s.x f1, a1); \ - ASM_GEN(fmv.s.x f2, a2); \ - ASM_GEN(insn f0, f1, f2); \ - ASM_GEN(fmv.x.s a0, f0); \ - ); - - TEST_FSGNJS(10, fsgnj.s, 0, 0, 0) - TEST_FSGNJS(11, fsgnj.s, 1, 0, 1) - TEST_FSGNJS(12, fsgnj.s, 0, 1, 0) - TEST_FSGNJS(13, fsgnj.s, 1, 1, 1) - - TEST_FSGNJS(20, fsgnjn.s, 1, 0, 0) - TEST_FSGNJS(21, fsgnjn.s, 0, 0, 1) - TEST_FSGNJS(22, fsgnjn.s, 1, 1, 0) - TEST_FSGNJS(23, fsgnjn.s, 0, 1, 1) - - TEST_FSGNJS(30, fsgnjx.s, 0, 0, 0) - TEST_FSGNJS(31, fsgnjx.s, 1, 0, 1) - TEST_FSGNJS(32, fsgnjx.s, 1, 1, 0) - TEST_FSGNJS(33, fsgnjx.s, 0, 1, 1) - - - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(0); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); +#define TEST_FSGNJS( n, insn, new_sign, rs1_sign, rs2_sign ) \ + TEST_CASE( n, a0, 0x12345678 | ( -( new_sign ) << 31 ), ASM_GEN( li a1, ( ( rs1_sign ) << 31 ) | 0x12345678 ); \ + ASM_GEN( li a2, -( rs2_sign ) ); \ + ASM_GEN( fmv.s.x f1, a1 ); \ + ASM_GEN( fmv.s.x f2, a2 ); \ + ASM_GEN( insn f0, f1, f2 ); \ + ASM_GEN( fmv.x.s a0, f0 ); ); + + TEST_FSGNJS( 10, fsgnj.s, 0, 0, 0 ) + TEST_FSGNJS( 11, fsgnj.s, 1, 0, 1 ) + TEST_FSGNJS( 12, fsgnj.s, 0, 1, 0 ) + TEST_FSGNJS( 13, fsgnj.s, 1, 1, 1 ) + + TEST_FSGNJS( 20, fsgnjn.s, 1, 0, 0 ) + TEST_FSGNJS( 21, fsgnjn.s, 0, 0, 1 ) + TEST_FSGNJS( 22, fsgnjn.s, 1, 1, 0 ) + TEST_FSGNJS( 23, fsgnjn.s, 0, 1, 1 ) + + TEST_FSGNJS( 30, fsgnjx.s, 0, 0, 0 ) + TEST_FSGNJS( 31, fsgnjx.s, 1, 0, 1 ) + TEST_FSGNJS( 32, fsgnjx.s, 1, 1, 0 ) + TEST_FSGNJS( 33, fsgnjx.s, 0, 1, 1 ) + + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); + + asm volatile( "fail:" ); + assert( 0 ); + + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/isa_test_macros.h b/test/isa/isa_test_macros.h index eaca3db4d..b682fbdcc 100644 --- a/test/isa/isa_test_macros.h +++ b/test/isa/isa_test_macros.h @@ -1,4 +1,4 @@ - +// clang-format off #ifndef __ISA_TEST_MACROS_H #define __ISA_TEST_MACROS_H diff --git a/test/isa/jal.c b/test/isa/jal.c index ca1990b97..e848b989b 100644 --- a/test/isa/jal.c +++ b/test/isa/jal.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,34 +11,35 @@ * */ -int main(){ - asm( - " mv t1, ra\n" - " j 3f\n" +int main() { + asm( " mv t1, ra\n" + " j 3f\n" - "1:\n" - " ret\n" - " .zero 0x80000-0x8\n" - "2:\n" - " ret\n" - " .zero 0x80000-0x8\n" - "3:\n" - " jal 1b\n" - " jal 2b\n" - " jal 4f\n" - " jal 5f\n" - " j 6f\n" - " ret\n" - " .zero 0x80000-0x4\n" - "4:\n" - " ret\n" - " .zero 0x80000-0x10\n" - "5:\n" - " ret\n" + "1:\n" + " ret\n" + " .zero 0x80000-0x8\n" + "2:\n" + " ret\n" + " .zero 0x80000-0x8\n" + "3:\n" + " jal 1b\n" + " jal 2b\n" + " jal 4f\n" + " jal 5f\n" + " j 6f\n" + " ret\n" + " .zero 0x80000-0x4\n" + "4:\n" + " ret\n" + " .zero 0x80000-0x10\n" + "5:\n" + " ret\n" - "6:\n" - " mv ra, t1\n" - : : : "t1"); + "6:\n" + " mv ra, t1\n" + : + : + : "t1" ); - return 0; + return 0; } diff --git a/test/isa/jalr.c b/test/isa/jalr.c index 68327f7ba..170de7dc2 100644 --- a/test/isa/jalr.c +++ b/test/isa/jalr.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,48 +11,58 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -#define FAIL do { asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); asm(".byte 0x00"); } while(0) +#define FAIL \ + do { \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + asm( ".byte 0x00" ); \ + } while( 0 ) -int main(int argc, char **argv){ - void* ret1 = 0, *retaddr1 = 0; +int main( void ) { + void *ret1 = 0, *retaddr1 = 0; - // Different input and output registers for JALR - asm goto( - " lla %1, l1\n" - " lla t0, %l2\n" - " jalr %0, 0(t0)\n" - "l1:\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - : "=&r"(ret1), "=&r"(retaddr1) : : "t0" : target1); + // Different input and output registers for JALR + asm goto( " lla %1, l1\n" + " lla t0, %l2\n" + " jalr %0, 0(t0)\n" + "l1:\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + : "=&r"( ret1 ), "=&r"( retaddr1 ) + : + : "t0" + : target1 ); + FAIL; +target1: + if( ret1 != retaddr1 ) FAIL; - target1: - if (ret1 != retaddr1) - FAIL; - // Same input and output registers for JALR - void* ret2 = 0, *retaddr2 = 0; - asm goto( - " lla %1, l2\n" - " lla %0, %l2\n" - " jalr %0, 0(%0)\n" - "l2:\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - : "=r"(ret2), "=&r"(retaddr2) : : : target2); + // Same input and output registers for JALR + void *ret2 = 0, *retaddr2 = 0; + asm goto( " lla %1, l2\n" + " lla %0, %l2\n" + " jalr %0, 0(%0)\n" + "l2:\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + : "=r"( ret2 ), "=&r"( retaddr2 ) + : + : + : target2 ); + FAIL; +target2: + if( ret2 != retaddr2 ) FAIL; - target2: - if (ret2 != retaddr2) - FAIL; - return 0; + return 0; } diff --git a/test/isa/lb.c b/test/isa/lb.c index 330e4f053..6fc59cc67 100644 --- a/test/isa/lb.c +++ b/test/isa/lb.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,69 +11,55 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - - - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - TEST_LD_OP( 2, lb, 0xffffffffffffffff, 0, tdat ); - TEST_LD_OP( 3, lb, 0x0000000000000000, 1, tdat ); - TEST_LD_OP( 4, lb, 0xfffffffffffffff0, 2, tdat ); + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // + TEST_LD_OP( 2, lb, 0xffffffffffffffff, 0, tdat ); + TEST_LD_OP( 3, lb, 0x0000000000000000, 1, tdat ); + TEST_LD_OP( 4, lb, 0xfffffffffffffff0, 2, tdat ); TEST_LD_OP( 5, lb, 0x000000000000000f, 3, tdat ); //# Test with negative offset TEST_LD_OP( 6, lb, 0xffffffffffffffff, -3, tdat4 ); - TEST_LD_OP( 7, lb, 0x0000000000000000, -2, tdat4 ); - TEST_LD_OP( 8, lb, 0xfffffffffffffff0, -1, tdat4 ); - TEST_LD_OP( 9, lb, 0x000000000000000f, 0, tdat4 ); + TEST_LD_OP( 7, lb, 0x0000000000000000, -2, tdat4 ); + TEST_LD_OP( 8, lb, 0xfffffffffffffff0, -1, tdat4 ); + TEST_LD_OP( 9, lb, 0x000000000000000f, 0, tdat4 ); //# Test with a negative base - TEST_CASE( 10, x5, 0xffffffffffffffff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lb x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0xffffffffffffffff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lb x5, 32( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0x0000000000000000, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -6); \ - ASM_GEN(lb x5, 7(x6)); \ - ) - + TEST_CASE( 11, x5, 0x0000000000000000, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -6 ); ASM_GEN( lb x5, 7( x6 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .byte 0xff"); - asm ("tdat2: .byte 0x00"); - asm ("tdat3: .byte 0xf0"); - asm ("tdat4: .byte 0x0f"); +asm( "tdat:" ); +asm( "tdat1: .byte 0xff" ); +asm( "tdat2: .byte 0x00" ); +asm( "tdat3: .byte 0xf0" ); +asm( "tdat4: .byte 0x0f" ); RVTEST_DATA_END diff --git a/test/isa/lbu.c b/test/isa/lbu.c index 47c09d2d9..7f1cd82e7 100644 --- a/test/isa/lbu.c +++ b/test/isa/lbu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,70 +11,56 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // - - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - - TEST_LD_OP( 2, lbu, 0x00000000000000ff, 0, tdat ); - TEST_LD_OP( 3, lbu, 0x0000000000000000, 1, tdat ); - TEST_LD_OP( 4, lbu, 0x00000000000000f0, 2, tdat ); + TEST_LD_OP( 2, lbu, 0x00000000000000ff, 0, tdat ); + TEST_LD_OP( 3, lbu, 0x0000000000000000, 1, tdat ); + TEST_LD_OP( 4, lbu, 0x00000000000000f0, 2, tdat ); TEST_LD_OP( 5, lbu, 0x000000000000000f, 3, tdat ); // # Test with negative offset TEST_LD_OP( 6, lbu, 0x00000000000000ff, -3, tdat4 ); - TEST_LD_OP( 7, lbu, 0x0000000000000000, -2, tdat4 ); - TEST_LD_OP( 8, lbu, 0x00000000000000f0, -1, tdat4 ); - TEST_LD_OP( 9, lbu, 0x000000000000000f, 0, tdat4 ); + TEST_LD_OP( 7, lbu, 0x0000000000000000, -2, tdat4 ); + TEST_LD_OP( 8, lbu, 0x00000000000000f0, -1, tdat4 ); + TEST_LD_OP( 9, lbu, 0x000000000000000f, 0, tdat4 ); //# Test with a negative base - TEST_CASE( 10, x5, 0x00000000000000ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lbu x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0x00000000000000ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lbu x5, 32( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0x0000000000000000, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -6); \ - ASM_GEN(lbu x5, 7(x6)); \ - ) - + TEST_CASE( 11, x5, 0x0000000000000000, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -6 ); ASM_GEN( lbu x5, 7( x6 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .byte 0xff"); - asm ("tdat2: .byte 0x00"); - asm ("tdat3: .byte 0xf0"); - asm ("tdat4: .byte 0x0f"); +asm( "tdat:" ); +asm( "tdat1: .byte 0xff" ); +asm( "tdat2: .byte 0x00" ); +asm( "tdat3: .byte 0xf0" ); +asm( "tdat4: .byte 0x0f" ); RVTEST_DATA_END diff --git a/test/isa/ld.c b/test/isa/ld.c index 71bcedfed..1d2110a69 100644 --- a/test/isa/ld.c +++ b/test/isa/ld.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,74 +11,59 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - TEST_LD_OP( 2, ld, 0x00ff00ff00ff00ff, 0, tdat ); - TEST_LD_OP( 3, ld, 0xff00ff00ff00ff00, 8, tdat ); + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // + TEST_LD_OP( 2, ld, 0x00ff00ff00ff00ff, 0, tdat ); + TEST_LD_OP( 3, ld, 0xff00ff00ff00ff00, 8, tdat ); TEST_LD_OP( 4, ld, 0x0ff00ff00ff00ff0, 16, tdat ); TEST_LD_OP( 5, ld, 0xf00ff00ff00ff00f, 24, tdat ); - // # Test with negative offset + // # Test with negative offset TEST_LD_OP( 6, ld, 0x00ff00ff00ff00ff, -24, tdat4 ); TEST_LD_OP( 7, ld, 0xff00ff00ff00ff00, -16, tdat4 ); - TEST_LD_OP( 8, ld, 0x0ff00ff00ff00ff0, -8, tdat4 ); - TEST_LD_OP( 9, ld, 0xf00ff00ff00ff00f, 0, tdat4 ); + TEST_LD_OP( 8, ld, 0x0ff00ff00ff00ff0, -8, tdat4 ); + TEST_LD_OP( 9, ld, 0xf00ff00ff00ff00f, 0, tdat4 ); - // # Test with a negative base + // # Test with a negative base - TEST_CASE( 10, x5, 0x00ff00ff00ff00ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(ld x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0x00ff00ff00ff00ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( ld x5, 32( x6 ) ); ) - // # Test with unaligned base - - TEST_CASE( 11, x5, 0xff00ff00ff00ff00, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -3); \ - ASM_GEN(ld x5, 11(x6)); \ - ) + // # Test with unaligned base + TEST_CASE( 11, x5, 0xff00ff00ff00ff00, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -3 ); ASM_GEN( ld x5, 11( x6 ) ); ) //------------------------------------------------------------- // Source/Destination tests //------------------------------------------------------------- + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .dword 0x00ff00ff00ff00ff"); - asm ("tdat2: .dword 0xff00ff00ff00ff00"); - asm ("tdat3: .dword 0x0ff00ff00ff00ff0"); - asm ("tdat4: .dword 0xf00ff00ff00ff00f"); +asm( "tdat:" ); +asm( "tdat1: .dword 0x00ff00ff00ff00ff" ); +asm( "tdat2: .dword 0xff00ff00ff00ff00" ); +asm( "tdat3: .dword 0x0ff00ff00ff00ff0" ); +asm( "tdat4: .dword 0xf00ff00ff00ff00f" ); RVTEST_DATA_END diff --git a/test/isa/lh.c b/test/isa/lh.c index ed03c700a..9666e32e5 100644 --- a/test/isa/lh.c +++ b/test/isa/lh.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,65 +11,54 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" +int main( int argc, char** argv ) { -int main(int argc, char **argv){ + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - - TEST_LD_OP( 2, lh, 0x00000000000000ff, 0, tdat ); - TEST_LD_OP( 3, lh, 0xffffffffffffff00, 2, tdat ); - TEST_LD_OP( 4, lh, 0x0000000000000ff0, 4, tdat ); + TEST_LD_OP( 2, lh, 0x00000000000000ff, 0, tdat ); + TEST_LD_OP( 3, lh, 0xffffffffffffff00, 2, tdat ); + TEST_LD_OP( 4, lh, 0x0000000000000ff0, 4, tdat ); TEST_LD_OP( 5, lh, 0xfffffffffffff00f, 6, tdat ); //# Test with negative offset - TEST_LD_OP( 6, lh, 0x00000000000000ff, -6, tdat4 ); - TEST_LD_OP( 7, lh, 0xffffffffffffff00, -4, tdat4 ); - TEST_LD_OP( 8, lh, 0x0000000000000ff0, -2, tdat4 ); - TEST_LD_OP( 9, lh, 0xfffffffffffff00f, 0, tdat4 ); - - - TEST_CASE( 10, x5, 0x00000000000000ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lh x5, 32(x6)); \ - ) + TEST_LD_OP( 6, lh, 0x00000000000000ff, -6, tdat4 ); + TEST_LD_OP( 7, lh, 0xffffffffffffff00, -4, tdat4 ); + TEST_LD_OP( 8, lh, 0x0000000000000ff0, -2, tdat4 ); + TEST_LD_OP( 9, lh, 0xfffffffffffff00f, 0, tdat4 ); - // # Test with unaligned base - currently fails + TEST_CASE( 10, x5, 0x00000000000000ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lh x5, 32( x6 ) ); ) - TEST_CASE( 11, x5, 0xffffffffffffff00, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -5); \ - ASM_GEN(lh x5, 7(x6)); \ - ) + // # Test with unaligned base - currently fails + TEST_CASE( 11, x5, 0xffffffffffffff00, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -5 ); ASM_GEN( lh x5, 7( x6 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .half 0x00ff"); - asm ("tdat2: .half 0xff00"); - asm ("tdat3: .half 0x0ff0"); - asm ("tdat4: .half 0xf00f"); +asm( "tdat:" ); +asm( "tdat1: .half 0x00ff" ); +asm( "tdat2: .half 0xff00" ); +asm( "tdat3: .half 0x0ff0" ); +asm( "tdat4: .half 0xf00f" ); RVTEST_DATA_END diff --git a/test/isa/lhu.c b/test/isa/lhu.c index 8b4ba7345..22a4aaf92 100644 --- a/test/isa/lhu.c +++ b/test/isa/lhu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,70 +11,56 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - - TEST_LD_OP( 2, lhu, 0x00000000000000ff, 0, tdat ); - TEST_LD_OP( 3, lhu, 0x000000000000ff00, 2, tdat ); - TEST_LD_OP( 4, lhu, 0x0000000000000ff0, 4, tdat ); + TEST_LD_OP( 2, lhu, 0x00000000000000ff, 0, tdat ); + TEST_LD_OP( 3, lhu, 0x000000000000ff00, 2, tdat ); + TEST_LD_OP( 4, lhu, 0x0000000000000ff0, 4, tdat ); TEST_LD_OP( 5, lhu, 0x000000000000f00f, 6, tdat ); // # Test with negative offset - TEST_LD_OP( 6, lhu, 0x00000000000000ff, -6, tdat4 ); - TEST_LD_OP( 7, lhu, 0x000000000000ff00, -4, tdat4 ); - TEST_LD_OP( 8, lhu, 0x0000000000000ff0, -2, tdat4 ); - TEST_LD_OP( 9, lhu, 0x000000000000f00f, 0, tdat4 ); + TEST_LD_OP( 6, lhu, 0x00000000000000ff, -6, tdat4 ); + TEST_LD_OP( 7, lhu, 0x000000000000ff00, -4, tdat4 ); + TEST_LD_OP( 8, lhu, 0x0000000000000ff0, -2, tdat4 ); + TEST_LD_OP( 9, lhu, 0x000000000000f00f, 0, tdat4 ); - // # Test with a negative base + // # Test with a negative base - TEST_CASE( 10, x5, 0x00000000000000ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lhu x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0x00000000000000ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lhu x5, 32( x6 ) ); ) - // # Test with unaligned base - currently fails + // # Test with unaligned base - currently fails - TEST_CASE( 11, x5, 0x000000000000ff00, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -5); \ - ASM_GEN(lhu x5, 7(x6)); \ - ) + TEST_CASE( 11, x5, 0x000000000000ff00, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -5 ); ASM_GEN( lhu x5, 7( x6 ) ); ) + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( "fail:" ); + assert( false ); -asm volatile("fail:" ); - assert(false); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .half 0x00ff"); - asm ("tdat2: .half 0xff00"); - asm ("tdat3: .half 0x0ff0"); - asm ("tdat4: .half 0xf00f"); +asm( "tdat:" ); +asm( "tdat1: .half 0x00ff" ); +asm( "tdat2: .half 0xff00" ); +asm( "tdat3: .half 0x0ff0" ); +asm( "tdat4: .half 0xf00f" ); RVTEST_DATA_END diff --git a/test/isa/lw.c b/test/isa/lw.c index 83f56f45c..373a66352 100644 --- a/test/isa/lw.c +++ b/test/isa/lw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,69 +11,55 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- - - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - - TEST_LD_OP( 2, lw, 0x0000000000ff00ff, 0, tdat ); - TEST_LD_OP( 3, lw, 0xffffffffff00ff00, 4, tdat ); - TEST_LD_OP( 4, lw, 0x000000000ff00ff0, 8, tdat ); + TEST_LD_OP( 2, lw, 0x0000000000ff00ff, 0, tdat ); + TEST_LD_OP( 3, lw, 0xffffffffff00ff00, 4, tdat ); + TEST_LD_OP( 4, lw, 0x000000000ff00ff0, 8, tdat ); TEST_LD_OP( 5, lw, 0xfffffffff00ff00f, 12, tdat ); // # Test with negative offset TEST_LD_OP( 6, lw, 0x0000000000ff00ff, -12, tdat4 ); - TEST_LD_OP( 7, lw, 0xffffffffff00ff00, -8, tdat4 ); - TEST_LD_OP( 8, lw, 0x000000000ff00ff0, -4, tdat4 ); - TEST_LD_OP( 9, lw, 0xfffffffff00ff00f, 0, tdat4 ); + TEST_LD_OP( 7, lw, 0xffffffffff00ff00, -8, tdat4 ); + TEST_LD_OP( 8, lw, 0x000000000ff00ff0, -4, tdat4 ); + TEST_LD_OP( 9, lw, 0xfffffffff00ff00f, 0, tdat4 ); //# Test with a negative base - TEST_CASE( 10, x5, 0x0000000000ff00ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lw x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0x0000000000ff00ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lw x5, 32( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0xffffffffff00ff00, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -3); \ - ASM_GEN(lw x5, 7(x6)); \ - ) - + TEST_CASE( 11, x5, 0xffffffffff00ff00, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -3 ); ASM_GEN( lw x5, 7( x6 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .word 0x00ff00ff"); - asm ("tdat2: .word 0xff00ff00"); - asm ("tdat3: .word 0x0ff00ff0"); - asm ("tdat4: .word 0xf00ff00f"); +asm( "tdat:" ); +asm( "tdat1: .word 0x00ff00ff" ); +asm( "tdat2: .word 0xff00ff00" ); +asm( "tdat3: .word 0x0ff00ff0" ); +asm( "tdat4: .word 0xf00ff00f" ); RVTEST_DATA_END diff --git a/test/isa/lwu.c b/test/isa/lwu.c index dfc7d1544..628bd39ef 100644 --- a/test/isa/lwu.c +++ b/test/isa/lwu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,71 +11,55 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- - - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - - TEST_LD_OP( 2, lwu, 0x0000000000ff00ff, 0, tdat ); - TEST_LD_OP( 3, lwu, 0x00000000ff00ff00, 4, tdat ); - TEST_LD_OP( 4, lwu, 0x000000000ff00ff0, 8, tdat ); + TEST_LD_OP( 2, lwu, 0x0000000000ff00ff, 0, tdat ); + TEST_LD_OP( 3, lwu, 0x00000000ff00ff00, 4, tdat ); + TEST_LD_OP( 4, lwu, 0x000000000ff00ff0, 8, tdat ); TEST_LD_OP( 5, lwu, 0x00000000f00ff00f, 12, tdat ); // # Test with negative offset TEST_LD_OP( 6, lwu, 0x0000000000ff00ff, -12, tdat4 ); - TEST_LD_OP( 7, lwu, 0x00000000ff00ff00, -8, tdat4 ); - TEST_LD_OP( 8, lwu, 0x000000000ff00ff0, -4, tdat4 ); - TEST_LD_OP( 9, lwu, 0x00000000f00ff00f, 0, tdat4 ); - + TEST_LD_OP( 7, lwu, 0x00000000ff00ff00, -8, tdat4 ); + TEST_LD_OP( 8, lwu, 0x000000000ff00ff0, -4, tdat4 ); + TEST_LD_OP( 9, lwu, 0x00000000f00ff00f, 0, tdat4 ); //# Test with a negative base - TEST_CASE( 10, x5, 0x0000000000ff00ff, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -32); \ - ASM_GEN(lwu x5, 32(x6)); \ - ) + TEST_CASE( 10, x5, 0x0000000000ff00ff, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -32 ); ASM_GEN( lwu x5, 32( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0x00000000ff00ff00, \ - ASM_GEN(la x6, tdat); \ - ASM_GEN(addi x6, x6, -3); \ - ASM_GEN(lwu x5, 7(x6)); \ - ) - + TEST_CASE( 11, x5, 0x00000000ff00ff00, ASM_GEN( la x6, tdat ); ASM_GEN( addi x6, x6, -3 ); ASM_GEN( lwu x5, 7( x6 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - -asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .word 0x00ff00ff"); - asm ("tdat2: .word 0xff00ff00"); - asm ("tdat3: .word 0x0ff00ff0"); - asm ("tdat4: .word 0xf00ff00f"); +asm( "tdat:" ); +asm( "tdat1: .word 0x00ff00ff" ); +asm( "tdat2: .word 0xff00ff00" ); +asm( "tdat3: .word 0x0ff00ff0" ); +asm( "tdat4: .word 0xf00ff00f" ); RVTEST_DATA_END diff --git a/test/isa/mul.c b/test/isa/mul.c index 2e86e5fd5..7733bea90 100644 --- a/test/isa/mul.c +++ b/test/isa/mul.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,30 +11,30 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP(32, mul, 0x0000000000001200, 0x0000000000007e00, 0x6db6db6db6db6db7 ); - TEST_RR_OP(33, mul, 0x0000000000001240, 0x0000000000007fc0, 0x6db6db6db6db6db7 ); + TEST_RR_OP( 32, mul, 0x0000000000001200, 0x0000000000007e00, 0x6db6db6db6db6db7 ); + TEST_RR_OP( 33, mul, 0x0000000000001240, 0x0000000000007fc0, 0x6db6db6db6db6db7 ); - TEST_RR_OP( 2, mul, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, mul, 0x00000001, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, mul, 0x00000015, 0x00000003, 0x00000007 ); + TEST_RR_OP( 2, mul, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, mul, 0x00000001, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, mul, 0x00000015, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, mul, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, mul, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, mul, 0x0000400000000000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, mul, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, mul, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, mul, 0x0000400000000000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP(30, mul, 0x000000000000ff7f, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d ); - TEST_RR_OP(31, mul, 0x000000000000ff7f, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab ); + TEST_RR_OP( 30, mul, 0x000000000000ff7f, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d ); + TEST_RR_OP( 31, mul, 0x000000000000ff7f, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab ); //#------------------------------------------------------------- //# Source/Destination tests @@ -44,16 +44,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 9, mul, 154, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 10, mul, 169, 13 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/mulh.c b/test/isa/mulh.c index d62285bd1..3fe40a3a5 100644 --- a/test/isa/mulh.c +++ b/test/isa/mulh.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,42 +11,42 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, mulh, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, mulh, 0x00000000, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, mulh, 0x00000000, 0x00000003, 0x00000007 ); + TEST_RR_OP( 2, mulh, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, mulh, 0x00000000, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, mulh, 0x00000000, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, mulh, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, mulh, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, mulh, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, mulh, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, mulh, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, mulh, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 ); - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 8, mulh, 143, 13<<32, 11<<32 ); - TEST_RR_SRC2_EQ_DEST( 9, mulh, 154, 14<<32, 11<<32 ); - TEST_RR_SRC12_EQ_DEST( 10, mulh, 169, 13<<32 ); + TEST_RR_SRC1_EQ_DEST( 8, mulh, 143, 13 << 32, 11 << 32 ); + TEST_RR_SRC2_EQ_DEST( 9, mulh, 154, 14 << 32, 11 << 32 ); + TEST_RR_SRC12_EQ_DEST( 10, mulh, 169, 13 << 32 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/mulhsu.c b/test/isa/mulhsu.c index b7b6d9c10..980152835 100644 --- a/test/isa/mulhsu.c +++ b/test/isa/mulhsu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,41 +11,41 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, mulhsu, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, mulhsu, 0x00000000, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, mulhsu, 0x00000000, 0x00000003, 0x00000007 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, mulhsu, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, mulhsu, 0x00000000, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, mulhsu, 0x00000000, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, mulhsu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, mulhsu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, mulhsu, 0xffffffff80000000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, mulhsu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, mulhsu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, mulhsu, 0xffffffff80000000, 0xffffffff80000000, 0xffffffffffff8000 ); - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 8, mulhsu, 143, 13<<32, 11<<32 ); - TEST_RR_SRC2_EQ_DEST( 9, mulhsu, 154, 14<<32, 11<<32 ); - TEST_RR_SRC12_EQ_DEST( 10, mulhsu, 169, 13<<32 ); + TEST_RR_SRC1_EQ_DEST( 8, mulhsu, 143, 13 << 32, 11 << 32 ); + TEST_RR_SRC2_EQ_DEST( 9, mulhsu, 154, 14 << 32, 11 << 32 ); + TEST_RR_SRC12_EQ_DEST( 10, mulhsu, 169, 13 << 32 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/mulhu.c b/test/isa/mulhu.c index b4d05da59..803742259 100644 --- a/test/isa/mulhu.c +++ b/test/isa/mulhu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,44 +11,44 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, mulhu, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, mulhu, 0x00000000, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, mulhu, 0x00000000, 0x00000003, 0x00000007 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, mulhu, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, mulhu, 0x00000000, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, mulhu, 0x00000000, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, mulhu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, mulhu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, mulhu, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, mulhu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, mulhu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, mulhu, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP(30, mulhu, 0x000000000001fefe, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d ); - TEST_RR_OP(31, mulhu, 0x000000000001fefe, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab ); + TEST_RR_OP( 30, mulhu, 0x000000000001fefe, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d ); + TEST_RR_OP( 31, mulhu, 0x000000000001fefe, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab ); -// #------------------------------------------------------------- -// # Source/Destination tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 8, mulhu, 143, 13<<32, 11<<32 ); - TEST_RR_SRC2_EQ_DEST( 9, mulhu, 154, 14<<32, 11<<32 ); - TEST_RR_SRC12_EQ_DEST( 10, mulhu, 169, 13<<32 ); + TEST_RR_SRC1_EQ_DEST( 8, mulhu, 143, 13 << 32, 11 << 32 ); + TEST_RR_SRC2_EQ_DEST( 9, mulhu, 154, 14 << 32, 11 << 32 ); + TEST_RR_SRC12_EQ_DEST( 10, mulhu, 169, 13 << 32 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/mulw.c b/test/isa/mulw.c index 3703f6825..d8d24dd20 100644 --- a/test/isa/mulw.c +++ b/test/isa/mulw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,41 +11,41 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, mulw, 0x00000000, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, mulw, 0x00000001, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, mulw, 0x00000015, 0x00000003, 0x00000007 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, mulw, 0x00000000, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, mulw, 0x00000001, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, mulw, 0x00000015, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, mulw, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, mulw, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); - TEST_RR_OP( 7, mulw, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, mulw, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, mulw, 0x0000000000000000, 0xffffffff80000000, 0x00000000 ); + TEST_RR_OP( 7, mulw, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 ); -// #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- TEST_RR_SRC1_EQ_DEST( 8, mulw, 143, 13, 11 ); TEST_RR_SRC2_EQ_DEST( 9, mulw, 154, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 10, mulw, 169, 13 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/or.c b/test/isa/or.c index 0ad4773cf..ae7c323cb 100644 --- a/test/isa/or.c +++ b/test/isa/or.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_RR_OP( 2, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); TEST_RR_OP( 3, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); @@ -35,15 +35,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 7, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); TEST_RR_SRC12_EQ_DEST( 8, or, 0xff00ff00, 0xff00ff00 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/ori.c b/test/isa/ori.c index 76480eaca..6de1a9dde 100644 --- a/test/isa/ori.c +++ b/test/isa/ori.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_IMM_OP( 2, ori, 0xffffffffffffff0f, 0xffffffffff00ff00, 0xf0f ); TEST_IMM_OP( 3, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 ); @@ -33,15 +33,15 @@ int main(int argc, char **argv){ TEST_IMM_SRC1_EQ_DEST( 6, ori, 0xff00fff0, 0xff00ff00, 0x0f0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/rem.c b/test/isa/rem.c index db2050a97..52f72cc1b 100644 --- a/test/isa/rem.c +++ b/test/isa/rem.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, rem, 2, 20, 6 ); - TEST_RR_OP( 3, rem, -2, -20, 6 ); - TEST_RR_OP( 4, rem, 2, 20, -6 ); - TEST_RR_OP( 5, rem, -2, -20, -6 ); + TEST_RR_OP( 2, rem, 2, 20, 6 ); + TEST_RR_OP( 3, rem, -2, -20, 6 ); + TEST_RR_OP( 4, rem, 2, 20, -6 ); + TEST_RR_OP( 5, rem, -2, -20, -6 ); - TEST_RR_OP( 6, rem, 0, -1<<63, 1 ); - TEST_RR_OP( 7, rem, 0, -1<<63, -1 ); + TEST_RR_OP( 6, rem, 0, -1 << 63, 1 ); + TEST_RR_OP( 7, rem, 0, -1 << 63, -1 ); - TEST_RR_OP( 8, rem, -1<<63, -1<<63, 0 ); - TEST_RR_OP( 9, rem, 1, 1, 0 ); - TEST_RR_OP(10, rem, 0, 0, 0 ); + TEST_RR_OP( 8, rem, -1 << 63, -1 << 63, 0 ); + TEST_RR_OP( 9, rem, 1, 1, 0 ); + TEST_RR_OP( 10, rem, 0, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/remu.c b/test/isa/remu.c index 49fd2b272..ce5b8ccc2 100644 --- a/test/isa/remu.c +++ b/test/isa/remu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, remu, 2, 20, 6 ); - TEST_RR_OP( 3, remu, 2, -20, 6 ); - TEST_RR_OP( 4, remu, 20, 20, -6 ); - TEST_RR_OP( 5, remu, -20, -20, -6 ); + TEST_RR_OP( 2, remu, 2, 20, 6 ); + TEST_RR_OP( 3, remu, 2, -20, 6 ); + TEST_RR_OP( 4, remu, 20, 20, -6 ); + TEST_RR_OP( 5, remu, -20, -20, -6 ); - TEST_RR_OP( 6, remu, 0, -1<<63, 1 ); - TEST_RR_OP( 7, remu, -1<<63, -1<<63, -1 ); + TEST_RR_OP( 6, remu, 0, -1 << 63, 1 ); + TEST_RR_OP( 7, remu, -1 << 63, -1 << 63, -1 ); - TEST_RR_OP( 8, remu, -1<<63, -1<<63, 0 ); - TEST_RR_OP( 9, remu, 1, 1, 0 ); - TEST_RR_OP(10, remu, 0, 0, 0 ); + TEST_RR_OP( 8, remu, -1 << 63, -1 << 63, 0 ); + TEST_RR_OP( 9, remu, 1, 1, 0 ); + TEST_RR_OP( 10, remu, 0, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/remuw.c b/test/isa/remuw.c index 68133c610..74b6747e1 100644 --- a/test/isa/remuw.c +++ b/test/isa/remuw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,38 +11,38 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, remuw, 2, 20, 6 ); - TEST_RR_OP( 3, remuw, 2, -20, 6 ); - TEST_RR_OP( 4, remuw, 20, 20, -6 ); - TEST_RR_OP( 5, remuw, -20, -20, -6 ); + TEST_RR_OP( 2, remuw, 2, 20, 6 ); + TEST_RR_OP( 3, remuw, 2, -20, 6 ); + TEST_RR_OP( 4, remuw, 20, 20, -6 ); + TEST_RR_OP( 5, remuw, -20, -20, -6 ); - TEST_RR_OP( 6, remuw, 0, -1<<31, 1 ); - TEST_RR_OP( 7, remuw, -1<<31, -1<<31, -1 ); + TEST_RR_OP( 6, remuw, 0, -1 << 31, 1 ); + TEST_RR_OP( 7, remuw, -1 << 31, -1 << 31, -1 ); - TEST_RR_OP( 8, remuw, -1<<31, -1<<31, 0 ); - TEST_RR_OP( 9, remuw, 1, 1, 0 ); - TEST_RR_OP(10, remuw, 0, 0, 0 ); + TEST_RR_OP( 8, remuw, -1 << 31, -1 << 31, 0 ); + TEST_RR_OP( 9, remuw, 1, 1, 0 ); + TEST_RR_OP( 10, remuw, 0, 0, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/remw.c b/test/isa/remw.c index 5e0be39c1..8e92be9ee 100644 --- a/test/isa/remw.c +++ b/test/isa/remw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,40 +11,39 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- +int main( int argc, char** argv ) { - TEST_RR_OP( 2, remw, 2, 20, 6 ); - TEST_RR_OP( 3, remw, -2, -20, 6 ); - TEST_RR_OP( 4, remw, 2, 20, -6 ); - TEST_RR_OP( 5, remw, -2, -20, -6 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 6, remw, 0, -1<<31, 1 ); - TEST_RR_OP( 7, remw, 0, -1<<31, -1 ); + TEST_RR_OP( 2, remw, 2, 20, 6 ); + TEST_RR_OP( 3, remw, -2, -20, 6 ); + TEST_RR_OP( 4, remw, 2, 20, -6 ); + TEST_RR_OP( 5, remw, -2, -20, -6 ); - TEST_RR_OP( 8, remw, -1<<31, -1<<31, 0 ); - TEST_RR_OP( 9, remw, 1, 1, 0 ); - TEST_RR_OP(10, remw, 0, 0, 0 ); - TEST_RR_OP(11, remw, 0xfffffffffffff897, 0xfffffffffffff897, 0 ); + TEST_RR_OP( 6, remw, 0, -1 << 31, 1 ); + TEST_RR_OP( 7, remw, 0, -1 << 31, -1 ); + TEST_RR_OP( 8, remw, -1 << 31, -1 << 31, 0 ); + TEST_RR_OP( 9, remw, 1, 1, 0 ); + TEST_RR_OP( 10, remw, 0, 0, 0 ); + TEST_RR_OP( 11, remw, 0xfffffffffffff897, 0xfffffffffffff897, 0 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/rev-isa-test.py b/test/isa/rev-isa-test.py old mode 100644 new mode 100755 index 7bd8fced6..e84819107 --- a/test/isa/rev-isa-test.py +++ b/test/isa/rev-isa-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -27,15 +28,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", sys.argv[1]), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", sys.argv[1]), # Target executable + "splash": 1 # Display the splash message }) comp_cpu.enableAllStatistics() diff --git a/test/isa/run_asm_test.sh b/test/isa/run_asm_test.sh index 847befba3..acf275b87 100755 --- a/test/isa/run_asm_test.sh +++ b/test/isa/run_asm_test.sh @@ -4,8 +4,8 @@ make # Check that the exec was built... -if [ -x $RVASM.exe ]; then - sst --add-lib-path=../../build/src/ --model-options=$RVASM.exe ./rev-isa-test.py +if [[ -x $RVASM.exe ]]; then + sst --add-lib-path=../../build/src/ "--model-options=$RVASM.exe" ./rev-isa-test.py else echo "Test $RVASM ASM: File not found - likely build failed" exit 1 diff --git a/test/isa/sb.c b/test/isa/sb.c index 6b4259a66..f08aaf769 100644 --- a/test/isa/sb.c +++ b/test/isa/sb.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,17 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- TEST_ST_OP( 2, lb, sb, 0xffffffffffffffaa, 0, tdat ); TEST_ST_OP( 3, lb, sb, 0x0000000000000000, 1, tdat ); @@ -33,53 +32,44 @@ int main(int argc, char **argv){ TEST_ST_OP( 6, lb, sb, 0xffffffffffffffaa, -3, tdat8 ); TEST_ST_OP( 7, lb, sb, 0x0000000000000000, -2, tdat8 ); TEST_ST_OP( 8, lb, sb, 0xffffffffffffffa0, -1, tdat8 ); - TEST_ST_OP( 9, lb, sb, 0x000000000000000a, 0, tdat8 ); + TEST_ST_OP( 9, lb, sb, 0x000000000000000a, 0, tdat8 ); - //# Test with a negative base + //# Test with a negative base - TEST_CASE( 10, x5, 0x78, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x12345678); \ - ASM_GEN(addi x10, x6, -32); \ - ASM_GEN(sb x7, 32(x10)); \ - ASM_GEN(lb x5, 0(x6)); \ - ) + TEST_CASE( 10, x5, 0x78, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x12345678 ); ASM_GEN( addi x10, x6, -32 ); + ASM_GEN( sb x7, 32( x10 ) ); + ASM_GEN( lb x5, 0( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0xffffffffffffff98, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x00003098); \ - ASM_GEN(addi x6, x6, -6); \ - ASM_GEN(sb x7, 7(x6)); \ - ASM_GEN(la x10, tdat10); \ - ASM_GEN(lb x5, 0(x10)); \ - ) - + TEST_CASE( 11, x5, 0xffffffffffffff98, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x00003098 ); ASM_GEN( addi x6, x6, -6 ); + ASM_GEN( sb x7, 7( x6 ) ); + ASM_GEN( la x10, tdat10 ); + ASM_GEN( lb x5, 0( x10 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .byte 0xef"); - asm ("tdat2: .byte 0xef"); - asm ("tdat3: .byte 0xef"); - asm ("tdat4: .byte 0xef"); - asm ("tdat5: .byte 0xef"); - asm ("tdat6: .byte 0xef"); - asm ("tdat7: .byte 0xef"); - asm ("tdat8: .byte 0xef"); - asm ("tdat9: .byte 0xef"); - asm ("tdat10: .byte 0xef"); +asm( "tdat:" ); +asm( "tdat1: .byte 0xef" ); +asm( "tdat2: .byte 0xef" ); +asm( "tdat3: .byte 0xef" ); +asm( "tdat4: .byte 0xef" ); +asm( "tdat5: .byte 0xef" ); +asm( "tdat6: .byte 0xef" ); +asm( "tdat7: .byte 0xef" ); +asm( "tdat8: .byte 0xef" ); +asm( "tdat9: .byte 0xef" ); +asm( "tdat10: .byte 0xef" ); RVTEST_DATA_END diff --git a/test/isa/sd.c b/test/isa/sd.c index 268f30609..0af20584e 100644 --- a/test/isa/sd.c +++ b/test/isa/sd.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,76 +11,67 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - // - TEST_ST_OP( 2, ld, sd, 0x00aa00aa00aa00aa, 0, tdat ); - TEST_ST_OP( 3, ld, sd, 0xaa00aa00aa00aa00, 8, tdat ); - TEST_ST_OP( 4, ld, sd, 0x0aa00aa00aa00aa0, 16, tdat ); + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- + // + TEST_ST_OP( 2, ld, sd, 0x00aa00aa00aa00aa, 0, tdat ); + TEST_ST_OP( 3, ld, sd, 0xaa00aa00aa00aa00, 8, tdat ); + TEST_ST_OP( 4, ld, sd, 0x0aa00aa00aa00aa0, 16, tdat ); TEST_ST_OP( 5, ld, sd, 0xa00aa00aa00aa00a, 24, tdat ); //# Test with negative offset TEST_ST_OP( 6, ld, sd, 0x00aa00aa00aa00aa, -24, tdat8 ); TEST_ST_OP( 7, ld, sd, 0xaa00aa00aa00aa00, -16, tdat8 ); - TEST_ST_OP( 8, ld, sd, 0x0aa00aa00aa00aa0, -8, tdat8 ); - TEST_ST_OP( 9, ld, sd, 0xa00aa00aa00aa00a, 0, tdat8 ); + TEST_ST_OP( 8, ld, sd, 0x0aa00aa00aa00aa0, -8, tdat8 ); + TEST_ST_OP( 9, ld, sd, 0xa00aa00aa00aa00a, 0, tdat8 ); - //# Test with a negative base + //# Test with a negative base - TEST_CASE( 10, x5, 0x1234567812345678, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x1234567812345678); \ - ASM_GEN(addi x10, x6, -32); \ - ASM_GEN(sd x7, 32(x10)); \ - ASM_GEN(ld x5, 0(x6)); \ - ) + TEST_CASE( 10, x5, 0x1234567812345678, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x1234567812345678 ); + ASM_GEN( addi x10, x6, -32 ); + ASM_GEN( sd x7, 32( x10 ) ); + ASM_GEN( ld x5, 0( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0x5821309858213098, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x5821309858213098); \ - ASM_GEN(addi x6, x6, -3); \ - ASM_GEN(sd x7, 11(x6)); \ - ASM_GEN(la x10, tdat10); \ - ASM_GEN(ld x5, 0(x10)); \ - ) - + TEST_CASE( 11, x5, 0x5821309858213098, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x5821309858213098 ); ASM_GEN( addi x6, x6, -3 ); + ASM_GEN( sd x7, 11( x6 ) ); + ASM_GEN( la x10, tdat10 ); + ASM_GEN( ld x5, 0( x10 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .dword 0xdeadbeefdeadbeef"); - asm ("tdat2: .dword 0xdeadbeefdeadbeef"); - asm ("tdat3: .dword 0xdeadbeefdeadbeef"); - asm ("tdat4: .dword 0xdeadbeefdeadbeef"); - asm ("tdat5: .dword 0xdeadbeefdeadbeef"); - asm ("tdat6: .dword 0xdeadbeefdeadbeef"); - asm ("tdat7: .dword 0xdeadbeefdeadbeef"); - asm ("tdat8: .dword 0xdeadbeefdeadbeef"); - asm ("tdat9: .dword 0xdeadbeefdeadbeef"); - asm ("tdat10: .dword 0xdeadbeefdeadbeef"); +asm( "tdat:" ); +asm( "tdat1: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat2: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat3: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat4: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat5: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat6: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat7: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat8: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat9: .dword 0xdeadbeefdeadbeef" ); +asm( "tdat10: .dword 0xdeadbeefdeadbeef" ); RVTEST_DATA_END diff --git a/test/isa/sh.c b/test/isa/sh.c index 22f2dad72..8d1cf5c36 100644 --- a/test/isa/sh.c +++ b/test/isa/sh.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,81 +11,70 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" +int main( int argc, char** argv ) { -int main(int argc, char **argv){ - - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- TEST_ST_OP( 2, lh, sh, 0x00000000000000aa, 0, tdat ); TEST_ST_OP( 3, lh, sh, 0xffffffffffffaa00, 2, tdat ); TEST_ST_OP( 4, lw, sh, 0xffffffffbeef0aa0, 4, tdat ); TEST_ST_OP( 5, lh, sh, 0xffffffffffffa00a, 6, tdat ); - TEST_ST_OP( 6, lhu, sh, 0x0000000000002345, 0, tdat4 ); + TEST_ST_OP( 6, lhu, sh, 0x0000000000002345, 0, tdat4 ); TEST_ST_OP( 7, lwu, sh, 0x0000000023456789, -2, tdat4 ); - TEST_ST_OP( 8, lhu, sh, 0x0000000000001337, 2, tdat4 ); - TEST_ST_OP( 9, ld, sh, 0xBEEF133723456789, -2, tdat4 ); + TEST_ST_OP( 8, lhu, sh, 0x0000000000001337, 2, tdat4 ); + TEST_ST_OP( 9, ld, sh, 0xBEEF133723456789, -2, tdat4 ); // # Test with negative offset TEST_ST_OP( 10, lh, sh, 0x00000000000000aa, -6, tdat8 ); TEST_ST_OP( 11, lh, sh, 0xffffffffffffaa00, -4, tdat8 ); TEST_ST_OP( 12, lh, sh, 0x0000000000000aa0, -2, tdat8 ); - TEST_ST_OP( 13, lh, sh, 0xffffffffffffa00a, 0, tdat8 ); - + TEST_ST_OP( 13, lh, sh, 0xffffffffffffa00a, 0, tdat8 ); - //# Test with a negative base + //# Test with a negative base - TEST_CASE( 14, x5, 0x5678, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x12345678); \ - ASM_GEN(addi x10, x6, -32); \ - ASM_GEN(sh x7, 32(x10)); \ - ASM_GEN(lh x5, 0(x6)); \ - ) + TEST_CASE( 14, x5, 0x5678, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x12345678 ); ASM_GEN( addi x10, x6, -32 ); + ASM_GEN( sh x7, 32( x10 ) ); + ASM_GEN( lh x5, 0( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 15, x5, 0x3098, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x00003098); \ - ASM_GEN(addi x6, x6, -5); \ - ASM_GEN(sh x7, 7(x6)); \ - ASM_GEN(la x10, tdat10); \ - ASM_GEN(lh x5, 0(x10)); \ - ) - + TEST_CASE( 15, x5, 0x3098, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x00003098 ); ASM_GEN( addi x6, x6, -5 ); + ASM_GEN( sh x7, 7( x6 ) ); + ASM_GEN( la x10, tdat10 ); + ASM_GEN( lh x5, 0( x10 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .half 0xbeef"); - asm ("tdat2: .half 0xbeef"); - asm ("tdat3: .half 0xbeef"); - asm ("tdat4: .half 0xbeef"); - asm ("tdat5: .half 0xbeef"); - asm ("tdat6: .half 0xbeef"); - asm ("tdat7: .half 0xbeef"); - asm ("tdat8: .half 0xbeef"); - asm ("tdat9: .half 0xbeef"); - asm ("tdat10: .half 0xbeef"); +asm( "tdat:" ); +asm( "tdat1: .half 0xbeef" ); +asm( "tdat2: .half 0xbeef" ); +asm( "tdat3: .half 0xbeef" ); +asm( "tdat4: .half 0xbeef" ); +asm( "tdat5: .half 0xbeef" ); +asm( "tdat6: .half 0xbeef" ); +asm( "tdat7: .half 0xbeef" ); +asm( "tdat8: .half 0xbeef" ); +asm( "tdat9: .half 0xbeef" ); +asm( "tdat10: .half 0xbeef" ); RVTEST_DATA_END diff --git a/test/isa/sll.c b/test/isa/sll.c index ba4a2c430..62abf32a3 100644 --- a/test/isa/sll.c +++ b/test/isa/sll.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,36 +11,36 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, sll, 0x0000000000000001, 0x0000000000000001, 0 ); - TEST_RR_OP( 3, sll, 0x0000000000000002, 0x0000000000000001, 1 ); - TEST_RR_OP( 4, sll, 0x0000000000000080, 0x0000000000000001, 7 ); - TEST_RR_OP( 5, sll, 0x0000000000004000, 0x0000000000000001, 14 ); - TEST_RR_OP( 6, sll, 0x0000000080000000, 0x0000000000000001, 31 ); + TEST_RR_OP( 2, sll, 0x0000000000000001, 0x0000000000000001, 0 ); + TEST_RR_OP( 3, sll, 0x0000000000000002, 0x0000000000000001, 1 ); + TEST_RR_OP( 4, sll, 0x0000000000000080, 0x0000000000000001, 7 ); + TEST_RR_OP( 5, sll, 0x0000000000004000, 0x0000000000000001, 14 ); + TEST_RR_OP( 6, sll, 0x0000000080000000, 0x0000000000000001, 31 ); - TEST_RR_OP( 7, sll, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_RR_OP( 8, sll, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); - TEST_RR_OP( 9, sll, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); + TEST_RR_OP( 7, sll, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_RR_OP( 8, sll, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); + TEST_RR_OP( 9, sll, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); TEST_RR_OP( 10, sll, 0xffffffffffffc000, 0xffffffffffffffff, 14 ); TEST_RR_OP( 11, sll, 0xffffffff80000000, 0xffffffffffffffff, 31 ); - TEST_RR_OP( 12, sll, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_RR_OP( 13, sll, 0x0000000042424242, 0x0000000021212121, 1 ); - TEST_RR_OP( 14, sll, 0x0000001090909080, 0x0000000021212121, 7 ); + TEST_RR_OP( 12, sll, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_RR_OP( 13, sll, 0x0000000042424242, 0x0000000021212121, 1 ); + TEST_RR_OP( 14, sll, 0x0000001090909080, 0x0000000021212121, 7 ); TEST_RR_OP( 15, sll, 0x0000084848484000, 0x0000000021212121, 14 ); TEST_RR_OP( 16, sll, 0x1090909080000000, 0x0000000021212121, 31 ); - // # Verify that shifts only use bottom six(rv64) or five(rv32) bits + // # Verify that shifts only use bottom six(rv64) or five(rv32) bits TEST_RR_OP( 17, sll, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffc0 ); TEST_RR_OP( 18, sll, 0x0000000042424242, 0x0000000021212121, 0xffffffffffffffc1 ); @@ -54,23 +54,23 @@ int main(int argc, char **argv){ TEST_RR_OP( 52, sll, 0x0909080000000000, 0x0000000021212121, 43 ); #endif - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 22, sll, 0x00000080, 0x00000001, 7 ); + TEST_RR_SRC1_EQ_DEST( 22, sll, 0x00000080, 0x00000001, 7 ); TEST_RR_SRC2_EQ_DEST( 23, sll, 0x00004000, 0x00000001, 14 ); TEST_RR_SRC12_EQ_DEST( 24, sll, 24, 3 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/slli.c b/test/isa/slli.c index c0bc3ce48..c41d3461b 100644 --- a/test/isa/slli.c +++ b/test/isa/slli.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,32 +11,32 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- -TEST_IMM_OP( 2, slli, 0x0000000000000001, 0x0000000000000001, 0 ); - TEST_IMM_OP( 3, slli, 0x0000000000000002, 0x0000000000000001, 1 ); - TEST_IMM_OP( 4, slli, 0x0000000000000080, 0x0000000000000001, 7 ); - TEST_IMM_OP( 5, slli, 0x0000000000004000, 0x0000000000000001, 14 ); - TEST_IMM_OP( 6, slli, 0x0000000080000000, 0x0000000000000001, 31 ); + TEST_IMM_OP( 2, slli, 0x0000000000000001, 0x0000000000000001, 0 ); + TEST_IMM_OP( 3, slli, 0x0000000000000002, 0x0000000000000001, 1 ); + TEST_IMM_OP( 4, slli, 0x0000000000000080, 0x0000000000000001, 7 ); + TEST_IMM_OP( 5, slli, 0x0000000000004000, 0x0000000000000001, 14 ); + TEST_IMM_OP( 6, slli, 0x0000000080000000, 0x0000000000000001, 31 ); - TEST_IMM_OP( 7, slli, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_IMM_OP( 8, slli, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); - TEST_IMM_OP( 9, slli, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); + TEST_IMM_OP( 7, slli, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_IMM_OP( 8, slli, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); + TEST_IMM_OP( 9, slli, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); TEST_IMM_OP( 10, slli, 0xffffffffffffc000, 0xffffffffffffffff, 14 ); TEST_IMM_OP( 11, slli, 0xffffffff80000000, 0xffffffffffffffff, 31 ); - TEST_IMM_OP( 12, slli, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_IMM_OP( 13, slli, 0x0000000042424242, 0x0000000021212121, 1 ); - TEST_IMM_OP( 14, slli, 0x0000001090909080, 0x0000000021212121, 7 ); + TEST_IMM_OP( 12, slli, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_IMM_OP( 13, slli, 0x0000000042424242, 0x0000000021212121, 1 ); + TEST_IMM_OP( 14, slli, 0x0000001090909080, 0x0000000021212121, 7 ); TEST_IMM_OP( 15, slli, 0x0000084848484000, 0x0000000021212121, 14 ); TEST_IMM_OP( 16, slli, 0x1090909080000000, 0x0000000021212121, 31 ); @@ -46,21 +46,21 @@ TEST_IMM_OP( 2, slli, 0x0000000000000001, 0x0000000000000001, 0 ); TEST_IMM_OP( 52, slli, 0x0909080000000000, 0x0000000021212121, 43 ); #endif - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- -//TEST_IMM_SRC1_EQ_DEST( 17, slli, 0x00000080, 0x00000001, 7 ); + //TEST_IMM_SRC1_EQ_DEST( 17, slli, 0x00000080, 0x00000001, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/slliw.c b/test/isa/slliw.c index 013dffcab..52adfa518 100644 --- a/test/isa/slliw.c +++ b/test/isa/slliw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,32 +11,32 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, slliw, 0x0000000000000001, 0x0000000000000001, 0 ); - TEST_IMM_OP( 3, slliw, 0x0000000000000002, 0x0000000000000001, 1 ); - TEST_IMM_OP( 4, slliw, 0x0000000000000080, 0x0000000000000001, 7 ); - TEST_IMM_OP( 5, slliw, 0x0000000000004000, 0x0000000000000001, 14 ); - TEST_IMM_OP( 6, slliw, 0xffffffff80000000, 0x0000000000000001, 31 ); + TEST_IMM_OP( 2, slliw, 0x0000000000000001, 0x0000000000000001, 0 ); + TEST_IMM_OP( 3, slliw, 0x0000000000000002, 0x0000000000000001, 1 ); + TEST_IMM_OP( 4, slliw, 0x0000000000000080, 0x0000000000000001, 7 ); + TEST_IMM_OP( 5, slliw, 0x0000000000004000, 0x0000000000000001, 14 ); + TEST_IMM_OP( 6, slliw, 0xffffffff80000000, 0x0000000000000001, 31 ); - TEST_IMM_OP( 7, slliw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_IMM_OP( 8, slliw, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); - TEST_IMM_OP( 9, slliw, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); + TEST_IMM_OP( 7, slliw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_IMM_OP( 8, slliw, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); + TEST_IMM_OP( 9, slliw, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); TEST_IMM_OP( 10, slliw, 0xffffffffffffc000, 0xffffffffffffffff, 14 ); TEST_IMM_OP( 11, slliw, 0xffffffff80000000, 0xffffffffffffffff, 31 ); - TEST_IMM_OP( 12, slliw, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_IMM_OP( 13, slliw, 0x0000000042424242, 0x0000000021212121, 1 ); - TEST_IMM_OP( 14, slliw, 0xffffffff90909080, 0x0000000021212121, 7 ); + TEST_IMM_OP( 12, slliw, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_IMM_OP( 13, slliw, 0x0000000042424242, 0x0000000021212121, 1 ); + TEST_IMM_OP( 14, slliw, 0xffffffff90909080, 0x0000000021212121, 7 ); TEST_IMM_OP( 15, slliw, 0x0000000048484000, 0x0000000021212121, 14 ); TEST_IMM_OP( 16, slliw, 0xffffffff80000000, 0x0000000021212121, 31 ); @@ -52,15 +52,15 @@ int main(int argc, char **argv){ //TEST_IMM_SRC1_EQ_DEST( 17, slliw, 0x00000080, 0x00000001, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sllw.c b/test/isa/sllw.c index 0bf9d281c..1a2f1faf7 100644 --- a/test/isa/sllw.c +++ b/test/isa/sllw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,67 +11,66 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, sllw, 0x0000000000000001, 0x0000000000000001, 0 ); - TEST_RR_OP( 3, sllw, 0x0000000000000002, 0x0000000000000001, 1 ); - TEST_RR_OP( 4, sllw, 0x0000000000000080, 0x0000000000000001, 7 ); - TEST_RR_OP( 5, sllw, 0x0000000000004000, 0x0000000000000001, 14 ); - TEST_RR_OP( 6, sllw, 0xffffffff80000000, 0x0000000000000001, 31 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, sllw, 0x0000000000000001, 0x0000000000000001, 0 ); + TEST_RR_OP( 3, sllw, 0x0000000000000002, 0x0000000000000001, 1 ); + TEST_RR_OP( 4, sllw, 0x0000000000000080, 0x0000000000000001, 7 ); + TEST_RR_OP( 5, sllw, 0x0000000000004000, 0x0000000000000001, 14 ); + TEST_RR_OP( 6, sllw, 0xffffffff80000000, 0x0000000000000001, 31 ); - TEST_RR_OP( 7, sllw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_RR_OP( 8, sllw, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); - TEST_RR_OP( 9, sllw, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); - TEST_RR_OP( 10, sllw, 0xffffffffffffc000, 0xffffffffffffffff, 14 ); - TEST_RR_OP( 11, sllw, 0xffffffff80000000, 0xffffffffffffffff, 31 ); + TEST_RR_OP( 7, sllw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_RR_OP( 8, sllw, 0xfffffffffffffffe, 0xffffffffffffffff, 1 ); + TEST_RR_OP( 9, sllw, 0xffffffffffffff80, 0xffffffffffffffff, 7 ); + TEST_RR_OP( 10, sllw, 0xffffffffffffc000, 0xffffffffffffffff, 14 ); + TEST_RR_OP( 11, sllw, 0xffffffff80000000, 0xffffffffffffffff, 31 ); - TEST_RR_OP( 12, sllw, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_RR_OP( 13, sllw, 0x0000000042424242, 0x0000000021212121, 1 ); - TEST_RR_OP( 14, sllw, 0xffffffff90909080, 0x0000000021212121, 7 ); - TEST_RR_OP( 15, sllw, 0x0000000048484000, 0x0000000021212121, 14 ); - TEST_RR_OP( 16, sllw, 0xffffffff80000000, 0x0000000021212121, 31 ); + TEST_RR_OP( 12, sllw, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_RR_OP( 13, sllw, 0x0000000042424242, 0x0000000021212121, 1 ); + TEST_RR_OP( 14, sllw, 0xffffffff90909080, 0x0000000021212121, 7 ); + TEST_RR_OP( 15, sllw, 0x0000000048484000, 0x0000000021212121, 14 ); + TEST_RR_OP( 16, sllw, 0xffffffff80000000, 0x0000000021212121, 31 ); - // # Verify that shifts only use bottom five bits + // # Verify that shifts only use bottom five bits - TEST_RR_OP( 17, sllw, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffe0 ); - TEST_RR_OP( 18, sllw, 0x0000000042424242, 0x0000000021212121, 0xffffffffffffffe1 ); - TEST_RR_OP( 19, sllw, 0xffffffff90909080, 0x0000000021212121, 0xffffffffffffffe7 ); - TEST_RR_OP( 20, sllw, 0x0000000048484000, 0x0000000021212121, 0xffffffffffffffee ); - TEST_RR_OP( 21, sllw, 0xffffffff80000000, 0x0000000021212121, 0xffffffffffffffff ); + TEST_RR_OP( 17, sllw, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffe0 ); + TEST_RR_OP( 18, sllw, 0x0000000042424242, 0x0000000021212121, 0xffffffffffffffe1 ); + TEST_RR_OP( 19, sllw, 0xffffffff90909080, 0x0000000021212121, 0xffffffffffffffe7 ); + TEST_RR_OP( 20, sllw, 0x0000000048484000, 0x0000000021212121, 0xffffffffffffffee ); + TEST_RR_OP( 21, sllw, 0xffffffff80000000, 0x0000000021212121, 0xffffffffffffffff ); - //# Verify that shifts ignore top 32 (using true 64-bit values) + //# Verify that shifts ignore top 32 (using true 64-bit values) - TEST_RR_OP( 44, sllw, 0x0000000012345678, 0xffffffff12345678, 0 ); - TEST_RR_OP( 45, sllw, 0x0000000023456780, 0xffffffff12345678, 4 ); - TEST_RR_OP( 46, sllw, 0xffffffff92345678, 0x0000000092345678, 0 ); - TEST_RR_OP( 47, sllw, 0xffffffff93456780, 0x0000000099345678, 4 ); + TEST_RR_OP( 44, sllw, 0x0000000012345678, 0xffffffff12345678, 0 ); + TEST_RR_OP( 45, sllw, 0x0000000023456780, 0xffffffff12345678, 4 ); + TEST_RR_OP( 46, sllw, 0xffffffff92345678, 0x0000000092345678, 0 ); + TEST_RR_OP( 47, sllw, 0xffffffff93456780, 0x0000000099345678, 4 ); //------------------------------------------------------------- // Source/Destination tests //------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 22, sllw, 0x00000080, 0x00000001, 7 ); - TEST_RR_SRC2_EQ_DEST( 23, sllw, 0x00004000, 0x00000001, 14 ); - TEST_RR_SRC12_EQ_DEST( 24, sllw, 24, 3 ); - + TEST_RR_SRC1_EQ_DEST( 22, sllw, 0x00000080, 0x00000001, 7 ); + TEST_RR_SRC2_EQ_DEST( 23, sllw, 0x00004000, 0x00000001, 14 ); + TEST_RR_SRC12_EQ_DEST( 24, sllw, 24, 3 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/slt.c b/test/isa/slt.c index c9ca31cd6..04d800c11 100644 --- a/test/isa/slt.c +++ b/test/isa/slt.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, slt, 0, 0x0000000000000000, 0x0000000000000000 ); - TEST_RR_OP( 3, slt, 0, 0x0000000000000001, 0x0000000000000001 ); - TEST_RR_OP( 4, slt, 1, 0x0000000000000003, 0x0000000000000007 ); - TEST_RR_OP( 5, slt, 0, 0x0000000000000007, 0x0000000000000003 ); + TEST_RR_OP( 2, slt, 0, 0x0000000000000000, 0x0000000000000000 ); + TEST_RR_OP( 3, slt, 0, 0x0000000000000001, 0x0000000000000001 ); + TEST_RR_OP( 4, slt, 1, 0x0000000000000003, 0x0000000000000007 ); + TEST_RR_OP( 5, slt, 0, 0x0000000000000007, 0x0000000000000003 ); - TEST_RR_OP( 6, slt, 0, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 7, slt, 1, 0xffffffff80000000, 0x0000000000000000 ); - TEST_RR_OP( 8, slt, 1, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, slt, 0, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 7, slt, 1, 0xffffffff80000000, 0x0000000000000000 ); + TEST_RR_OP( 8, slt, 1, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP( 9, slt, 1, 0x0000000000000000, 0x0000000000007fff ); + TEST_RR_OP( 9, slt, 1, 0x0000000000000000, 0x0000000000007fff ); TEST_RR_OP( 10, slt, 0, 0x000000007fffffff, 0x0000000000000000 ); TEST_RR_OP( 11, slt, 0, 0x000000007fffffff, 0x0000000000007fff ); @@ -50,15 +50,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 18, slt, 1, 11, 13 ); TEST_RR_SRC12_EQ_DEST( 19, slt, 0, 13 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/slti.c b/test/isa/slti.c index 9b215b78e..67635f7f0 100644 --- a/test/isa/slti.c +++ b/test/isa/slti.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, slti, 0, 0x0000000000000000, 0x000 ); - TEST_IMM_OP( 3, slti, 0, 0x0000000000000001, 0x001 ); - TEST_IMM_OP( 4, slti, 1, 0x0000000000000003, 0x007 ); - TEST_IMM_OP( 5, slti, 0, 0x0000000000000007, 0x003 ); + TEST_IMM_OP( 2, slti, 0, 0x0000000000000000, 0x000 ); + TEST_IMM_OP( 3, slti, 0, 0x0000000000000001, 0x001 ); + TEST_IMM_OP( 4, slti, 1, 0x0000000000000003, 0x007 ); + TEST_IMM_OP( 5, slti, 0, 0x0000000000000007, 0x003 ); - TEST_IMM_OP( 6, slti, 0, 0x0000000000000000, 0x800 ); - TEST_IMM_OP( 7, slti, 1, 0xffffffff80000000, 0x000 ); - TEST_IMM_OP( 8, slti, 1, 0xffffffff80000000, 0x800 ); + TEST_IMM_OP( 6, slti, 0, 0x0000000000000000, 0x800 ); + TEST_IMM_OP( 7, slti, 1, 0xffffffff80000000, 0x000 ); + TEST_IMM_OP( 8, slti, 1, 0xffffffff80000000, 0x800 ); - TEST_IMM_OP( 9, slti, 1, 0x0000000000000000, 0x7ff ); + TEST_IMM_OP( 9, slti, 1, 0x0000000000000000, 0x7ff ); TEST_IMM_OP( 10, slti, 0, 0x000000007fffffff, 0x000 ); TEST_IMM_OP( 11, slti, 0, 0x000000007fffffff, 0x7ff ); @@ -42,21 +42,19 @@ int main(int argc, char **argv){ TEST_IMM_OP( 15, slti, 1, 0xffffffffffffffff, 0x001 ); TEST_IMM_OP( 16, slti, 0, 0xffffffffffffffff, 0xfff ); -// #------------------------------------------------------------- -// # Source/Destination tests -// #------------------------------------------------------------- - - + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sltiu.c b/test/isa/sltiu.c index 831e9cdc8..f971b8c47 100644 --- a/test/isa/sltiu.c +++ b/test/isa/sltiu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,31 +11,31 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, sltiu, 0, 0x0000000000000000, 0x000 ); - TEST_IMM_OP( 3, sltiu, 0, 0x0000000000000001, 0x001 ); - TEST_IMM_OP( 4, sltiu, 1, 0x0000000000000003, 0x007 ); - TEST_IMM_OP( 5, sltiu, 0, 0x0000000000000007, 0x003 ); + TEST_IMM_OP( 2, sltiu, 0, 0x0000000000000000, 0x000 ); + TEST_IMM_OP( 3, sltiu, 0, 0x0000000000000001, 0x001 ); + TEST_IMM_OP( 4, sltiu, 1, 0x0000000000000003, 0x007 ); + TEST_IMM_OP( 5, sltiu, 0, 0x0000000000000007, 0x003 ); - TEST_IMM_OP( 6, sltiu, 1, 0x0000000000000000, 0x800 ); - TEST_IMM_OP( 7, sltiu, 0, 0xffffffff80000000, 0x000 ); - TEST_IMM_OP( 8, sltiu, 1, 0xffffffff80000000, 0x800 ); + TEST_IMM_OP( 6, sltiu, 1, 0x0000000000000000, 0x800 ); + TEST_IMM_OP( 7, sltiu, 0, 0xffffffff80000000, 0x000 ); + TEST_IMM_OP( 8, sltiu, 1, 0xffffffff80000000, 0x800 ); - TEST_IMM_OP( 9, sltiu, 1, 0x0000000000000000, 0x7ff ); + TEST_IMM_OP( 9, sltiu, 1, 0x0000000000000000, 0x7ff ); TEST_IMM_OP( 10, sltiu, 0, 0x000000007fffffff, 0x000 ); TEST_IMM_OP( 11, sltiu, 0, 0x000000007fffffff, 0x7ff ); @@ -52,16 +52,15 @@ int main(int argc, char **argv){ //TEST_IMM_SRC1_EQ_DEST( 17, sltiu, 1, 11, 13 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sltu.c b/test/isa/sltu.c index df08c0277..67038eced 100644 --- a/test/isa/sltu.c +++ b/test/isa/sltu.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, sltu, 0, 0x00000000, 0x00000000 ); - TEST_RR_OP( 3, sltu, 0, 0x00000001, 0x00000001 ); - TEST_RR_OP( 4, sltu, 1, 0x00000003, 0x00000007 ); - TEST_RR_OP( 5, sltu, 0, 0x00000007, 0x00000003 ); + TEST_RR_OP( 2, sltu, 0, 0x00000000, 0x00000000 ); + TEST_RR_OP( 3, sltu, 0, 0x00000001, 0x00000001 ); + TEST_RR_OP( 4, sltu, 1, 0x00000003, 0x00000007 ); + TEST_RR_OP( 5, sltu, 0, 0x00000007, 0x00000003 ); - TEST_RR_OP( 6, sltu, 1, 0x00000000, 0xffff8000 ); - TEST_RR_OP( 7, sltu, 0, 0x80000000, 0x00000000 ); - TEST_RR_OP( 8, sltu, 1, 0x80000000, 0xffff8000 ); + TEST_RR_OP( 6, sltu, 1, 0x00000000, 0xffff8000 ); + TEST_RR_OP( 7, sltu, 0, 0x80000000, 0x00000000 ); + TEST_RR_OP( 8, sltu, 1, 0x80000000, 0xffff8000 ); - TEST_RR_OP( 9, sltu, 1, 0x00000000, 0x00007fff ); + TEST_RR_OP( 9, sltu, 1, 0x00000000, 0x00007fff ); TEST_RR_OP( 10, sltu, 0, 0x7fffffff, 0x00000000 ); TEST_RR_OP( 11, sltu, 0, 0x7fffffff, 0x00007fff ); @@ -42,25 +42,23 @@ int main(int argc, char **argv){ TEST_RR_OP( 15, sltu, 0, 0xffffffff, 0x00000001 ); TEST_RR_OP( 16, sltu, 0, 0xffffffff, 0xffffffff ); -// #------------------------------------------------------------- -// # Source/Destination tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- TEST_RR_SRC1_EQ_DEST( 17, sltu, 0, 14, 13 ); TEST_RR_SRC2_EQ_DEST( 18, sltu, 1, 11, 13 ); TEST_RR_SRC12_EQ_DEST( 19, sltu, 0, 13 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); + asm volatile( "fail:" ); + assert( false ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); - -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sra.c b/test/isa/sra.c index 026b91c1f..f660e9e51 100644 --- a/test/isa/sra.c +++ b/test/isa/sra.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,36 +11,36 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, sra, 0xffffffff80000000, 0xffffffff80000000, 0 ); - TEST_RR_OP( 3, sra, 0xffffffffc0000000, 0xffffffff80000000, 1 ); - TEST_RR_OP( 4, sra, 0xffffffffff000000, 0xffffffff80000000, 7 ); - TEST_RR_OP( 5, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); - TEST_RR_OP( 6, sra, 0xffffffffffffffff, 0xffffffff80000001, 31 ); + TEST_RR_OP( 2, sra, 0xffffffff80000000, 0xffffffff80000000, 0 ); + TEST_RR_OP( 3, sra, 0xffffffffc0000000, 0xffffffff80000000, 1 ); + TEST_RR_OP( 4, sra, 0xffffffffff000000, 0xffffffff80000000, 7 ); + TEST_RR_OP( 5, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); + TEST_RR_OP( 6, sra, 0xffffffffffffffff, 0xffffffff80000001, 31 ); - TEST_RR_OP( 7, sra, 0x000000007fffffff, 0x000000007fffffff, 0 ); - TEST_RR_OP( 8, sra, 0x000000003fffffff, 0x000000007fffffff, 1 ); - TEST_RR_OP( 9, sra, 0x0000000000ffffff, 0x000000007fffffff, 7 ); + TEST_RR_OP( 7, sra, 0x000000007fffffff, 0x000000007fffffff, 0 ); + TEST_RR_OP( 8, sra, 0x000000003fffffff, 0x000000007fffffff, 1 ); + TEST_RR_OP( 9, sra, 0x0000000000ffffff, 0x000000007fffffff, 7 ); TEST_RR_OP( 10, sra, 0x000000000001ffff, 0x000000007fffffff, 14 ); TEST_RR_OP( 11, sra, 0x0000000000000000, 0x000000007fffffff, 31 ); - TEST_RR_OP( 12, sra, 0xffffffff81818181, 0xffffffff81818181, 0 ); - TEST_RR_OP( 13, sra, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); - TEST_RR_OP( 14, sra, 0xffffffffff030303, 0xffffffff81818181, 7 ); + TEST_RR_OP( 12, sra, 0xffffffff81818181, 0xffffffff81818181, 0 ); + TEST_RR_OP( 13, sra, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); + TEST_RR_OP( 14, sra, 0xffffffffff030303, 0xffffffff81818181, 7 ); TEST_RR_OP( 15, sra, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); TEST_RR_OP( 16, sra, 0xffffffffffffffff, 0xffffffff81818181, 31 ); - // # Verify that shifts only use bottom six(rv64) or five(rv32) bits + // # Verify that shifts only use bottom six(rv64) or five(rv32) bits TEST_RR_OP( 17, sra, 0xffffffff81818181, 0xffffffff81818181, 0xffffffffffffffc0 ); TEST_RR_OP( 18, sra, 0xffffffffc0c0c0c0, 0xffffffff81818181, 0xffffffffffffffc1 ); @@ -48,23 +48,23 @@ int main(int argc, char **argv){ TEST_RR_OP( 20, sra, 0xfffffffffffe0606, 0xffffffff81818181, 0xffffffffffffffce ); TEST_RR_OP( 21, sra, 0xffffffffffffffff, 0xffffffff81818181, 0xffffffffffffffff ); -// #------------------------------------------------------------- -// # Source/Destination tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- - TEST_RR_SRC1_EQ_DEST( 22, sra, 0xffffffffff000000, 0xffffffff80000000, 7 ); + TEST_RR_SRC1_EQ_DEST( 22, sra, 0xffffffffff000000, 0xffffffff80000000, 7 ); TEST_RR_SRC2_EQ_DEST( 23, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); TEST_RR_SRC12_EQ_DEST( 24, sra, 0, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/srai.c b/test/isa/srai.c index 285516fe2..c08cdc81b 100644 --- a/test/isa/srai.c +++ b/test/isa/srai.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,50 +11,50 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, srai, 0xffffff8000000000, 0xffffff8000000000, 0 ); - TEST_IMM_OP( 3, srai, 0xffffffffc0000000, 0xffffffff80000000, 1 ); - TEST_IMM_OP( 4, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); - TEST_IMM_OP( 5, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); - TEST_IMM_OP( 6, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 ); + TEST_IMM_OP( 2, srai, 0xffffff8000000000, 0xffffff8000000000, 0 ); + TEST_IMM_OP( 3, srai, 0xffffffffc0000000, 0xffffffff80000000, 1 ); + TEST_IMM_OP( 4, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); + TEST_IMM_OP( 5, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); + TEST_IMM_OP( 6, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 ); - TEST_IMM_OP( 7, srai, 0x000000007fffffff, 0x000000007fffffff, 0 ); - TEST_IMM_OP( 8, srai, 0x000000003fffffff, 0x000000007fffffff, 1 ); - TEST_IMM_OP( 9, srai, 0x0000000000ffffff, 0x000000007fffffff, 7 ); + TEST_IMM_OP( 7, srai, 0x000000007fffffff, 0x000000007fffffff, 0 ); + TEST_IMM_OP( 8, srai, 0x000000003fffffff, 0x000000007fffffff, 1 ); + TEST_IMM_OP( 9, srai, 0x0000000000ffffff, 0x000000007fffffff, 7 ); TEST_IMM_OP( 10, srai, 0x000000000001ffff, 0x000000007fffffff, 14 ); TEST_IMM_OP( 11, srai, 0x0000000000000000, 0x000000007fffffff, 31 ); - TEST_IMM_OP( 12, srai, 0xffffffff81818181, 0xffffffff81818181, 0 ); - TEST_IMM_OP( 13, srai, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); - TEST_IMM_OP( 14, srai, 0xffffffffff030303, 0xffffffff81818181, 7 ); + TEST_IMM_OP( 12, srai, 0xffffffff81818181, 0xffffffff81818181, 0 ); + TEST_IMM_OP( 13, srai, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); + TEST_IMM_OP( 14, srai, 0xffffffffff030303, 0xffffffff81818181, 7 ); TEST_IMM_OP( 15, srai, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); TEST_IMM_OP( 16, srai, 0xffffffffffffffff, 0xffffffff81818181, 31 ); - // #------------------------------------------------------------- -// # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- -// TEST_IMM_SRC1_EQ_DEST( 17, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); + // TEST_IMM_SRC1_EQ_DEST( 17, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sraiw.c b/test/isa/sraiw.c index 9829c1366..60b28626d 100644 --- a/test/isa/sraiw.c +++ b/test/isa/sraiw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,36 +11,36 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_IMM_OP( 2, sraiw, 0xffffffff80000000, 0xffffffff80000000, 0 ); - TEST_IMM_OP( 3, sraiw, 0xffffffffc0000000, 0xffffffff80000000, 1 ); - TEST_IMM_OP( 4, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7 ); - TEST_IMM_OP( 5, sraiw, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); - TEST_IMM_OP( 6, sraiw, 0xffffffffffffffff, 0xffffffff80000001, 31 ); + TEST_IMM_OP( 2, sraiw, 0xffffffff80000000, 0xffffffff80000000, 0 ); + TEST_IMM_OP( 3, sraiw, 0xffffffffc0000000, 0xffffffff80000000, 1 ); + TEST_IMM_OP( 4, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7 ); + TEST_IMM_OP( 5, sraiw, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); + TEST_IMM_OP( 6, sraiw, 0xffffffffffffffff, 0xffffffff80000001, 31 ); - TEST_IMM_OP( 7, sraiw, 0x000000007fffffff, 0x000000007fffffff, 0 ); - TEST_IMM_OP( 8, sraiw, 0x000000003fffffff, 0x000000007fffffff, 1 ); - TEST_IMM_OP( 9, sraiw, 0x0000000000ffffff, 0x000000007fffffff, 7 ); + TEST_IMM_OP( 7, sraiw, 0x000000007fffffff, 0x000000007fffffff, 0 ); + TEST_IMM_OP( 8, sraiw, 0x000000003fffffff, 0x000000007fffffff, 1 ); + TEST_IMM_OP( 9, sraiw, 0x0000000000ffffff, 0x000000007fffffff, 7 ); TEST_IMM_OP( 10, sraiw, 0x000000000001ffff, 0x000000007fffffff, 14 ); TEST_IMM_OP( 11, sraiw, 0x0000000000000000, 0x000000007fffffff, 31 ); - TEST_IMM_OP( 12, sraiw, 0xffffffff81818181, 0xffffffff81818181, 0 ); - TEST_IMM_OP( 13, sraiw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); - TEST_IMM_OP( 14, sraiw, 0xffffffffff030303, 0xffffffff81818181, 7 ); + TEST_IMM_OP( 12, sraiw, 0xffffffff81818181, 0xffffffff81818181, 0 ); + TEST_IMM_OP( 13, sraiw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); + TEST_IMM_OP( 14, sraiw, 0xffffffffff030303, 0xffffffff81818181, 7 ); TEST_IMM_OP( 15, sraiw, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); TEST_IMM_OP( 16, sraiw, 0xffffffffffffffff, 0xffffffff81818181, 31 ); - // # Verify that shifts ignore top 32 (using true 64-bit values) + // # Verify that shifts ignore top 32 (using true 64-bit values) TEST_IMM_OP( 44, sraiw, 0x0000000012345678, 0xffffffff12345678, 0 ); TEST_IMM_OP( 45, sraiw, 0x0000000001234567, 0xffffffff12345678, 4 ); @@ -53,15 +53,15 @@ int main(int argc, char **argv){ //TEST_IMM_SRC1_EQ_DEST( 17, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sraw.c b/test/isa/sraw.c index 275b9e52c..f90426b4f 100644 --- a/test/isa/sraw.c +++ b/test/isa/sraw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,63 +11,62 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, sraw, 0xffffffff80000000, 0xffffffff80000000, 0 ); - TEST_RR_OP( 3, sraw, 0xffffffffc0000000, 0xffffffff80000000, 1 ); - TEST_RR_OP( 4, sraw, 0xffffffffff000000, 0xffffffff80000000, 7 ); - TEST_RR_OP( 5, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); - TEST_RR_OP( 6, sraw, 0xffffffffffffffff, 0xffffffff80000001, 31 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, sraw, 0xffffffff80000000, 0xffffffff80000000, 0 ); + TEST_RR_OP( 3, sraw, 0xffffffffc0000000, 0xffffffff80000000, 1 ); + TEST_RR_OP( 4, sraw, 0xffffffffff000000, 0xffffffff80000000, 7 ); + TEST_RR_OP( 5, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); + TEST_RR_OP( 6, sraw, 0xffffffffffffffff, 0xffffffff80000001, 31 ); - TEST_RR_OP( 7, sraw, 0x000000007fffffff, 0x000000007fffffff, 0 ); - TEST_RR_OP( 8, sraw, 0x000000003fffffff, 0x000000007fffffff, 1 ); - TEST_RR_OP( 9, sraw, 0x0000000000ffffff, 0x000000007fffffff, 7 ); - TEST_RR_OP( 10, sraw, 0x000000000001ffff, 0x000000007fffffff, 14 ); - TEST_RR_OP( 11, sraw, 0x0000000000000000, 0x000000007fffffff, 31 ); + TEST_RR_OP( 7, sraw, 0x000000007fffffff, 0x000000007fffffff, 0 ); + TEST_RR_OP( 8, sraw, 0x000000003fffffff, 0x000000007fffffff, 1 ); + TEST_RR_OP( 9, sraw, 0x0000000000ffffff, 0x000000007fffffff, 7 ); + TEST_RR_OP( 10, sraw, 0x000000000001ffff, 0x000000007fffffff, 14 ); + TEST_RR_OP( 11, sraw, 0x0000000000000000, 0x000000007fffffff, 31 ); - TEST_RR_OP( 12, sraw, 0xffffffff81818181, 0xffffffff81818181, 0 ); - TEST_RR_OP( 13, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); - TEST_RR_OP( 14, sraw, 0xffffffffff030303, 0xffffffff81818181, 7 ); - TEST_RR_OP( 15, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); - TEST_RR_OP( 16, sraw, 0xffffffffffffffff, 0xffffffff81818181, 31 ); + TEST_RR_OP( 12, sraw, 0xffffffff81818181, 0xffffffff81818181, 0 ); + TEST_RR_OP( 13, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); + TEST_RR_OP( 14, sraw, 0xffffffffff030303, 0xffffffff81818181, 7 ); + TEST_RR_OP( 15, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); + TEST_RR_OP( 16, sraw, 0xffffffffffffffff, 0xffffffff81818181, 31 ); - //# Verify that shifts only use bottom five bits + //# Verify that shifts only use bottom five bits - TEST_RR_OP( 17, sraw, 0xffffffff81818181, 0xffffffff81818181, 0xffffffffffffffe0 ); - TEST_RR_OP( 18, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 0xffffffffffffffe1 ); - TEST_RR_OP( 19, sraw, 0xffffffffff030303, 0xffffffff81818181, 0xffffffffffffffe7 ); - TEST_RR_OP( 20, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 0xffffffffffffffee ); - TEST_RR_OP( 21, sraw, 0xffffffffffffffff, 0xffffffff81818181, 0xffffffffffffffff ); + TEST_RR_OP( 17, sraw, 0xffffffff81818181, 0xffffffff81818181, 0xffffffffffffffe0 ); + TEST_RR_OP( 18, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 0xffffffffffffffe1 ); + TEST_RR_OP( 19, sraw, 0xffffffffff030303, 0xffffffff81818181, 0xffffffffffffffe7 ); + TEST_RR_OP( 20, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 0xffffffffffffffee ); + TEST_RR_OP( 21, sraw, 0xffffffffffffffff, 0xffffffff81818181, 0xffffffffffffffff ); - //# Verify that shifts ignore top 32 (using true 64-bit values) + //# Verify that shifts ignore top 32 (using true 64-bit values) - TEST_RR_OP( 44, sraw, 0x0000000012345678, 0xffffffff12345678, 0 ); - TEST_RR_OP( 45, sraw, 0x0000000001234567, 0xffffffff12345678, 4 ); - TEST_RR_OP( 46, sraw, 0xffffffff92345678, 0x0000000092345678, 0 ); - TEST_RR_OP( 47, sraw, 0xfffffffff9234567, 0x0000000092345678, 4 ); + TEST_RR_OP( 44, sraw, 0x0000000012345678, 0xffffffff12345678, 0 ); + TEST_RR_OP( 45, sraw, 0x0000000001234567, 0xffffffff12345678, 4 ); + TEST_RR_OP( 46, sraw, 0xffffffff92345678, 0x0000000092345678, 0 ); + TEST_RR_OP( 47, sraw, 0xfffffffff9234567, 0x0000000092345678, 4 ); //------------------------------------------------------------- // Source/Destination tests //------------------------------------------------------------- + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/srli.c b/test/isa/srli.c index 35ea2faf4..c3bbbb360 100644 --- a/test/isa/srli.c +++ b/test/isa/srli.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,52 +11,50 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { -// #------------------------------------------------------------- -// # Arithmetic tests -// #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- -#define TEST_SRLI(n, v, a) \ - TEST_IMM_OP(n, srli, ((v) & ((1 << (__riscv_xlen-1) << 1) - 1)) >> (a), v, a) +#define TEST_SRLI( n, v, a ) TEST_IMM_OP( n, srli, ( ( v ) & ( ( 1 << ( __riscv_xlen - 1 ) << 1 ) - 1 ) ) >> ( a ), v, a ) - TEST_SRLI( 2, 0xffffffff80000000, 0 ); - TEST_SRLI( 3, 0xffffffff80000000, 1 ); - TEST_SRLI( 4, 0xffffffff80000000, 7 ); - TEST_SRLI( 5, 0xffffffff80000000, 14 ); - TEST_SRLI( 6, 0xffffffff80000001, 31 ); + TEST_SRLI( 2, 0xffffffff80000000, 0 ); + TEST_SRLI( 3, 0xffffffff80000000, 1 ); + TEST_SRLI( 4, 0xffffffff80000000, 7 ); + TEST_SRLI( 5, 0xffffffff80000000, 14 ); + TEST_SRLI( 6, 0xffffffff80000001, 31 ); - TEST_SRLI( 7, 0xffffffffffffffff, 0 ); - TEST_SRLI( 8, 0xffffffffffffffff, 1 ); - TEST_SRLI( 9, 0xffffffffffffffff, 7 ); + TEST_SRLI( 7, 0xffffffffffffffff, 0 ); + TEST_SRLI( 8, 0xffffffffffffffff, 1 ); + TEST_SRLI( 9, 0xffffffffffffffff, 7 ); TEST_SRLI( 10, 0xffffffffffffffff, 14 ); TEST_SRLI( 11, 0xffffffffffffffff, 31 ); - TEST_SRLI( 12, 0x0000000021212121, 0 ); - TEST_SRLI( 13, 0x0000000021212121, 1 ); - TEST_SRLI( 14, 0x0000000021212121, 7 ); + TEST_SRLI( 12, 0x0000000021212121, 0 ); + TEST_SRLI( 13, 0x0000000021212121, 1 ); + TEST_SRLI( 14, 0x0000000021212121, 7 ); TEST_SRLI( 15, 0x0000000021212121, 14 ); TEST_SRLI( 16, 0x0000000021212121, 31 ); - // #------------------------------------------------------------- -// # Source/Destination tests - // #------------------------------------------------------------- - + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/srliw.c b/test/isa/srliw.c index d8a22f4fc..b6040e469 100644 --- a/test/isa/srliw.c +++ b/test/isa/srliw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,40 +11,40 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_IMM_OP( 2, srliw, 0xffffffff80000000, 0xffffffff80000000, 0 ); - TEST_IMM_OP( 3, srliw, 0x0000000040000000, 0xffffffff80000000, 1 ); - TEST_IMM_OP( 4, srliw, 0x0000000001000000, 0xffffffff80000000, 7 ); - TEST_IMM_OP( 5, srliw, 0x0000000000020000, 0xffffffff80000000, 14 ); - TEST_IMM_OP( 6, srliw, 0x0000000000000001, 0xffffffff80000001, 31 ); + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_IMM_OP( 2, srliw, 0xffffffff80000000, 0xffffffff80000000, 0 ); + TEST_IMM_OP( 3, srliw, 0x0000000040000000, 0xffffffff80000000, 1 ); + TEST_IMM_OP( 4, srliw, 0x0000000001000000, 0xffffffff80000000, 7 ); + TEST_IMM_OP( 5, srliw, 0x0000000000020000, 0xffffffff80000000, 14 ); + TEST_IMM_OP( 6, srliw, 0x0000000000000001, 0xffffffff80000001, 31 ); - TEST_IMM_OP( 7, srliw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_IMM_OP( 8, srliw, 0x000000007fffffff, 0xffffffffffffffff, 1 ); - TEST_IMM_OP( 9, srliw, 0x0000000001ffffff, 0xffffffffffffffff, 7 ); + TEST_IMM_OP( 7, srliw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_IMM_OP( 8, srliw, 0x000000007fffffff, 0xffffffffffffffff, 1 ); + TEST_IMM_OP( 9, srliw, 0x0000000001ffffff, 0xffffffffffffffff, 7 ); TEST_IMM_OP( 10, srliw, 0x000000000003ffff, 0xffffffffffffffff, 14 ); TEST_IMM_OP( 11, srliw, 0x0000000000000001, 0xffffffffffffffff, 31 ); - TEST_IMM_OP( 12, srliw, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_IMM_OP( 13, srliw, 0x0000000010909090, 0x0000000021212121, 1 ); - TEST_IMM_OP( 14, srliw, 0x0000000000424242, 0x0000000021212121, 7 ); + TEST_IMM_OP( 12, srliw, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_IMM_OP( 13, srliw, 0x0000000010909090, 0x0000000021212121, 1 ); + TEST_IMM_OP( 14, srliw, 0x0000000000424242, 0x0000000021212121, 7 ); TEST_IMM_OP( 15, srliw, 0x0000000000008484, 0x0000000021212121, 14 ); TEST_IMM_OP( 16, srliw, 0x0000000000000000, 0x0000000021212121, 31 ); //# Verify that shifts ignore top 32 (using true 64-bit values) - TEST_IMM_OP( 44, srliw, 0x0000000012345678, 0xffffffff12345678, 0 ); - TEST_IMM_OP( 45, srliw, 0x0000000001234567, 0xffffffff12345678, 4 ); - TEST_IMM_OP( 46, srliw, 0xffffffff92345678, 0x0000000092345678, 0 ); - TEST_IMM_OP( 47, srliw, 0x0000000009234567, 0x0000000092345678, 4 ); + TEST_IMM_OP( 44, srliw, 0x0000000012345678, 0xffffffff12345678, 0 ); + TEST_IMM_OP( 45, srliw, 0x0000000001234567, 0xffffffff12345678, 4 ); + TEST_IMM_OP( 46, srliw, 0xffffffff92345678, 0x0000000092345678, 0 ); + TEST_IMM_OP( 47, srliw, 0x0000000009234567, 0x0000000092345678, 4 ); //------------------------------------------------------------- // Source/Destination tests @@ -52,15 +52,15 @@ int main(int argc, char **argv){ // TEST_IMM_SRC1_EQ_DEST( 17, srliw, 0x0000000001000000, 0xffffffff80000000, 7 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/srlw.c b/test/isa/srlw.c index a3ee62605..8408de3bd 100644 --- a/test/isa/srlw.c +++ b/test/isa/srlw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,33 +11,33 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- - TEST_RR_OP( 2, srlw, 0xffffffff80000000, 0xffffffff80000000, 0 ); - TEST_RR_OP( 3, srlw, 0x0000000040000000, 0xffffffff80000000, 1 ); - TEST_RR_OP( 4, srlw, 0x0000000001000000, 0xffffffff80000000, 7 ); - TEST_RR_OP( 5, srlw, 0x0000000000020000, 0xffffffff80000000, 14 ); - TEST_RR_OP( 6, srlw, 0x0000000000000001, 0xffffffff80000001, 31 ); - - TEST_RR_OP( 7, srlw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); - TEST_RR_OP( 8, srlw, 0x000000007fffffff, 0xffffffffffffffff, 1 ); - TEST_RR_OP( 9, srlw, 0x0000000001ffffff, 0xffffffffffffffff, 7 ); - TEST_RR_OP( 10, srlw, 0x000000000003ffff, 0xffffffffffffffff, 14 ); - TEST_RR_OP( 11, srlw, 0x0000000000000001, 0xffffffffffffffff, 31 ); - - TEST_RR_OP( 12, srlw, 0x0000000021212121, 0x0000000021212121, 0 ); - TEST_RR_OP( 13, srlw, 0x0000000010909090, 0x0000000021212121, 1 ); - TEST_RR_OP( 14, srlw, 0x0000000000424242, 0x0000000021212121, 7 ); - TEST_RR_OP( 15, srlw, 0x0000000000008484, 0x0000000021212121, 14 ); - TEST_RR_OP( 16, srlw, 0x0000000000000000, 0x0000000021212121, 31 ); +int main( int argc, char** argv ) { + + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- + TEST_RR_OP( 2, srlw, 0xffffffff80000000, 0xffffffff80000000, 0 ); + TEST_RR_OP( 3, srlw, 0x0000000040000000, 0xffffffff80000000, 1 ); + TEST_RR_OP( 4, srlw, 0x0000000001000000, 0xffffffff80000000, 7 ); + TEST_RR_OP( 5, srlw, 0x0000000000020000, 0xffffffff80000000, 14 ); + TEST_RR_OP( 6, srlw, 0x0000000000000001, 0xffffffff80000001, 31 ); + + TEST_RR_OP( 7, srlw, 0xffffffffffffffff, 0xffffffffffffffff, 0 ); + TEST_RR_OP( 8, srlw, 0x000000007fffffff, 0xffffffffffffffff, 1 ); + TEST_RR_OP( 9, srlw, 0x0000000001ffffff, 0xffffffffffffffff, 7 ); + TEST_RR_OP( 10, srlw, 0x000000000003ffff, 0xffffffffffffffff, 14 ); + TEST_RR_OP( 11, srlw, 0x0000000000000001, 0xffffffffffffffff, 31 ); + + TEST_RR_OP( 12, srlw, 0x0000000021212121, 0x0000000021212121, 0 ); + TEST_RR_OP( 13, srlw, 0x0000000010909090, 0x0000000021212121, 1 ); + TEST_RR_OP( 14, srlw, 0x0000000000424242, 0x0000000021212121, 7 ); + TEST_RR_OP( 15, srlw, 0x0000000000008484, 0x0000000021212121, 14 ); + TEST_RR_OP( 16, srlw, 0x0000000000000000, 0x0000000021212121, 31 ); //# Verify that shifts only use bottom five bits @@ -57,21 +57,19 @@ int main(int argc, char **argv){ // Source/Destination tests //------------------------------------------------------------- - - TEST_RR_SRC1_EQ_DEST( 22, srlw, 0x0000000001000000, 0xffffffff80000000, 7 ); + TEST_RR_SRC1_EQ_DEST( 22, srlw, 0x0000000001000000, 0xffffffff80000000, 7 ); TEST_RR_SRC2_EQ_DEST( 23, srlw, 0x0000000000020000, 0xffffffff80000000, 14 ); TEST_RR_SRC12_EQ_DEST( 24, srlw, 0, 7 ); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); - -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sub.c b/test/isa/sub.c index fbc768f84..c8270212f 100644 --- a/test/isa/sub.c +++ b/test/isa/sub.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,27 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include"isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- -TEST_RR_OP( 2, sub, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 ); - TEST_RR_OP( 3, sub, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 ); - TEST_RR_OP( 4, sub, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 ); + TEST_RR_OP( 2, sub, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 ); + TEST_RR_OP( 3, sub, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 ); + TEST_RR_OP( 4, sub, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 ); - TEST_RR_OP( 5, sub, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, sub, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 ); - TEST_RR_OP( 7, sub, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, sub, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, sub, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 ); + TEST_RR_OP( 7, sub, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP( 8, sub, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff ); - TEST_RR_OP( 9, sub, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); + TEST_RR_OP( 8, sub, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff ); + TEST_RR_OP( 9, sub, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); TEST_RR_OP( 10, sub, 0x000000007fff8000, 0x000000007fffffff, 0x0000000000007fff ); TEST_RR_OP( 11, sub, 0xffffffff7fff8001, 0xffffffff80000000, 0x0000000000007fff ); @@ -49,15 +49,15 @@ TEST_RR_OP( 2, sub, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 TEST_RR_SRC2_EQ_DEST( 17, sub, 3, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 18, sub, 0, 13 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/subw.c b/test/isa/subw.c index 4fbd68073..baa2567de 100644 --- a/test/isa/subw.c +++ b/test/isa/subw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,28 +11,27 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" - -int main(int argc, char **argv){ - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- +int main( int argc, char** argv ) { + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- - TEST_RR_OP( 2, subw, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 ); - TEST_RR_OP( 3, subw, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 ); - TEST_RR_OP( 4, subw, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 ); + TEST_RR_OP( 2, subw, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 ); + TEST_RR_OP( 3, subw, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 ); + TEST_RR_OP( 4, subw, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 ); - TEST_RR_OP( 5, subw, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 ); - TEST_RR_OP( 6, subw, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 ); - TEST_RR_OP( 7, subw, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 ); + TEST_RR_OP( 5, subw, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 ); + TEST_RR_OP( 6, subw, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 ); + TEST_RR_OP( 7, subw, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 ); - TEST_RR_OP( 8, subw, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff ); - TEST_RR_OP( 9, subw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); + TEST_RR_OP( 8, subw, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff ); + TEST_RR_OP( 9, subw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); TEST_RR_OP( 10, subw, 0x000000007fff8000, 0x000000007fffffff, 0x0000000000007fff ); TEST_RR_OP( 11, subw, 0x000000007fff8001, 0xffffffff80000000, 0x0000000000007fff ); @@ -42,23 +41,23 @@ int main(int argc, char **argv){ TEST_RR_OP( 14, subw, 0xfffffffffffffffe, 0xffffffffffffffff, 0x0000000000000001 ); TEST_RR_OP( 15, subw, 0x0000000000000000, 0xffffffffffffffff, 0xffffffffffffffff ); - // #------------------------------------------------------------- - // # Source/Destination tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Source/Destination tests + // #------------------------------------------------------------- TEST_RR_SRC1_EQ_DEST( 16, subw, 2, 13, 11 ); TEST_RR_SRC2_EQ_DEST( 17, subw, 3, 14, 11 ); TEST_RR_SRC12_EQ_DEST( 18, subw, 0, 13 ); -asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/sw.c b/test/isa/sw.c index 3aeb81a67..b26657ad5 100644 --- a/test/isa/sw.c +++ b/test/isa/sw.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,77 +11,66 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" +int main( int argc, char** argv ) { -int main(int argc, char **argv){ + // #------------------------------------------------------------- + // # Basic tests + // #------------------------------------------------------------- - // #------------------------------------------------------------- - // # Basic tests - // #------------------------------------------------------------- - - TEST_ST_OP( 2, lw, sw, 0x0000000000aa00aa, 0, tdat ); - TEST_ST_OP( 3, lw, sw, 0xffffffffaa00aa00, 4, tdat ); - TEST_ST_OP( 4, lw, sw, 0x000000000aa00aa0, 8, tdat ); + TEST_ST_OP( 2, lw, sw, 0x0000000000aa00aa, 0, tdat ); + TEST_ST_OP( 3, lw, sw, 0xffffffffaa00aa00, 4, tdat ); + TEST_ST_OP( 4, lw, sw, 0x000000000aa00aa0, 8, tdat ); TEST_ST_OP( 5, lw, sw, 0xffffffffa00aa00a, 12, tdat ); // # Test with negative offset TEST_ST_OP( 6, lw, sw, 0x0000000000aa00aa, -12, tdat8 ); - TEST_ST_OP( 7, lw, sw, 0xffffffffaa00aa00, -8, tdat8 ); - TEST_ST_OP( 8, lw, sw, 0x000000000aa00aa0, -4, tdat8 ); - TEST_ST_OP( 9, lw, sw, 0xffffffffa00aa00a, 0, tdat8 ); - + TEST_ST_OP( 7, lw, sw, 0xffffffffaa00aa00, -8, tdat8 ); + TEST_ST_OP( 8, lw, sw, 0x000000000aa00aa0, -4, tdat8 ); + TEST_ST_OP( 9, lw, sw, 0xffffffffa00aa00a, 0, tdat8 ); - //# Test with a negative base + //# Test with a negative base - TEST_CASE( 10, x5, 0x12345678, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x12345678); \ - ASM_GEN(addi x10, x6, -32); \ - ASM_GEN(sw x7, 32(x10)); \ - ASM_GEN(lw x5, 0(x6)); \ - ) + TEST_CASE( 10, x5, 0x12345678, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x12345678 ); ASM_GEN( addi x10, x6, -32 ); + ASM_GEN( sw x7, 32( x10 ) ); + ASM_GEN( lw x5, 0( x6 ) ); ) //# Test with unaligned base - TEST_CASE( 11, x5, 0x58213098, \ - ASM_GEN(la x6, tdat9); \ - ASM_GEN(li x7, 0x58213098); \ - ASM_GEN(addi x6, x6, -3); \ - ASM_GEN(sw x7, 7(x6)); \ - ASM_GEN(la x10, tdat10); \ - ASM_GEN(lw x5, 0(x10)); \ - ) - + TEST_CASE( 11, x5, 0x58213098, ASM_GEN( la x6, tdat9 ); ASM_GEN( li x7, 0x58213098 ); ASM_GEN( addi x6, x6, -3 ); + ASM_GEN( sw x7, 7( x6 ) ); + ASM_GEN( la x10, tdat10 ); + ASM_GEN( lw x5, 0( x10 ) ); ) - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } - asm(".data"); +asm( ".data" ); RVTEST_DATA_BEGIN - asm ("tdat:"); - asm ("tdat1: .word 0xdeadbeef"); - asm ("tdat2: .word 0xdeadbeef"); - asm ("tdat3: .word 0xdeadbeef"); - asm ("tdat4: .word 0xdeadbeef"); - asm ("tdat5: .word 0xdeadbeef"); - asm ("tdat6: .word 0xdeadbeef"); - asm ("tdat7: .word 0xdeadbeef"); - asm ("tdat8: .word 0xdeadbeef"); - asm ("tdat9: .word 0xdeadbeef"); - asm ("tdat10: .word 0xdeadbeef"); +asm( "tdat:" ); +asm( "tdat1: .word 0xdeadbeef" ); +asm( "tdat2: .word 0xdeadbeef" ); +asm( "tdat3: .word 0xdeadbeef" ); +asm( "tdat4: .word 0xdeadbeef" ); +asm( "tdat5: .word 0xdeadbeef" ); +asm( "tdat6: .word 0xdeadbeef" ); +asm( "tdat7: .word 0xdeadbeef" ); +asm( "tdat8: .word 0xdeadbeef" ); +asm( "tdat9: .word 0xdeadbeef" ); +asm( "tdat10: .word 0xdeadbeef" ); RVTEST_DATA_END diff --git a/test/isa/xor.c b/test/isa/xor.c index e97e2b59c..6a4b05dfa 100644 --- a/test/isa/xor.c +++ b/test/isa/xor.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_RR_OP( 2, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); TEST_RR_OP( 3, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); @@ -35,15 +35,15 @@ int main(int argc, char **argv){ TEST_RR_SRC2_EQ_DEST( 7, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); TEST_RR_SRC12_EQ_DEST( 8, xor, 0x00000000, 0xff00ff00 ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/isa/xori.c b/test/isa/xori.c index 771d34db8..633b38f6f 100644 --- a/test/isa/xori.c +++ b/test/isa/xori.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ +#include "isa_test_macros.h" +#include #include #include -#include -#include "isa_test_macros.h" -int main(int argc, char **argv){ +int main( int argc, char** argv ) { - // #------------------------------------------------------------- - // # Arithmetic tests - // #------------------------------------------------------------- + // #------------------------------------------------------------- + // # Arithmetic tests + // #------------------------------------------------------------- TEST_IMM_OP( 2, xori, 0xffffffffff00f00f, 0x0000000000ff0f00, 0xf0f ); TEST_IMM_OP( 3, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 ); @@ -33,15 +33,15 @@ int main(int argc, char **argv){ TEST_IMM_SRC1_EQ_DEST( 6, xori, 0xffffffffff00f00f, 0xffffffffff00f700, 0x70f ); - asm volatile(" bne x0, gp, pass;"); -asm volatile("pass:" ); - asm volatile("j continue"); + asm volatile( " bne x0, gp, pass;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); -asm volatile("fail:" ); - assert(false); + asm volatile( "fail:" ); + assert( false ); -asm volatile("continue:"); -asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/large_bss/Makefile b/test/large_bss/Makefile index 751efde03..1d9edc196 100644 --- a/test/large_bss/Makefile +++ b/test/large_bss/Makefile @@ -3,7 +3,7 @@ # # makefile: large_bss # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/large_bss/large_bss.c b/test/large_bss/large_bss.c index 1f6e6f552..ed8983f32 100644 --- a/test/large_bss/large_bss.c +++ b/test/large_bss/large_bss.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64G * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,4 +13,8 @@ #include -char t[1024*1024*12]; int main() { return 0; } +char t[1024 * 1024 * 12]; + +int main() { + return 0; +} diff --git a/test/lwsp/.gitignore b/test/lwsp/.gitignore new file mode 100644 index 000000000..5107a41b5 --- /dev/null +++ b/test/lwsp/.gitignore @@ -0,0 +1,3 @@ +*.dis +*.log +*.tmplog diff --git a/test/lwsp/Makefile b/test/lwsp/Makefile new file mode 100644 index 000000000..c420599d4 --- /dev/null +++ b/test/lwsp/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: lwsp +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src +EXAMPLE=lwsp +CXX=${RVCXX} +ARCH=rv64gc +INCLUDE=-I../../common/syscalls -I../include + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) -march=$(ARCH) -static $(INCLUDE) -o $(EXAMPLE).exe $(EXAMPLE).cc +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/lwsp/lwsp.cc b/test/lwsp/lwsp.cc new file mode 100644 index 000000000..55eb0d3c9 --- /dev/null +++ b/test/lwsp/lwsp.cc @@ -0,0 +1,30 @@ +// clang-format off +#include "rev-macros.h" +#include "syscalls.h" + +#undef assert +#define assert TRACE_ASSERT + +int main() { + uint64_t v64 = 0x80000000000aced1UL; + uint64_t c64 = 0xbad1; + int c32 = 0xbad0; + + asm volatile( + "c.addi16sp sp, -224 \n\t" // alloc on sp + "c.sdsp %2, 144(sp) \n\t" // save v64 + "c.swsp zero, 152(sp) \n\t" // save 0 + "slli zero, zero, 10 \n\t" // do nothing + "c.lwsp %0, 152(sp) \n\t" // read 0 ( failure will be reading from physical address -1 ) + "c.ldsp %1, 144(sp) \n\t" // read v64 + "c.addi16sp sp, 224 \n\t" // restore sp + : "=r"(c32), "=r"(c64) + : "r"(v64) + ); + + assert(c32==0x0); + assert(c64==0x80000000000aced1UL); + + return 0; +} + diff --git a/test/many_core/Makefile b/test/many_core/Makefile index 90d5ed9cf..ee4720e90 100644 --- a/test/many_core/Makefile +++ b/test/many_core/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/many_core/many_core.c b/test/many_core/many_core.c index 35ee561e9..f87936924 100644 --- a/test/many_core/many_core.c +++ b/test/many_core/many_core.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,8 +13,8 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { int i = 9; - i = i + argc; + i = i + argc; return i; } diff --git a/test/many_core/rev-many-core.py b/test/many_core/rev-many-core.py old mode 100644 new mode 100755 index bfa96a2ac..1da4155c1 --- a/test/many_core/rev-many-core.py +++ b/test/many_core/rev-many-core.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 4, # Verbosity - "numCores" : 96, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[CORES:RV64GC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "many_core.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 4, # Verbosity + "numCores": 96, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[CORES:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "many_core.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/many_core/run_many_core.sh b/test/many_core/run_many_core.sh index d3b5af4df..96d436739 100755 --- a/test/many_core/run_many_core.sh +++ b/test/many_core/run_many_core.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x many_core.exe ]; then +if [[ -x many_core.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-many-core.py else echo "Test MANY_CORE: many_core.exe not Found - likely build failed" diff --git a/test/mem_dump/.gitignore b/test/mem_dump/.gitignore new file mode 100644 index 000000000..8e7f1f33b --- /dev/null +++ b/test/mem_dump/.gitignore @@ -0,0 +1,2 @@ +range*.dump.init +range*.dump.final diff --git a/test/mem_dump/Makefile b/test/mem_dump/Makefile new file mode 100644 index 000000000..10a5c8d27 --- /dev/null +++ b/test/mem_dump/Makefile @@ -0,0 +1,25 @@ +# +# Makefile +# +# makefile: basi +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=basic +CC=${RVCC} +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -o $(EXAMPLE).exe $(EXAMPLE).c -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/mem_dump/basic.c b/test/mem_dump/basic.c new file mode 100644 index 000000000..36fa0e85e --- /dev/null +++ b/test/mem_dump/basic.c @@ -0,0 +1,16 @@ +// Generic simple c program + +int main() { + int a = 10; + int b = 20; + int c = a + b; + + for( int i = 0; i < 10; i++ ) { + c += i; + } + if( c != 40 ) { + return 1; + } else { + return 0; + } +} diff --git a/test/mem_dump/mem_dump.py b/test/mem_dump/mem_dump.py new file mode 100755 index 000000000..90ac84459 --- /dev/null +++ b/test/mem_dump/mem_dump.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# mem_dump.py +# + +import argparse +import sst + +DEBUG_L1 = 0 +DEBUG_MEM = 0 +DEBUG_LEVEL = 10 +VERBOSE = 2 +memSize = 1024 * 1024 * 10 - 1 + +# Setup argument parser +parser = argparse.ArgumentParser(description="Run Rev SST Simulation") +parser.add_argument( + "--numCores", type=int, help="Number of Rev Cores per RevCPU", default=1 +) +parser.add_argument( + "--numHarts", type=int, help="Number of HARTs per Rev Core", default=1 +) +parser.add_argument( + "--program", help="The program executable to run in the simulation", default="a.out" +) +parser.add_argument( + "--enableMemH", + type=int, + choices=[0, 1], + help="Enable (1) or disable (0) memHierarchy backend", + default=0, +) +parser.add_argument("--verbose", type=int, help="Verbosity level", default=2) +parser.add_argument( + "--machine", help="Machine type/configuration", default="[CORES:RV64GC]" +) +parser.add_argument( + "--args", help="Command line arguments to pass to the target executable", default="" +) +parser.add_argument( + "--startSymbol", help="ELF Symbol Rev should begin execution at", default="[0:main]" +) + +# Parse arguments +args = parser.parse_args() + +# Print arguments nicely +print("Rev SST Simulation Configuration:") +for arg in vars(args): + print("\t", arg, " = ", getattr(args, arg)) + +# SST core options and parameters +clock = "2.0GHz" + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams( + { + "verbose": args.verbose, + "numCores": args.numCores, + "numHarts": args.numHarts, + "clock": clock, + "memSize": memSize, + "machine": args.machine, + "memCost": "[0:1:10]", + "program": "basic.exe", + "startAddr": "[0:0x00000000]", + "startSymbol": args.startSymbol, + "args": args.args, + "splash": 1, + "memDumpRanges": ["range1", "range2"], + "range1.startAddr": 0x010000, + "range1.size": 0x100000, + "range2.startAddr": 0x090000, + "range2.size": 0x100, + } +) + +sst.setStatisticOutput("sst.statOutputCSV") +sst.setStatisticLoadLevel(4) +sst.enableAllStatisticsForComponentType("revcpu.RevCPU") diff --git a/test/mem_dump/run_mem_dump.sh b/test/mem_dump/run_mem_dump.sh new file mode 100755 index 000000000..7598345bf --- /dev/null +++ b/test/mem_dump/run_mem_dump.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +#Build the test +make clean && make + +# Check that the exec was built... +if [[ -x basic.exe ]]; then + sst --add-lib-path=../../build/src/ ./mem_dump.py +else + echo "Test mem_dump (python config options - not syscall version): basic.exe not Found - likely build failed" + exit 1 +fi diff --git a/test/memset/Makefile b/test/memset/Makefile index c64c9da67..5ac3a8e3b 100644 --- a/test/memset/Makefile +++ b/test/memset/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/memset/memset.c b/test/memset/memset.c index 915164c2a..d06763838 100644 --- a/test/memset/memset.c +++ b/test/memset/memset.c @@ -1,22 +1,22 @@ #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) -#define N (1024) +#define N ( 1024 ) char mem[N]; int main() { - memset(mem, 42, N); - for (int i = 0; i < N; i++) { - assert(mem[i] == 42); + memset( mem, 42, N ); + for( int i = 0; i < N; i++ ) { + assert( mem[i] == 42 ); } - memset(mem, 0, N); - for (int i = 0; i < N; i++) { - assert(mem[i] == 0); + memset( mem, 0, N ); + for( int i = 0; i < N; i++ ) { + assert( mem[i] == 0 ); } return 0; } diff --git a/test/memset/memset.py b/test/memset/memset.py old mode 100644 new mode 100755 index c6118b44b..158b04cc3 --- a/test/memset/memset.py +++ b/test/memset/memset.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV32I for core 0 - "startAddr" : "[0:0x00000000]", - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "memset.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV32I for core 0 + "startAddr": "[0:0x00000000]", + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "memset.exe"), # Target executable + "splash": 1 # Display the splash message }) comp_cpu.enableAllStatistics() diff --git a/test/memset/run_memset.sh b/test/memset/run_memset.sh index 9a807512b..b97f96ba6 100755 --- a/test/memset/run_memset.sh +++ b/test/memset/run_memset.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -f memset.exe ]; then +if [[ -f memset.exe ]]; then sst --add-lib-path=../../build/src/ ./memset.py else echo "Test MEMSET: memset.exe not Found - likely build failed" diff --git a/test/memset_2/Makefile b/test/memset_2/Makefile index ff570e6cd..d65d2e70d 100644 --- a/test/memset_2/Makefile +++ b/test/memset_2/Makefile @@ -3,7 +3,7 @@ # # makefile: memset_2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/memset_2/memset_2.c b/test/memset_2/memset_2.c index 926e065e6..bab7c2926 100644 --- a/test/memset_2/memset_2.c +++ b/test/memset_2/memset_2.c @@ -1,42 +1,42 @@ #include #include #define u16 unsigned short -#define u8 unsigned char -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define u8 unsigned char +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) /* * Write 0 to a memory, hammer down ones around it, * check that it is still 0 at the end. */ -#define hammer(type) \ - int hammer_##type(type *addr, size_t size) { \ - int ret = 0; \ - type ff = (type)0xffffffffffff; \ - for (size_t i = 2; i < size - 2; i++) { \ - addr[i] = 0; \ - for (size_t j = 0; j < 10; j++) { \ - addr[i - 1] = ff; \ - addr[i - 2] = ff; \ - addr[i + 1] = ff; \ - addr[i + 2] = ff; \ - } \ - ret |= (addr[i] != 0); \ - } \ - return ret; \ +#define hammer( type ) \ + int hammer_##type( type* addr, size_t size ) { \ + int ret = 0; \ + type ff = (type) 0xffffffffffff; \ + for( size_t i = 2; i < size - 2; i++ ) { \ + addr[i] = 0; \ + for( size_t j = 0; j < 10; j++ ) { \ + addr[i - 1] = ff; \ + addr[i - 2] = ff; \ + addr[i + 1] = ff; \ + addr[i + 2] = ff; \ + } \ + ret |= ( addr[i] != 0 ); \ + } \ + return ret; \ } -hammer(u16) +hammer( u16 ) - int test_3(void *addr, size_t size) { + int test_3( void* addr, size_t size ) { int ret = 0; - ret |= hammer_u16(addr, size / 2); + ret |= hammer_u16( addr, size / 2 ); return ret; } @@ -44,4 +44,6 @@ hammer(u16) #define SIZE 1000 u8 mem[SIZE]; -int main() { assert(!test_3(mem, SIZE)); } +int main() { + assert( !test_3( mem, SIZE ) ); +} diff --git a/test/minfft/Makefile b/test/minfft/Makefile index 4188381c1..afc05d52a 100644 --- a/test/minfft/Makefile +++ b/test/minfft/Makefile @@ -3,7 +3,7 @@ # # makefile: ex1 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/minfft/ex1.c b/test/minfft/ex1.c index d0b1be404..5ecdc03be 100644 --- a/test/minfft/ex1.c +++ b/test/minfft/ex1.c @@ -1,11 +1,10 @@ // -#include -#include #include "minfft.h" +#include +#include - -#define P 16 +#define P 16 /*minfft_aux* minfft_mkaux_dft_1d_local (int N) { minfft_aux *a; @@ -41,99 +40,97 @@ minfft_mkaux_dft_1d_local (int N) { return NULL; }*/ -static const minfft_real pi_l=3.141592653589793238462643383279502884L; -static minfft_real nsin_l (int, int); +static const minfft_real pi_l = 3.141592653589793238462643383279502884L; +static minfft_real nsin_l( int, int ); + // cos(2*pi*n/N) -static minfft_real -ncos_l (int n, int N) { - // reduce n to 0..N/8 - if (n<0) - return ncos_l(-n, N); - else if (n>=N/2) - return -ncos_l(n-N/2, N); - else if (n>=N/4) - return -nsin_l(n-N/4, N); - else if (n>N/8) - return nsin_l(N/4-n, N); - else +static minfft_real ncos_l( int n, int N ) { + // reduce n to 0..N/8 + if( n < 0 ) + return ncos_l( -n, N ); + else if( n >= N / 2 ) + return -ncos_l( n - N / 2, N ); + else if( n >= N / 4 ) + return -nsin_l( n - N / 4, N ); + else if( n > N / 8 ) + return nsin_l( N / 4 - n, N ); + else #if MINFFT_SINGLE - return cosf(2*pi_l*n/N); + return cosf( 2 * pi_l * n / N ); #elif MINFFT_EXTENDED - return cosl(2*pi_l*n/N); + return cosl( 2 * pi_l * n / N ); #else - return (2*pi_l*n/N); + return ( 2 * pi_l * n / N ); #endif } // sin(2*pi*n/N) -static minfft_real -nsin_l (int n, int N) { - // reduce n to 0..N/8 - if (n<0) - return -nsin_l(-n, N); - else if (n>=N/2) - return -nsin_l(n-N/2, N); - else if (n>=N/4) - return ncos_l(n-N/4, N); - else if (n>N/8) - return ncos_l(N/4-n, N); - else +static minfft_real nsin_l( int n, int N ) { + // reduce n to 0..N/8 + if( n < 0 ) + return -nsin_l( -n, N ); + else if( n >= N / 2 ) + return -nsin_l( n - N / 2, N ); + else if( n >= N / 4 ) + return ncos_l( n - N / 4, N ); + else if( n > N / 8 ) + return ncos_l( N / 4 - n, N ); + else #if MINFFT_SINGLE - return sinf(2*pi_l*n/N); + return sinf( 2 * pi_l * n / N ); #elif MINFFT_EXTENDED - return sinl(2*pi_l*n/N); + return sinl( 2 * pi_l * n / N ); #else - return (2*pi_l*n/N); + return ( 2 * pi_l * n / N ); #endif } -int main() -{ - minfft_cmpl x[P], y[P]; // input and output buffers - minfft_cmpl t[P], e2[P]; // input and output buffers - //minfft_aux *a; // aux data - // prepare aux data - //a=minfft_mkaux_dft_1d(P); - minfft_aux a; - minfft_real *e; - a.N = P; +int main() { + minfft_cmpl x[P], y[P]; // input and output buffers + minfft_cmpl t[P], e2[P]; // input and output buffers + //minfft_aux *a; // aux data + // prepare aux data + //a=minfft_mkaux_dft_1d(P); + minfft_aux a; + minfft_real* e; + a.N = P; int ddd0 = rand(); int ddd1 = rand(); int ddd2 = rand(); int ddd3 = rand(); - int N = P; - // if (N>=16) { -// a.t=t; -// a.e=e2; -// e=(minfft_real*)a.e; -// while (N>=16) { -// //for (int n=0; n= 16){ - for(int n=0; n< N; ++n){ - *e++=ddd1*pi_l+(n*ddd2); + int N = P; + // if (N>=16) { + // a.t=t; + // a.e=e2; + // e=(minfft_real*)a.e; + // while (N>=16) { + // //for (int n=0; n= 16 ) { + for( int n = 0; n < N; ++n ) { + *e++ = ddd1 * pi_l + ( n * ddd2 ); } - }else{ + } else { a.t = NULL; a.e = NULL; } a.sub1 = a.sub2 = NULL; - // do transforms + // do transforms // volatile int* rev = 0xDEADBEEF; // *rev = 0x0AAA0001; - minfft_dft(x, y, &a); - //minfft_invdft(y, x, &a); - // free aux data - //minfft_free_aux(a); + minfft_dft( x, y, &a ); + //minfft_invdft(y, x, &a); + // free aux data + //minfft_free_aux(a); - // exit normally - return 0; + // exit normally + return 0; } diff --git a/test/minfft/minfft.c b/test/minfft/minfft.c index 64c862b3a..26375feb8 100644 --- a/test/minfft/minfft.c +++ b/test/minfft/minfft.c @@ -3,141 +3,133 @@ // SPDX-License-Identifier: MIT #include "minfft.h" -#include #include +#include // constants -static const minfft_real pi=3.141592653589793238462643383279502884L; -static const minfft_real sqrt2=1.414213562373095048801688724209698079L; -static const minfft_real invsqrt2=0.707106781186547524400844362104849039L; - +static const minfft_real pi = 3.141592653589793238462643383279502884L; +static const minfft_real sqrt2 = 1.414213562373095048801688724209698079L; +static const minfft_real invsqrt2 = 0.707106781186547524400844362104849039L; // *** higher-order functions *** // a pointer to a strided 1d complex transform routine -typedef -void (*s_cx_1d_t) -(minfft_cmpl*, minfft_cmpl*, int, const minfft_aux*); +typedef void ( *s_cx_1d_t )( minfft_cmpl*, minfft_cmpl*, int, const minfft_aux* ); // make a strided any-dimensional complex transform // by repeated application of its strided one-dimensional routine -inline static void -mkcx (minfft_cmpl *x, minfft_cmpl *y, int sy, const minfft_aux *a, s_cx_1d_t s_1d) { +inline static void mkcx( minfft_cmpl* x, minfft_cmpl* y, int sy, const minfft_aux* a, s_cx_1d_t s_1d ) { // volatile int* rev = 0xDEADBEEF; -// *rev = 0x0BBB0004; - if (a->sub2==NULL) - (*s_1d)(x, y, sy, a); + // *rev = 0x0BBB0004; + if( a->sub2 == NULL ) + ( *s_1d )( x, y, sy, a ); else { - int N1=a->sub1->N, N2=a->sub2->N; // transform lengths - int n; // counter - minfft_cmpl *t=a->t; // temporary buffer + int N1 = a->sub1->N, N2 = a->sub2->N; // transform lengths + int n; // counter + minfft_cmpl* t = a->t; // temporary buffer // strided transform of contiguous hyperplanes - for (n=0; nsub1, s_1d); + for( n = 0; n < N2; ++n ) { + mkcx( x + n * N1, t + n, N2, a->sub1, s_1d ); } // strided transform of contiguous rows - for (n=0; nsub2); + for( n = 0; n < N1; ++n ) + ( *s_1d )( t + n * N2, y + sy * n, sy * N1, a->sub2 ); } } // a pointer to a strided 1d real transform routine -typedef -void (*s_rx_1d_t) -(minfft_real*, minfft_real*, int, const minfft_aux*); +typedef void ( *s_rx_1d_t )( minfft_real*, minfft_real*, int, const minfft_aux* ); // make a strided any-dimensional real transform // by repeated application of its strided one-dimensional routine -inline static void -mkrx (minfft_real *x, minfft_real *y, int sy, const minfft_aux *a, s_rx_1d_t s_1d) { - if (a->sub2==NULL) - (*s_1d)(x, y, sy, a); +inline static void mkrx( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a, s_rx_1d_t s_1d ) { + if( a->sub2 == NULL ) + ( *s_1d )( x, y, sy, a ); else { - int N1=a->sub1->N, N2=a->sub2->N; // transform lengths - int n; // counter - minfft_real *t=a->t; // temporary buffer + int N1 = a->sub1->N, N2 = a->sub2->N; // transform lengths + int n; // counter + minfft_real* t = a->t; // temporary buffer // strided transform of contiguous hyperplanes - for (n=0; nsub1, s_1d); + for( n = 0; n < N2; ++n ) + mkrx( x + n * N1, t + n, N2, a->sub1, s_1d ); // strided transform of contiguous rows - for (n=0; nsub2); + for( n = 0; n < N1; ++n ) + ( *s_1d )( t + n * N2, y + sy * n, sy * N1, a->sub2 ); } } // *** complex transforms *** // recursive strided one-dimensional DFT -inline static void -rs_dft_1d (int N, minfft_cmpl *x, minfft_cmpl *t, minfft_cmpl *y, int sy, const minfft_cmpl *e) { - int n; // counter +inline static void rs_dft_1d( int N, minfft_cmpl* x, minfft_cmpl* t, minfft_cmpl* y, int sy, const minfft_cmpl* e ) { + int n; // counter // split-radix DIF // volatile int* rev = 0xDEADBEEF; - if (N==1) { + if( N == 1 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real *xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real *xi = xr + 1, *yi = yr + 1; // y[0]=x[0]; - yr[0]=xr[0]; - yi[0]=xi[0]; + yr[0] = xr[0]; + yi[0] = xi[0]; return; } - if (N==2) { + if( N == 2 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r; register minfft_real t0i, t1i; // t0=x[0]+x[1]; - t0r=xr[0]+xr[2]; - t0i=xi[0]+xi[2]; + t0r = xr[0] + xr[2]; + t0i = xi[0] + xi[2]; // t1=x[0]-x[1]; - t1r=xr[0]-xr[2]; - t1i=xi[0]-xi[2]; + t1r = xr[0] - xr[2]; + t1i = xi[0] - xi[2]; // y[0]=t0; - yr[0]=t0r; - yi[0]=t0i; + yr[0] = t0r; + yi[0] = t0i; // y[sy]=t1; - yr[2*sy]=t1r; - yi[2*sy]=t1i; + yr[2 * sy] = t1r; + yi[2 * sy] = t1i; return; } - if (N==4) { + if( N == 4 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r, t2r, t3r; register minfft_real t0i, t1i, t2i, t3i; // t0=x[0]+x[2]; - t0r=xr[0]+xr[4]; - t0i=xi[0]+xi[4]; + t0r = xr[0] + xr[4]; + t0i = xi[0] + xi[4]; // t1=x[1]+x[3]; - t1r=xr[2]+xr[6]; - t1i=xi[2]+xi[6]; + t1r = xr[2] + xr[6]; + t1i = xi[2] + xi[6]; // t2=x[0]-x[2]; - t2r=xr[0]-xr[4]; - t2i=xi[0]-xi[4]; + t2r = xr[0] - xr[4]; + t2i = xi[0] - xi[4]; // t3=I*(x[1]-x[3]); - t3r=-xi[2]+xi[6]; - t3i=xr[2]-xr[6]; + t3r = -xi[2] + xi[6]; + t3i = xr[2] - xr[6]; // y[0]=t0+t1; - yr[0]=t0r+t1r; - yi[0]=t0i+t1i; + yr[0] = t0r + t1r; + yi[0] = t0i + t1i; // y[sy]=t2-t3; - yr[2*sy]=t2r-t3r; - yi[2*sy]=t2i-t3i; + yr[2 * sy] = t2r - t3r; + yi[2 * sy] = t2i - t3i; // y[2*sy]=t0-t1; - yr[4*sy]=t0r-t1r; - yi[4*sy]=t0i-t1i; + yr[4 * sy] = t0r - t1r; + yi[4 * sy] = t0i - t1i; // y[3*sy]=t2+t3; - yr[6*sy]=t2r+t3r; - yi[6*sy]=t2i+t3i; + yr[6 * sy] = t2r + t3r; + yi[6 * sy] = t2i + t3i; return; } - if (N==8) { + if( N == 8 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r, t2r, t3r; register minfft_real t0i, t1i, t2i, t3i; register minfft_real t00r, t01r, t02r, t03r; @@ -146,219 +138,215 @@ rs_dft_1d (int N, minfft_cmpl *x, minfft_cmpl *t, minfft_cmpl *y, int sy, const register minfft_real t10i, t11i, t12i, t13i; register minfft_real ttr, tti; // t0=x[0]+x[4]; - t0r=xr[0]+xr[8]; - t0i=xi[0]+xi[8]; + t0r = xr[0] + xr[8]; + t0i = xi[0] + xi[8]; // t1=x[2]+x[6]; - t1r=xr[4]+xr[12]; - t1i=xi[4]+xi[12]; + t1r = xr[4] + xr[12]; + t1i = xi[4] + xi[12]; // t2=x[0]-x[4]; - t2r=xr[0]-xr[8]; - t2i=xi[0]-xi[8]; + t2r = xr[0] - xr[8]; + t2i = xi[0] - xi[8]; // t3=I*(x[2]-x[6]); - t3r=-xi[4]+xi[12]; - t3i=xr[4]-xr[12]; + t3r = -xi[4] + xi[12]; + t3i = xr[4] - xr[12]; // t00=t0+t1; - t00r=t0r+t1r; - t00i=t0i+t1i; + t00r = t0r + t1r; + t00i = t0i + t1i; // t01=t2-t3; - t01r=t2r-t3r; - t01i=t2i-t3i; + t01r = t2r - t3r; + t01i = t2i - t3i; // t02=t0-t1; - t02r=t0r-t1r; - t02i=t0i-t1i; + t02r = t0r - t1r; + t02i = t0i - t1i; // t03=t2+t3; - t03r=t2r+t3r; - t03i=t2i+t3i; + t03r = t2r + t3r; + t03i = t2i + t3i; // t0=x[1]+x[5]; - t0r=xr[2]+xr[10]; - t0i=xi[2]+xi[10]; + t0r = xr[2] + xr[10]; + t0i = xi[2] + xi[10]; // t1=x[3]+x[7]; - t1r=xr[6]+xr[14]; - t1i=xi[6]+xi[14]; + t1r = xr[6] + xr[14]; + t1i = xi[6] + xi[14]; // t2=x[1]-x[5]; - t2r=xr[2]-xr[10]; - t2i=xi[2]-xi[10]; + t2r = xr[2] - xr[10]; + t2i = xi[2] - xi[10]; // t3=I*(x[3]-x[7]); - t3r=-xi[6]+xi[14]; - t3i=xr[6]-xr[14]; + t3r = -xi[6] + xi[14]; + t3i = xr[6] - xr[14]; // t10=t0+t1; - t10r=t0r+t1r; - t10i=t0i+t1i; + t10r = t0r + t1r; + t10i = t0i + t1i; // t11=(t2-t3)*invsqrt2*(1-I); - ttr=t2r-t3r; - tti=t2i-t3i; - t11r=invsqrt2*(ttr+tti); - t11i=invsqrt2*(tti-ttr); + ttr = t2r - t3r; + tti = t2i - t3i; + t11r = invsqrt2 * ( ttr + tti ); + t11i = invsqrt2 * ( tti - ttr ); // t12=(t0-t1)*(-I); - t12r=t0i-t1i; - t12i=-t0r+t1r; + t12r = t0i - t1i; + t12i = -t0r + t1r; // t13=(t2+t3)*invsqrt2*(-1-I); - ttr=t2r+t3r; - tti=t2i+t3i; - t13r=invsqrt2*(tti-ttr); - t13i=-invsqrt2*(tti+ttr); + ttr = t2r + t3r; + tti = t2i + t3i; + t13r = invsqrt2 * ( tti - ttr ); + t13i = -invsqrt2 * ( tti + ttr ); // y[0]=t00+t10; - yr[0]=t00r+t10r; - yi[0]=t00i+t10i; + yr[0] = t00r + t10r; + yi[0] = t00i + t10i; // y[sy]=t01+t11; - yr[2*sy]=t01r+t11r; - yi[2*sy]=t01i+t11i; + yr[2 * sy] = t01r + t11r; + yi[2 * sy] = t01i + t11i; // y[2*sy]=t02+t12; - yr[4*sy]=t02r+t12r; - yi[4*sy]=t02i+t12i; + yr[4 * sy] = t02r + t12r; + yi[4 * sy] = t02i + t12i; // y[3*sy]=t03+t13; - yr[6*sy]=t03r+t13r; - yi[6*sy]=t03i+t13i; + yr[6 * sy] = t03r + t13r; + yi[6 * sy] = t03i + t13i; // y[4*sy]=t00-t10; - yr[8*sy]=t00r-t10r; - yi[8*sy]=t00i-t10i; + yr[8 * sy] = t00r - t10r; + yi[8 * sy] = t00i - t10i; // y[5*sy]=t01-t11; - yr[10*sy]=t01r-t11r; - yi[10*sy]=t01i-t11i; + yr[10 * sy] = t01r - t11r; + yi[10 * sy] = t01i - t11i; // y[6*sy]=t02-t12; - yr[12*sy]=t02r-t12r; - yi[12*sy]=t02i-t12i; + yr[12 * sy] = t02r - t12r; + yi[12 * sy] = t02i - t12i; // y[7*sy]=t03-t13; - yr[14*sy]=t03r-t13r; - yi[14*sy]=t03i-t13i; + yr[14 * sy] = t03r - t13r; + yi[14 * sy] = t03i - t13i; return; } // recursion - minfft_real *xr=(minfft_real*)x, *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *xi=xr+1, *ti=tr+1, *ei=er+1; + minfft_real *xr = (minfft_real*) x, *tr = (minfft_real*) t, *er = (minfft_real*) e; + minfft_real *xi = xr + 1, *ti = tr + 1, *ei = er + 1; // prepare sub-transform inputs int loopCount = N / 4; - for (n=0; nN, x, a->t, y, sy, a->e); +inline static void s_dft_1d( minfft_cmpl* x, minfft_cmpl* y, int sy, const minfft_aux* a ) { + rs_dft_1d( a->N, x, a->t, y, sy, a->e ); } // strided DFT of arbitrary dimension -inline static void -s_dft (minfft_cmpl *x, minfft_cmpl *y, int sy, const minfft_aux *a) { +inline static void s_dft( minfft_cmpl* x, minfft_cmpl* y, int sy, const minfft_aux* a ) { // volatile int* rev = 0xDEADBEEF; // *rev = 0x0CCC0003; - mkcx(x, y, sy, a, s_dft_1d); + mkcx( x, y, sy, a, s_dft_1d ); } // user interface -void -minfft_dft (minfft_cmpl *x, minfft_cmpl *y, const minfft_aux *a) { +void minfft_dft( minfft_cmpl* x, minfft_cmpl* y, const minfft_aux* a ) { // volatile int* rev = 0xDEADBEEF; // *rev = 0x0CCC0002; - s_dft(x, y, 1, a); + s_dft( x, y, 1, a ); } // recursive strided one-dimensional inverse DFT -inline static void -rs_invdft_1d (int N, minfft_cmpl *x, minfft_cmpl *t, minfft_cmpl *y, int sy, const minfft_cmpl *e) { - int n; // counter +inline static void rs_invdft_1d( int N, minfft_cmpl* x, minfft_cmpl* t, minfft_cmpl* y, int sy, const minfft_cmpl* e ) { + int n; // counter // split-radix DIF - if (N==1) { + if( N == 1 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real *xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real *xi = xr + 1, *yi = yr + 1; // y[0]=x[0]; - yr[0]=xr[0]; - yi[0]=xi[0]; + yr[0] = xr[0]; + yi[0] = xi[0]; return; } - if (N==2) { + if( N == 2 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r; register minfft_real t0i, t1i; // t0=x[0]+x[1]; - t0r=xr[0]+xr[2]; - t0i=xi[0]+xi[2]; + t0r = xr[0] + xr[2]; + t0i = xi[0] + xi[2]; // t1=x[0]-x[1]; - t1r=xr[0]-xr[2]; - t1i=xi[0]-xi[2]; + t1r = xr[0] - xr[2]; + t1i = xi[0] - xi[2]; // y[0]=t0; - yr[0]=t0r; - yi[0]=t0i; + yr[0] = t0r; + yi[0] = t0i; // y[sy]=t1; - yr[2*sy]=t1r; - yi[2*sy]=t1i; + yr[2 * sy] = t1r; + yi[2 * sy] = t1i; return; } - if (N==4) { + if( N == 4 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r, t2r, t3r; register minfft_real t0i, t1i, t2i, t3i; // t0=x[0]+x[2]; - t0r=xr[0]+xr[4]; - t0i=xi[0]+xi[4]; + t0r = xr[0] + xr[4]; + t0i = xi[0] + xi[4]; // t1=x[1]+x[3]; - t1r=xr[2]+xr[6]; - t1i=xi[2]+xi[6]; + t1r = xr[2] + xr[6]; + t1i = xi[2] + xi[6]; // t2=x[0]-x[2]; - t2r=xr[0]-xr[4]; - t2i=xi[0]-xi[4]; + t2r = xr[0] - xr[4]; + t2i = xi[0] - xi[4]; // t3=I*(x[1]-x[3]); - t3r=-xi[2]+xi[6]; - t3i=xr[2]-xr[6]; + t3r = -xi[2] + xi[6]; + t3i = xr[2] - xr[6]; // y[0]=t0+t1; - yr[0]=t0r+t1r; - yi[0]=t0i+t1i; + yr[0] = t0r + t1r; + yi[0] = t0i + t1i; // y[sy]=t2+t3; - yr[2*sy]=t2r+t3r; - yi[2*sy]=t2i+t3i; + yr[2 * sy] = t2r + t3r; + yi[2 * sy] = t2i + t3i; // y[2*sy]=t0-t1; - yr[4*sy]=t0r-t1r; - yi[4*sy]=t0i-t1i; + yr[4 * sy] = t0r - t1r; + yi[4 * sy] = t0i - t1i; // y[3*sy]=t2-t3; - yr[6*sy]=t2r-t3r; - yi[6*sy]=t2i-t3i; + yr[6 * sy] = t2r - t3r; + yi[6 * sy] = t2i - t3i; return; } - if (N==8) { + if( N == 8 ) { // terminal case - minfft_real *xr=(minfft_real*)x, *yr=(minfft_real*)y; - minfft_real *xi=xr+1, *yi=yr+1; + minfft_real * xr = (minfft_real*) x, *yr = (minfft_real*) y; + minfft_real * xi = xr + 1, *yi = yr + 1; register minfft_real t0r, t1r, t2r, t3r; register minfft_real t0i, t1i, t2i, t3i; register minfft_real t00r, t01r, t02r, t03r; @@ -367,608 +355,583 @@ rs_invdft_1d (int N, minfft_cmpl *x, minfft_cmpl *t, minfft_cmpl *y, int sy, con register minfft_real t10i, t11i, t12i, t13i; register minfft_real ttr, tti; // t0=x[0]+x[4]; - t0r=xr[0]+xr[8]; - t0i=xi[0]+xi[8]; + t0r = xr[0] + xr[8]; + t0i = xi[0] + xi[8]; // t1=x[2]+x[6]; - t1r=xr[4]+xr[12]; - t1i=xi[4]+xi[12]; + t1r = xr[4] + xr[12]; + t1i = xi[4] + xi[12]; // t2=x[0]-x[4]; - t2r=xr[0]-xr[8]; - t2i=xi[0]-xi[8]; + t2r = xr[0] - xr[8]; + t2i = xi[0] - xi[8]; // t3=I*(x[2]-x[6]); - t3r=-xi[4]+xi[12]; - t3i=xr[4]-xr[12]; + t3r = -xi[4] + xi[12]; + t3i = xr[4] - xr[12]; // t00=t0+t1; - t00r=t0r+t1r; - t00i=t0i+t1i; + t00r = t0r + t1r; + t00i = t0i + t1i; // t01=t2+t3; - t01r=t2r+t3r; - t01i=t2i+t3i; + t01r = t2r + t3r; + t01i = t2i + t3i; // t02=t0-t1; - t02r=t0r-t1r; - t02i=t0i-t1i; + t02r = t0r - t1r; + t02i = t0i - t1i; // t03=t2-t3; - t03r=t2r-t3r; - t03i=t2i-t3i; + t03r = t2r - t3r; + t03i = t2i - t3i; // t0=x[1]+x[5]; - t0r=xr[2]+xr[10]; - t0i=xi[2]+xi[10]; + t0r = xr[2] + xr[10]; + t0i = xi[2] + xi[10]; // t1=x[3]+x[7]; - t1r=xr[6]+xr[14]; - t1i=xi[6]+xi[14]; + t1r = xr[6] + xr[14]; + t1i = xi[6] + xi[14]; // t2=x[1]-x[5]; - t2r=xr[2]-xr[10]; - t2i=xi[2]-xi[10]; + t2r = xr[2] - xr[10]; + t2i = xi[2] - xi[10]; // t3=I*(x[3]-x[7]); - t3r=-xi[6]+xi[14]; - t3i=xr[6]-xr[14]; + t3r = -xi[6] + xi[14]; + t3i = xr[6] - xr[14]; // t10=t0+t1; - t10r=t0r+t1r; - t10i=t0i+t1i; + t10r = t0r + t1r; + t10i = t0i + t1i; // t11=(t2+t3)*invsqrt2*(1+I); - ttr=t2r+t3r; - tti=t2i+t3i; - t11r=invsqrt2*(ttr-tti); - t11i=invsqrt2*(ttr+tti); + ttr = t2r + t3r; + tti = t2i + t3i; + t11r = invsqrt2 * ( ttr - tti ); + t11i = invsqrt2 * ( ttr + tti ); // t12=(t0-t1)*I; - t12r=-t0i+t1i; - t12i=t0r-t1r; + t12r = -t0i + t1i; + t12i = t0r - t1r; // t13=(t2-t3)*invsqrt2*(-1+I); - ttr=t2r-t3r; - tti=t2i-t3i; - t13r=-invsqrt2*(ttr+tti); - t13i=invsqrt2*(ttr-tti); + ttr = t2r - t3r; + tti = t2i - t3i; + t13r = -invsqrt2 * ( ttr + tti ); + t13i = invsqrt2 * ( ttr - tti ); // y[0]=t00+t10; - yr[0]=t00r+t10r; - yi[0]=t00i+t10i; + yr[0] = t00r + t10r; + yi[0] = t00i + t10i; // y[sy]=t01+t11; - yr[2*sy]=t01r+t11r; - yi[2*sy]=t01i+t11i; + yr[2 * sy] = t01r + t11r; + yi[2 * sy] = t01i + t11i; // y[2*sy]=t02+t12; - yr[4*sy]=t02r+t12r; - yi[4*sy]=t02i+t12i; + yr[4 * sy] = t02r + t12r; + yi[4 * sy] = t02i + t12i; // y[3*sy]=t03+t13; - yr[6*sy]=t03r+t13r; - yi[6*sy]=t03i+t13i; + yr[6 * sy] = t03r + t13r; + yi[6 * sy] = t03i + t13i; // y[4*sy]=t00-t10; - yr[8*sy]=t00r-t10r; - yi[8*sy]=t00i-t10i; + yr[8 * sy] = t00r - t10r; + yi[8 * sy] = t00i - t10i; // y[5*sy]=t01-t11; - yr[10*sy]=t01r-t11r; - yi[10*sy]=t01i-t11i; + yr[10 * sy] = t01r - t11r; + yi[10 * sy] = t01i - t11i; // y[6*sy]=t02-t12; - yr[12*sy]=t02r-t12r; - yi[12*sy]=t02i-t12i; + yr[12 * sy] = t02r - t12r; + yi[12 * sy] = t02i - t12i; // y[7*sy]=t03-t13; - yr[14*sy]=t03r-t13r; - yi[14*sy]=t03i-t13i; + yr[14 * sy] = t03r - t13r; + yi[14 * sy] = t03i - t13i; return; } // recursion - minfft_real *xr=(minfft_real*)x, *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *xi=xr+1, *ti=tr+1, *ei=er+1; + minfft_real *xr = (minfft_real*) x, *tr = (minfft_real*) t, *er = (minfft_real*) e; + minfft_real *xi = xr + 1, *ti = tr + 1, *ei = er + 1; // prepare sub-transform inputs - for (n=0; nN, x, a->t, y, sy, a->e); +inline static void s_invdft_1d( minfft_cmpl* x, minfft_cmpl* y, int sy, const minfft_aux* a ) { + rs_invdft_1d( a->N, x, a->t, y, sy, a->e ); } // strided inverse DFT of arbitrary dimension -inline static void -s_invdft (minfft_cmpl *x, minfft_cmpl *y, int sy, const minfft_aux *a) { - mkcx(x, y, sy, a, s_invdft_1d); +inline static void s_invdft( minfft_cmpl* x, minfft_cmpl* y, int sy, const minfft_aux* a ) { + mkcx( x, y, sy, a, s_invdft_1d ); } // user interface -void -minfft_invdft (minfft_cmpl *x, minfft_cmpl *y, const minfft_aux *a) { - s_invdft(x, y, 1, a); +void minfft_invdft( minfft_cmpl* x, minfft_cmpl* y, const minfft_aux* a ) { + s_invdft( x, y, 1, a ); } // *** real transforms *** // strided one-dimensional real DFT -inline static void -s_realdft_1d (minfft_real *x, minfft_cmpl *z, int sz, const minfft_aux *a) { - int n; // counter - int N=a->N; // transform length - minfft_cmpl *e=a->e; // exponent vector - minfft_cmpl *w=(minfft_cmpl*)x; // alias - minfft_cmpl *t=a->t; // temporary buffer - minfft_real *zr=(minfft_real*)z; - minfft_real *zi=zr+1; - if (N==1) { +inline static void s_realdft_1d( minfft_real* x, minfft_cmpl* z, int sz, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* e = a->e; // exponent vector + minfft_cmpl* w = (minfft_cmpl*) x; // alias + minfft_cmpl* t = a->t; // temporary buffer + minfft_real* zr = (minfft_real*) z; + minfft_real* zi = zr + 1; + if( N == 1 ) { // trivial case - zr[0]=x[0]; - zi[0]=0; + zr[0] = x[0]; + zi[0] = 0; return; } - if (N==2) { + if( N == 2 ) { // trivial case register minfft_real t0, t1; - t0=x[0]; - t1=x[1]; + t0 = x[0]; + t1 = x[1]; // z[0]=t0+t1; - zr[0]=t0+t1; - zi[0]=0; + zr[0] = t0 + t1; + zi[0] = 0; // z[sz]=t0-t1; - zr[2*sz]=t0-t1; - zi[2*sz]=0; + zr[2 * sz] = t0 - t1; + zi[2 * sz] = 0; return; } // reduce to complex DFT of length N/2 // do complex DFT - s_dft_1d(w, t, 1, a->sub1); + s_dft_1d( w, t, 1, a->sub1 ); // recover results register minfft_real ur, vr; register minfft_real ui, vi; - minfft_real *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *ti=tr+1, *ei=er+1; + minfft_real * tr = (minfft_real*) t, *er = (minfft_real*) e; + minfft_real * ti = tr + 1, *ei = er + 1; // u=t[0]; - ur=tr[0]; - ui=ti[0]; + ur = tr[0]; + ui = ti[0]; // z[0]=creal(u)+cimag(u); - zr[0]=ur+ui; - zi[0]=0; + zr[0] = ur + ui; + zi[0] = 0; // z[sz*N/2]=creal(u)-cimag(u); - zr[sz*N]=ur-ui; - zi[sz*N]=0; - for (n=1; nsub2==NULL) - s_realdft_1d(x, z, 1, a); +void minfft_realdft( minfft_real* x, minfft_cmpl* z, const minfft_aux* a ) { + if( a->sub2 == NULL ) + s_realdft_1d( x, z, 1, a ); else { - int N1=a->sub1->N, N2=a->sub2->N; // transform lengths - int n; // counter - minfft_cmpl *t=a->t; // temporary buffer + int N1 = a->sub1->N, N2 = a->sub2->N; // transform lengths + int n; // counter + minfft_cmpl* t = a->t; // temporary buffer // strided real DFT of contiguous rows - for (n=0; nsub1); + for( n = 0; n < N2; ++n ) + s_realdft_1d( x + n * N1, t + n, N2, a->sub1 ); // strided complex DFT of contiguous hyperplanes - for (n=0; nsub2); + for( n = 0; n < N1 / 2 + 1; ++n ) + s_dft( t + n * N2, z + n, N1 / 2 + 1, a->sub2 ); } } // one-dimensional inverse real DFT -inline static void -invrealdft_1d (minfft_cmpl *z, minfft_real *y, const minfft_aux *a) { - int n; // counter - int N=a->N; // transform length - minfft_cmpl *e=a->e; // exponent vector - minfft_cmpl *w=(minfft_cmpl*)y; // alias - minfft_cmpl *t=a->t; // temporary buffer - minfft_real *zr=(minfft_real*)z; - minfft_real *zi=zr+1; - if (N==1) { +inline static void invrealdft_1d( minfft_cmpl* z, minfft_real* y, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* e = a->e; // exponent vector + minfft_cmpl* w = (minfft_cmpl*) y; // alias + minfft_cmpl* t = a->t; // temporary buffer + minfft_real* zr = (minfft_real*) z; + minfft_real* zi = zr + 1; + if( N == 1 ) { // trivial case - y[0]=zr[0]; + y[0] = zr[0]; return; } - if (N==2) { + if( N == 2 ) { // trivial case - register minfft_real t0, t1; // temporary values - t0=zr[0]; - t1=zr[2]; - y[0]=t0+t1; - y[1]=t0-t1; + register minfft_real t0, t1; // temporary values + t0 = zr[0]; + t1 = zr[2]; + y[0] = t0 + t1; + y[1] = t0 - t1; return; } // reduce to inverse complex DFT of length N/2 // prepare complex DFT inputs - minfft_real *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *ti=tr+1, *ei=er+1; + minfft_real *tr = (minfft_real*) t, *er = (minfft_real*) e; + minfft_real *ti = tr + 1, *ei = er + 1; // t[0]=(z[0]+z[N/2])+I*(z[0]-z[N/2]); - tr[0]=zr[0]+zr[N]; - ti[0]=zr[0]-zr[N]; - for (n=1; nsub1); + s_invdft_1d( t, w, 1, a->sub1 ); } // inverse real DFT of arbitrary dimension -void -minfft_invrealdft (minfft_cmpl *z, minfft_real *y, const minfft_aux *a) { - if (a->sub2==NULL) - invrealdft_1d(z, y, a); +void minfft_invrealdft( minfft_cmpl* z, minfft_real* y, const minfft_aux* a ) { + if( a->sub2 == NULL ) + invrealdft_1d( z, y, a ); else { - int N1=a->sub1->N, N2=a->sub2->N; // transform lengths - int n; // counter - minfft_cmpl *t=a->t; // temporary buffer - minfft_real *zr=(minfft_real*)z, *tr=(minfft_real*)t; - minfft_real *zi=zr+1, *ti=tr+1; - int k; + int N1 = a->sub1->N, N2 = a->sub2->N; // transform lengths + int n; // counter + minfft_cmpl* t = a->t; // temporary buffer + minfft_real *zr = (minfft_real*) z, *tr = (minfft_real*) t; + minfft_real *zi = zr + 1, *ti = tr + 1; + int k; // transpose - for (n=0; nsub2); + for( n = 0; n < N1 / 2 + 1; ++n ) + s_invdft( t + n * N2, z + n, N1 / 2 + 1, a->sub2 ); // inverse real DFT of contiguous rows - for (n=0; nsub1); + for( n = 0; n < N2; ++n ) + invrealdft_1d( z + n * ( N1 / 2 + 1 ), y + n * N1, a->sub1 ); } } // *** real symmetric transforms *** // strided one-dimensional DCT-2 -inline static void -s_dct2_1d (minfft_real *x, minfft_real *y, int sy, const minfft_aux *a) { - int n; // counter - int N=a->N; // transform length - minfft_real *t=a->t; // temporary buffer - minfft_cmpl *z=(minfft_cmpl*)t; // its alias - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dct2_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_real* t = a->t; // temporary buffer + minfft_cmpl* z = (minfft_cmpl*) t; // its alias + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=2*x[0]; + y[0] = 2 * x[0]; return; } // reduce to real DFT of length N // prepare sub-transform inputs - for (n=0; nsub1); + s_realdft_1d( t, z, 1, a->sub1 ); // recover results - minfft_real *er=(minfft_real*)e; - minfft_real *ei=er+1; + minfft_real* er = (minfft_real*) e; + minfft_real* ei = er + 1; // y[0]=2*creal(z[0]); - y[0]=2*t[0]; - for (n=1; nN; // transform length - minfft_real *t=a->t; // temporary buffer - minfft_cmpl *z=(minfft_cmpl*)t; // its alias - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dst2_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_real* t = a->t; // temporary buffer + minfft_cmpl* z = (minfft_cmpl*) t; // its alias + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=2*x[0]; + y[0] = 2 * x[0]; return; } // reduce to real DFT of length N // prepare sub-transform inputs - for (n=0; nsub1); + s_realdft_1d( t, z, 1, a->sub1 ); // recover results - minfft_real *er=(minfft_real*)e; - minfft_real *ei=er+1; + minfft_real* er = (minfft_real*) e; + minfft_real* ei = er + 1; // y[sy*(N-1)]=2*creal(z[0]); - y[sy*(N-1)]=2*t[0]; - for (n=1; nN; // transform length - minfft_cmpl *z=a->t; // temporary buffer - minfft_real *t=(minfft_real*)z; // its alias - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dct3_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* z = a->t; // temporary buffer + minfft_real* t = (minfft_real*) z; // its alias + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=x[0]; + y[0] = x[0]; return; } // reduce to inverse real DFT of length N // prepare sub-transform inputs - minfft_real *er=(minfft_real*)e, *zr=(minfft_real*)z; - minfft_real *ei=er+1, *zi=zr+1; + minfft_real *er = (minfft_real*) e, *zr = (minfft_real*) z; + minfft_real *ei = er + 1, *zi = zr + 1; // z[0]=x[0]; - zr[0]=x[0]; - zi[0]=0; - for (n=1; nsub1); + invrealdft_1d( z, t, a->sub1 ); // recover results - for (n=0; nN; // transform length - minfft_cmpl *z=a->t; // temporary buffer - minfft_real *t=(minfft_real*)z; // its alias - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dst3_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* z = a->t; // temporary buffer + minfft_real* t = (minfft_real*) z; // its alias + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=x[0]; + y[0] = x[0]; return; } // reduce to inverse real DFT of length N // prepare sub-transform inputs - minfft_real *er=(minfft_real*)e, *zr=(minfft_real*)z; - minfft_real *ei=er+1, *zi=zr+1; + minfft_real *er = (minfft_real*) e, *zr = (minfft_real*) z; + minfft_real *ei = er + 1, *zi = zr + 1; // z[0]=x[N-1]; - zr[0]=x[N-1]; - zi[0]=0; - for (n=1; nsub1); + invrealdft_1d( z, t, a->sub1 ); // recover results - for (n=0; nN; // transform length - minfft_cmpl *t=a->t; // temporary buffer - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dct4_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* t = a->t; // temporary buffer + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=sqrt2*x[0]; + y[0] = sqrt2 * x[0]; return; } // reduce to complex DFT of length N/2 // prepare sub-transform inputs - minfft_real *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *ti=tr+1, *ei=er+1; - for (n=0; nsub1); + s_dft_1d( t, t, 1, a->sub1 ); // recover results - er+=N; - ei+=N; - for (n=0; nN; // transform length - minfft_cmpl *t=a->t; // temporary buffer - minfft_cmpl *e=a->e; // exponent vector - if (N==1) { +inline static void s_dst4_1d( minfft_real* x, minfft_real* y, int sy, const minfft_aux* a ) { + int n; // counter + int N = a->N; // transform length + minfft_cmpl* t = a->t; // temporary buffer + minfft_cmpl* e = a->e; // exponent vector + if( N == 1 ) { // trivial case - y[0]=sqrt2*x[0]; + y[0] = sqrt2 * x[0]; return; } // reduce to complex DFT of length N/2 // prepare sub-transform inputs - minfft_real *tr=(minfft_real*)t, *er=(minfft_real*)e; - minfft_real *ti=tr+1, *ei=er+1; - for (n=0; nsub1); + s_dft_1d( t, t, 1, a->sub1 ); // recover results - er+=N; - ei+=N; - for (n=0; n=N/2) - return -ncos(n-N/2, N); - else if (n>=N/4) - return -nsin(n-N/4, N); - else if (n>N/8) - return nsin(N/4-n, N); + if( n < 0 ) + return ncos( -n, N ); + else if( n >= N / 2 ) + return -ncos( n - N / 2, N ); + else if( n >= N / 4 ) + return -nsin( n - N / 4, N ); + else if( n > N / 8 ) + return nsin( N / 4 - n, N ); else #if MINFFT_SINGLE - return cosf(2*pi*n/N); + return cosf( 2 * pi * n / N ); #elif MINFFT_EXTENDED - return cosl(2*pi*n/N); + return cosl( 2 * pi * n / N ); #else - return cos(2*pi*n/N); + return cos( 2 * pi * n / N ); #endif } // sin(2*pi*n/N) -static minfft_real -nsin (int n, int N) { +static minfft_real nsin( int n, int N ) { // reduce n to 0..N/8 - if (n<0) - return -nsin(-n, N); - else if (n>=N/2) - return -nsin(n-N/2, N); - else if (n>=N/4) - return ncos(n-N/4, N); - else if (n>N/8) - return ncos(N/4-n, N); + if( n < 0 ) + return -nsin( -n, N ); + else if( n >= N / 2 ) + return -nsin( n - N / 2, N ); + else if( n >= N / 4 ) + return ncos( n - N / 4, N ); + else if( n > N / 8 ) + return ncos( N / 4 - n, N ); else #if MINFFT_SINGLE - return sinf(2*pi*n/N); + return sinf( 2 * pi * n / N ); #elif MINFFT_EXTENDED - return sinl(2*pi*n/N); + return sinl( 2 * pi * n / N ); #else - return sin(2*pi*n/N); + return sin( 2 * pi * n / N ); #endif } // make aux data for any transform of arbitrary dimension // using its one-dimensional version -static minfft_aux* -make_aux (int d, int *Ns, int datasz, minfft_aux* (*aux_1d)(int N)) { - minfft_aux *a; - int p; // product of all transform lengths - int i; // array index - if (d==1) - return (*aux_1d)(Ns[0]); +static minfft_aux* make_aux( int d, int* Ns, int datasz, minfft_aux* ( *aux_1d )( int N ) ) { + minfft_aux* a; + int p; // product of all transform lengths + int i; // array index + if( d == 1 ) + return ( *aux_1d )( Ns[0] ); else { - p=1; - for (i=0; iN=p; - a->t=malloc(p*datasz); - if (a->t==NULL) + a->N = p; + a->t = malloc( p * datasz ); + if( a->t == NULL ) goto err; - a->e=NULL; - a->sub1=make_aux(d-1, Ns+1, datasz, aux_1d); - if (a->sub1==NULL) + a->e = NULL; + a->sub1 = make_aux( d - 1, Ns + 1, datasz, aux_1d ); + if( a->sub1 == NULL ) goto err; - a->sub2=(*aux_1d)(Ns[0]); - if (a->sub2==NULL) + a->sub2 = ( *aux_1d )( Ns[0] ); + if( a->sub2 == NULL ) goto err; return a; } - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // make aux data for one-dimensional forward or inverse complex DFT -minfft_aux* -minfft_mkaux_dft_1d (int N) { - minfft_aux *a; - int n; - minfft_real *e; - if (N<=0 || N&(N-1)) +minfft_aux* minfft_mkaux_dft_1d( int N ) { + minfft_aux* a; + int n; + minfft_real* e; + if( N <= 0 || N & ( N - 1 ) ) // error if N is negative or not a power of two return NULL; - a=malloc(sizeof(minfft_aux)); - if (a==NULL) + a = malloc( sizeof( minfft_aux ) ); + if( a == NULL ) goto err; - a->N=N; - if (N>=16) { - a->t=malloc(N*sizeof(minfft_cmpl)); - if (a->t==NULL) + a->N = N; + if( N >= 16 ) { + a->t = malloc( N * sizeof( minfft_cmpl ) ); + if( a->t == NULL ) goto err; - a->e=malloc(N*sizeof(minfft_cmpl)); - if (a->e==NULL) + a->e = malloc( N * sizeof( minfft_cmpl ) ); + if( a->e == NULL ) goto err; - e=(minfft_real*)a->e; - while (N>=16) { - for (n=0; ne; + while( N >= 16 ) { + for( n = 0; n < N / 4; ++n ) { + *e++ = ncos( -n, N ); + *e++ = nsin( -n, N ); + *e++ = ncos( -3 * n, N ); + *e++ = nsin( -3 * n, N ); } - N/=2; + N /= 2; } } else { - a->t=NULL; - a->e=NULL; + a->t = NULL; + a->e = NULL; } - a->sub1=a->sub2=NULL; + a->sub1 = a->sub2 = NULL; return a; - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // make aux data for any-dimensional forward or inverse complex DFT -minfft_aux* -minfft_mkaux_dft (int d, int *Ns) { - return make_aux(d, Ns, sizeof(minfft_cmpl), minfft_mkaux_dft_1d); +minfft_aux* minfft_mkaux_dft( int d, int* Ns ) { + return make_aux( d, Ns, sizeof( minfft_cmpl ), minfft_mkaux_dft_1d ); } // convenience routines for two- and three-dimensional complex DFT -minfft_aux* -minfft_mkaux_dft_2d (int N1, int N2) { - int Ns[2]={N1, N2}; - return minfft_mkaux_dft(2, Ns); +minfft_aux* minfft_mkaux_dft_2d( int N1, int N2 ) { + int Ns[2] = { N1, N2 }; + return minfft_mkaux_dft( 2, Ns ); } -minfft_aux* -minfft_mkaux_dft_3d (int N1, int N2, int N3) { - int Ns[3]={N1, N2, N3}; - return minfft_mkaux_dft(3, Ns); + +minfft_aux* minfft_mkaux_dft_3d( int N1, int N2, int N3 ) { + int Ns[3] = { N1, N2, N3 }; + return minfft_mkaux_dft( 3, Ns ); } // make aux data for one-dimensional forward or inverse real DFT -minfft_aux* -minfft_mkaux_realdft_1d (int N) { - minfft_aux *a; - int n; - minfft_real *e; - if (N<=0 || N&(N-1)) +minfft_aux* minfft_mkaux_realdft_1d( int N ) { + minfft_aux* a; + int n; + minfft_real* e; + if( N <= 0 || N & ( N - 1 ) ) // error if N is negative or not a power of two return NULL; - a=malloc(sizeof(minfft_aux)); - if (a==NULL) + a = malloc( sizeof( minfft_aux ) ); + if( a == NULL ) goto err; - a->N=N; - if (N>=4) { - a->t=malloc((N/2)*sizeof(minfft_cmpl)); - if (a->t==NULL) + a->N = N; + if( N >= 4 ) { + a->t = malloc( ( N / 2 ) * sizeof( minfft_cmpl ) ); + if( a->t == NULL ) goto err; - a->e=malloc((N/4)*sizeof(minfft_cmpl)); - if (a->e==NULL) + a->e = malloc( ( N / 4 ) * sizeof( minfft_cmpl ) ); + if( a->e == NULL ) goto err; - e=(minfft_real*)a->e; - for (n=0; ne; + for( n = 0; n < N / 4; ++n ) { + *e++ = ncos( -n, N ); + *e++ = nsin( -n, N ); } - a->sub1=minfft_mkaux_dft_1d(N/2); + a->sub1 = minfft_mkaux_dft_1d( N / 2 ); } else { - a->t=NULL; - a->e=NULL; - a->sub1=NULL; + a->t = NULL; + a->e = NULL; + a->sub1 = NULL; } - a->sub2=NULL; + a->sub2 = NULL; return a; - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // make aux data for any-dimensional real DFT -minfft_aux* -minfft_mkaux_realdft (int d, int *Ns) { - minfft_aux *a; - int p; // product of transform lengths - int i; // array index - if (d==1) - return minfft_mkaux_realdft_1d(Ns[0]); +minfft_aux* minfft_mkaux_realdft( int d, int* Ns ) { + minfft_aux* a; + int p; // product of transform lengths + int i; // array index + if( d == 1 ) + return minfft_mkaux_realdft_1d( Ns[0] ); else { - p=1; - for (i=0; iN=Ns[d-1]*p; - a->t=malloc((Ns[d-1]/2+1)*p*sizeof(minfft_cmpl)); - if (a->t==NULL) + a->N = Ns[d - 1] * p; + a->t = malloc( ( Ns[d - 1] / 2 + 1 ) * p * sizeof( minfft_cmpl ) ); + if( a->t == NULL ) goto err; - a->e=NULL; - a->sub1=minfft_mkaux_realdft_1d(Ns[d-1]); - if (a->sub1==NULL) + a->e = NULL; + a->sub1 = minfft_mkaux_realdft_1d( Ns[d - 1] ); + if( a->sub1 == NULL ) goto err; - a->sub2=minfft_mkaux_dft(d-1, Ns); - if (a->sub2==NULL) + a->sub2 = minfft_mkaux_dft( d - 1, Ns ); + if( a->sub2 == NULL ) goto err; return a; } - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // convenience routines for two- and three-dimensional real DFT -minfft_aux* -minfft_mkaux_realdft_2d (int N1, int N2) { - int Ns[2]={N1, N2}; - return minfft_mkaux_realdft(2, Ns); +minfft_aux* minfft_mkaux_realdft_2d( int N1, int N2 ) { + int Ns[2] = { N1, N2 }; + return minfft_mkaux_realdft( 2, Ns ); } -minfft_aux* -minfft_mkaux_realdft_3d (int N1, int N2, int N3) { - int Ns[3]={N1, N2, N3}; - return minfft_mkaux_realdft(3, Ns); + +minfft_aux* minfft_mkaux_realdft_3d( int N1, int N2, int N3 ) { + int Ns[3] = { N1, N2, N3 }; + return minfft_mkaux_realdft( 3, Ns ); } // make aux data for one-dimensional Type-2 or Type-3 transforms -minfft_aux* -minfft_mkaux_t2t3_1d (int N) { - minfft_aux *a; - int n; - minfft_real *e; - if (N<=0 || N&(N-1)) +minfft_aux* minfft_mkaux_t2t3_1d( int N ) { + minfft_aux* a; + int n; + minfft_real* e; + if( N <= 0 || N & ( N - 1 ) ) // error if N is negative or not a power of two return NULL; - a=malloc(sizeof(minfft_aux)); - if (a==NULL) + a = malloc( sizeof( minfft_aux ) ); + if( a == NULL ) goto err; - a->N=N; - if (N>=2) { - a->t=malloc((N+2)*sizeof(minfft_real)); // for in-place real DFT - if (a->t==NULL) + a->N = N; + if( N >= 2 ) { + a->t = malloc( ( N + 2 ) * sizeof( minfft_real ) ); // for in-place real DFT + if( a->t == NULL ) goto err; - a->e=malloc((N/2)*sizeof(minfft_cmpl)); - if (a->e==NULL) + a->e = malloc( ( N / 2 ) * sizeof( minfft_cmpl ) ); + if( a->e == NULL ) goto err; - e=(minfft_real*)a->e; - for (n=0; ne; + for( n = 0; n < N / 2; ++n ) { + *e++ = ncos( -n, 4 * N ); + *e++ = nsin( -n, 4 * N ); } } else { - a->t=NULL; - a->e=NULL; + a->t = NULL; + a->e = NULL; } - a->sub1=minfft_mkaux_realdft_1d(N); - if (a->sub1==NULL) + a->sub1 = minfft_mkaux_realdft_1d( N ); + if( a->sub1 == NULL ) goto err; - a->sub2=NULL; + a->sub2 = NULL; return a; - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // make aux data for any-dimensional Type-2 or Type-3 transforms -minfft_aux* -minfft_mkaux_t2t3 (int d, int *Ns) { - return make_aux(d, Ns, sizeof(minfft_real), minfft_mkaux_t2t3_1d); +minfft_aux* minfft_mkaux_t2t3( int d, int* Ns ) { + return make_aux( d, Ns, sizeof( minfft_real ), minfft_mkaux_t2t3_1d ); } // convenience routines for two- and three-dimensional Type 2 or 3 transforms -minfft_aux* -minfft_mkaux_t2t3_2d (int N1, int N2) { - int Ns[2]={N1, N2}; - return minfft_mkaux_t2t3(2, Ns); +minfft_aux* minfft_mkaux_t2t3_2d( int N1, int N2 ) { + int Ns[2] = { N1, N2 }; + return minfft_mkaux_t2t3( 2, Ns ); } -minfft_aux* -minfft_mkaux_t2t3_3d (int N1, int N2, int N3) { - int Ns[3]={N1, N2, N3}; - return minfft_mkaux_t2t3(3, Ns); + +minfft_aux* minfft_mkaux_t2t3_3d( int N1, int N2, int N3 ) { + int Ns[3] = { N1, N2, N3 }; + return minfft_mkaux_t2t3( 3, Ns ); } // make aux data for an one-dimensional Type-4 transform -minfft_aux* -minfft_mkaux_t4_1d (int N) { - minfft_aux *a; - int n; - minfft_real *e; - if (N<=0 || N&(N-1)) +minfft_aux* minfft_mkaux_t4_1d( int N ) { + minfft_aux* a; + int n; + minfft_real* e; + if( N <= 0 || N & ( N - 1 ) ) // error if N is negative or not a power of two return NULL; - a=malloc(sizeof(minfft_aux)); - if (a==NULL) + a = malloc( sizeof( minfft_aux ) ); + if( a == NULL ) goto err; - a->N=N; - if (N>=2) { - a->t=malloc((N/2)*sizeof(minfft_cmpl)); - if (a->t==NULL) + a->N = N; + if( N >= 2 ) { + a->t = malloc( ( N / 2 ) * sizeof( minfft_cmpl ) ); + if( a->t == NULL ) goto err; - a->e=malloc((N/2+N)*sizeof(minfft_cmpl)); - if (a->e==NULL) + a->e = malloc( ( N / 2 + N ) * sizeof( minfft_cmpl ) ); + if( a->e == NULL ) goto err; - e=(minfft_real*)a->e; - for (n=0; ne; + for( n = 0; n < N / 2; ++n ) { + *e++ = ncos( -n, 2 * N ); + *e++ = nsin( -n, 2 * N ); } - for (n=0; nsub1=minfft_mkaux_dft_1d(N/2); - if (a->sub1==NULL) + a->sub1 = minfft_mkaux_dft_1d( N / 2 ); + if( a->sub1 == NULL ) goto err; } else { - a->t=NULL; - a->e=NULL; - a->sub1=NULL; + a->t = NULL; + a->e = NULL; + a->sub1 = NULL; } - a->sub2=NULL; + a->sub2 = NULL; return a; - err: // memory allocation error - minfft_free_aux(a); +err: // memory allocation error + minfft_free_aux( a ); return NULL; } // make aux data for an any-dimensional Type-4 transform -minfft_aux* -minfft_mkaux_t4 (int d, int *Ns) { - return make_aux(d, Ns, sizeof(minfft_real), minfft_mkaux_t4_1d); +minfft_aux* minfft_mkaux_t4( int d, int* Ns ) { + return make_aux( d, Ns, sizeof( minfft_real ), minfft_mkaux_t4_1d ); } // convenience routines for two- and three-dimensional Type 4 transforms -minfft_aux* -minfft_mkaux_t4_2d (int N1, int N2) { - int Ns[2]={N1, N2}; - return minfft_mkaux_t4(2, Ns); +minfft_aux* minfft_mkaux_t4_2d( int N1, int N2 ) { + int Ns[2] = { N1, N2 }; + return minfft_mkaux_t4( 2, Ns ); } -minfft_aux* -minfft_mkaux_t4_3d (int N1, int N2, int N3) { - int Ns[3]={N1, N2, N3}; - return minfft_mkaux_t4(3, Ns); + +minfft_aux* minfft_mkaux_t4_3d( int N1, int N2, int N3 ) { + int Ns[3] = { N1, N2, N3 }; + return minfft_mkaux_t4( 3, Ns ); } // free aux chain -void -minfft_free_aux (minfft_aux *a) { - if (a==NULL) +void minfft_free_aux( minfft_aux* a ) { + if( a == NULL ) return; - free(a->t); - free(a->e); - minfft_free_aux(a->sub1); - minfft_free_aux(a->sub2); - free(a); + free( a->t ); + free( a->e ); + minfft_free_aux( a->sub1 ); + minfft_free_aux( a->sub2 ); + free( a ); } diff --git a/test/minfft/minfft.h b/test/minfft/minfft.h index 4ee0e88b6..44ec925af 100644 --- a/test/minfft/minfft.h +++ b/test/minfft/minfft.h @@ -1,6 +1,7 @@ // A minimalistic FFT library // Copyright (c) 2016-2022 Alexander Mukhin // SPDX-License-Identifier: MIT +// clang-format off #ifndef MINFFT_H #define MINFFT_H diff --git a/test/minfft/minfft_new.cc b/test/minfft/minfft_new.cc index a35154b17..5e10055e4 100644 --- a/test/minfft/minfft_new.cc +++ b/test/minfft/minfft_new.cc @@ -7,81 +7,82 @@ using namespace std; #define M_PI 3.1415926535897932384 #endif -int log2(int N) /*function to calculate the log2(.) of int numbers*/ +int log2( int N ) /*function to calculate the log2(.) of int numbers*/ { int k = N, i = 0; - while(k) { + while( k ) { k >>= 1; i++; } return i - 1; } -int check(int n) //checking if the number of element is a power of 2 +int check( int n ) //checking if the number of element is a power of 2 { - return n > 0 && (n & (n - 1)) == 0; + return n > 0 && ( n & ( n - 1 ) ) == 0; } -int reverse(int N, int n) //calculating revers number +int reverse( int N, int n ) //calculating revers number { int j, p = 0; - for(j = 1; j <= log2(N); j++) { - if(n & (1 << (log2(N) - j))) - p |= 1 << (j - 1); + for( j = 1; j <= log2( N ); j++ ) { + if( n & ( 1 << ( log2( N ) - j ) ) ) + p |= 1 << ( j - 1 ); } return p; } -void ordina(complex* f1, int N) //using the reverse order in the array +void ordina( + complex* f1, + int N +) //using the reverse order in the array { complex f2[MAX]; - for(int i = 0; i < N; i++) - f2[i] = f1[reverse(N, i)]; - for(int j = 0; j < N; j++) + for( int i = 0; i < N; i++ ) + f2[i] = f1[reverse( N, i )]; + for( int j = 0; j < N; j++ ) f1[j] = f2[j]; } -void transform(complex* f, int N) // +void transform( complex* f, int N ) // { - ordina(f, N); //first: reverse order - complex *W; - W = (complex *)malloc(N / 2 * sizeof(complex)); - W[1] = polar(1., -2. * M_PI / N); + ordina( f, N ); //first: reverse order + complex* W; + W = (complex*) malloc( N / 2 * sizeof( complex ) ); + W[1] = polar( 1., -2. * M_PI / N ); W[0] = 1; - for(int i = 2; i < N / 2; i++) - W[i] = pow(W[1], i); + for( int i = 2; i < N / 2; i++ ) + W[i] = pow( W[1], i ); int n = 1; int a = N / 2; - for(int j = 0; j < log2(N); j++) { - for(int i = 0; i < N; i++) { - if(!(i & n)) { + for( int j = 0; j < log2( N ); j++ ) { + for( int i = 0; i < N; i++ ) { + if( !( i & n ) ) { complex temp = f[i]; - complex Temp = W[(i * a) % (n * a)] * f[i + n]; - f[i] = temp + Temp; - f[i + n] = temp - Temp; + complex Temp = W[( i * a ) % ( n * a )] * f[i + n]; + f[i] = temp + Temp; + f[i + n] = temp - Temp; } } n *= 2; a = a / 2; } - free(W); + free( W ); } -void FFT(complex* f, int N, double d) -{ - transform(f, N); - for(int i = 0; i < N; i++) - f[i] *= d; //multiplying by step +void FFT( complex* f, int N, double d ) { + transform( f, N ); + for( int i = 0; i < N; i++ ) + f[i] *= d; //multiplying by step } -int main() -{ - int n = MAX; - double d = 10.; +int main() { + int n = MAX; + double d = 10.; complex vec[MAX]; - for(int i = 0; i < n; i++) { + for( int i = 0; i < n; i++ ) { vec[i] = rand(); } - FFT(vec, n, d); + FFT( vec, n, d ); return 0; } diff --git a/test/minfft/rev-test-minfft.py b/test/minfft/rev-test-minfft.py old mode 100644 new mode 100755 index 35afb8565..babb84908 --- a/test/minfft/rev-test-minfft.py +++ b/test/minfft/rev-test-minfft.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 4, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024*8, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV32I for core 0 - "startAddr" : "[0:0x000]", # Starting address for core 0 - "memCost" : "[0:5:40]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "minfft.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 4, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024*8, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV32I for core 0 + "startAddr": "[0:0x000]", # Starting address for core 0 + "memCost": "[0:5:40]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "minfft.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/minfft/run_minfft.sh b/test/minfft/run_minfft.sh index d1b5e6f0c..568298e09 100755 --- a/test/minfft/run_minfft.sh +++ b/test/minfft/run_minfft.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -f minfft.exe ]; then +if [[ -f minfft.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-test-minfft.py else echo "Test MINFFT: minfft.exe not Found - likely build failed" diff --git a/test/pan_mbox_test1/Makefile b/test/pan_mbox_test1/Makefile index 7897eade4..b064b68b2 100644 --- a/test/pan_mbox_test1/Makefile +++ b/test/pan_mbox_test1/Makefile @@ -3,7 +3,7 @@ # # makefile: pan_test # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/pan_mbox_test1/pan_spin.c b/test/pan_mbox_test1/pan_spin.c index 9d1b861c3..deca1e73f 100644 --- a/test/pan_mbox_test1/pan_spin.c +++ b/test/pan_mbox_test1/pan_spin.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,15 @@ * */ -#include -#include #include "../../common/include/PanAddr.h" +#include +#include - -int main(int argc, char **argv){ - uint64_t *ptr = (uint64_t *)(_PAN_COMPLETION_ADDR_); +int main( int argc, char** argv ) { + uint64_t* ptr = (uint64_t*) ( _PAN_COMPLETION_ADDR_ ); volatile uint64_t value = *ptr; - while( value == 0x00ull){ + while( value == 0x00ull ) { value = *ptr; } diff --git a/test/pan_mbox_test1/pan_test.c b/test/pan_mbox_test1/pan_test.c index a27738d45..75f36dd56 100644 --- a/test/pan_mbox_test1/pan_test.c +++ b/test/pan_mbox_test1/pan_test.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,73 +11,73 @@ * */ -#include -#include #include "../../common/include/PanAddr.h" +#include +#include -typedef struct{ +typedef struct { uint64_t Base; uint64_t Addr; uint64_t Data; -}Command; +} Command; -Command get_cmd; -Command reserve_cmd; -Command revoke_cmd; -Command complete_cmd; -MBoxEntry *Mailbox = (MBoxEntry *)(_PAN_RDMA_MAILBOX_); +Command get_cmd; +Command reserve_cmd; +Command revoke_cmd; +Command complete_cmd; +MBoxEntry* Mailbox = (MBoxEntry*) ( _PAN_RDMA_MAILBOX_ ); -uint32_t Token = 0xfeedbeef; -uint32_t Tag = 0x1; -uint64_t Input = 0x1; +uint32_t Token = 0xfeedbeef; +uint32_t Tag = 0x1; +uint64_t Input = 0x1; -void cmd_wait(){ +void cmd_wait() { // this function blocks until the command is cleared from the mailbox volatile uint64_t value = Mailbox[0].Valid; - while( value != _PAN_ENTRY_INJECTED_ ){ + while( value != _PAN_ENTRY_INJECTED_ ) { value = Mailbox[0].Valid; } Mailbox[0].Valid = _PAN_ENTRY_INVALID_; } -void send_completion(){ +void send_completion() { complete_cmd.Base = 0x80403feedbeef; complete_cmd.Addr = _PAN_COMPLETION_ADDR_; //complete_cmd.Data = 0xdeadbeef; - complete_cmd.Data = (uint64_t)(&Input); // updated to include buffer - Mailbox[0].Addr = (uint64_t)(&complete_cmd); - Mailbox[0].Dest = 1; - Mailbox[0].Valid = _PAN_ENTRY_VALID_; + complete_cmd.Data = (uint64_t) ( &Input ); // updated to include buffer + Mailbox[0].Addr = (uint64_t) ( &complete_cmd ); + Mailbox[0].Dest = 1; + Mailbox[0].Valid = _PAN_ENTRY_VALID_; cmd_wait(); - uint64_t *ptr = (uint64_t *)(_PAN_COMPLETION_ADDR_); - *ptr = 0x001ull; + uint64_t* ptr = (uint64_t*) ( _PAN_COMPLETION_ADDR_ ); + *ptr = 0x001ull; Tag++; } -void send_put_cmd(){ +void send_put_cmd() { // payload = 0x402feedbeef Tag++; } -void send_reserve_cmd(){ +void send_reserve_cmd() { reserve_cmd.Base = 0x4001feedbeef; - Mailbox[0].Addr = (uint64_t)(&reserve_cmd.Base); - Mailbox[0].Dest = 1; + Mailbox[0].Addr = (uint64_t) ( &reserve_cmd.Base ); + Mailbox[0].Dest = 1; Mailbox[0].Valid = _PAN_ENTRY_VALID_; cmd_wait(); Tag++; } -void send_revoke_cmd(){ - revoke_cmd.Base = 0x5004feedbeef; - Mailbox[0].Addr = (uint64_t)(&revoke_cmd); - Mailbox[0].Dest = 1; +void send_revoke_cmd() { + revoke_cmd.Base = 0x5004feedbeef; + Mailbox[0].Addr = (uint64_t) ( &revoke_cmd ); + Mailbox[0].Dest = 1; Mailbox[0].Valid = _PAN_ENTRY_VALID_; cmd_wait(); } -int main(int argc, char **argv){ - uint64_t *ptr = (uint64_t *)(_PAN_COMPLETION_ADDR_); +int main( int argc, char** argv ) { + uint64_t* ptr = (uint64_t*) ( _PAN_COMPLETION_ADDR_ ); volatile uint64_t value; send_reserve_cmd(); @@ -89,7 +89,7 @@ int main(int argc, char **argv){ send_revoke_cmd(); value = *ptr; - while( value == 0x00ull){ + while( value == 0x00ull ) { value = *ptr; } diff --git a/test/pan_mbox_test1/rev-pan-test.py b/test/pan_mbox_test1/rev-pan-test.py old mode 100644 new mode 100755 index 6d9c49c8c..26b847418 --- a/test/pan_mbox_test1/rev-pan-test.py +++ b/test/pan_mbox_test1/rev-pan-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -33,105 +34,105 @@ max_addr_gb = 1 # Define the simulation components -#-- HOST CPU +# -- HOST CPU host_cpu0 = sst.Component("cpu0", "revcpu.RevCPU") host_cpu0.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GC]", # Core:Config; RV64G for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_test.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 0, # Disable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "testIters" : 10, # Number of command packets for each test - "msgPerCycle" : 5, # Number of messages per cycle - "RDMAPerCycle" : 1, # Number of RDMA messages to flush to network per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64G for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_test.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 0, # Disable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "testIters": 10, # Number of command packets for each test + "msgPerCycle": 5, # Number of messages per cycle + "RDMAPerCycle": 1, # Number of RDMA messages to flush to network per cycle + "splash": 1 # Display the splash message }) -#-- PAN CPU +# -- PAN CPU pan_cpu1 = sst.Component("cpu1", "revcpu.RevCPU") pan_cpu1.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GP]", # Core:Config; RV64GP for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_spin.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 0, # Disable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "msgPerCycle" : 5, # Number of messages per cycle - "RDMAPerCycle" : 1, # Number of RDMA messages to flush to network per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GP]", # Core:Config; RV64GP for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_spin.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 0, # Disable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "msgPerCycle": 5, # Number of messages per cycle + "RDMAPerCycle": 1, # Number of RDMA messages to flush to network per cycle + "splash": 1 # Display the splash message }) # setup the NICs -nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") #-- host -nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") #-- pan +nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") # -- host +nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") # -- pan -iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") #-- host -iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") #-- pan +iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") # -- host +iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") # -- pan # setup the router router = sst.Component("router", "merlin.hr_router") router.setSubComponent("topology", "merlin.singlerouter") # set the network params -#-- host +# -- host host_verb_params = { - "verbose" : 6, - "host_device" : 1 + "verbose": 6, + "host_device": 1 } -#-- pan +# -- pan pan_verb_params = { - "verbose" : 6, - "host_device" : 0 + "verbose": 6, + "host_device": 0 } -#-- host network config +# -- host network config host_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "1GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "1GB/s" } -#-- pan network config +# -- pan network config pan_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "10GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "10GB/s" } -nic0.addParams(host_verb_params) #-- host -nic1.addParams(pan_verb_params) #-- pan +nic0.addParams(host_verb_params) # -- host +nic1.addParams(pan_verb_params) # -- pan -iface0.addParams(host_net_params) #-- host -iface1.addParams(pan_net_params) #-- pan -router.addParams(pan_net_params) #-- pan router +iface0.addParams(host_net_params) # -- host +iface1.addParams(pan_net_params) # -- pan +router.addParams(pan_net_params) # -- pan router router.addParams({ - "xbar_bw" : "10GB/s", - "flit_size" : "32B", - "num_ports" : "2", - "id" : 0 + "xbar_bw": "10GB/s", + "flit_size": "32B", + "num_ports": "2", + "id": 0 }) # setup the links link0 = sst.Link("link0") -link0.connect( (iface0, "rtr_port", "1ms"), (router, "port0", "1ms") ) +link0.connect((iface0, "rtr_port", "1ms"), (router, "port0", "1ms")) link1 = sst.Link("link1") -link1.connect( (iface1, "rtr_port", "1ms"), (router, "port1", "1ms") ) +link1.connect((iface1, "rtr_port", "1ms"), (router, "port1", "1ms")) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/pan_test1/Makefile b/test/pan_test1/Makefile index a49c03b21..832c0d76f 100644 --- a/test/pan_test1/Makefile +++ b/test/pan_test1/Makefile @@ -3,7 +3,7 @@ # # makefile: pan_test # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/pan_test1/pan_test.c b/test/pan_test1/pan_test.c index 230dffcf6..564adbd12 100644 --- a/test/pan_test1/pan_test.c +++ b/test/pan_test1/pan_test.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ -#include #include +#include #define _PAN_COMPLETION_ADDR_ 0x30000000 -int main(int argc, char **argv){ - uint64_t *ptr = (uint64_t *)(_PAN_COMPLETION_ADDR_); +int main( int argc, char** argv ) { + uint64_t* ptr = (uint64_t*) ( _PAN_COMPLETION_ADDR_ ); volatile uint64_t value = *ptr; - while( value == 0x00ull){ + while( value == 0x00ull ) { value = *ptr; } diff --git a/test/pan_test1/rev-pan-test.py b/test/pan_test1/rev-pan-test.py old mode 100644 new mode 100755 index c2d4ce9f5..fd7751cd9 --- a/test/pan_test1/rev-pan-test.py +++ b/test/pan_test1/rev-pan-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -33,104 +34,104 @@ max_addr_gb = 1 # Define the simulation components -#-- HOST CPU +# -- HOST CPU host_cpu0 = sst.Component("cpu0", "revcpu.RevCPU") host_cpu0.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64G for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_test.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 1, # Enable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "testIters" : 10, # Number of command packets for each test - "msgPerCycle" : 5, # Number of messages per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64G for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_test.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 1, # Enable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "testIters": 10, # Number of command packets for each test + "msgPerCycle": 5, # Number of messages per cycle + "splash": 1 # Display the splash message }) -#-- PAN CPU +# -- PAN CPU pan_cpu1 = sst.Component("cpu1", "revcpu.RevCPU") pan_cpu1.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GP]", # Core:Config; RV64GP for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_test.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 0, # Disable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "enableRDMAMbox" : 0, # Disable the RDMA Mailbox - "msgPerCycle" : 5, # Number of messages per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GP]", # Core:Config; RV64GP for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_test.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 0, # Disable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "enableRDMAMbox": 0, # Disable the RDMA Mailbox + "msgPerCycle": 5, # Number of messages per cycle + "splash": 1 # Display the splash message }) # setup the NICs -nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") #-- host -nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") #-- pan +nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") # -- host +nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") # -- pan -iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") #-- host -iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") #-- pan +iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") # -- host +iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") # -- pan # setup the router router = sst.Component("router", "merlin.hr_router") router.setSubComponent("topology", "merlin.singlerouter") # set the network params -#-- host +# -- host host_verb_params = { - "verbose" : 6, - "host_device" : 1 + "verbose": 6, + "host_device": 1 } -#-- pan +# -- pan pan_verb_params = { - "verbose" : 6, - "host_device" : 0 + "verbose": 6, + "host_device": 0 } -#-- host network config +# -- host network config host_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "1GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "1GB/s" } -#-- pan network config +# -- pan network config pan_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "10GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "10GB/s" } -nic0.addParams(host_verb_params) #-- host -nic1.addParams(pan_verb_params) #-- pan +nic0.addParams(host_verb_params) # -- host +nic1.addParams(pan_verb_params) # -- pan -iface0.addParams(host_net_params) #-- host -iface1.addParams(pan_net_params) #-- pan -router.addParams(pan_net_params) #-- pan router +iface0.addParams(host_net_params) # -- host +iface1.addParams(pan_net_params) # -- pan +router.addParams(pan_net_params) # -- pan router router.addParams({ - "xbar_bw" : "10GB/s", - "flit_size" : "32B", - "num_ports" : "2", - "id" : 0 + "xbar_bw": "10GB/s", + "flit_size": "32B", + "num_ports": "2", + "id": 0 }) # setup the links link0 = sst.Link("link0") -link0.connect( (iface0, "rtr_port", "1ms"), (router, "port0", "1ms") ) +link0.connect((iface0, "rtr_port", "1ms"), (router, "port0", "1ms")) link1 = sst.Link("link1") -link1.connect( (iface1, "rtr_port", "1ms"), (router, "port1", "1ms") ) +link1.connect((iface1, "rtr_port", "1ms"), (router, "port1", "1ms")) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/pan_test2/Makefile b/test/pan_test2/Makefile index a49c03b21..832c0d76f 100644 --- a/test/pan_test2/Makefile +++ b/test/pan_test2/Makefile @@ -3,7 +3,7 @@ # # makefile: pan_test # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/pan_test2/pan_test.c b/test/pan_test2/pan_test.c index 230dffcf6..564adbd12 100644 --- a/test/pan_test2/pan_test.c +++ b/test/pan_test2/pan_test.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,16 +11,16 @@ * */ -#include #include +#include #define _PAN_COMPLETION_ADDR_ 0x30000000 -int main(int argc, char **argv){ - uint64_t *ptr = (uint64_t *)(_PAN_COMPLETION_ADDR_); +int main( int argc, char** argv ) { + uint64_t* ptr = (uint64_t*) ( _PAN_COMPLETION_ADDR_ ); volatile uint64_t value = *ptr; - while( value == 0x00ull){ + while( value == 0x00ull ) { value = *ptr; } diff --git a/test/pan_test2/rev-pan-test.py b/test/pan_test2/rev-pan-test.py old mode 100644 new mode 100755 index 3c1271438..5eecaeb10 --- a/test/pan_test2/rev-pan-test.py +++ b/test/pan_test2/rev-pan-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -33,104 +34,104 @@ max_addr_gb = 1 # Define the simulation components -#-- HOST CPU +# -- HOST CPU host_cpu0 = sst.Component("cpu0", "revcpu.RevCPU") host_cpu0.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64G]", # Core:Config; RV64G for core 0 - "startAddr" : "[0:0x0001014c]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_test.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 1, # Enable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "testIters" : 254, # Number of command packets for each test - "msgPerCycle" : 5, # Number of messages per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64G]", # Core:Config; RV64G for core 0 + "startAddr": "[0:0x0001014c]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_test.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 1, # Enable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "testIters": 254, # Number of command packets for each test + "msgPerCycle": 5, # Number of messages per cycle + "splash": 1 # Display the splash message }) -#-- PAN CPU +# -- PAN CPU pan_cpu1 = sst.Component("cpu1", "revcpu.RevCPU") pan_cpu1.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GP]", # Core:Config; RV64GP for core 0 - "startAddr" : "[0:0x0001014c]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "pan_test.exe"), # Target executable - "pan_nic" : "revcpu.PanNet", # Use the PAN NIC - "enable_pan" : 1, # Enable the internal RevNIC - "enable_test" : 0, # Disable the PAN test harness - "enable_pan_stats" : 1, # Enable the PAN statistics - "enableRDMAMbox" : 0, # Disable the RDMA Mailbox - "msgPerCycle" : 5, # Number of messages per cycle - "splash" : 1 # Display the splash message + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GP]", # Core:Config; RV64GP for core 0 + "startAddr": "[0:0x0001014c]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "pan_test.exe"), # Target executable + "pan_nic": "revcpu.PanNet", # Use the PAN NIC + "enable_pan": 1, # Enable the internal RevNIC + "enable_test": 0, # Disable the PAN test harness + "enable_pan_stats": 1, # Enable the PAN statistics + "enableRDMAMbox": 0, # Disable the RDMA Mailbox + "msgPerCycle": 5, # Number of messages per cycle + "splash": 1 # Display the splash message }) # setup the NICs -nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") #-- host -nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") #-- pan +nic0 = host_cpu0.setSubComponent("pan_nic", "revcpu.PanNet") # -- host +nic1 = pan_cpu1.setSubComponent("pan_nic", "revcpu.PanNet") # -- pan -iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") #-- host -iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") #-- pan +iface0 = nic0.setSubComponent("iface", "merlin.linkcontrol") # -- host +iface1 = nic1.setSubComponent("iface", "merlin.linkcontrol") # -- pan # setup the router router = sst.Component("router", "merlin.hr_router") router.setSubComponent("topology", "merlin.singlerouter") # set the network params -#-- host +# -- host host_verb_params = { - "verbose" : 6, - "host_device" : 1 + "verbose": 6, + "host_device": 1 } -#-- pan +# -- pan pan_verb_params = { - "verbose" : 6, - "host_device" : 0 + "verbose": 6, + "host_device": 0 } -#-- host network config +# -- host network config host_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "1GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "1GB/s" } -#-- pan network config +# -- pan network config pan_net_params = { - "input_buf_size" : "512B", - "output_buf_size" : "512B", - "link_bw" : "10GB/s" + "input_buf_size": "512B", + "output_buf_size": "512B", + "link_bw": "10GB/s" } -nic0.addParams(host_verb_params) #-- host -nic1.addParams(pan_verb_params) #-- pan +nic0.addParams(host_verb_params) # -- host +nic1.addParams(pan_verb_params) # -- pan -iface0.addParams(host_net_params) #-- host -iface1.addParams(pan_net_params) #-- pan -router.addParams(pan_net_params) #-- pan router +iface0.addParams(host_net_params) # -- host +iface1.addParams(pan_net_params) # -- pan +router.addParams(pan_net_params) # -- pan router router.addParams({ - "xbar_bw" : "10GB/s", - "flit_size" : "32B", - "num_ports" : "2", - "id" : 0 + "xbar_bw": "10GB/s", + "flit_size": "32B", + "num_ports": "2", + "id": 0 }) # setup the links link0 = sst.Link("link0") -link0.connect( (iface0, "rtr_port", "1ms"), (router, "port0", "1ms") ) +link0.connect((iface0, "rtr_port", "1ms"), (router, "port0", "1ms")) link1 = sst.Link("link1") -link1.connect( (iface1, "rtr_port", "1ms"), (router, "port1", "1ms") ) +link1.connect((iface1, "rtr_port", "1ms"), (router, "port1", "1ms")) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/rdcycle/Makefile b/test/rdcycle/Makefile new file mode 100644 index 000000000..ed8eee955 --- /dev/null +++ b/test/rdcycle/Makefile @@ -0,0 +1,27 @@ +# +# Makefile +# +# makefile: rdcycle +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +EXAMPLE=rdcycle +CC="${RVCC}" +# ARCH=rv64gc_zicntr +ARCH=rv64gc +ABI=lp64d + +CFLAGS=-I ../../common/syscalls -O1 + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) $(CFLAGS) -march=$(ARCH) -mabi=$(ABI) -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/rdcycle/rdcycle.c b/test/rdcycle/rdcycle.c new file mode 100644 index 000000000..5cd647bc8 --- /dev/null +++ b/test/rdcycle/rdcycle.c @@ -0,0 +1,119 @@ +/* + * rdcycle.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include "syscalls.h" +#include +#include +#include + +#define NOP1 asm( " nop" ); +#define NOP2 NOP1 NOP1 +#define NOP4 NOP2 NOP2 +#define NOP8 NOP4 NOP4 +#define NOP16 NOP8 NOP8 +#define NOP32 NOP16 NOP16 +#define NOP64 NOP32 NOP32 +#define NOP128 NOP64 NOP64 +#define NOP256 NOP128 NOP128 +#define NOP512 NOP256 NOP256 +#define NOP1024 NOP512 NOP512 + +#define VERBOSE 0 + +int main( int argc, char** argv ) { + size_t cycle1, cycle2; + + { + asm volatile( " rdcycle %0" : "=r"( cycle1 ) ); + + // 1024 nops produces around 1024 cycles + NOP1024; + + asm volatile( " rdcycle %0" : "=r"( cycle2 ) ); + + size_t diff = cycle2 - cycle1; + +#if VERBOSE + char cycles[64]; + snprintf( cycles, sizeof( cycles ), "%zu cycles\n", diff ); + rev_write( 1, cycles, strlen( cycles ) ); +#endif + + // Make sure the number of cycles is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrsi %0, 0xc00, 0" : "=r"( cycle1 ) ); + + // 1024 nops produces around 1024 cycles + NOP1024; + + asm volatile( " csrrsi %0, 0xc00, 0" : "=r"( cycle2 ) ); + + size_t diff = cycle2 - cycle1; + +#if VERBOSE + char cycles[64]; + snprintf( cycles, sizeof( cycles ), "%zu cycles\n", diff ); + rev_write( 1, cycles, strlen( cycles ) ); +#endif + + // Make sure the number of cycles is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrci %0, 0xc00, 0" : "=r"( cycle1 ) ); + + // 1024 nops produces around 1024 cycles + NOP1024; + + asm volatile( " csrrci %0, 0xc00, 0" : "=r"( cycle2 ) ); + + size_t diff = cycle2 - cycle1; + +#if VERBOSE + char cycles[64]; + snprintf( cycles, sizeof( cycles ), "%zu cycles\n", diff ); + rev_write( 1, cycles, strlen( cycles ) ); +#endif + + // Make sure the number of cycles is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrc %0, 0xc00, zero" : "=r"( cycle1 ) ); + + // 1024 nops produces around 1024 cycles + NOP1024; + + asm volatile( " csrrc %0, 0xc00, zero" : "=r"( cycle2 ) ); + + size_t diff = cycle2 - cycle1; + +#if VERBOSE + char cycles[64]; + snprintf( cycles, sizeof( cycles ), "%zu cycles\n", diff ); + rev_write( 1, cycles, strlen( cycles ) ); +#endif + + // Make sure the number of cycles is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + return 0; +} diff --git a/test/rdinstret/Makefile b/test/rdinstret/Makefile new file mode 100644 index 000000000..5c057c422 --- /dev/null +++ b/test/rdinstret/Makefile @@ -0,0 +1,27 @@ +# +# Makefile +# +# makefile: rdinstret +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +EXAMPLE=rdinstret +CC="${RVCC}" +# ARCH=rv64gc_zicntr +ARCH=rv64gc +ABI=lp64d + +CFLAGS=-I ../../common/syscalls -O1 + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) $(CFLAGS) -march=$(ARCH) -mabi=$(ABI) -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/rdinstret/rdinstret.c b/test/rdinstret/rdinstret.c new file mode 100644 index 000000000..eb231d80b --- /dev/null +++ b/test/rdinstret/rdinstret.c @@ -0,0 +1,119 @@ +/* + * rdinstret.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include "syscalls.h" +#include +#include +#include + +#define NOP1 asm( " nop" ); +#define NOP2 NOP1 NOP1 +#define NOP4 NOP2 NOP2 +#define NOP8 NOP4 NOP4 +#define NOP16 NOP8 NOP8 +#define NOP32 NOP16 NOP16 +#define NOP64 NOP32 NOP32 +#define NOP128 NOP64 NOP64 +#define NOP256 NOP128 NOP128 +#define NOP512 NOP256 NOP256 +#define NOP1024 NOP512 NOP512 + +#define VERBOSE 0 + +int main( int argc, char** argv ) { + size_t retired1, retired2; + + { + asm volatile( " rdinstret %0" : "=r"( retired1 ) ); + + // 1024 nops produces around 1024 retireds + NOP1024; + + asm volatile( " rdinstret %0" : "=r"( retired2 ) ); + + size_t diff = retired2 - retired1; + +#if VERBOSE + char retired[64]; + snprintf( retired, sizeof( retired ), "%zu instructions retired\n", diff ); + rev_write( 1, retired, strlen( retired ) ); +#endif + + // Make sure the instructions retired is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrsi %0, 0xc02, 0" : "=r"( retired1 ) ); + + // 1024 nops produces around 1024 retireds + NOP1024; + + asm volatile( " csrrsi %0, 0xc02, 0" : "=r"( retired2 ) ); + + size_t diff = retired2 - retired1; + +#if VERBOSE + char retired[64]; + snprintf( retired, sizeof( retired ), "%zu instructions retired\n", diff ); + rev_write( 1, retired, strlen( retired ) ); +#endif + + // Make sure the instructions retired is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrci %0, 0xc02, 0" : "=r"( retired1 ) ); + + // 1024 nops produces around 1024 retireds + NOP1024; + + asm volatile( " csrrci %0, 0xc02, 0" : "=r"( retired2 ) ); + + size_t diff = retired2 - retired1; + +#if VERBOSE + char retired[64]; + snprintf( retired, sizeof( retired ), "%zu instructions retired\n", diff ); + rev_write( 1, retired, strlen( retired ) ); +#endif + + // Make sure the instructions retired is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrc %0, 0xc02, zero" : "=r"( retired1 ) ); + + // 1024 nops produces around 1024 retireds + NOP1024; + + asm volatile( " csrrc %0, 0xc02, zero" : "=r"( retired2 ) ); + + size_t diff = retired2 - retired1; + +#if VERBOSE + char retired[64]; + snprintf( retired, sizeof( retired ), "%zu instructions retired\n", diff ); + rev_write( 1, retired, strlen( retired ) ); +#endif + + // Make sure the instructions retired is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + return 0; +} diff --git a/test/rdtime/Makefile b/test/rdtime/Makefile new file mode 100644 index 000000000..4a1e89658 --- /dev/null +++ b/test/rdtime/Makefile @@ -0,0 +1,27 @@ +# +# Makefile +# +# makefile: rdtime +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +EXAMPLE=rdtime +CC="${RVCC}" +# ARCH=rv64gc_zicntr +ARCH=rv64gc +ABI=lp64d + +CFLAGS=-I ../../common/syscalls -O1 + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) $(CFLAGS) -march=$(ARCH) -mabi=$(ABI) -static -o $(EXAMPLE).exe $(EXAMPLE).c +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/rdtime/rdtime.c b/test/rdtime/rdtime.c new file mode 100644 index 000000000..440bcda0e --- /dev/null +++ b/test/rdtime/rdtime.c @@ -0,0 +1,119 @@ +/* + * rdtime.c + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +#include "syscalls.h" +#include +#include +#include + +#define NOP1 asm( " nop" ); +#define NOP2 NOP1 NOP1 +#define NOP4 NOP2 NOP2 +#define NOP8 NOP4 NOP4 +#define NOP16 NOP8 NOP8 +#define NOP32 NOP16 NOP16 +#define NOP64 NOP32 NOP32 +#define NOP128 NOP64 NOP64 +#define NOP256 NOP128 NOP128 +#define NOP512 NOP256 NOP256 +#define NOP1024 NOP512 NOP512 + +#define VERBOSE 0 + +int main( int argc, char** argv ) { + size_t time1, time2; + + { + asm volatile( " rdtime %0" : "=r"( time1 ) ); + + // 1024 nops produces around 1024 times + NOP1024; + + asm volatile( " rdtime %0" : "=r"( time2 ) ); + + size_t diff = time2 - time1; + +#if VERBOSE + char time[64]; + snprintf( time, sizeof( time ), "%zu time\n", diff ); + rev_write( 1, time, strlen( time ) ); +#endif + + // Make sure the time is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrsi %0, 0xc01, 0" : "=r"( time1 ) ); + + // 1024 nops produces around 1024 times + NOP1024; + + asm volatile( " csrrsi %0, 0xc01, 0" : "=r"( time2 ) ); + + size_t diff = time2 - time1; + +#if VERBOSE + char time[64]; + snprintf( time, sizeof( time ), "%zu time\n", diff ); + rev_write( 1, time, strlen( time ) ); +#endif + + // Make sure the time is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrci %0, 0xc01, 0" : "=r"( time1 ) ); + + // 1024 nops produces around 1024 times + NOP1024; + + asm volatile( " csrrci %0, 0xc01, 0" : "=r"( time2 ) ); + + size_t diff = time2 - time1; + +#if VERBOSE + char time[64]; + snprintf( time, sizeof( time ), "%zu time\n", diff ); + rev_write( 1, time, strlen( time ) ); +#endif + + // Make sure the time is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + { + asm volatile( " csrrc %0, 0xc01, zero" : "=r"( time1 ) ); + + // 1024 nops produces around 1024 times + NOP1024; + + asm volatile( " csrrc %0, 0xc01, zero" : "=r"( time2 ) ); + + size_t diff = time2 - time1; + +#if VERBOSE + char time[64]; + snprintf( time, sizeof( time ), "%zu time\n", diff ); + rev_write( 1, time, strlen( time ) ); +#endif + + // Make sure the time is between 1024 and 1026 + if( diff < 1024 || diff > 1026 ) + asm( " .word 0" ); + } + + return 0; +} diff --git a/test/rev-model-options-config.py b/test/rev-model-options-config.py old mode 100644 new mode 100755 index d5ab7df0a..b7f9fcbfc --- a/test/rev-model-options-config.py +++ b/test/rev-model-options-config.py @@ -1,22 +1,23 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # # See LICENSE in the top level directory for licensing details # -# rev-basic-config.py +# rev-mode-options-config.py # -import os import argparse +import os import sst DEBUG_L1 = 0 DEBUG_MEM = 0 DEBUG_LEVEL = 10 VERBOSE = 2 -MEM_SIZE = 1024*1024*1024-1 +memSize = 1024*1024*1024-1 # Setup argument parser parser = argparse.ArgumentParser(description="Run Rev SST Simulation") @@ -28,6 +29,9 @@ parser.add_argument("--machine", help="Machine type/configuration", default="[CORES:RV64GC]") parser.add_argument("--args", help="Command line arguments to pass to the target executable", default="") parser.add_argument("--startSymbol", help="ELF Symbol Rev should begin execution at", default="[0:main]") +parser.add_argument("--trcStartCycle", help="Starting cycle for rev tracer [default: 0 (off)]") +parser.add_argument("--trcLimit", help="Max trace records per core [default: 0 (no limit)]", default=0) +parser.add_argument("--statDir", help="Location for statistics files", default=".") # Parse arguments args = parser.parse_args() @@ -38,28 +42,32 @@ print("\t", arg, " = ", getattr(args, arg)) # SST core options and parameters -mem_size = 1024*1024*1024-1 clock = "2.0GHz" # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : args.verbose, - "numCores" : args.numCores, - "numHarts" : args.numHarts, - "clock" : clock, - "memSize" : mem_size, - "machine" : args.machine, - "memCost" : "[0:1:10]", - "program" : args.program, - "startAddr" : "[0:0x00000000]", - "startSymbol" : args.startSymbol, - "enable_memH" : args.enableMemH, + "verbose": args.verbose, + "numCores": args.numCores, + "numHarts": args.numHarts, + "clock": clock, + "memSize": memSize, + "machine": args.machine, + "memCost": "[0:1:10]", + "program": args.program, + "startAddr": "[0:0x00000000]", + "startSymbol": args.startSymbol, + "enableMemH": args.enableMemH, "args": args.args, - "splash" : 1 + "trcStartCycle": args.trcStartCycle, + "trcLimit": args.trcLimit, + "splash": 1 }) -sst.setStatisticOutput("sst.statOutputCSV") +os.makedirs(args.statDir, exist_ok=True) +sst.setStatisticOutput("sst.statOutputCSV", { + "filepath": f"{args.statDir}/StatisticOutput.csv", +}) sst.setStatisticLoadLevel(4) sst.enableAllStatisticsForComponentType("revcpu.RevCPU") @@ -68,44 +76,42 @@ # Create the RevMemCtrl subcomponent comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl") comp_lsq.addParams({ - "verbose" : "5", - "clock" : "2.0Ghz", - "max_loads" : 16, - "max_stores" : 16, - "max_flush" : 16, - "max_llsc" : 16, - "max_readlock" : 16, - "max_writeunlock" : 16, - "max_custom" : 16, - "ops_per_cycle" : 16 + "verbose": "5", + "clock": "2.0Ghz", + "max_loads": 16, + "max_stores": 16, + "max_flush": 16, + "max_llsc": 16, + "max_readlock": 16, + "max_writeunlock": 16, + "max_custom": 16, + "ops_per_cycle": 16 }) - comp_lsq.enableAllStatistics({"type":"sst.AccumulatorStatistic"}) + comp_lsq.enableAllStatistics({"type": "sst.AccumulatorStatistic"}) iface = comp_lsq.setSubComponent("memIface", "memHierarchy.standardInterface") iface.addParams({ - "verbose" : VERBOSE + "verbose": VERBOSE }) memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams({ - "debug" : DEBUG_MEM, - "debug_level" : DEBUG_LEVEL, - "clock" : "2GHz", - "verbose" : VERBOSE, - "addr_range_start" : 0, - "addr_range_end" : MEM_SIZE, - "backing" : "malloc" + "debug": DEBUG_MEM, + "debug_level": DEBUG_LEVEL, + "clock": "2GHz", + "verbose": VERBOSE, + "addr_range_start": 0, + "addr_range_end": memSize, + "backing": "malloc" }) memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams({ - "access_time" : "100ns", - "mem_size" : "8GB" + "access_time": "100ns", + "mem_size": "8GB" }) link_iface_mem = sst.Link("link_iface_mem") - link_iface_mem.connect( (iface, "port", "50ps"), (memctrl, "direct_link", "50ps") ) - - + link_iface_mem.connect((iface, "port", "50ps"), (memctrl, "direct_link", "50ps")) # Setup for memHierarchy backend # ... (Include your memHierarchy setup here) diff --git a/test/strlen_c/Makefile b/test/strlen_c/Makefile index 69192d2ac..73d1e64fa 100644 --- a/test/strlen_c/Makefile +++ b/test/strlen_c/Makefile @@ -3,7 +3,7 @@ # # makefile: strlen_c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/strlen_c/run_strlen_c.sh b/test/strlen_c/run_strlen_c.sh index 281a9f3d9..4f75d4130 100755 --- a/test/strlen_c/run_strlen_c.sh +++ b/test/strlen_c/run_strlen_c.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x strlen_c.exe ]; then +if [[ -x strlen_c.exe ]]; then sst --add-lib-path=../../build/src/ ./strlen_c.py else echo "Test STRLEN_C: strlen_c.exe not Found - likely build failed" diff --git a/test/strlen_c/strlen_c.c b/test/strlen_c/strlen_c.c index d46bb99fb..969d9b4fd 100644 --- a/test/strlen_c/strlen_c.c +++ b/test/strlen_c/strlen_c.c @@ -1,7 +1,7 @@ #include -int main(){ +int main() { char txt[] = "some really nice text"; - int l = strlen(txt); + int l = strlen( txt ); return l; } diff --git a/test/strlen_c/strlen_c.py b/test/strlen_c/strlen_c.py old mode 100644 new mode 100755 index 40fc7f45f..4bb0b81c5 --- a/test/strlen_c/strlen_c.py +++ b/test/strlen_c/strlen_c.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -7,7 +8,6 @@ # # -import os import sst # Define SST core options @@ -21,19 +21,19 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 0, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 -# "startSymbol" : "[0:_start]", - "memCost" : "[0:1:1]", # Memory loads required 1-10 cycles - "program" : "strlen_c.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 0, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + # "startSymbol": "[0:_start]", + "memCost": "[0:1:1]", # Memory loads required 1-10 cycles + "program": "strlen_c.exe", # Target executable + "splash": 1 # Display the splash message }) -#sst.setStatisticOutput("sst.statOutputCSV") -#sst.enableAllStatisticsForAllComponents() +# sst.setStatisticOutput("sst.statOutputCSV") +# sst.enableAllStatisticsForAllComponents() # EOF diff --git a/test/strlen_cxx/Makefile b/test/strlen_cxx/Makefile index ef91d4a89..7693d8f94 100644 --- a/test/strlen_cxx/Makefile +++ b/test/strlen_cxx/Makefile @@ -3,7 +3,7 @@ # # makefile: strlen_c # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/strlen_cxx/run_strlen_cxx.sh b/test/strlen_cxx/run_strlen_cxx.sh index 020fb3397..673b3da59 100755 --- a/test/strlen_cxx/run_strlen_cxx.sh +++ b/test/strlen_cxx/run_strlen_cxx.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x strlen_cxx.exe ]; then +if [[ -x strlen_cxx.exe ]]; then sst --add-lib-path=../../build/src/ ./strlen_cxx.py else echo "Test STRLEN_CXX: strlen_cxx.exe not Found - likely build failed" diff --git a/test/strlen_cxx/strlen_cxx.cc b/test/strlen_cxx/strlen_cxx.cc index c492ca557..8080d5a8e 100644 --- a/test/strlen_cxx/strlen_cxx.cc +++ b/test/strlen_cxx/strlen_cxx.cc @@ -1,7 +1,7 @@ #include -int main(int argc, char **argv){ +int main( int argc, char** argv ) { char txt[] = "some really nice text"; - int l = strlen(txt); + int l = strlen( txt ); return l; } diff --git a/test/strlen_cxx/strlen_cxx.py b/test/strlen_cxx/strlen_cxx.py old mode 100644 new mode 100755 index 974947f6e..dc6ca3026 --- a/test/strlen_cxx/strlen_cxx.py +++ b/test/strlen_cxx/strlen_cxx.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -7,7 +8,6 @@ # # -import os import sst # Define SST core options @@ -21,19 +21,19 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 0, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 -# "startSymbol" : "[0:_start]", - "memCost" : "[0:1:1]", # Memory loads required 1-10 cycles - "program" : "strlen_cxx.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 0, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + # "startSymbol": "[0:_start]", + "memCost": "[0:1:1]", # Memory loads required 1-10 cycles + "program": "strlen_cxx.exe", # Target executable + "splash": 1 # Display the splash message }) -#sst.setStatisticOutput("sst.statOutputCSV") -#sst.enableAllStatisticsForAllComponents() +# sst.setStatisticOutput("sst.statOutputCSV") +# sst.enableAllStatisticsForAllComponents() # EOF diff --git a/test/strstr/Makefile b/test/strstr/Makefile index 2fa9f5aba..60cc27d4b 100644 --- a/test/strstr/Makefile +++ b/test/strstr/Makefile @@ -3,7 +3,7 @@ # # makefile: strstr # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/strstr/rev-strstr.py b/test/strstr/rev-strstr.py old mode 100644 new mode 100755 index b38730aca..9de473835 --- a/test/strstr/rev-strstr.py +++ b/test/strstr/rev-strstr.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64GC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "strstr.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64GC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "strstr.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/strstr/run_strstr.sh b/test/strstr/run_strstr.sh index 5fa0974f4..35ddc2a21 100755 --- a/test/strstr/run_strstr.sh +++ b/test/strstr/run_strstr.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x strstr.exe ]; then +if [[ -x strstr.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-strstr.py else echo "Test STRSTR: strstr.exe not Found - likely build failed" diff --git a/test/strstr/strstr.c b/test/strstr/strstr.c index 8234f1a97..69f631225 100644 --- a/test/strstr/strstr.c +++ b/test/strstr/strstr.c @@ -1,17 +1,16 @@ #include #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) -const char *const text = - "Hello I am a normal text with some pattern hidden inside."; +const char* const text = "Hello I am a normal text with some pattern hidden inside."; int main() { - assert(strstr(text, "pattern") == text + 35); + assert( strstr( text, "pattern" ) == text + 35 ); return 0; } diff --git a/test/syscalls/CMakeLists.txt b/test/syscalls/CMakeLists.txt index 2d8174fab..e2a43d753 100644 --- a/test/syscalls/CMakeLists.txt +++ b/test/syscalls/CMakeLists.txt @@ -1,8 +1,7 @@ -add_rev_test(CHDIR chdir 30 "all;rv64;syscalls;memh") -add_rev_test(WRITE write 30 "all;rv64;syscalls;memh") -add_rev_test(FILE_IO file_io 30 "all;rv64;syscalls;memh") -add_rev_test(GETCWD getcwd 30 "all;rv64;syscalls;memh") -add_rev_test(MUNMAP munmap 30 "all;rv64;syscalls;memh") -add_rev_test(PERF_STATS perf_stats 30 "all;rv64;syscalls;memh") -# TODO: Merge this PR then merge the sbrk fix then re-enable this test -# add_rev_test(VECTOR vector 30 "all;rv64;syscalls") +add_rev_test(CHDIR chdir 30 "rv64;syscalls;memh") +add_rev_test(WRITE write 30 "test_level=2;rv64;syscalls;memh") +add_rev_test(FILE_IO file_io 30 "rv64;syscalls;memh") +add_rev_test(GETCWD getcwd 30 "rv64;syscalls;memh") +add_rev_test(MUNMAP munmap 30 "rv64;syscalls;memh") +add_rev_test(PERF_STATS perf_stats 30 "test_level=2;rv64;syscalls;memh") +add_rev_test(MEM_DUMP_SYSCALLS mem_dump_syscalls 30 "test_level=2;rv64;syscalls") diff --git a/test/syscalls/chdir/Makefile b/test/syscalls/chdir/Makefile index 0cb619aa0..3c4bf7083 100644 --- a/test/syscalls/chdir/Makefile +++ b/test/syscalls/chdir/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/chdir/chdir.c b/test/syscalls/chdir/chdir.c index e3676fb90..eb7b42bcf 100644 --- a/test/syscalls/chdir/chdir.c +++ b/test/syscalls/chdir/chdir.c @@ -1,6 +1,6 @@ -#include -#include #include "../../../common/syscalls/syscalls.h" +#include +#include int main() { /* @@ -9,9 +9,9 @@ int main() { * This is a known issue with Text data in assembly */ const char dir[5] = "/tmp"; - int result = rev_chdir(&dir[0]); + int result = rev_chdir( &dir[0] ); - if (result != 0) { + if( result != 0 ) { return 1; } else { return 0; diff --git a/test/syscalls/clock_gettime/Makefile b/test/syscalls/clock_gettime/Makefile index ab3b5afd0..a78b2088c 100644 --- a/test/syscalls/clock_gettime/Makefile +++ b/test/syscalls/clock_gettime/Makefile @@ -1,7 +1,7 @@ # # Makefile # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/clock_gettime/clock_gettime.c b/test/syscalls/clock_gettime/clock_gettime.c index c5b07c45f..20c4c9259 100644 --- a/test/syscalls/clock_gettime/clock_gettime.c +++ b/test/syscalls/clock_gettime/clock_gettime.c @@ -1,28 +1,29 @@ #include "../../../common/syscalls/syscalls.h" -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) -int main(int argc, char *argv[]) { - int sum = 0; +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) + +int main( int argc, char* argv[] ) { + int sum = 0; struct __kernel_timespec s, e; - int ret = rev_clock_gettime(0, &s); - assert(ret == 0); + int ret = rev_clock_gettime( 0, &s ); + assert( ret == 0 ); /* * Dummy code that is the subject of measurement. * We use argc to discourage compiler from removing * dead code. */ - for (int i = 0; i < 100 * argc; i++) + for( int i = 0; i < 100 * argc; i++ ) sum++; - ret = rev_clock_gettime(0, &e); - assert(ret == 0); + ret = rev_clock_gettime( 0, &e ); + assert( ret == 0 ); - assert((e.tv_nsec - s.tv_nsec) >= 0); + assert( ( e.tv_nsec - s.tv_nsec ) >= 0 ); return sum; } diff --git a/test/syscalls/cpuinfo/cpuinfo.c b/test/syscalls/cpuinfo/cpuinfo.c index d54bc5154..e2674389f 100644 --- a/test/syscalls/cpuinfo/cpuinfo.c +++ b/test/syscalls/cpuinfo/cpuinfo.c @@ -1,17 +1,17 @@ #include "../../../common/syscalls/syscalls.h" -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { struct rev_cpuinfo info; - int ret = rev_cpuinfo(&info); - assert(ret == 0); - assert(info.cores == 1); - assert(info.harts_per_core == 1); + int ret = rev_cpuinfo( &info ); + assert( ret == 0 ); + assert( info.cores == 1 ); + assert( info.harts_per_core == 1 ); return 0; } diff --git a/test/syscalls/file_io/Makefile b/test/syscalls/file_io/Makefile index b4c38c18f..ca800c56d 100644 --- a/test/syscalls/file_io/Makefile +++ b/test/syscalls/file_io/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/file_io/file_io.c b/test/syscalls/file_io/file_io.c index 7f2e8c6ea..a079a7a4c 100644 --- a/test/syscalls/file_io/file_io.c +++ b/test/syscalls/file_io/file_io.c @@ -5,12 +5,12 @@ #define BUF_SIZE 1024 -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { char buffer[BUF_SIZE]; @@ -19,22 +19,22 @@ int main() { // Open the file "test.txt" under the current directory // rev_write(STDOUT_FILENO, OpenMsg, sizeof(OpenMsg)); - int fd = rev_openat(AT_FDCWD, path, 0, O_RDONLY); + int fd = rev_openat( AT_FDCWD, path, 0, O_RDONLY ); // Read from the file - uint64_t bytesRead = rev_read(fd, buffer, 29); + uint64_t bytesRead = rev_read( fd, buffer, 29 ); // Null-terminate the buffer so we can use it as a string - buffer[bytesRead] = '\0'; + buffer[bytesRead] = '\0'; // Write to STDOUT - rev_write(STDOUT_FILENO, buffer, bytesRead); + rev_write( STDOUT_FILENO, buffer, bytesRead ); // rev_write(STDOUT_FILENO, "\n", 1); // rev_write(STDOUT_FILENO, buffer, bytesRead); // Close the file and directory // rev_write(STDOUT_FILENO, CloseMsg, sizeof(CloseMsg)); - rev_close(fd); + rev_close( fd ); // rev_write(STDOUT_FILENO, ClosedMsg, sizeof(ClosedMsg)); return 0; diff --git a/test/syscalls/getcwd/Makefile b/test/syscalls/getcwd/Makefile index d327e8006..1ba7bc365 100644 --- a/test/syscalls/getcwd/Makefile +++ b/test/syscalls/getcwd/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/getcwd/getcwd.c b/test/syscalls/getcwd/getcwd.c index e319c2b34..ed0e67f1a 100644 --- a/test/syscalls/getcwd/getcwd.c +++ b/test/syscalls/getcwd/getcwd.c @@ -1,6 +1,6 @@ -#include -#include #include "../../../common/syscalls/syscalls.h" +#include +#include int main() { /* @@ -9,9 +9,9 @@ int main() { * This is a known issue with Text data in assembly */ char buf[100]; - int result = rev_getcwd(buf, 100); + int result = rev_getcwd( buf, 100 ); - if (result != 0) { + if( result != 0 ) { return 1; } else { return 0; diff --git a/test/syscalls/mem_dump_syscalls/.gitignore b/test/syscalls/mem_dump_syscalls/.gitignore new file mode 100644 index 000000000..b348a2218 --- /dev/null +++ b/test/syscalls/mem_dump_syscalls/.gitignore @@ -0,0 +1 @@ +*_dump.txt diff --git a/test/syscalls/mem_dump_syscalls/Makefile b/test/syscalls/mem_dump_syscalls/Makefile new file mode 100644 index 000000000..d5988ca27 --- /dev/null +++ b/test/syscalls/mem_dump_syscalls/Makefile @@ -0,0 +1,27 @@ +# +# Makefile +# +# makefile: mem_dump_syscalls +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +.PHONY: src + +EXAMPLE=mem_dump_syscalls +#CC=riscv64-unknown-elf-gcc +CC="${RVCC}" +#ARCH=rv64g +ARCH=rv64gc + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).c + $(CC) -march=$(ARCH) -O0 -o $(EXAMPLE).exe $(EXAMPLE).c -static +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/syscalls/mem_dump_syscalls/mem_dump.py b/test/syscalls/mem_dump_syscalls/mem_dump.py new file mode 100755 index 000000000..ebcb9f663 --- /dev/null +++ b/test/syscalls/mem_dump_syscalls/mem_dump.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# +# rev-basic-config.py +# + +import argparse +import sst + +DEBUG_L1 = 0 +DEBUG_MEM = 0 +DEBUG_LEVEL = 10 +VERBOSE = 2 +memSize = 1024 * 1024 * 10 - 1 + +# Setup argument parser +parser = argparse.ArgumentParser(description="Run Rev SST Simulation") +parser.add_argument( + "--numCores", type=int, help="Number of Rev Cores per RevCPU", default=1 +) +parser.add_argument( + "--numHarts", type=int, help="Number of HARTs per Rev Core", default=1 +) +parser.add_argument( + "--program", help="The program executable to run in the simulation", default="a.out" +) +parser.add_argument( + "--enableMemH", + type=int, + choices=[0, 1], + help="Enable (1) or disable (0) memHierarchy backend", + default=0, +) +parser.add_argument("--verbose", type=int, help="Verbosity level", default=2) +parser.add_argument( + "--machine", help="Machine type/configuration", default="[CORES:RV64GC]" +) +parser.add_argument( + "--args", help="Command line arguments to pass to the target executable", default="" +) +parser.add_argument( + "--startSymbol", help="ELF Symbol Rev should begin execution at", default="[0:main]" +) + +# Parse arguments +args = parser.parse_args() + +# Print arguments nicely +print("Rev SST Simulation Configuration:") +for arg in vars(args): + print("\t", arg, " = ", getattr(args, arg)) + +# SST core options and parameters +clock = "2.0GHz" + +# Define the simulation components +comp_cpu = sst.Component("cpu", "revcpu.RevCPU") +comp_cpu.addParams( + { + "verbose": args.verbose, + "numCores": args.numCores, + "numHarts": args.numHarts, + "clock": clock, + "memSize": memSize, + "machine": args.machine, + "memCost": "[0:1:10]", + "program": args.program, + "startAddr": "[0:0x00000000]", + "startSymbol": args.startSymbol, + "enableMemH": args.enableMemH, + "args": args.args, + "splash": 1, + "memDumpRanges": ["range1", "range2"], + "range1.startAddr": 0x010000, + "range1.size": 0x100000, + "range2.startAddr": 0x090000, + "range2.size": 0x100, + } +) + +sst.setStatisticOutput("sst.statOutputCSV") +sst.setStatisticLoadLevel(4) +sst.enableAllStatisticsForComponentType("revcpu.RevCPU") + +# Conditional setup for memory hierarchy +if args.enableMemH: + # Create the RevMemCtrl subcomponent + comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl") + comp_lsq.addParams( + { + "verbose": "5", + "clock": "2.0Ghz", + "max_loads": 16, + "max_stores": 16, + "max_flush": 16, + "max_llsc": 16, + "max_readlock": 16, + "max_writeunlock": 16, + "max_custom": 16, + "ops_per_cycle": 16, + } + ) + comp_lsq.enableAllStatistics({"type": "sst.AccumulatorStatistic"}) + + iface = comp_lsq.setSubComponent("memIface", "memHierarchy.standardInterface") + iface.addParams({"verbose": VERBOSE}) + memctrl = sst.Component("memory", "memHierarchy.MemController") + memctrl.addParams( + { + "debug": DEBUG_MEM, + "debug_level": DEBUG_LEVEL, + "clock": "2GHz", + "verbose": VERBOSE, + "addr_range_start": 0, + "addr_range_end": memSize, + "backing": "malloc", + } + ) + + memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") + memory.addParams({"access_time": "100ns", "mem_size": "8GB"}) + + link_iface_mem = sst.Link("link_iface_mem") + link_iface_mem.connect((iface, "port", "50ps"), (memctrl, "direct_link", "50ps")) diff --git a/test/syscalls/mem_dump_syscalls/mem_dump_syscalls.c b/test/syscalls/mem_dump_syscalls/mem_dump_syscalls.c new file mode 100644 index 000000000..64279abac --- /dev/null +++ b/test/syscalls/mem_dump_syscalls/mem_dump_syscalls.c @@ -0,0 +1,10 @@ +#include "../../../common/syscalls/syscalls.h" +#include +#include + +int main() { + dump_mem_range( 0x50000, 0x55000 ); + dump_mem_range_to_file( "full_mem_dump.txt", 0, 1024 * 1024 * 10 - 1 ); + dump_stack_to_file( "stack_dump.txt" ); + dump_stack(); +} diff --git a/test/syscalls/munmap/Makefile b/test/syscalls/munmap/Makefile index 8e1032f69..66b3300f0 100644 --- a/test/syscalls/munmap/Makefile +++ b/test/syscalls/munmap/Makefile @@ -3,7 +3,7 @@ # # makefile: munmap # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/munmap/munmap.c b/test/syscalls/munmap/munmap.c index 5ed792c12..57fb58550 100644 --- a/test/syscalls/munmap/munmap.c +++ b/test/syscalls/munmap/munmap.c @@ -1,30 +1,31 @@ #include "../../../common/syscalls/syscalls.h" #include "unistd.h" // #include "sys/mman.h" -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) int main() { - uint64_t *addr; + uint64_t* addr; #define N 237 // Create an anonymous memory mapping - addr = (uint64_t *)rev_mmap( - 0, // Let rev choose the address - N * sizeof(uint64_t), - PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions - MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous - -1, // No file descriptor because it's an anonymous mapping - 0); // No offset, irrelevant for anonymous mappings + addr = (uint64_t*) rev_mmap( + 0, // Let rev choose the address + N * sizeof( uint64_t ), + PROT_READ | PROT_WRITE | PROT_EXEC, // RWX permissions + MAP_PRIVATE | MAP_ANONYMOUS, // Not shared, anonymous + -1, // No file descriptor because it's an anonymous mapping + 0 + ); // No offset, irrelevant for anonymous mappings - for (uint64_t i = 0; i < N; i++) { + for( uint64_t i = 0; i < N; i++ ) { addr[i] = i; } - for (uint64_t i = 0; i < N; i++) { - assert(addr[i] == i); + for( uint64_t i = 0; i < N; i++ ) { + assert( addr[i] == i ); } } diff --git a/test/syscalls/perf_stats/perf_stats.c b/test/syscalls/perf_stats/perf_stats.c index a165b7057..77708df45 100644 --- a/test/syscalls/perf_stats/perf_stats.c +++ b/test/syscalls/perf_stats/perf_stats.c @@ -2,21 +2,26 @@ #include #include -void print(const char *prefix, unsigned long x) { +#define VERBOSE 0 + +void print( const char* prefix, unsigned long x ) { char buf[256]; - sprintf(buf, "%s%lu\n", prefix, x); - rev_write(STDOUT_FILENO, buf, strlen(buf)); + sprintf( buf, "%s%lu\n", prefix, x ); + rev_write( STDOUT_FILENO, buf, strlen( buf ) ); } -int main(int argc, char *argv[]) { - int ret = 0; - struct rev_stats rs1,rs2; - rev_perf_stats(&rs1); - for(int i = 0; i < 10 * argc; i++) - ret++; - rev_perf_stats(&rs2); +int main( int argc, char* argv[] ) { + int ret = 0; + struct rev_stats rs1, rs2; + rev_perf_stats( &rs1 ); + for( int i = 0; i < 10 * argc; i++ ) + ret++; + rev_perf_stats( &rs2 ); + +#if VERBOSE + print( "instructions: ", rs2.instructions - rs1.instructions ); + print( "cycles: ", rs2.cycles - rs1.cycles ); +#endif - print("instructions: ", rs2.instructions - rs1.instructions); - print("cycles: ", rs2.cycles - rs1.cycles); return ret; } diff --git a/test/syscalls/printf/Makefile b/test/syscalls/printf/Makefile index 17c88b265..8225441ed 100644 --- a/test/syscalls/printf/Makefile +++ b/test/syscalls/printf/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/printf/printf.c b/test/syscalls/printf/printf.c index 7b274f3aa..10acd76d8 100644 --- a/test/syscalls/printf/printf.c +++ b/test/syscalls/printf/printf.c @@ -1,29 +1,29 @@ #include "../../../common/syscalls/syscalls.h" -#include #include "printf.h" +#include int main() { - const char msg[10] = "Greetings\n"; - ssize_t bytes_written = rev_write(STDOUT_FILENO, msg, sizeof(msg)); + const char msg[10] = "Greetings\n"; + ssize_t bytes_written = rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); - if( bytes_written < 0 ){ - rev_exit(1); + if( bytes_written < 0 ) { + rev_exit( 1 ); } - const char msg2[67] = "Greetings - this is a much longer text string. Just larger than 64\n"; - ssize_t bytes_written2 = rev_write(STDOUT_FILENO, msg2, sizeof(msg2)); + const char msg2[67] = "Greetings - this is a much longer text string. Just larger than 64\n"; + ssize_t bytes_written2 = rev_write( STDOUT_FILENO, msg2, sizeof( msg2 ) ); - if( bytes_written2 < 0 ){ - rev_exit(1); + if( bytes_written2 < 0 ) { + rev_exit( 1 ); } - printf("Test: %s\n", msg2); + printf( "Test: %s\n", msg2 ); int i = 42; - printf("The meaning of life is %d\n", i); + printf( "The meaning of life is %d\n", i ); - //The test below fails - we are reaching into invalid address space, this appears unrealted to most recent changes -/* const char msg3[98] = "Greetings - this is a much longer message and some nice text, in fact, it is bigger than 64 bytes\n"; + //The test below fails - we are reaching into invalid address space, this appears unrealted to most recent changes + /* const char msg3[98] = "Greetings - this is a much longer message and some nice text, in fact, it is bigger than 64 bytes\n"; ssize_t bytes_written3 = rev_write(STDOUT_FILENO, msg3, sizeof(msg3)); if( bytes_written3 < 0 ){ diff --git a/test/syscalls/printf/printf.h b/test/syscalls/printf/printf.h index 891c006e4..e952e4864 100644 --- a/test/syscalls/printf/printf.h +++ b/test/syscalls/printf/printf.h @@ -1,10 +1,10 @@ // See LICENSE for license details. -#include -#include +#include #include +#include #include -#include +#include //#include //#include "util.h" #include "../../../common/syscalls/syscalls.h" @@ -18,122 +18,109 @@ extern volatile uint64_t fromhost; #define NUM_COUNTERS 2 static uintptr_t counters[NUM_COUNTERS]; -static char* counter_names[NUM_COUNTERS]; +static char* counter_names[NUM_COUNTERS]; -void printstr(const char* s) -{ - ssize_t bytes_written2 = rev_write(STDOUT_FILENO, s, strlen(s)); +void printstr( const char* s ) { + ssize_t bytes_written2 = rev_write( STDOUT_FILENO, s, strlen( s ) ); } #undef putchar -int putchar(int ch) -{ - static __thread char buf[64] __attribute__((aligned(64))); - static __thread int buflen = 0; - buf[buflen++] = ch; +int putchar( int ch ) { + static __thread char buf[64] __attribute__( ( aligned( 64 ) ) ); + static __thread int buflen = 0; + + buf[buflen++] = ch; - if (ch == '\n' || buflen == sizeof(buf)) - { - ssize_t bytes_written2 = rev_write(STDOUT_FILENO, buf, buflen); - buflen = 0; + if( ch == '\n' || buflen == sizeof( buf ) ) { + ssize_t bytes_written2 = rev_write( STDOUT_FILENO, buf, buflen ); + buflen = 0; } return 0; } -void printhex(uint64_t x) -{ +void printhex( uint64_t x ) { char str[17]; - int i; - for (i = 0; i < 16; i++) - { - str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); + int i; + for( i = 0; i < 16; i++ ) { + str[15 - i] = ( x & 0xF ) + ( ( x & 0xF ) < 10 ? '0' : 'a' - 10 ); x >>= 4; } str[16] = 0; - printstr(str); + printstr( str ); } -static inline void printnum(void (*putch)(int, void**), void **putdat, - unsigned long long num, unsigned base, int width, int padc) -{ - unsigned digs[sizeof(num)*CHAR_BIT]; - int pos = 0; +static inline void + printnum( void ( *putch )( int, void** ), void** putdat, unsigned long long num, unsigned base, int width, int padc ) { + unsigned digs[sizeof( num ) * CHAR_BIT]; + int pos = 0; - while (1) - { + while( 1 ) { digs[pos++] = num % base; - if (num < base) + if( num < base ) break; num /= base; } - while (width-- > pos) - putch(padc, putdat); + while( width-- > pos ) + putch( padc, putdat ); - while (pos-- > 0) - putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + while( pos-- > 0 ) + putch( digs[pos] + ( digs[pos] >= 10 ? 'a' - 10 : '0' ), putdat ); } -static unsigned long long getuint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, unsigned long long); - else if (lflag) - return va_arg(*ap, unsigned long); +static unsigned long long getuint( va_list* ap, int lflag ) { + if( lflag >= 2 ) + return va_arg( *ap, unsigned long long ); + else if( lflag ) + return va_arg( *ap, unsigned long ); else - return va_arg(*ap, unsigned int); + return va_arg( *ap, unsigned int ); } -static long long getint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, long long); - else if (lflag) - return va_arg(*ap, long); +static long long getint( va_list* ap, int lflag ) { + if( lflag >= 2 ) + return va_arg( *ap, long long ); + else if( lflag ) + return va_arg( *ap, long ); else - return va_arg(*ap, int); + return va_arg( *ap, int ); } -static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) -{ +static void vprintfmt( void ( *putch )( int, void** ), void** putdat, const char* fmt, va_list ap ) { register const char* p; - const char* last_fmt; - register int ch, err; - unsigned long long num; - int base, lflag, width, precision, altflag; - char padc; - - while (1) { - while ((ch = *(unsigned char *) fmt) != '%') { - if (ch == '\0') + const char* last_fmt; + register int ch, err; + unsigned long long num; + int base, lflag, width, precision, altflag; + char padc; + + while( 1 ) { + while( ( ch = *(unsigned char*) fmt ) != '%' ) { + if( ch == '\0' ) return; fmt++; - putch(ch, putdat); + putch( ch, putdat ); } fmt++; // Process a %-escape sequence - last_fmt = fmt; - padc = ' '; - width = -1; + last_fmt = fmt; + padc = ' '; + width = -1; precision = -1; - lflag = 0; - altflag = 0; + lflag = 0; + altflag = 0; reswitch: - switch (ch = *(unsigned char *) fmt++) { + switch( ch = *(unsigned char*) fmt++ ) { // flag to pad on the right - case '-': - padc = '-'; - goto reswitch; - + case '-': padc = '-'; goto reswitch; + // flag to pad with 0's instead of spaces - case '0': - padc = '0'; - goto reswitch; + case '0': padc = '0'; goto reswitch; // width field case '1': @@ -145,20 +132,18 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt case '7': case '8': case '9': - for (precision = 0; ; ++fmt) { + for( precision = 0;; ++fmt ) { precision = precision * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') + ch = *fmt; + if( ch < '0' || ch > '9' ) break; } goto process_precision; - case '*': - precision = va_arg(ap, int); - goto process_precision; + case '*': precision = va_arg( ap, int ); goto process_precision; case '.': - if (width < 0) + if( width < 0 ) width = 0; goto reswitch; @@ -167,49 +152,43 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt goto reswitch; process_precision: - if (width < 0) + if( width < 0 ) width = precision, precision = -1; goto reswitch; // long flag (doubled for long long) - case 'l': - lflag++; - goto reswitch; + case 'l': lflag++; goto reswitch; // character - case 'c': - putch(va_arg(ap, int), putdat); - break; + case 'c': putch( va_arg( ap, int ), putdat ); break; // string case 's': - if ((p = va_arg(ap, char *)) == NULL) + if( ( p = va_arg( ap, char* ) ) == NULL ) p = "(null)"; - if (width > 0 && padc != '-') - for (width -= strnlen(p, precision); width > 0; width--) - putch(padc, putdat); - for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { - putch(ch, putdat); + if( width > 0 && padc != '-' ) + for( width -= strnlen( p, precision ); width > 0; width-- ) + putch( padc, putdat ); + for( ; ( ch = *p ) != '\0' && ( precision < 0 || --precision >= 0 ); width-- ) { + putch( ch, putdat ); p++; } - for (; width > 0; width--) - putch(' ', putdat); + for( ; width > 0; width-- ) + putch( ' ', putdat ); break; // (signed) decimal case 'd': - num = getint(&ap, lflag); - if ((long long) num < 0) { - putch('-', putdat); + num = getint( &ap, lflag ); + if( (long long) num < 0 ) { + putch( '-', putdat ); num = -(long long) num; } base = 10; goto signed_number; // unsigned decimal - case 'u': - base = 10; - goto unsigned_number; + case 'u': base = 10; goto unsigned_number; // (unsigned) octal case 'o': @@ -221,63 +200,59 @@ static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt case 'p': //static_assert(sizeof(long) == sizeof(void*)); lflag = 1; - putch('0', putdat); - putch('x', putdat); + putch( '0', putdat ); + putch( 'x', putdat ); /* fall through to 'x' */ // (unsigned) hexadecimal case 'x': base = 16; unsigned_number: - num = getuint(&ap, lflag); + num = getuint( &ap, lflag ); signed_number: - printnum(putch, putdat, num, base, width, padc); + printnum( putch, putdat, num, base, width, padc ); break; // escaped '%' character - case '%': - putch(ch, putdat); - break; - + case '%': putch( ch, putdat ); break; + // unrecognized escape sequence - just print it literally default: - putch('%', putdat); + putch( '%', putdat ); fmt = last_fmt; break; } } } -int printf(const char* fmt, ...) -{ +int printf( const char* fmt, ... ) { va_list ap; - va_start(ap, fmt); + va_start( ap, fmt ); - vprintfmt((void*)putchar, 0, fmt, ap); + vprintfmt( (void*) putchar, 0, fmt, ap ); - va_end(ap); - return 0; // incorrect return value, but who cares, anyway? + va_end( ap ); + return 0; // incorrect return value, but who cares, anyway? } -int sprintf(char* str, const char* fmt, ...) -{ +int sprintf( char* str, const char* fmt, ... ) { va_list ap; - char* str0 = str; - va_start(ap, fmt); - - void sprintf_putch(int ch, void** data) - { - char** pstr = (char**)data; - **pstr = ch; - (*pstr)++; + char* str0 = str; + va_start( ap, fmt ); + + void sprintf_putch( int ch, void** data ) { + char** pstr = (char**) data; + **pstr = ch; + ( *pstr )++; } - vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + vprintfmt( sprintf_putch, (void**) &str, fmt, ap ); *str = 0; - va_end(ap); + va_end( ap ); return str - str0; } + /* void* memcpy(void* dest, const void* src, size_t len) { diff --git a/test/syscalls/vector/Makefile b/test/syscalls/vector/Makefile index 34e6df887..aa4fde4a8 100644 --- a/test/syscalls/vector/Makefile +++ b/test/syscalls/vector/Makefile @@ -3,7 +3,7 @@ # # makefile: vector # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/vector/rev-test.py b/test/syscalls/vector/rev-test.py old mode 100644 new mode 100755 index 863588a14..87c235b67 --- a/test/syscalls/vector/rev-test.py +++ b/test/syscalls/vector/rev-test.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -8,7 +9,6 @@ # rev-test.py # -import os import sst # Define SST core options @@ -22,15 +22,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 10, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : "vector.exe", # Target executable - "splash" : 1 # Display the splash message + "verbose": 10, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": "vector.exe", # Target executable + "splash": 1 # Display the splash message }) # sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/syscalls/vector/vector.c b/test/syscalls/vector/vector.c index eb571af82..ff81eeec6 100644 --- a/test/syscalls/vector/vector.c +++ b/test/syscalls/vector/vector.c @@ -1,6 +1,7 @@ #include + int main() { std::vector v; - v.push_back(1); + v.push_back( 1 ); return 0; } diff --git a/test/syscalls/write/Makefile b/test/syscalls/write/Makefile index 7228ab514..777f77638 100644 --- a/test/syscalls/write/Makefile +++ b/test/syscalls/write/Makefile @@ -3,7 +3,7 @@ # # makefile: ex2 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/syscalls/write/write.c b/test/syscalls/write/write.c index cddf5a59e..41ad2e7e2 100644 --- a/test/syscalls/write/write.c +++ b/test/syscalls/write/write.c @@ -3,21 +3,21 @@ int main() { - const char msg[10] = "Greetings\n"; - ssize_t bytes_written = rev_write(STDOUT_FILENO, msg, sizeof(msg)); + const char msg[10] = "Greetings\n"; + ssize_t bytes_written = rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); - if( bytes_written < 0 ){ - rev_exit(1); + if( bytes_written < 0 ) { + rev_exit( 1 ); } - const char msg2[67] = "Greetings - this is a much longer text string. Just larger than 64\n"; - ssize_t bytes_written2 = rev_write(STDOUT_FILENO, msg2, sizeof(msg2)); + const char msg2[67] = "Greetings - this is a much longer text string. Just larger than 64\n"; + ssize_t bytes_written2 = rev_write( STDOUT_FILENO, msg2, sizeof( msg2 ) ); - if( bytes_written2 < 0 ){ - rev_exit(1); + if( bytes_written2 < 0 ) { + rev_exit( 1 ); } - //The test below fails - we are reaching into invalid address space, this appears unrealted to most recent changes -/* const char msg3[98] = "Greetings - this is a much longer message and some nice text, in fact, it is bigger than 64 bytes\n"; + //The test below fails - we are reaching into invalid address space, this appears unrealted to most recent changes + /* const char msg3[98] = "Greetings - this is a much longer message and some nice text, in fact, it is bigger than 64 bytes\n"; ssize_t bytes_written3 = rev_write(STDOUT_FILENO, msg3, sizeof(msg3)); if( bytes_written3 < 0 ){ diff --git a/test/threading/pthreads/CMakeLists.txt b/test/threading/pthreads/CMakeLists.txt index 7bde189a7..4783fcab1 100644 --- a/test/threading/pthreads/CMakeLists.txt +++ b/test/threading/pthreads/CMakeLists.txt @@ -1,2 +1,2 @@ -add_rev_test(PTHREAD_ARG_PASSING pthread_arg_passing 30 "rv64;memh;multithreading;pthreads;all") -add_rev_test(PTHREAD_BASIC pthread_basic 30 "rv64;memh;multithreading;pthreads;all") +add_rev_test(PTHREAD_ARG_PASSING pthread_arg_passing 30 "rv64;memh;multithreading;pthreads") +add_rev_test(PTHREAD_BASIC pthread_basic 30 "test_level=2;rv64;memh;multithreading;pthreads") diff --git a/test/threading/pthreads/permute/Makefile b/test/threading/pthreads/permute/Makefile index 48ca0c899..1235d2b85 100644 --- a/test/threading/pthreads/permute/Makefile +++ b/test/threading/pthreads/permute/Makefile @@ -3,7 +3,7 @@ # # makefile: simple_pthreads # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -15,7 +15,7 @@ TEST_NAME = simple_pthreads REV_ROOT=../../../.. CC=${RVCC} -OBJDUMP=${RISCV}/bin/riscv64-unknown-elf-objdump -D --source +OBJDUMP=${RISCV}/bin/riscv64-unknown-elf-objdump -D --source INCLUDE = -I$(REV_ROOT)/common/syscalls -I$(REV_ROOT)/test/include # permute architectures diff --git a/test/threading/pthreads/permute/rev-test-pthread.py b/test/threading/pthreads/permute/rev-test-pthread.py old mode 100644 new mode 100755 index 98a689bd4..400e3ed60 --- a/test/threading/pthreads/permute/rev-test-pthread.py +++ b/test/threading/pthreads/permute/rev-test-pthread.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -10,16 +11,17 @@ import os import sst +import sys # Environment settings rev_exe = os.getenv("REV_EXE", "") -arch = os.getenv("ARCH","RV32I").upper() +arch = os.getenv("ARCH", "RV32I").upper() simNodes = int(os.getenv('SIM_NODES', 1)) -numHarts = os.getenv("NUM_HARTS",1) +numHarts = os.getenv("NUM_HARTS", 1) -if ( rev_exe == "" ): - print("ERROR: REV_EXE is not set",file=sys.stderr); - exit(1); +if (rev_exe == ""): + print("ERROR: REV_EXE is not set", file=sys.stderr) + exit(1) print(f"REV_EXE={rev_exe}") print(f"ARCH={arch}") @@ -35,23 +37,23 @@ # Define the simulation components # Instantiate all the CPUs for i in range(0, simNodes): - print("Building "+ str(i)) - comp_cpu = sst.Component("cpu" + str(i), "revcpu.RevCPU") - comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "numHarts" : numHarts, # Number of harts - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : f"[CORES:{arch}]", # Core:Config; common arch for all - "startAddr" : "[CORES:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : rev_exe, # Target executable - "splash" : 0, # Display the splash message - # "trcOp": "slli", # base command for tracing [default: slli] - # "trcLimit": 0, # Maximum number of trace lines [default: 0] - # "trcStartCycle" : 0 # Starting trace cycle [default: 0] - }) + print("Building " + str(i)) + comp_cpu = sst.Component("cpu" + str(i), "revcpu.RevCPU") + comp_cpu.addParams({ + "verbose": 5, # Verbosity + "numCores": 1, # Number of cores + "numHarts": numHarts, # Number of harts + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": f"[CORES:{arch}]", # Core:Config; common arch for all + "startAddr": "[CORES:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": rev_exe, # Target executable + "splash": 0, # Display the splash message + # "trcOp": "slli", # base command for tracing [default: slli] + # "trcLimit": 0, # Maximum number of trace lines [default: 0] + # "trcStartCycle": 0 # Starting trace cycle [default: 0] + }) # comp_cpu.enableAllStatistics() # sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/threading/pthreads/permute/simple_pthreads.c b/test/threading/pthreads/permute/simple_pthreads.c index ad131f4ca..4882a01c6 100644 --- a/test/threading/pthreads/permute/simple_pthreads.c +++ b/test/threading/pthreads/permute/simple_pthreads.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I, RV64G * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,9 +11,9 @@ * */ -#include "stdlib.h" -#include "stdint.h" #include "rev-macros.h" +#include "stdint.h" +#include "stdlib.h" #include "syscalls.h" #define assert TRACE_ASSERT @@ -22,36 +22,39 @@ volatile unsigned thread1_counter = 0; volatile unsigned thread2_counter = 0; volatile unsigned thread3_counter = 0; -void *thread1() { - for (int i=0;i<10;i++) thread1_counter++; +void* thread1() { + for( int i = 0; i < 10; i++ ) + thread1_counter++; return 0; } -void *thread2() { - for (int i=0;i<10;i++) thread2_counter+=2; +void* thread2() { + for( int i = 0; i < 10; i++ ) + thread2_counter += 2; return 0; } -void *thread3() { - for (int i=0;i<10;i++) thread3_counter+=3; +void* thread3() { + for( int i = 0; i < 10; i++ ) + thread3_counter += 3; return 0; } -int main(int argc, char **argv){ +int main( int argc, char** argv ) { TRACE_ON - rev_pthread_t tid1, tid2, tid3; - rev_pthread_create(&tid1, NULL, (void *)thread1, NULL); - rev_pthread_create(&tid2, NULL, (void *)thread2, NULL); - rev_pthread_create(&tid3, NULL, (void *)thread3, NULL); - - rev_pthread_join(tid1); - rev_pthread_join(tid2); - rev_pthread_join(tid3); - - TRACE_ASSERT(thread1_counter==10); - TRACE_ASSERT(thread2_counter==20); - TRACE_ASSERT(thread3_counter==30); - - TRACE_OFF + rev_pthread_t tid1, tid2, tid3; + rev_pthread_create( &tid1, NULL, (void*) thread1, NULL ); + rev_pthread_create( &tid2, NULL, (void*) thread2, NULL ); + rev_pthread_create( &tid3, NULL, (void*) thread3, NULL ); + + rev_pthread_join( tid1 ); + rev_pthread_join( tid2 ); + rev_pthread_join( tid3 ); + + TRACE_ASSERT( thread1_counter == 10 ); + TRACE_ASSERT( thread2_counter == 20 ); + TRACE_ASSERT( thread3_counter == 30 ); + + TRACE_OFF return 0; } diff --git a/test/threading/pthreads/pthread_arg_passing/Makefile b/test/threading/pthreads/pthread_arg_passing/Makefile index 28ea3c2b6..3d7243518 100644 --- a/test/threading/pthreads/pthread_arg_passing/Makefile +++ b/test/threading/pthreads/pthread_arg_passing/Makefile @@ -3,7 +3,7 @@ # # makefile: pthread_arg_passing # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/threading/pthreads/pthread_arg_passing/pthread_arg_passing.c b/test/threading/pthreads/pthread_arg_passing/pthread_arg_passing.c index 71a2a616a..e9e3cd06a 100644 --- a/test/threading/pthreads/pthread_arg_passing/pthread_arg_passing.c +++ b/test/threading/pthreads/pthread_arg_passing/pthread_arg_passing.c @@ -1,11 +1,11 @@ #include "../../../../common/syscalls/syscalls.h" -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) struct ThreadInfo { int a; @@ -13,46 +13,46 @@ struct ThreadInfo { }; // create the function to be executed as a thread -void *thread1(struct ThreadInfo *info) { +void* thread1( struct ThreadInfo* info ) { const char msg[29] = "Hello from thread1 function\n"; // Append tid to msg - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); // Convert the number to a string - assert(info->a == 1); + assert( info->a == 1 ); return 0; } -void *thread2(struct ThreadInfo *info) { +void* thread2( struct ThreadInfo* info ) { const char msg[29] = "Howdy from thread2 function\n"; // Append tid to msg - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); - assert(info->a == 2); + assert( info->a == 2 ); // Convert the number to a string return 0; } -int main(int argc, char **argv) { +int main( int argc, char** argv ) { // Create three instances of structs to pass to threads struct ThreadInfo thread1_info, thread2_info; - thread1_info.a = 1; - thread2_info.a = 2; + thread1_info.a = 1; + thread2_info.a = 2; const char first_msg[23] = "Welcome to the circus\n"; - rev_write(STDOUT_FILENO, first_msg, sizeof(first_msg)); + rev_write( STDOUT_FILENO, first_msg, sizeof( first_msg ) ); // create the thread objs rev_pthread_t tid1, tid2; // uint64_t thr = 1; // uint64_t thr2 = 2; // start the threads - rev_pthread_create(&tid1, NULL, (void *)thread1, &thread1_info); - rev_pthread_create(&tid2, NULL, (void *)thread2, &thread2_info); + rev_pthread_create( &tid1, NULL, (void*) thread1, &thread1_info ); + rev_pthread_create( &tid2, NULL, (void*) thread2, &thread2_info ); - rev_pthread_join(tid1); - rev_pthread_join(tid2); + rev_pthread_join( tid1 ); + rev_pthread_join( tid2 ); const char msg[26] = "Bonjour from main thread\n"; - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); // rev_exit(99); return 0; } diff --git a/test/threading/pthreads/pthread_basic/Makefile b/test/threading/pthreads/pthread_basic/Makefile index df34c5cca..6686970cd 100644 --- a/test/threading/pthreads/pthread_basic/Makefile +++ b/test/threading/pthreads/pthread_basic/Makefile @@ -3,7 +3,7 @@ # # makefile: pthread_basic # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/threading/pthreads/pthread_basic/pthread_basic.c b/test/threading/pthreads/pthread_basic/pthread_basic.c index bd516c2a6..20108cdf9 100644 --- a/test/threading/pthreads/pthread_basic/pthread_basic.c +++ b/test/threading/pthreads/pthread_basic/pthread_basic.c @@ -1,48 +1,48 @@ #include "../../../../common/syscalls/syscalls.h" -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) // create the function to be executed as a thread -void *thread1() { +void* thread1() { const char msg[29] = "Hello from thread1 function\n"; // Append tid to msg - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); // Convert the number to a string return 0; } -void *thread2() { +void* thread2() { const char msg[29] = "Howdy from thread2 function\n"; // Append tid to msg - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); // Convert the number to a string return 0; } -int main(int argc, char **argv) { +int main( int argc, char** argv ) { const char first_msg[23] = "Welcome to the circus\n"; - rev_write(STDOUT_FILENO, first_msg, sizeof(first_msg)); + rev_write( STDOUT_FILENO, first_msg, sizeof( first_msg ) ); // create the thread objs rev_pthread_t tid1, tid2; // uint64_t thr = 1; // uint64_t thr2 = 2; // start the threads - rev_pthread_create(&tid1, NULL, (void *)thread1, NULL); - rev_pthread_create(&tid2, NULL, (void *)thread2, NULL); + rev_pthread_create( &tid1, NULL, (void*) thread1, NULL ); + rev_pthread_create( &tid2, NULL, (void*) thread2, NULL ); const char joined_msg[76] = "thread w/ tid1 has finished and been joined. " "Now proceeding with execution\n"; - rev_pthread_join(tid1); - rev_write(STDOUT_FILENO, joined_msg, sizeof(joined_msg)); - rev_pthread_join(tid2); + rev_pthread_join( tid1 ); + rev_write( STDOUT_FILENO, joined_msg, sizeof( joined_msg ) ); + rev_pthread_join( tid2 ); const char msg[26] = "Bonjour from main thread\n"; - rev_write(STDOUT_FILENO, msg, sizeof(msg)); + rev_write( STDOUT_FILENO, msg, sizeof( msg ) ); return 0; } diff --git a/test/tls/Makefile b/test/tls/Makefile index 837fcff09..d0f1dcff0 100644 --- a/test/tls/Makefile +++ b/test/tls/Makefile @@ -3,7 +3,7 @@ # # makefile: basic-tls # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/tls/basic-tls.c b/test/tls/basic-tls.c index bbe2f2ede..d5445bae2 100644 --- a/test/tls/basic-tls.c +++ b/test/tls/basic-tls.c @@ -3,6 +3,6 @@ __thread int tls_var = 42; int main() { - rev_write(0, &tls_var, sizeof(tls_var)); + rev_write( 0, &tls_var, sizeof( tls_var ) ); return 0; } diff --git a/test/tracer/.gitignore b/test/tracer/.gitignore index 7c255505e..3f83b0d92 100644 --- a/test/tracer/.gitignore +++ b/test/tracer/.gitignore @@ -4,3 +4,5 @@ *.trc *.d *.dis +*.revlog +*.tmplog diff --git a/test/tracer/Makefile b/test/tracer/Makefile index 1e19c3671..78a5d7632 100644 --- a/test/tracer/Makefile +++ b/test/tracer/Makefile @@ -3,26 +3,50 @@ # # makefile: tracer # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # # See LICENSE in the top level directory for licensing details # -.PHONY: src - EXAMPLE ?= tracer -TLIST ?= $(addprefix $(EXAMPLE),.mem.rv32i .mem.rv64g .memh.rv32i .memh.rv64g) +REVCFG = $(realpath ../rev-model-options-config.py) +NUMCORES ?= 1 +NUMHARTS ?= 1 + +# Set to compile and simulate for spike +# USE_SPIKE := 1 +ifdef USE_SPIKE + SPIKE = /opt/homebrew/bin/spike + OPTS += -DSPIKE +endif + +# C tests +ALLTESTS := $(addprefix $(EXAMPLE),.mem.rv32.c .mem.rv64.c .memh.rv32.c .memh.rv64.c) +# C++ tests +ALLTESTS += $(addprefix $(EXAMPLE),.mem.rv32.cpp .mem.rv64.cpp .memh.rv32.cpp .memh.rv64.cpp) + +TLIST = $(ALLTESTS) +# TLIST = $(filter-out %rv32.c %rv32.cpp,$(ALLTESTS)) +# TLIST = $(filter %.mem.rv64.cpp %.mem.rv32.cpp,$(ALLTESTS)) EXES = $(addsuffix .exe,$(TLIST)) DIASMS = $(addsuffix .dis,$(TLIST)) +ifndef USE_SPIKE LOGS = $(addsuffix .log,$(TLIST)) +REVLOGS = $(addsuffix .revlog,$(TLIST)) +else + +endif -TARGS = $(EXES) $(DIASMS) $(LOGS) +TARGS = $(EXES) $(DIASMS) $(LOGS) $(REVLOGS) CC=${RVCC} -OBJDUMP=${RISCV}/bin/riscv64-unknown-elf-objdump -D --source +CXX=${RVCXX} +REVPRINT=$(realpath ../../scripts/rev-print.py) + +OBJDUMP=${RISCV}/bin/riscv64-unknown-elf-objdump -D --source INCLUDE = -I../../common/syscalls -I../include all: $(TARGS) @@ -33,31 +57,50 @@ compile: $(EXES) $(DIASMS) %.dis: %.exe $(OBJDUMP) $< > $@ -%.rv32i.exe: ARCH=rv32i -%.rv32i.exe: OPTS=-mabi=ilp32 +%.c.exe: GCC = $(CC) +%.cpp.exe: GCC = $(CXX) -%.rv64g.exe: ARCH=rv64g -%.rv64g.exe: OPTS=-DRV64G +%.rv32.c.exe %.rv32.cpp.exe: ARCH=rv32i +%.rv32.c.exe %.rv32.cpp.exe: OPTS += -mabi=ilp32 -%.mem.rv32i.log: REVCFG=./rev-test-tracer.py -%.memh.rv32i.log: REVCFG=./rev-test-tracer-memh.py +%.rv64.c.exe %.rv64.cpp.exe: ARCH=rv64gc +%.rv64.c.exe %.rv64.cpp.exe: OPTS +=-DRV64G -%.mem.rv64g.log: REVCFG=./rev-test-tracer.py -%.memh.rv64g.log: REVCFG=./rev-test-tracer-memh.py +%.mem.rv32.c.log %.mem.rv32.cpp.log: MEMH=0 +%.memh.rv32.c.log %.memh.rv32.cpp.log: MEMH=1 -%.exe: tracer.c - $(CC) -g -O0 -march=$(ARCH) $(OPTS) $(INCLUDE) -o $@ $< +%.mem.rv64.c.log %.mem.rv64.cpp.log: MEMH=0 +%.memh.rv64.c.log %.memh.rv64.cpp.log: MEMH=1 + +%.exe: $(EXAMPLE).c + $(GCC) -g -O2 -march=$(ARCH) $(OPTS) $(INCLUDE) -o $@ $< + +%.rv32.c.log %.rv32.cpp.log: ARCH=rv32g +%.rv64.c.log %.rv64.cpp.log: ARCH=rv64gc -%.rv64g.log: ARCH=rv64g -%.rv32i.log: ARCH=rv32i %.log: %.exe @$(eval tmp := $(basename $@).tmplog) - ARCH=$(ARCH) REV_EXE=$< sst --add-lib-path=../../build/src $(REVCFG) > $(tmp) + sst --add-lib-path=../../build/src ../rev-model-options-config.py -- \ + --enableMemH=$(MEMH) --trcStartCycle=1 --verbose=5 --program=$< --machine=CORES:$(ARCH)_zicntr \ + --numCores=$(NUMCORES) --numHarts=$(NUMHARTS) > $(tmp) mv $(tmp) $@ -.PHONY: clean +%.revlog: %.log + $(REVPRINT) -l $< > $@ + +.PHONY: clean help clean: - rm -f $(EXES) $(DIASMS) $(LOGS) *.log.tmp + rm -f $(TARGS) *.tmplog + +help: + @echo make + @echo make compile + @echo make NUMHARTS=2 + @echo make NUMCORES=2 + @echo make USE_SPIKE=1 + @echo make TLIST=\"tracer.mem.rv32.c tracer.mem.rv64.c\" + @echo available tests: + @echo $(ALLTESTS) #-- EOF diff --git a/test/tracer/README.md b/test/tracer/README.md index 3c2ce684f..c960ae8e5 100644 --- a/test/tracer/README.md +++ b/test/tracer/README.md @@ -1,5 +1,5 @@ These tests demostrate the Rev Tracer usage. -For more details see /Documentation/Tracer.md +For more details see /Documentation/Tracer.md To build and run these samples simply: make clean; make diff --git a/test/tracer/rev-test-tracer-memh.py b/test/tracer/rev-test-tracer-memh.py deleted file mode 100644 index e3153302d..000000000 --- a/test/tracer/rev-test-tracer-memh.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC -# All Rights Reserved -# contact@tactcomplabs.com -# -# See LICENSE in the top level directory for licensing details -# -# rev-test-tracer.py -# - -import os -import sst - -# Environment settings -sim_nodes = int(os.getenv('SIM_NODES', 1)) -rev_exe = os.getenv("REV_EXE", "") -arch = os.getenv("ARCH","RV32I").upper() -if ( rev_exe == "" ): - print("ERROR: REV_EXE is not set",file=sys.stderr); - exit(1); - -print(f"SIM_NODES={sim_nodes}") -print(f"ARCH={arch}") -print(f"REV_EXE={rev_exe}") - -# memh settings -DEBUG_MEM = 0 -DEBUG_LEVEL = 10 -VERBOSE = 2 -MEM_SIZE = 1024*1024*1024-1 - -# Define SST core options -sst.setProgramOption("timebase", "1ps") - -# Tell SST what statistics handling we want -sst.setStatisticLoadLevel(4) - -# Define the simulation components -# Instantiate all the CPUs -for i in range(0, sim_nodes): - print("Building "+ str(i)) - comp_cpu = sst.Component("cpu" + str(i), "revcpu.RevCPU") - comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : f"[CORES:{arch}]", # Core:Config; RV32I for all - "startAddr" : "[CORES:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : rev_exe, # Target executable - "enable_memH" : 1, # Enable memHierarchy support - "splash" : 1, # Display the splash message - # "trcOp": "slli", # base command for tracing [default: slli] - # "trcLimit": 0, # Maximum number of trace lines [default: 0] - # "trcStartCycle" : 0 # Starting trace cycle [default: 0] - }) -# comp_cpu.enableAllStatistics() - -# Create the RevMemCtrl subcomponent -comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl"); -comp_lsq.addParams({ - "verbose" : "5", - "clock" : "2.0Ghz", - "max_loads" : 16, - "max_stores" : 16, - "max_flush" : 16, - "max_llsc" : 16, - "max_readlock" : 16, - "max_writeunlock" : 16, - "max_custom" : 16, - "ops_per_cycle" : 16 -}) -# comp_lsq.enableAllStatistics({"type":"sst.AccumulatorStatistic"}) - -iface = comp_lsq.setSubComponent("memIface", "memHierarchy.standardInterface") -iface.addParams({ - "verbose" : VERBOSE -}) - - -memctrl = sst.Component("memory", "memHierarchy.MemController") -memctrl.addParams({ - "debug" : DEBUG_MEM, - "debug_level" : DEBUG_LEVEL, - "clock" : "2GHz", - "verbose" : VERBOSE, - "addr_range_start" : 0, - "addr_range_end" : MEM_SIZE, - "backing" : "malloc" -}) - -memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") -memory.addParams({ - "access_time" : "100ns", - "mem_size" : "8GB" -}) - -# sst.setStatisticOutput("sst.statOutputCSV") -# sst.enableAllStatisticsForAllComponents() -# sst.enableAllStatisticsForAllComponents() - -link_iface_mem = sst.Link("link_iface_mem") -link_iface_mem.connect( (iface, "port", "50ps"), (memctrl, "direct_link", "50ps") ) - -# EOF diff --git a/test/tracer/rev-test-tracer.py b/test/tracer/rev-test-tracer.py deleted file mode 100644 index 1ee151c32..000000000 --- a/test/tracer/rev-test-tracer.py +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC -# All Rights Reserved -# contact@tactcomplabs.com -# -# See LICENSE in the top level directory for licensing details -# -# rev-test-tracer.py -# - -import os -import sst - -# Environment settings -sim_nodes = int(os.getenv('SIM_NODES', 1)) -rev_exe = os.getenv("REV_EXE", "") -arch = os.getenv("ARCH","RV32I").upper() -if ( rev_exe == "" ): - print("ERROR: REV_EXE is not set",file=sys.stderr); - exit(1); - -print(f"SIM_NODES={sim_nodes}") -print(f"ARCH={arch}") -print(f"REV_EXE={rev_exe}") - -# Define SST core options -sst.setProgramOption("timebase", "1ps") - -# Tell SST what statistics handling we want -sst.setStatisticLoadLevel(4) - -# Define the simulation components -# Instantiate all the CPUs -for i in range(0, sim_nodes): - print("Building "+ str(i)) - comp_cpu = sst.Component("cpu" + str(i), "revcpu.RevCPU") - comp_cpu.addParams({ - "verbose" : 5, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : f"[CORES:{arch}]", # Core:Config; RV32I for all - "startAddr" : "[CORES:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : rev_exe, # Target executable - "splash" : 1, # Display the splash message - # "trcOp": "slli", # base command for tracing [default: slli] - # "trcLimit": 0, # Maximum number of trace lines [default: 0] - # "trcStartCycle" : 0 # Starting trace cycle [default: 0] - }) -# comp_cpu.enableAllStatistics() - -# sst.setStatisticOutput("sst.statOutputCSV") -# sst.enableAllStatisticsForAllComponents() - -# EOF diff --git a/test/tracer/tracer.c b/test/tracer/tracer.c index 571cf4d37..0e0eb45b9 100644 --- a/test/tracer/tracer.c +++ b/test/tracer/tracer.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV32I * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -11,35 +11,63 @@ * */ -#include "stdlib.h" -#include "stdint.h" +#include + #include "rev-macros.h" +#include "stdint.h" +#include "stdlib.h" #include "syscalls.h" +#ifdef SPIKE +// #include "stdio.h" +#define printf( ... ) +#else +#define printf rev_fast_printf +#endif + #define assert TRACE_ASSERT +#if 1 +#define REV_TIME( X ) \ + do { \ + asm volatile( " rdtime %0" : "=r"( X ) ); \ + } while( 0 ) +#else +#define REV_TIME( X ) \ + do { \ + X = 0; \ + } while( 0 ) +#endif + +void trace_vec() { +#ifdef RV64GV + asm volatile( "vsetivli x0, 0, e8, m1, ta, ma \n\t" ); + +#endif +} + // inefficient calculation of r-s -int long_sub(int r, int s) { - for (int i=0;i\nhere->\n" ); + printf( "check back to back print with no new lines " ); + printf( " [no new line] " ); + printf( " [no new line] " ); + printf( " ... new line here->\n" ); + + trace_vec(); + + int res = 3000; + res = long_sub( res, 1000 ); // res == 2000; + printf( "Enable Tracing\n" ); // enable tracing TRACE_ON; - res = long_sub(res,20); + res = long_sub( res, 20 ); // res == 1980 - assert(res==1980); + assert( res == 1980 ); TRACE_OFF; + printf( "Tracing Disabled\n" ); // not traced - for (int i=0;i<1980/2;i++) + for( int i = 0; i < 1980 / 2; i++ ) res = res - 1; // assert macro enables tracing temporarily - assert(res*2==1980); + assert( res * 2 == 1980 ); // another delay loop to prove tracing still off - res = long_sub(res,1980/2); - assert(res==0); - + res = long_sub( res, 1980 / 2 ); + assert( res == 0 ); + // call subroutine that uses push/pop to enable/disable tracing - res = check_push_on(10,5); - assert(res==100000); + res = check_push_on( 10, 5 ); + assert( res == 100000 ); // call subroutine that will not be traced inside a traced loop. // again, the assert will be traced - for (int r=10;r<20;r+=10) { - for (int s=-10;s<10;s+=10) { - int rc = check_push_off(r,s); - assert(rc=r-s); + for( int r = 10; r < 20; r += 10 ) { + for( int s = -10; s < 10; s += 10 ) { + int rc = check_push_off( r, s ); + assert( rc = r - s ); } } TRACE_ON; - // Differentiate rv32i and rv64g operations - check_mem_access_sizes: - volatile size_t dst = 0; - asm volatile("addi t3, zero, -1 \n\t" - "sb t3, 0(%0) \n\t" - "lb t4, 0(%0) \n\t" - "sh t3, 0(%0) \n\t" - "lh t4, 0(%0) \n\t" - "sw t3, 0(%0) \n\t" - "lw t4, 0(%0) \n\t" - : : "r"(&dst) : "t3", "t4" - ); + // Differentiate rv32i and rv64g operations +check_mem_access_sizes: + volatile size_t dst = 0; + asm volatile( "addi t3, zero, -1 \n\t" + "sb t3, 0(%0) \n\t" + "lb t4, 0(%0) \n\t" + "sh t3, 0(%0) \n\t" + "lh t4, 0(%0) \n\t" + "sw t3, 0(%0) \n\t" + "lw t4, 0(%0) \n\t" + : + : "r"( &dst ) + : "t3", "t4" ); #ifdef RV64G - asm volatile("sd t3, 0(%0) \n\t" - "lwu t4, 0(%0) \n\t" - "ld t4, 0(%0) \n\t" - : : "r"(&dst) : "t3", "t4" - ); + asm volatile( "sd t3, 0(%0) \n\t" + "lwu t4, 0(%0) \n\t" + "ld t4, 0(%0) \n\t" + : + : "r"( &dst ) + : "t3", "t4" ); #endif - + // trace some memory operations with register dependencies // in a tight loop - check_tight_loop: +check_tight_loop: volatile uint32_t load_data = 0x1ace4fee; - asm volatile("addi t3, zero, 3 \n\t" // counter = 3 - "mem_loop: \n\t" - "lw t4, 0(%0) \n\t" - "addi t3, t3, -1 \n\t" // counter-- - "addi t4, t4, 1 \n\t" // stall? - "sw t4, 0(%0) \n\t" // more traffic - "bnez t3, mem_loop" - : : "r"(&load_data) : "t3", "t4" - ); + asm volatile( "addi t3, zero, 3 \n\t" // counter = 3 + "mem_loop: \n\t" + "lw t4, 0(%0) \n\t" + "addi t3, t3, -1 \n\t" // counter-- + "addi t4, t4, 1 \n\t" // stall? + "sw t4, 0(%0) \n\t" // more traffic + "bnez t3, mem_loop" + : + : "r"( &load_data ) + : "t3", "t4" ); // trace some threads -#if 0 +#if 1 + printf( "Thread test starting\n" ); rev_pthread_t tid1, tid2; - rev_pthread_create(&tid1, NULL, (void *)thread1, NULL); - rev_pthread_create(&tid2, NULL, (void *)thread2, NULL); - rev_pthread_join(tid1); - rev_pthread_join(tid2); - - TRACE_ASSERT(thread1_counter==10); - TRACE_ASSERT(thread2_counter==20); -#endif - + rev_pthread_create( &tid1, NULL, (void*) thread1, NULL ); + rev_pthread_create( &tid2, NULL, (void*) thread2, NULL ); + rev_pthread_join( tid1 ); + rev_pthread_join( tid2 ); + + TRACE_ASSERT( thread1_counter == 10 ); + TRACE_ASSERT( thread2_counter == 20 ); + printf( "Thread test finished\n" ); +#endif + + TRACE_ON; + +#if 1 + // use CSR to get time + size_t time1, time2; + REV_TIME( time1 ); + int fubar = long_sub( 100, 20 ); + REV_TIME( time2 ); + assert( fubar == 80 ); + printf( "Time check: %" PRId64 "\n", time2 - time1 ); +#endif + + check_lw_sign_ext(); + + printf( "tracer test completed normally\n" ); return 0; } diff --git a/test/x0/Makefile b/test/x0/Makefile index 95163df40..6727a3618 100644 --- a/test/x0/Makefile +++ b/test/x0/Makefile @@ -3,7 +3,7 @@ # # makefile: ex5 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/x0/rev-test-x0.py b/test/x0/rev-test-x0.py old mode 100644 new mode 100755 index 5be082b85..6438ea2e6 --- a/test/x0/rev-test-x0.py +++ b/test/x0/rev-test-x0.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -22,15 +23,15 @@ # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 6, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "1.0GHz", # Clock - "memSize" : 1024*1024*1024, # Memory size in bytes - "machine" : "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "x0.exe"), # Target executable - "splash" : 1 # Display the splash message + "verbose": 6, # Verbosity + "numCores": 1, # Number of cores + "clock": "1.0GHz", # Clock + "memSize": 1024*1024*1024, # Memory size in bytes + "machine": "[0:RV64IMAFDC]", # Core:Config; RV64I for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "x0.exe"), # Target executable + "splash": 1 # Display the splash message }) sst.setStatisticOutput("sst.statOutputCSV") diff --git a/test/x0/run_x0.sh b/test/x0/run_x0.sh index a039050c8..e61fcf8c0 100755 --- a/test/x0/run_x0.sh +++ b/test/x0/run_x0.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x x0.exe ]; then +if [[ -x x0.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-test-x0.py else echo "Test X0: x0.exe not Found - likely build failed" diff --git a/test/x0/x0.c b/test/x0/x0.c index 342fa452b..10012b7d7 100644 --- a/test/x0/x0.c +++ b/test/x0/x0.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64IMAFDC * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -13,29 +13,29 @@ #include -#define assert(x) \ - do \ - if (!(x)) { \ - asm(".dword 0x00000000"); \ - } \ - while (0) +#define assert( x ) \ + do \ + if( !( x ) ) { \ + asm( ".dword 0x00000000" ); \ + } \ + while( 0 ) -int main(int argc, char **argv) { +int main( int argc, char** argv ) { - asm volatile(" li a0, 6; \ + asm volatile( " li a0, 6; \ li a1, 6; \ addi zero, a0, 0; \ - add a0, zero, a0;"); + add a0, zero, a0;" ); - asm volatile(" bne a0, a1, fail;"); - asm volatile("pass:"); - asm volatile("j continue"); + asm volatile( " bne a0, a1, fail;" ); + asm volatile( "pass:" ); + asm volatile( "j continue" ); - asm volatile("fail:"); - assert(0); + asm volatile( "fail:" ); + assert( 0 ); - asm volatile("continue:"); - asm volatile("li ra, 0x0"); + asm volatile( "continue:" ); + asm volatile( "li ra, 0x0" ); return 0; } diff --git a/test/zfa/Makefile b/test/zfa/Makefile new file mode 100644 index 000000000..5cefb5218 --- /dev/null +++ b/test/zfa/Makefile @@ -0,0 +1,34 @@ +# +# Makefile +# +# makefile: zfa +# +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC +# All Rights Reserved +# contact@tactcomplabs.com +# +# See LICENSE in the top level directory for licensing details +# + +EXAMPLE=zfa +CXX="${RVCXX}" +ARCH=rv64gc_zfa +ABI=lp64d + +CXXFLAGS=-I ../../common/syscalls -O2 + +ifneq (,$(findstring clang,$(CXX))) + CXX_FLAGS += -ffp-model=strict +else + CXX_FLAGS += -fsignaling-nans +endif + +CXX_FLAGS += -frounding-math -ftrapping-math -Werror=double-promotion -Werror=conversion -ffp-contract=on + +all: $(EXAMPLE).exe +$(EXAMPLE).exe: $(EXAMPLE).cc + $(CXX) $(CXXFLAGS) -march=$(ARCH) -mabi=$(ABI) -static -o $(EXAMPLE).exe $(EXAMPLE).cc +clean: + rm -Rf $(EXAMPLE).exe + +#-- EOF diff --git a/test/zfa/run_zfa_tests.sh b/test/zfa/run_zfa_tests.sh new file mode 100755 index 000000000..d5ff4dd00 --- /dev/null +++ b/test/zfa/run_zfa_tests.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +set -e +sst --add-lib-path=../../build/src/ ../rev-model-options-config.py -- --program "zfa.exe" --machine="[CORES:RV64GC_Zfa]" --enableMemH=0 diff --git a/test/zfa/zfa.cc b/test/zfa/zfa.cc new file mode 100644 index 000000000..311c4a50a --- /dev/null +++ b/test/zfa/zfa.cc @@ -0,0 +1,199 @@ +/* + * zfa.cc + * + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC + * All Rights Reserved + * contact@tactcomplabs.com + * + * See LICENSE in the top level directory for licensing details + * + */ + +// #pragma STDC FENV_ACCESS ON + +#include +#include +#include +#include +#include +#include + +#define FLI_TEST( type, letter, value ) \ + do { \ + type expected = value; \ + type result; \ + asm volatile( "fli." #letter " %0, " #value : "=f"( result ) ); \ + if( memcmp( &result, &expected, sizeof( result ) ) ) \ + asm( ".word 0" ); \ + } while( 0 ) + +#define RUN_FLI_TESTS( type, letter ) \ + do { \ + type min = std::numeric_limits::min(); \ + type inf = std::numeric_limits::infinity(); \ + type nan = std::numeric_limits::quiet_NaN(); \ + FLI_TEST( type, letter, -0x1p+0 ); \ + FLI_TEST( type, letter, min ); \ + FLI_TEST( type, letter, 0x1p-16 ); \ + FLI_TEST( type, letter, 0x1p-15 ); \ + FLI_TEST( type, letter, 0x1p-8 ); \ + FLI_TEST( type, letter, 0x1p-7 ); \ + FLI_TEST( type, letter, 0x1p-4 ); \ + FLI_TEST( type, letter, 0x1p-3 ); \ + FLI_TEST( type, letter, 0x1p-2 ); \ + FLI_TEST( type, letter, 0x1.4p-2 ); \ + FLI_TEST( type, letter, 0x1.8p-2 ); \ + FLI_TEST( type, letter, 0x1.cp-2 ); \ + FLI_TEST( type, letter, 0x1p-1 ); \ + FLI_TEST( type, letter, 0x1.4p-1 ); \ + FLI_TEST( type, letter, 0x1.8p-1 ); \ + FLI_TEST( type, letter, 0x1.cp-1 ); \ + FLI_TEST( type, letter, 0x1p+0 ); \ + FLI_TEST( type, letter, 0x1.4p+0 ); \ + FLI_TEST( type, letter, 0x1.8p+0 ); \ + FLI_TEST( type, letter, 0x1.cp+0 ); \ + FLI_TEST( type, letter, 0x1p+1 ); \ + FLI_TEST( type, letter, 0x1.4p+1 ); \ + FLI_TEST( type, letter, 0x1.8p+1 ); \ + FLI_TEST( type, letter, 0x1p+2 ); \ + FLI_TEST( type, letter, 0x1p+3 ); \ + FLI_TEST( type, letter, 0x1p+4 ); \ + FLI_TEST( type, letter, 0x1p+7 ); \ + FLI_TEST( type, letter, 0x1p+8 ); \ + FLI_TEST( type, letter, 0x1p+15 ); \ + FLI_TEST( type, letter, 0x1p+16 ); \ + FLI_TEST( type, letter, inf ); \ + FLI_TEST( type, letter, nan ); \ + } while( 0 ) + +#define FMINMAXM_TEST( type, inst, letter, val1, val2 ) \ + do { \ + type arg1 = val1, arg2 = val2; \ + type result; \ + asm volatile( #inst "." #letter " %0, %1, %2 " : "=f"( result ) : "f"( arg1 ), "f"( arg2 ) ); \ + if( std::isnan( arg1 ) || std::isnan( arg2 ) ) { \ + if( !std::isnan( result ) ) \ + asm( ".word 0" ); \ + } else { \ + if( std::isnan( result ) ) \ + asm( ".word 0" ); \ + } \ + } while( 0 ) + +#define RUN_FMINMAXM_TESTS( type, inst, letter ) \ + do { \ + FMINMAXM_TEST( type, inst, letter, std::numeric_limits::quiet_NaN(), 0.0f ); \ + FMINMAXM_TEST( type, inst, letter, 0.0f, std::numeric_limits::quiet_NaN() ); \ + FMINMAXM_TEST( type, inst, letter, std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN() ); \ + FMINMAXM_TEST( type, inst, letter, std::numeric_limits::infinity(), 0.0f ); \ + } while( 0 ) + +#define ROUND_TEST( type, inst, letter, exceptions, val ) \ + do { \ + type result; \ + type arg = val; \ + std::feclearexcept( FE_ALL_EXCEPT ); \ + asm volatile( #inst "." #letter " %0, %1" : "=f"( result ) : "f"( arg ) ); \ + if( std::fetestexcept( FE_ALL_EXCEPT ) != exceptions ) \ + asm( ".word 0" ); \ + } while( 0 ) + +#define RUN_ROUND_TESTS( type, letter ) \ + do { \ + ROUND_TEST( type, froundnx, letter, FE_INVALID, std::numeric_limits::signaling_NaN() ); \ + ROUND_TEST( type, froundnx, letter, FE_INEXACT, 1.5f ); \ + ROUND_TEST( type, froundnx, letter, 0, 1.0f ); \ + ROUND_TEST( type, fround, letter, FE_INVALID, std::numeric_limits::signaling_NaN() ); \ + ROUND_TEST( type, fround, letter, 0, 1.5f ); \ + ROUND_TEST( type, fround, letter, 0, 1.0f ); \ + } while( 0 ) + +#define QUIET_COMPARE_TEST( type, inst, letter, val1, val2 ) \ + do { \ + size_t result; \ + std::feclearexcept( FE_ALL_EXCEPT ); \ + asm volatile( #inst "." #letter " %0, %1, %2" : "=r"( result ) : "f"( val1 ), "f"( val2 ) ); \ + if( std::fetestexcept( FE_INVALID ) ) \ + asm( ".word 0" ); \ + } while( 0 ) + +#define RUN_QUIET_COMPARE_TESTS( type, inst, letter ) \ + do { \ + QUIET_COMPARE_TEST( type, inst, letter, std::numeric_limits::signaling_NaN(), type{ 0 } ); \ + QUIET_COMPARE_TEST( type, inst, letter, std::numeric_limits::quiet_NaN(), type{ 0 } ); \ + QUIET_COMPARE_TEST( type, inst, letter, type{ 0 }, std::numeric_limits::signaling_NaN() ); \ + QUIET_COMPARE_TEST( type, inst, letter, type{ 0 }, std::numeric_limits::quiet_NaN() ); \ + QUIET_COMPARE_TEST( type, inst, letter, std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN() ); \ + QUIET_COMPARE_TEST( \ + type, inst, letter, std::numeric_limits::signaling_NaN(), std::numeric_limits::signaling_NaN() \ + ); \ + } while( 0 ) + +#ifdef __riscv_zfa + +#if __riscv_flen >= 64 + +void fcvtmod_w_d_test( double value, intptr_t expected, int exceptions ) { + intptr_t result; + std::feclearexcept( FE_ALL_EXCEPT ); + asm volatile( "fcvtmod.w.d %0, %1, rtz" : "=r"( result ) : "f"( value ) ); + if( result != expected ) + asm( ".word 0" ); + if( fetestexcept( FE_ALL_EXCEPT ) != exceptions ) + asm( ".word 0" ); +} + +void run_fcvtmod_w_d_tests() { + fcvtmod_w_d_test( std::numeric_limits::signaling_NaN(), 0, FE_INVALID ); + fcvtmod_w_d_test( std::numeric_limits::quiet_NaN(), 0, FE_INVALID ); + fcvtmod_w_d_test( std::numeric_limits::infinity(), 0, FE_INVALID ); + fcvtmod_w_d_test( 0x1p+32, 0, FE_INVALID ); + fcvtmod_w_d_test( 0x1p+31, -2147483647 - 1, FE_INVALID ); + fcvtmod_w_d_test( -0x1p+31, -2147483647 - 1, 0 ); + fcvtmod_w_d_test( -0x1.00000002p+31, -2147483647, FE_INVALID ); + fcvtmod_w_d_test( -0x1.0000000000001p+31, -2147483647 - 1, FE_INEXACT ); + fcvtmod_w_d_test( 1024.5, 1024, FE_INEXACT ); +} + +#endif + +#endif + +int main( int argc, char** argv ) { + +#ifdef __riscv_zfa + +#if __riscv_flen >= 32 + + RUN_FLI_TESTS( float, s ); + + RUN_FMINMAXM_TESTS( float, fminm, s ); + RUN_FMINMAXM_TESTS( float, fmaxm, s ); + + RUN_QUIET_COMPARE_TESTS( float, fltq, s ); + RUN_QUIET_COMPARE_TESTS( float, fleq, s ); + + RUN_ROUND_TESTS( float, s ); + +#endif + +#if __riscv_flen >= 64 + + RUN_FLI_TESTS( double, d ); + + RUN_FMINMAXM_TESTS( double, fminm, d ); + RUN_FMINMAXM_TESTS( double, fmaxm, d ); + + RUN_QUIET_COMPARE_TESTS( double, fltq, d ); + RUN_QUIET_COMPARE_TESTS( double, fleq, d ); + + RUN_ROUND_TESTS( double, d ); + + run_fcvtmod_w_d_tests(); + +#endif + +#endif + + return 0; +} diff --git a/test/zicbom/Makefile b/test/zicbom/Makefile index 52bc2626d..bb19dbe58 100644 --- a/test/zicbom/Makefile +++ b/test/zicbom/Makefile @@ -3,7 +3,7 @@ # # makefile: zicbom # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # diff --git a/test/zicbom/rev-test-zicbom.py b/test/zicbom/rev-test-zicbom.py old mode 100644 new mode 100755 index 44cfd594a..1d494167b --- a/test/zicbom/rev-test-zicbom.py +++ b/test/zicbom/rev-test-zicbom.py @@ -1,5 +1,6 @@ +#!/usr/bin/env python3 # -# Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC +# Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC # All Rights Reserved # contact@tactcomplabs.com # @@ -15,85 +16,85 @@ DEBUG_MEM = 10 DEBUG_LEVEL = 10 VERBOSE = 10 -MEM_SIZE = 1024*1024*1024-1 +memSize = 1024*1024*1024-1 # Define the simulation components comp_cpu = sst.Component("cpu", "revcpu.RevCPU") comp_cpu.addParams({ - "verbose" : 10, # Verbosity - "numCores" : 1, # Number of cores - "clock" : "2.0GHz", # Clock - "memSize" : MEM_SIZE, # Memory size in bytes - "machine" : "[0:RV64GC_Zicbom]", # Core:Config; RV64G for core 0 - "startAddr" : "[0:0x00000000]", # Starting address for core 0 - "memCost" : "[0:1:10]", # Memory loads required 1-10 cycles - "program" : os.getenv("REV_EXE", "zicbom.exe"), # Target executable - "enable_memH" : 1, # Enable memHierarchy support - "splash" : 1 # Display the splash message + "verbose": 10, # Verbosity + "numCores": 1, # Number of cores + "clock": "2.0GHz", # Clock + "memSize": memSize, # Memory size in bytes + "machine": "[0:RV64GC_Zicbom]", # Core:Config; RV64G for core 0 + "startAddr": "[0:0x00000000]", # Starting address for core 0 + "memCost": "[0:1:10]", # Memory loads required 1-10 cycles + "program": os.getenv("REV_EXE", "zicbom.exe"), # Target executable + "enableMemH": 1, # Enable memHierarchy support + "splash": 1 # Display the splash message }) comp_cpu.enableAllStatistics() # Create the RevMemCtrl subcomponent -comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl"); +comp_lsq = comp_cpu.setSubComponent("memory", "revcpu.RevBasicMemCtrl") comp_lsq.addParams({ - "verbose" : "10", - "clock" : "2.0Ghz", - "max_loads" : 64, - "max_stores" : 64, - "max_flush" : 64, - "max_llsc" : 64, - "max_readlock" : 64, - "max_writeunlock" : 64, - "max_custom" : 64, - "ops_per_cycle" : 64 + "verbose": "10", + "clock": "2.0Ghz", + "max_loads": 64, + "max_stores": 64, + "max_flush": 64, + "max_llsc": 64, + "max_readlock": 64, + "max_writeunlock": 64, + "max_custom": 64, + "ops_per_cycle": 64 }) -comp_lsq.enableAllStatistics({"type":"sst.AccumulatorStatistic"}) +comp_lsq.enableAllStatistics({"type": "sst.AccumulatorStatistic"}) iface = comp_lsq.setSubComponent("memIface", "memHierarchy.standardInterface") iface.addParams({ - "verbose" : VERBOSE + "verbose": VERBOSE }) l1cache = sst.Component("l1cache", "memHierarchy.Cache") l1cache.addParams({ - "access_latency_cycles" : "4", - "cache_frequency" : "2 Ghz", - "replacement_policy" : "lru", - "coherence_protocol" : "MESI", - "associativity" : "4", - "cache_line_size" : "64", - "debug" : 1, - "debug_level" : DEBUG_LEVEL, - "verbose" : VERBOSE, - "L1" : "1", - "cache_size" : "16KiB" + "access_latency_cycles": "4", + "cache_frequency": "2 Ghz", + "replacement_policy": "lru", + "coherence_protocol": "MESI", + "associativity": "4", + "cache_line_size": "64", + "debug": 1, + "debug_level": DEBUG_LEVEL, + "verbose": VERBOSE, + "L1": "1", + "cache_size": "16KiB" }) memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams({ - "debug" : DEBUG_MEM, - "debug_level" : DEBUG_LEVEL, - "clock" : "2GHz", - "verbose" : VERBOSE, - "addr_range_start" : 0, - "addr_range_end" : MEM_SIZE, - "backing" : "malloc" + "debug": DEBUG_MEM, + "debug_level": DEBUG_LEVEL, + "clock": "2GHz", + "verbose": VERBOSE, + "addr_range_start": 0, + "addr_range_end": memSize, + "backing": "malloc" }) memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams({ - "access_time" : "100ns", - "mem_size" : "8GB" + "access_time": "100ns", + "mem_size": "8GB" }) -#sst.setStatisticLoadLevel(7) -#sst.setStatisticOutput("sst.statOutputConsole") -#sst.enableAllStatisticsForAllComponents() +# sst.setStatisticLoadLevel(7) +# sst.setStatisticOutput("sst.statOutputConsole") +# sst.enableAllStatisticsForAllComponents() link1 = sst.Link("link1") -link1.connect( (iface, "port", "1ns"), (l1cache, "high_network_0", "1ns") ) +link1.connect((iface, "port", "1ns"), (l1cache, "high_network_0", "1ns")) link2 = sst.Link("link2") -link2.connect( (l1cache, "low_network_0", "1ns"), (memctrl, "direct_link", "1ns") ) +link2.connect((l1cache, "low_network_0", "1ns"), (memctrl, "direct_link", "1ns")) # EOF diff --git a/test/zicbom/run_zicbom.sh b/test/zicbom/run_zicbom.sh index aea5d9a32..fe9ad775f 100755 --- a/test/zicbom/run_zicbom.sh +++ b/test/zicbom/run_zicbom.sh @@ -4,7 +4,7 @@ make clean && make # Check that the exec was built... -if [ -x zicbom.exe ]; then +if [[ -x zicbom.exe ]]; then sst --add-lib-path=../../build/src/ ./rev-test-zicbom.py else echo "Test TEST_ZICBOM: zicbom.exe not Found - likely build failed" diff --git a/test/zicbom/zicbom.c b/test/zicbom/zicbom.c index c4f93672f..a3487dbb1 100644 --- a/test/zicbom/zicbom.c +++ b/test/zicbom/zicbom.c @@ -3,7 +3,7 @@ * * RISC-V ISA: RV64I_Zicbom * - * Copyright (C) 2017-2023 Tactical Computing Laboratories, LLC + * Copyright (C) 2017-2024 Tactical Computing Laboratories, LLC * All Rights Reserved * contact@tactcomplabs.com * @@ -19,23 +19,23 @@ int A[ARRAY]; int B[ARRAY]; int C[ARRAY]; -int main(int argc, char **argv){ - int rtn = 0; - int i = 0; - int *APtr = &(A[0]); - int *BPtr = &B[0]; - int *CPtr = &C[0]; +int main( int argc, char** argv ) { + int rtn = 0; + int i = 0; + int* APtr = &( A[0] ); + int* BPtr = &B[0]; + int* CPtr = &C[0]; // init some data - for( i=0; i