Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AArch64 Capstone Update / SME2 support #429

Merged
merged 34 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a55fe36
Temp change of UoB-HPC captone branch to next-update.
FinnWilkinson Aug 29, 2024
d57b227
Began migrating to new Capstone structure.
FinnWilkinson Aug 30, 2024
e0fe83a
Continued with Capstone update in SimEng.
FinnWilkinson Sep 3, 2024
75a0c31
Further changes to try get regression tests to all pass.
FinnWilkinson Sep 4, 2024
893568b
More fixes after Capstone update.
FinnWilkinson Sep 4, 2024
dce6b11
Finished ensuring regression tests pass.
FinnWilkinson Sep 5, 2024
584b13a
Got unit tests to pass.
FinnWilkinson Sep 5, 2024
547d14c
Final fixes to get default program working in emulation mode.
FinnWilkinson Sep 5, 2024
b5d8d1c
More changes and fixes.
FinnWilkinson Sep 6, 2024
5224317
Updated SVE predicate pattern to use new enum in instruction.
FinnWilkinson Sep 6, 2024
8cd7335
Began changes to update LLVM version to 18.1.8
FinnWilkinson Sep 11, 2024
0b9e7b8
Updated valid SVE vector lengths inline with Arm A profile reference …
FinnWilkinson Sep 17, 2024
4f851b6
Added table physical register count to model config.
FinnWilkinson Sep 17, 2024
df5e686
Fixed integration test.
FinnWilkinson Sep 17, 2024
11fc242
Added return identification properly.
FinnWilkinson Sep 17, 2024
3267c0d
Fixed RV64 regression tests / compressed instruction implementation.
FinnWilkinson Sep 17, 2024
f537e20
Updated aarch64 comment.
FinnWilkinson Sep 17, 2024
08f47d3
Removed print out.
FinnWilkinson Sep 19, 2024
a148bd2
Added new capstone archs to non-build list in cmake.
FinnWilkinson Sep 26, 2024
72d990b
Fixed microDecode to accomodate new sysop member of aarch64_cs_op.
FinnWilkinson Oct 1, 2024
26f4155
Updated aarch64 metadata.
FinnWilkinson Oct 2, 2024
a4aa026
Final fixes for capstone update.
FinnWilkinson Oct 2, 2024
ee07deb
Attended PR comments.
FinnWilkinson Oct 2, 2024
b440a93
Migrate away from add_subdirectory LLVM (#433)
tom91136 Oct 3, 2024
e974e98
Updated LLVM version to 18.1.8 in CMake download.
FinnWilkinson Oct 3, 2024
d198964
Updated docs.
FinnWilkinson Oct 3, 2024
aef0ad4
Updated cmake file.
FinnWilkinson Oct 4, 2024
fd44dd3
Added note to CMakeLists about making a new capstone branch each time…
FinnWilkinson Oct 10, 2024
952075c
Attended PR comments.
FinnWilkinson Oct 31, 2024
7146634
Reverted to using old-values for SVE VL and fixed AArch64 decode catc…
FinnWilkinson Nov 4, 2024
2ddbe03
Cmake fix for building LLVM.
FinnWilkinson Nov 7, 2024
5e73600
Updated LLVM version in LINUX_BUILD_TEST.
FinnWilkinson Nov 14, 2024
fc308db
Made instruction decode more efficient WRT group checking against mne…
FinnWilkinson Dec 10, 2024
1f0084f
Updated cmake file comments.
FinnWilkinson Dec 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/LINUX_BUILD_TEST.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:

env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
LLVM-VERSION: 14
LLVM-VERSION: 18
BENCHMARK_BRANCH: 'make-file-build-system' # The branch inside the benchmark repo that has the script to run all benchmarks.
PAT: ${{ secrets.SIMENGUOB_PAT }}

Expand Down
155 changes: 99 additions & 56 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.13)
include(FetchContent)
include(CheckCXXCompilerFlag)
include(ProcessorCount)
set(FETCHCONTENT_QUIET OFF)

# FetchContent_MakeAvailable was introduced in 3.14
Expand All @@ -14,21 +15,15 @@ macro(FetchContent_MakeAvailable_Args NAME ARGS)
endif()
endmacro()

# Need an additional macro for LLVM as a sub-directory needs to be targeted for llvm-14.0.5
macro(FetchContent_MakeAvailable_SubDir_Args NAME SUBDIR ARGS)
FetchContent_GetProperties(${NAME})
if(NOT ${NAME}_POPULATED)
FetchContent_Populate(${NAME})
add_subdirectory(${${NAME}_SOURCE_DIR}/${SUBDIR}/ ${${NAME}_BINARY_DIR} ${ARGS})
endif()
endmacro()

# we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a small part of it
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()

