diff --git a/.cproject b/.cproject index 23a37ba..d1ab12d 100644 --- a/.cproject +++ b/.cproject @@ -164,7 +164,7 @@ - + @@ -172,6 +172,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index 614430a..7070260 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /build/ -/Debug/ .settings /.venv* /Debug-PA/ @@ -23,3 +22,4 @@ /.direnv /TGC_C_XRB/ /.envrc.eyck +/.cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d7626a..d246468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scc/cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) project(TGC-ISS VERSION 1.0.0 LANGUAGES CXX) @@ -11,11 +11,13 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") set(CORE_NAME TGC5C CACHE STRING "The core to build the ISS for" ) option(BUILD_COMMON_FW "Enable the automatic download and build of some firmware to run on the ISS" OFF) option(ENABLE_SANITIZER "Enable address sanitizer" OFF) + option(ENABLE_GRPOF "Enable gprof instrumentation" OFF) option(ENABLE_CLANG_TIDY "Add clang-tidy and clang-format automatically to builds" OFF) option(WITH_TCC "Build TCC backend" OFF) option(WITH_LLVM "Build LLVM backend" OFF) - option(WITH_ASMJIT "Build ASMJIT backend" OFF) - + option(WITH_ASMJIT "Build ASMJIT backend" ON) + option(PORTABLE "Build executable without platform specific optimizations" OFF) + set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -24,12 +26,9 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") set(CMAKE_INSTALL_RPATH "${ORIGIN}") include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) - if(COMPILER_SUPPORTS_MARCH_NATIVE) - if("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") - elseif(NOT(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") - endif() + if(COMPILER_SUPPORTS_MARCH_NATIVE AND NOT PORTABLE) + message(STATUS "Applying platform specific optimizations") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") @@ -40,10 +39,16 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") set(warnings "/W4 /WX /EHsc") endif() if(ENABLE_SANITIZER) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") + list(APPEND CMAKE_C_FLAGS "-fsanitize=address") + list(APPEND CMAKE_CXX_FLAGS "-fsanitize=address") + list(APPEND CMAKE_EXE_LINKER_FLAGS "-fsanitize=address") + list(APPEND CMAKE_SHARED_LINKER_FLAGS "-fsanitize=address") + endif() + if(ENABLE_GPROF) + list(APPEND CMAKE_C_FLAGS "-pg") + list(APPEND CMAKE_CXX_FLAGS "-pg") + list(APPEND CMAKE_EXE_LINKER_FLAGS "-pg") + list(APPEND CMAKE_SHARED_LINKER_FLAGS "-pg") endif() include(GNUInstallDirs) include(ConanInline) @@ -85,7 +90,7 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") spdlog/1.9.2 boost/1.75.0 gsl-lite/0.37.0 - elfio/3.8 + elfio/3.11 lz4/1.9.3 yaml-cpp/0.7.0 jsoncpp/1.9.5 @@ -95,10 +100,10 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") if(WITH_LLVM) list(APPEND CONAN_PACKAGE_LIST llvm-core/${LLVM_VERSION}) - list(APPEND CONAN_PACKAGE_OPTIONS libiconv:shared=True) + list(APPEND CONAN_PACKAGE_OPTIONS libiconv:shared=True llvm-code:targets=X85) endif() if(WITH_ASMJIT) - list(APPEND CONAN_PACKAGE_LIST asmjit/cci.20230325) + list(APPEND CONAN_PACKAGE_LIST asmjit/cci.20240531) list(APPEND CONAN_PACKAGE_OPTIONS asmjit:shared=False) endif() if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dbt-rise-plugins) @@ -169,7 +174,7 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") # setup clang-format and clang-tidy ############################################################################### if (ENABLE_CLANG_TIDY) - set(CLANG_FORMAT_EXCLUDE_PATTERNS "scc" "install") + set(CLANG_FORMAT_EXCLUDE_PATTERNS "build" "install") find_package(ClangFormat) find_program (CLANG_TIDY_EXE NAMES "clang-tidy" PATHS /usr/bin ) if (CLANG_TIDY_EXE) @@ -213,7 +218,7 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") FetchContent_Declare( riscvfw GIT_REPOSITORY https://git.minres.com/Firmware/Firmwares.git - GIT_TAG main + GIT_TAG develop GIT_SHALLOW OFF UPDATE_DISCONNECTED ON ) @@ -225,12 +230,6 @@ if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS") endif() endif() -if(CMAKE_PROJECT_NAME STREQUAL "TGC-ISS" AND NOT USE_CWR_SYSTEMC) - set(SCC_CMAKE_CONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/scc) - add_subdirectory(scc/src/common) -else() - add_subdirectory(scc) -endif() add_subdirectory(dbt-rise-core) add_subdirectory(dbt-rise-tgc) if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dbt-rise-plugins) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..b782560 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,39 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + "configurePresets": [ + { + "name": "Debug", + "displayName": "Debug build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "Release", + "displayName": "Release build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + } + ], + "buildPresets": [ + { + "name": "Debug", + "description": "Debug build", + "displayName": "Debug" + } + ] +} \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index d21ea3d..f047755 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,7 +6,7 @@ void checkout_project(String repoUrl, String branch = 'develop') { ], extensions: [ [$class: 'CleanBeforeCheckout'], - [$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false] + [$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false, shallow: true] ], submoduleCfg: [], userRemoteConfigs: [ @@ -16,59 +16,99 @@ void checkout_project(String repoUrl, String branch = 'develop') { } pipeline { - agent { - docker { - image 'git.minres.com/tooling/riscof_sail:latest' - args ' -e CONAN_USER_HOME=/var/jenkins_home/workspace/riscof_sail' - } - } + agent any stages { - stage("Checkout TGC-ISS"){ - steps { - checkout_project("https://git.minres.com/TGFS/TGC-ISS.git", "develop") - } - } - stage("build TGC-ISS"){ - steps { - sh 'conan profile new default --detect --force ' - sh 'cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWITH_ASMJIT=ON -DWITH_TCC=ON -DWITH_LLVM=ON' - sh 'cmake --build build -j' - } - } - stage("Checkout TGC-Compliance"){ - steps { - dir("TGC-COMPLIANCE"){ - checkout_project("https://git.minres.com/TGFS/TGC-COMPLIANCE.git", "master") + stage("Checkout and build"){ + agent {docker { image 'ubuntu-riscv' }} + stages{ + stage("Checkout TGC-Compliance and TGC-GEN"){ + steps { + sh 'rm -rf * .??* ' + checkout_project("https://git.minres.com/TGFS/TGC-ISS.git", "develop") + dir("TGC-COMPLIANCE"){ + checkout_project("https://git.minres.com/TGFS/TGC-COMPLIANCE.git", "master") + } + dir("TGC-GEN"){ + checkout_project("https://git.minres.com/TGFS/TGC-GEN.git", "develop") + } + } + } + stage("Generate cores and build TGC-ISS"){ + steps { + sh ''' + for core in TGC5A TGC5B TGC5D TGC5E TGC5F RV32GC; do + for backend in interp llvm tcc asmjit; do + TGC-GEN/scripts/generate_iss.sh -o dbt-rise-tgc/ -c $core -b ${backend} TGC-GEN/CoreDSL/${core}.core_desc + done + done + for core in TGC6B TGC6C TGC6D TGC6E RV64GC; do + for backend in interp llvm asmjit; do + TGC-GEN/scripts/generate_iss.sh -o dbt-rise-tgc/ -c $core -b ${backend} TGC-GEN/CoreDSL/${core}.core_desc + done + done + ''' + sh 'conan profile new default --detect --force' + sh 'rm -rf build' + sh 'cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWITH_ASMJIT=ON -DWITH_TCC=ON -DWITH_LLVM=ON' + sh 'cmake --build build -j' + sh 'build/dbt-rise-tgc/tgc-sim --isa ?' + } } } } - stage("Test backends"){ - parallel { - stage("Test interp") { - steps { - sh "mkdir interp" - sh "python3 TGC-COMPLIANCE/run_act.py -core TGC5C -sim build/dbt-rise-tgc/tgc-sim -w interp --dockerless --backend interp" + stage("Run test suite") { + agent { + docker { + image 'git.minres.com/tooling/riscof_sail:latest' + args ' -e CONAN_USER_HOME=/var/jenkins_home/workspace/riscof_sail' + } + } + stages { + stage('ACT 32bit') { + matrix { + axes { + axis { + name 'CORE' + values 'TGC5A', 'TGC5B', 'TGC5C', 'TGC5D', 'TGC5E', 'TGC5F', 'RV32GC' + } + axis { + name 'BACKEND' + values 'interp', 'llvm', 'tcc', 'asmjit' + } + } + stages { + stage('Run riscof') { + steps { + sh "mkdir -p ${BACKEND}" + sh "python3 TGC-COMPLIANCE/run_act.py -core ${CORE} -sim build/dbt-rise-tgc/tgc-sim -w ${BACKEND} --local --backend ${BACKEND}" + } + } + } } } - stage("Test tcc") { - steps { - sh "mkdir tcc" - sh "python3 TGC-COMPLIANCE/run_act.py -core TGC5C -sim build/dbt-rise-tgc/tgc-sim -w tcc --dockerless --backend tcc" - } - } - stage("Test asmjit") { - steps { - sh "mkdir asmjit" - sh "python3 TGC-COMPLIANCE/run_act.py -core TGC5C -sim build/dbt-rise-tgc/tgc-sim -w asmjit --dockerless --backend asmjit" - } - } - stage("Test llvm") { - steps { - sh "mkdir llvm" - sh "python3 TGC-COMPLIANCE/run_act.py -core TGC5C -sim build/dbt-rise-tgc/tgc-sim -w llvm --dockerless --backend llvm" + stage('ACT 64bit') { + matrix { + axes { + axis { + name 'CORE' + values 'TGC6B', 'TGC6C', 'TGC6D', 'TGC6E', 'RV64GC' + } + axis { + name 'BACKEND' + values 'interp', 'llvm', 'asmjit' + } + } + stages { + stage('Run riscof') { + steps { + sh "mkdir -p ${BACKEND}" + sh "python3 TGC-COMPLIANCE/run_act.py -core ${CORE} -sim build/dbt-rise-tgc/tgc-sim -w ${BACKEND} --local --backend ${BACKEND}" + } + } + } } } } - } + } } } diff --git a/cmake/ConanInline.cmake b/cmake/ConanInline.cmake new file mode 100644 index 0000000..64a5d08 --- /dev/null +++ b/cmake/ConanInline.cmake @@ -0,0 +1,107 @@ + +set(CONAN_CMAKE_LIST_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +macro(conan_check) + # for backwards compatibility + cmake_parse_arguments(MARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + find_program(CONAN conan) + if(NOT EXISTS ${CONAN}) + message(FATAL_ERROR "Conan is required. Please see README.md") + return() + endif() + execute_process(COMMAND ${CONAN} --version + OUTPUT_VARIABLE CONAN_VERSION_OUTPUT) + string(REGEX MATCHALL "[0-9.]+" CONAN_VERSION ${CONAN_VERSION_OUTPUT}) + if (NOT (CONAN_VERSION VERSION_GREATER_EQUAL 1.36.0)) + message(FATAL_ERROR "Please upgrade your conan to a version greater or equal 1.36") + endif() + + if(NOT EXISTS ${CONAN_CMAKE_LIST_DIR}/conan.cmake) + message("Downloading conan.cmake to ${CONAN_CMAKE_LIST_DIR}") + set(URL https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake) + file(DOWNLOAD ${URL} ${CONAN_CMAKE_LIST_DIR}/conan.cmake TIMEOUT 60 STATUS DOWNLOAD_STATUS) + list(GET DOWNLOAD_STATUS 0 STATUS_CODE) + list(GET DOWNLOAD_STATUS 1 ERROR_MESSAGE) + if(NOT (${STATUS_CODE} EQUAL 0)) + # Exit CMake if the download failed, printing the error message. + message(FATAL_ERROR "Error occurred during download: ${ERROR_MESSAGE}") + endif() + if(NOT EXISTS ${CONAN_CMAKE_LIST_DIR}/conan.cmake) + message(FATAL_ERROR "Could not download conan.cmake. Please check your internet connection or proxy settings") + endif() + file (SIZE ${CONAN_CMAKE_LIST_DIR}/conan.cmake CONAN_CMAKE_SIZE) + if(${CONAN_CMAKE_SIZE} EQUAL 0) + message(FATAL_ERROR "Could not download conan.cmake. Please check your internet connection or proxy settings") + endif() + endif() + if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE Release) + endif() + + + include(${CONAN_CMAKE_LIST_DIR}/conan.cmake) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_BINARY_DIR}) +endmacro() + +macro(conan_setup) + set(options TARGETS) + cmake_parse_arguments(MARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + + set(conanfile_cmake_paths ${CMAKE_BINARY_DIR}/conan_paths.cmake) + + set(conanfile_cmake ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + set(conanfile_cmake ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + endif() + + if(EXISTS "${conanfile_cmake_paths}") + include(${conanfile_cmake_paths}) + elseif(EXISTS "${conanfile_cmake}") + include(${conanfile_cmake}) + if( MARGS_TARGETS) + conan_basic_setup(TARGETS) + else() + conan_basic_setup() + endif() + endif() +endmacro() + +function(conan_configure) + conan_cmake_generate_conanfile(OFF ${ARGV}) +endfunction() + +macro(conan_install) + set(options BUILD_TYPE BUILD) + set(oneValueArgs BUILD_TYPE BUILD) + cmake_parse_arguments(MARGS "" "${oneValueArgs}" "" ${ARGN} ) + if(MARGS_BUILD_TYPE) + conan_cmake_autodetect(settings BUILD_TYPE ${MARGS_BUILD_TYPE}) + else() + conan_cmake_autodetect(settings BUILD_TYPE) + endif() + if(CMAKE_CXX_STANDARD) + list(APPEND settings compiler.cppstd=${CMAKE_CXX_STANDARD}) + endif() + if(USE_NCSC_SYSTEMC) + list(APPEND settings compiler.libcxx=libstdc++) + endif() + if (NOT "$ENV{CONAN_PROFILE_NAME}" STREQUAL "") + set(CONAN_PROFILE "$ENV{CONAN_PROFILE_NAME}" CACHE INTERNAL "Copied from environment variable") + else() + set(CONAN_PROFILE "default" CACHE INTERNAL "Copied from environment variable") + endif() + + if(MARGS_BUILD) + conan_cmake_install(PATH_OR_REFERENCE . + BUILD ${MARGS_BUILD} + PROFILE_BUILD ${CONAN_PROFILE} + SETTINGS ${settings}) + else() + conan_cmake_install(PATH_OR_REFERENCE . + BUILD missing + PROFILE_BUILD ${CONAN_PROFILE} + SETTINGS ${settings}) + endif() +endmacro() diff --git a/cmake/FindClangFormat.cmake b/cmake/FindClangFormat.cmake new file mode 100644 index 0000000..aba73fe --- /dev/null +++ b/cmake/FindClangFormat.cmake @@ -0,0 +1,34 @@ +# Find Clang format +# +# +if(NOT CLANG_FORMAT_BIN_NAME) + set(CLANG_FORMAT_BIN_NAME clang-format) +endif() + +# if custom path check there first +if(CLANG_FORMAT_ROOT_DIR) + find_program(CLANG_FORMAT_BIN + NAMES + ${CLANG_FORMAT_BIN_NAME} + PATHS + "${CLANG_FORMAT_ROOT_DIR}" + NO_DEFAULT_PATH) +else() + find_program(CLANG_FORMAT_BIN NAMES ${CLANG_FORMAT_BIN_NAME}) +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + ClangFormat + DEFAULT_MSG + CLANG_FORMAT_BIN) + +mark_as_advanced( + CLANG_FORMAT_BIN) + +if(ClangFormat_FOUND) + # A CMake script to find all source files and setup clang-format targets for them + include(clang-format) +else() + message("clang-format not found. Not setting up format targets") +endif() \ No newline at end of file diff --git a/cmake/clang-format.cmake b/cmake/clang-format.cmake new file mode 100644 index 0000000..5388d00 --- /dev/null +++ b/cmake/clang-format.cmake @@ -0,0 +1,40 @@ +# additional target to perform clang-format run, requires clang-format + +set(CLANG_FORMAT_CXX_FILE_EXTENSIONS ${CLANG_FORMAT_CXX_FILE_EXTENSIONS} *.cpp *.h *.cxx *.hxx *.hpp *.cc *.ipp) +file(GLOB_RECURSE ALL_SOURCE_FILES ${CLANG_FORMAT_CXX_FILE_EXTENSIONS}) + +# Don't include some common build folders +set(CLANG_FORMAT_EXCLUDE_PATTERNS ${CLANG_FORMAT_EXCLUDE_PATTERNS} "/CMakeFiles/" "cmake") + +# get all project files file +foreach (SOURCE_FILE ${ALL_SOURCE_FILES}) + foreach (EXCLUDE_PATTERN ${CLANG_FORMAT_EXCLUDE_PATTERNS}) + string(FIND ${SOURCE_FILE} ${EXCLUDE_PATTERN} EXCLUDE_FOUND) + if (NOT ${EXCLUDE_FOUND} EQUAL -1) + list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) + endif () + endforeach () +endforeach () + +set(FORMAT_TARGET_NAME format) +if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set(FORMAT_TARGET_NAME format-${PROJECT_NAME}) +endif() + +add_custom_target(${FORMAT_TARGET_NAME} + COMMENT "Running clang-format to change files" + COMMAND ${CLANG_FORMAT_BIN} -style=file -i ${ALL_SOURCE_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + + +add_custom_target(${FORMAT_TARGET_NAME}-check + COMMENT "Checking clang-format changes" + # Use ! to negate the result for correct output + COMMAND ! + ${CLANG_FORMAT_BIN} + -style=file + -output-replacements-xml + ${ALL_SOURCE_FILES} + | grep -q "replacement offset" +) \ No newline at end of file diff --git a/dbt-rise-core b/dbt-rise-core index b725ff3..678c8ac 160000 --- a/dbt-rise-core +++ b/dbt-rise-core @@ -1 +1 @@ -Subproject commit b725ff307be15ae274b5b4e97bcb73856212b1b4 +Subproject commit 678c8ac223892d444da6f4e38ac92b7641bb152d diff --git a/dbt-rise-tgc b/dbt-rise-tgc index 346b177..f7e3db1 160000 --- a/dbt-rise-tgc +++ b/dbt-rise-tgc @@ -1 +1 @@ -Subproject commit 346b177a87b8bfa9f3e895e63910f9c7cf7a1561 +Subproject commit f7e3db11ad7b65b53d9bc2e82204a532aa9bcb0d diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..25f9233 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,5 @@ +*.log +*.dis +*.asm +*.ll +*tcc_* diff --git a/docs/offsets.txt b/docs/offsets.txt new file mode 100644 index 0000000..89b10f3 --- /dev/null +++ b/docs/offsets.txt @@ -0,0 +1,43 @@ +X0 (zero) : 0 (0x00) +X1 (ra) : 4 (0x04) +X2 (sp) : 8 (0x08) +X3 (gp) : 12 (0x0c) +X4 (tp) : 16 (0x10) +X5 (t0) : 20 (0x14) +X6 (t1) : 24 (0x18) +X7 (t2) : 28 (0x1c) +X8 (s0/fp): 32 (0x20) +X9 (s1) : 36 (0x24) +X10 (a0) : 40 (0x28) +X11 (a1) : 44 (0x2c) +X12 (a2) : 48 (0x30) +X13 (a3) : 52 (0x34) +X14 (a4) : 56 (0x38) +X15 (a5) : 60 (0x3c) +X16 (a6) : 64 (0x40) +X17 (a7) : 68 (0x44) +X18 (s2) : 72 (0x48) +X19 (s3) : 76 (0x4c) +X20 (s4) : 80 (0x50) +X21 (s5) : 84 (0x54) +X22 (s6) : 88 (0x58) +X23 (s7) : 92 (0x5c) +X24 (s8) : 96 (0x60) +X25 (s9) : 100 (0x64) +X26 (s10) : 104 (0x68) +X27 (s11) : 108 (0x6c) +X28 (t3) : 112 (0x70) +X29 (t4) : 116 (0x74) +X30 (t5) : 120 (0x78) +X31 (t6) : 124 (0x7c) +PC : 128 (0x80) +NEXT_PC : 132 (0x84) +PRIV : 136 (0x88) +DPC : 137 (0x89) +trap_state : 141 (0x8d) +pending_trap : 145 (0x91) +icount : 149 (0x95) +cycle : 157 (0x9d) +instret : 165 (0xa5) +instruction : 173 (0xad) +last_branch : 177 (0xb1) diff --git a/scc b/scc deleted file mode 160000 index 59d07fb..0000000 --- a/scc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 59d07fbc6678f5676dc508925ed1982007e350f1 diff --git a/scripts/annotate_addr_to_signature.py b/scripts/annotate_addr_to_signature.py new file mode 100644 index 0000000..f839e02 --- /dev/null +++ b/scripts/annotate_addr_to_signature.py @@ -0,0 +1,75 @@ +import argparse +import os +import subprocess + + +def get_address_from_objdump(elf_file, symbol): + result = subprocess.run( + ["riscv64-unknown-elf-objdump", "-t", elf_file], capture_output=True, text=True + ) + for line in result.stdout.splitlines(): + if symbol in line: + return int(line.split()[0], 16) + return None + + +def annotate_dump(signature_file, elf_file): + begin_signature = get_address_from_objdump(elf_file, "begin_signature") + end_signature = get_address_from_objdump(elf_file, "end_signature") + + if begin_signature is None or end_signature is None: + print(f"Symbols not found in {elf_file}") + return + + address = begin_signature + annotated_lines = [] + + with open(signature_file, "r") as sig_file: + for line in sig_file: + annotated_lines.append(f"{hex(address)}: {line.strip()}") + address += 4 + + output_file = signature_file + ".annotated" + with open(output_file, "w") as out_file: + out_file.write("\n".join(annotated_lines)) + print(f"Annotated file created: {output_file}") + + +def process_directory(root_dir): + for subdir, _, files in os.walk(root_dir): + elf_file = None + signature_file = None + + for file in files: + if file.endswith(".elf"): + elf_file = os.path.join(subdir, file) + elif file.endswith(".signature"): + signature_file = os.path.join(subdir, file) + + if elf_file and signature_file: + annotate_dump(signature_file, elf_file) + elif signature_file: + print(f"No ELF file found for {signature_file}") + + +def main(): + parser = argparse.ArgumentParser( + description=""" + Annotate memory dumps with addresses. Parses all subdirectories from the given root. + Expects a .signature with a corresponding .elf in the same directory. + Designed to annotate riscof signatures.""" + ) + parser.add_argument( + "root_dir", type=str, help="Root directory to search for .signature files" + ) + args = parser.parse_args() + + if not os.path.isdir(args.root_dir): + print("Invalid root directory") + return + + process_directory(args.root_dir) + + +if __name__ == "__main__": + main() diff --git a/scripts/create_reg_traces.py b/scripts/create_reg_traces.py new file mode 100644 index 0000000..f0106d2 --- /dev/null +++ b/scripts/create_reg_traces.py @@ -0,0 +1,157 @@ +import argparse +import os +import shutil +import subprocess +from pathlib import Path + + +def validate_elf_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise argparse.ArgumentTypeError(f"{filepath} is not a valid file.") + + # Use the 'file' command to check if it's an ELF file + result = subprocess.run( + ["file", filepath], capture_output=True, text=True, check=False + ) + if "ELF" not in result.stdout: + raise argparse.ArgumentTypeError(f"{filepath} is not a valid ELF file.") + + return filepath + + +def run_test_and_move_output(elf_file: str, backend: str, isa: str = "tgc5c") -> None: + # Call 'test' with the specified backend mode + os.chdir(Path(__file__).parent.parent) + sim_path = "build/Debug/dbt-rise-tgc/tgc-sim" + run_command = [ + sim_path, + "-f", + elf_file, + "--backend", + backend, + "--isa", + isa, + "-p", + "build/Debug/dbt-rise-plugins/pctrace/pctrace.so=dbt-rise-tgc/contrib/instr/TGC5C_instr.yaml", + "-i", + "10000", + ] + print(f"Running: \n{' '.join(run_command)}") + try: + subprocess.run(run_command, check=False, timeout=10) + except subprocess.TimeoutExpired: + print("Execution timed out") + + # Move the output.trc file + if os.path.exists("output.trc"): + shutil.move("output.trc", f"Debug/{backend}.trc") + else: + print( + f"output.trc does not exist after running with backend {backend}, so it cannot be renamed." + ) + + +def create_shortened_diff_files(backend: str) -> None: + file1_path = "Debug/interp.trc" + file2_path = f"Debug/{backend}.trc" + + def validate_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise ValueError(f"{filepath} is not a valid file.") + return filepath + + file1_path = validate_file(file1_path) + file2_path = validate_file(file2_path) + + with open(file1_path, "r", encoding="utf8") as file1, open( + file2_path, "r", encoding="utf8" + ) as file2: + lines1 = file1.readlines() + lines2 = file2.readlines() + + diff_index = -1 + for index, (line1, line2) in enumerate(zip(lines1, lines2)): + if line1 != line2: + diff_index = index + break + + if diff_index == -1: + print("The files are identical.") + return + + start_index = max(0, diff_index - 5) + end_index = min(len(lines1), diff_index + 6) + + shortened_lines1 = lines1[start_index:end_index] + shortened_lines2 = lines2[start_index:end_index] + + with open("Debug/short_interp.trc", "w", encoding="utf8") as short_file1: + short_file1.writelines(shortened_lines1) + + with open(f"Debug/short_{backend}.trc", "w", encoding="utf8") as short_file2: + short_file2.writelines(shortened_lines2) + + +def create_disassembly(elf_file_path: str) -> None: + def validate_file(filepath: str) -> str: + if not os.path.isfile(filepath): + raise ValueError(f"{filepath} is not a valid file.") + return filepath + + elf_file_path = validate_file(elf_file_path) + + output_file_path = "Debug/dut.dis" + with open(output_file_path, "w", encoding="utf8") as output_file: + subprocess.run( + [ + "riscv64-unknown-elf-objdump", + "-d", + "-Mnumeric", + "-Mno-aliases", + elf_file_path, + ], + stdout=output_file, + check=True, + ) + + +def main(args: argparse.Namespace) -> None: + elf_file = args.elf_file + backend = args.backend + isa = args.isa + + # Set environment variable + os.environ["REGDUMP"] = "True" + + # Run the tests and move the output files + run_test_and_move_output(elf_file, "interp", isa) + run_test_and_move_output(elf_file, backend, isa) + create_shortened_diff_files(backend) + create_disassembly(elf_file) + + +if __name__ == "__main__": + # sys.exit( + # "This script needs to be adapted, it assumed to be in a directory named 'Debug'" + # ) + parser = argparse.ArgumentParser( + description="Process an ELF file with a specified backend. Generates register traces for interp and the specified backend" + ) + parser.add_argument( + "elf_file", type=validate_elf_file, help="The ELF file to be processed." + ) + parser.add_argument( + "--backend", + type=str, + default="asmjit", + help="The backend to be used. Default is asmjit.", + required=False, + ) + parser.add_argument( + "--isa", + type=str, + default="tgc5c", + help="The isa to be used. Default 'tgc5c'", + required=False, + ) + main(args=parser.parse_args()) diff --git a/scripts/simplify_sail_trace.py b/scripts/simplify_sail_trace.py new file mode 100644 index 0000000..384ae9c --- /dev/null +++ b/scripts/simplify_sail_trace.py @@ -0,0 +1,29 @@ +import argparse +import re + + +def simplify_trace(input_file, output_file): + with open(input_file, "r") as infile, open(output_file, "w") as outfile: + for line in infile: + # Enhanced regex to match the instruction number, mode, and PC + match = re.search(r"\[\d+\] \[[MI]\]: (0x[0-9A-Fa-f]+)", line) + if match: + pc = match.group(1).lower() + outfile.write(f"{pc}\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Simplify a trace from an instruction set simulator." + ) + parser.add_argument("input_file", type=str, help="The input trace file") + parser.add_argument( + "output_file", type=str, help="The output file for the simplified trace" + ) + + args = parser.parse_args() + simplify_trace(args.input_file, args.output_file) + + +if __name__ == "__main__": + main() diff --git a/scripts/simplify_tgc_trace.py b/scripts/simplify_tgc_trace.py new file mode 100644 index 0000000..004c74c --- /dev/null +++ b/scripts/simplify_tgc_trace.py @@ -0,0 +1,26 @@ +import argparse + + +def simplify_trace(input_file, output_file): + with open(input_file, "r") as infile, open(output_file, "w") as outfile: + for line in infile: + # Split the line by the first comma and take the PC part + pc = line.split(",")[0].strip().lower() + outfile.write(f"{pc}\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Simplify traces from instruction set simulators." + ) + parser.add_argument("input_file", type=str, help="The input trace file") + parser.add_argument( + "output_file", type=str, help="The output file for the simplified trace" + ) + + args = parser.parse_args() + simplify_trace(args.input_file, args.output_file) + + +if __name__ == "__main__": + main()