# we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a relatively small part of it
FetchContent_Declare(
llvm
URL https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.5/llvm-14.0.5.src.tar.xz
URL_HASH MD5=6bd202e403d950c78985048ce499a518
llvm
URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz
URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96
)

FetchContent_Declare(
Expand All @@ -39,14 +34,13 @@ FetchContent_Declare(
GIT_PROGRESS TRUE
)

# WARNING: When updating capstone version, we MUST make a new, discrete branch in the UoB-HPC Capstone fork to ensure
# current / previous SimEng versions continue to operate correctly.
FetchContent_Declare(
capstone-lib
GIT_REPOSITORY https://github.com/UoB-HPC/capstone.git
GIT_TAG next
GIT_TAG next-update # Branch for SimEng version 0.9.7
GIT_PROGRESS TRUE

# Old Git tag pre-Armv9.2
# GIT_TAG e7be7d99e718ef9741026b80fc6f5e100fdf4f94 # trunk
)

cmake_policy(SET CMP0048 NEW)
Expand Down Expand Up @@ -89,20 +83,26 @@ set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "Disable Capstone shared library")
set(CAPSTONE_BUILD_CSTOOL OFF CACHE BOOL "Disable cstool build")
set(CAPSTONE_INSTALL OFF CACHE BOOL "Disable install of capstone")

set(CAPSTONE_ARM_SUPPORT OFF CACHE BOOL "Disable A32 support")
set(CAPSTONE_ARM_SUPPORT OFF CACHE BOOL "Disable Arm32 support")
set(CAPSTONE_MIPS_SUPPORT OFF CACHE BOOL "Disable MIPS support")
set(CAPSTONE_X86_SUPPORT OFF CACHE BOOL "Disable x86 support")
set(CAPSTONE_PPC_SUPPORT OFF CACHE BOOL "Disable PowerPC support")
set(CAPSTONE_X86_SUPPORT OFF CACHE BOOL "Disable x86 support")
set(CAPSTONE_SPARC_SUPPORT OFF CACHE BOOL "Disable Sparc support")
set(CAPSTONE_SYSZ_SUPPORT OFF CACHE BOOL "Disable SystemZ support")
set(CAPSTONE_SYSTEMZ_SUPPORT OFF CACHE BOOL "Disable SystemZ support")
set(CAPSTONE_XCORE_SUPPORT OFF CACHE BOOL "Disable XCore support")
set(CAPSTONE_M68K_SUPPORT OFF CACHE BOOL "Disable M68K support")
set(CAPSTONE_TMS320C64X_SUPPORT OFF CACHE BOOL "Disable TMS320C64x")
set(CAPSTONE_TMS320C64X_SUPPORT OFF CACHE BOOL "Disable TMS320C64x support")
set(CAPSTONE_M680X_SUPPORT OFF CACHE BOOL "Disable M680x support")
set(CAPSTONE_EVM_SUPPORT OFF CACHE BOOL "Disable EVM support")
set(CAPSTONE_MOS65XX_SUPPORT OFF CACHE BOOL "Disable MSO65XX support")
set(CAPSTONE_WASM_SUPPORT OFF CACHE BOOL "Disable WASM support")
set(CAPSTONE_MOS65XX_SUPPORT OFF CACHE BOOL "Disable MSO65XX support")
set(CAPSTONE_BPF_SUPPORT OFF CACHE BOOL "Disable BPF support")
set(CAPSTONE_SH_SUPPORT OFF CACHE BOOL "Disable SH support")
set(CAPSTONE_TRICORE_SUPPORT OFF CACHE BOOL "Disable TriCore support")
set(CAPSTONE_ALPHA_SUPPORT OFF CACHE BOOL "Disable Alpha support")
set(CAPSTONE_HPPA_SUPPORT OFF CACHE BOOL "Disable HPPA support")
set(CAPSTONE_LOONGARCH_SUPPORT OFF CACHE BOOL "Disable LoongArch support")


FetchContent_MakeAvailable_Args(capstone-lib EXCLUDE_FROM_ALL)
include_directories("${capstone_BINARY_DIR}/include" "${capstone_SOURCE_DIR}/include")
Expand Down Expand Up @@ -149,46 +149,89 @@ if(SIMENG_ENABLE_TESTS)
find_package(LLVM REQUIRED CONFIG NO_CMAKE_BUILDS_PATH)

# Check LLVM version
if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "14.1"))
message(FATAL_ERROR "LLVM version must be >= 8.0 and <= 14.0")
if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "18.2"))
ABenC377 marked this conversation as resolved.
Show resolved Hide resolved
message(FATAL_ERROR "LLVM version must be >= 8.0 and < 18.2")
endif()

# Print message containing if the full test suite will run
if (${LLVM_PACKAGE_VERSION} VERSION_LESS "14.0")
message(STATUS "LLVM version does not support AArch64 extensions SME or SVE2. These test suites will be skipped.")
endif()
if (${LLVM_PACKAGE_VERSION} VERSION_LESS "18.0")
message(STATUS "LLVM version does not support AArch64 extensions SME2. These test suites will be skipped.")
endif()

else()

set(LLVM_TARGETS_TO_BUILD "AArch64;RISCV" CACHE INTERNAL "")

set(LLVM_BUILD_RUNTIME OFF)

set(LLVM_BUILD_TOOLS OFF)
set(LLVM_INCLUDE_TOOLS OFF)

set(LLVM_BUILD_EXAMPLES OFF)
set(LLVM_INCLUDE_EXAMPLES OFF)

set(LLVM_BUILD_TESTS OFF)
set(LLVM_INCLUDE_TESTS OFF)

set(LLVM_BUILD_BENCHMARKS OFF)
set(LLVM_INCLUDE_BENCHMARKS OFF)

set(LLVM_BUILD_DOCS OFF)
set(LLVM_INCLUDE_DOCS OFF)

set(LLVM_INCLUDE_DOCS OFF)
set(LLVM_ENABLE_BINDINGS OFF)
set(LLVM_INSTALL_UTILS OFF)

set(LLVM_ENABLE_WARNINGS OFF)

# XXX all LLVM specific cmake variables must be set BEFORE FetchContent_MakeAvailable otherwise they have no effect
FetchContent_MakeAvailable_SubDir_Args(llvm llvm-14.0.5.src EXCLUDE_FROM_ALL)
# make sure we get the headers too
include_directories("${llvm_BINARY_DIR}/include" "${llvm_SOURCE_DIR}/include")
# If external LLVM not provided, download LLVM and build only what we need. Then point SimEng to use this sub-build
FetchContent_GetProperties(llvm)
if(NOT llvm_POPULATED)
FetchContent_Populate(llvm)

set(COMMAND_ECHO_OPTION "")
# COMMAND_ECHO supported only in CMake >= 3.15
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.15")
set(COMMAND_ECHO_OPTION COMMAND_ECHO STDOUT)
endif()

execute_process(
COMMAND ${CMAKE_COMMAND}
-S ${llvm_SOURCE_DIR}/llvm
-B ${llvm_BINARY_DIR}
-DCMAKE_WARN_DEPRECATED=OFF
-DCMAKE_INSTALL_MESSAGE=LAZY
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${llvm_BINARY_DIR}/dist
-DCMAKE_SKIP_RPATH=OFF # keep the rpath prefix to avoid libLLVM.so
-DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}
-G${CMAKE_GENERATOR}

-DLLVM_INCLUDE_BENCHMARKS=OFF
-DLLVM_INCLUDE_TESTS=OFF
-DLLVM_INCLUDE_DOCS=OFF
-DLLVM_INCLUDE_EXAMPLES=OFF
-DLLVM_BUILD_TESTS=OFF
-DLLVM_BUILD_DOCS=OFF
-DLLVM_BUILD_RUNTIME=OFF
-DLLVM_BUILD_TOOLS=OFF
-DLLVM_BUILD_EXAMPLES=OFF
-DLLVM_ENABLE_BINDINGS=OFF
-DLLVM_ENABLE_WARNINGS=OFF
"-DLLVM_TARGETS_TO_BUILD=AArch64\\;RISCV"

${COMMAND_ECHO_OPTION}
RESULT_VARIABLE SUCCESS)

# TODO: replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19)
if (NOT SUCCESS EQUAL "0")
message(FATAL_ERROR "LLVM configure did not succeed")
else ()
message(STATUS "LLVM configuration complete, starting build...")
endif ()

ProcessorCount(NPROC)
execute_process(
COMMAND ${CMAKE_COMMAND}
--build ${llvm_BINARY_DIR}
--target
# The full list of targets can be discovered via `ninja -t targets` inside the build
install-LLVMObject
install-LLVMAArch64AsmParser
install-LLVMRISCVAsmParser
# We also include the headers and CMake exports for a *complete* build
install-llvm-headers
install-cmake-exports
-j ${NPROC}

${COMMAND_ECHO_OPTION}
RESULT_VARIABLE SUCCESS)

# TODO: replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19)
if (NOT SUCCESS EQUAL "0")
message(FATAL_ERROR "LLVM build did not succeed")
endif ()
endif()

find_package(LLVM REQUIRED CONFIG NO_DEFAULT_PATH
PATHS "${llvm_BINARY_DIR}/lib/cmake/llvm")
Expand Down Expand Up @@ -238,10 +281,10 @@ if (SIMENG_ENABLE_SST)
endif()
else()
message(WARNING "SST build was selected but SST install directory was not specified.
Please specify -DSST_INSTALL_DIR=<path> for the SST build to proceed.")
Please specify -DSST_INSTALL_DIR=<path> for the SST build to proceed.")
endif()
endif()

# Install SimEng model configs in the build directory
set(SIMENG_CONFIG_INSTALL_DIR "${CMAKE_BINARY_DIR}/simeng-configs")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/configs/ DESTINATION ${SIMENG_CONFIG_INSTALL_DIR})
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/configs/ DESTINATION ${SIMENG_CONFIG_INSTALL_DIR})
3 changes: 2 additions & 1 deletion configs/a64fx_SME.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Register-Set:
FloatingPoint/SVE-Count: 128
Predicate-Count: 48
Conditional-Count: 128
Matrix-Count: 2
SME-Matrix-Count: 2
SME-Lookup-Table-Count: 8
Pipeline-Widths:
Commit: 4
FrontEnd: 4
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/developer/arch/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SimEng architecture definitions are responsible for describing the features and

To achieve this, SimEng defines a set of abstract architecture-related classes. Discrete implementations of these classes are provided for each of the ISAs SimEng supports by default, and must also be implemented for adding support for new or custom ISAs.

ISA support is achieved through the use of the `Capstone <https://github.com/aquynh/capstone/>`_ disassembly framework, which disassembles a binary instruction into a C/C++ object that include operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here <https://github.com/capstone-engine/capstone/pull/1907>`_, and other useful ISA updating tools present in Capstone can be found `here <https://github.com/capstone-engine/capstone/tree/next/suite/synctools>`_.
ISA support is achieved through the use of an in-house fork of the `Capstone <https://github.com/aquynh/capstone/>`_ disassembly framework, which disassembles a binary instruction into a C/C++ object that includes operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here <https://github.com/capstone-engine/capstone/pull/1907>`_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a.

Below provides more information on the abstract structure of a SimEng architecture and currently supported ISAs.

Expand Down
13 changes: 7 additions & 6 deletions docs/sphinx/developer/arch/supported/aarch64.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
AArch64
=======

SimEng provides an implementation of the 64-bit AArch64 architecture, specifically the Armv9.2-a ISA. This implementation provides support for decoding and executing a range of common instructions, sufficient to run a number of simple benchmarks. It is also capable of handling supervisor call (syscall) exceptions via basic system call emulation, allowing the execution of programs that have been statically compiled with the standard library.
SimEng provides an implementation of the 64-bit AArch64 architecture, specifically the Armv9.4-a ISA. This implementation provides support for decoding and executing a range of common instructions, sufficient to run a number of simple benchmarks. It is also capable of handling supervisor call (syscall) exceptions via basic system call emulation, allowing the execution of programs that have been statically compiled with the standard library.

.. contents:: Contents

Expand Down Expand Up @@ -135,7 +135,8 @@ There are several useful variables that execution behaviours have access to:
``results``
This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register.

Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the start of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``.
Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the **start** of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``.
Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classed as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``.

Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``.

Expand All @@ -158,6 +159,8 @@ SME instructions can also operate on sub-tile slices; individual rows or columns

Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``sourceValues_`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged.

Additionally, a fixed width 512-bit register ``ZT0`` was introduced with SME2 and is also now supported by SimEng. It can be treated in the same way as an SVE vector register.

Before implementing any further SME functionality we highly recommend familiarising yourself with the specification; found `here <https://developer.arm.com/documentation/ddi0616/latest>`_.

.. Note:: We strongly encourage adding regression tests for each implemented instruction at the same time as adding execution behaviour to ensure functional validity.
Expand All @@ -184,7 +187,7 @@ cstool

Capstone provides a ``cstool`` utility, which provides a visual representation of the ``metadata`` information available for any given instruction. For example, feeding it the bytes for the ``str`` instruction displayed above results in the following::

$ cstool -d arm64 f30f1ef8
$ cstool -d -r aarch64 f30f1ef8
0 f3 0f 1e f8 str x19, [sp, #-0x20]!
op_count: 2
operands[0].type: REG = x19
Expand Down Expand Up @@ -223,9 +226,7 @@ Concerning SVE & SME loads and stores, an effort should be made to merge contigu
Instruction aliases
*******************

As Capstone is primarily a disassembler, it will attempt to generate the correct aliases for instructions: for example, the ``cmp w0, #0`` instruction is an alias for ``subs wzr, w0, #0``. As it's the underlying instruction that is of use (in this case, the ``subs`` instruction), this implementation includes a de-aliasing component that reverses this conversion. The logic for this may be found in ``src/lib/arch/aarch64/InstructionMetadata``.

If a known but unsupported alias is encountered, it will generate an invalid instruction error, and the output will identify the instruction as unknown in place of the usual textual representation. It is recommended to reference a disassembled version of the program to identify what the instruction at this address should be correctly disassembled to, and implement the necessary dealiasing logic accordingly.
Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction information may not match the internal opcode used.

Common Instruction Execution behaviour issues
*********************************************
Expand Down
Loading
Loading