diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f6b8fdf --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +--- +BasedOnStyle: LLVM diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 173386d..50cfa0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,6 @@ name: CI on: - push: pull_request: jobs: @@ -24,13 +23,15 @@ jobs: - name: Run clang-format style check uses: jidicula/clang-format-action@v4.14.0 with: - clang-format-version: '19' + clang-format-version: '20' check-path: '.' - build: + test: needs: formatting-check - name: Build + name: Test runs-on: ubuntu-22.04 + container: + image: ghcr.io/egorshamshura/protea-build:latest strategy: fail-fast: false matrix: @@ -44,11 +45,8 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.4.8' - bundler-cache: true - - name: Build run: ci-extra/build.sh "$CMAKE_PRESET" + + - name: Run tests + run: ci-extra/test.sh "$CMAKE_PRESET" diff --git a/CMakeLists.txt b/CMakeLists.txt index 85689ce..c8d4133 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.22 FATAL_ERROR) project(protea) +set(TARGET_NAME RISCV) + +option(PROTEA_BUILD_TESTS + "Enable tests build (requires riscv gnu toolchain)" OFF) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set_property(CACHE CMAKE_INSTALL_PREFIX @@ -9,12 +13,22 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) endif() find_package(Ruby 3.4.8 EXACT REQUIRED) +find_package(Python3 3.12 EXACT REQUIRED COMPONENTS Interpreter) +message("Python found: ${Python3_EXECUTABLE}") +include(ExternalProject) include(cmake/Bundler.cmake) +include(cmake/QEMU.cmake) include(cmake/CompilerOptions.cmake) include(cmake/CPM.cmake) include(cmake/dependencies.cmake) +include(cmake/CompilerConfig.cmake) + +if(PROTEA_BUILD_TESTS) + enable_testing() +endif() add_subdirectory(lib) add_subdirectory(sim_lib) add_subdirectory(sim_gen) +add_subdirectory(test) diff --git a/CMakePresets.json b/CMakePresets.json index d6d1a3f..0d67ae2 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -8,13 +8,11 @@ "configurePresets": [ { "name": "Base", - "description": "General preset that applies to all configurations", "hidden": true, "binaryDir": "${sourceDir}/build/${presetName}" }, { "name": "Default-Release", - "description": "Release build", "inherits": "Base", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -22,23 +20,107 @@ }, { "name": "Default-Debug", - "description": "Debug build", "inherits": "Base", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } + }, + { + "name": "Default-RelWithDebInfo", + "inherits": "Base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "Default-Sanitized", + "inherits": "Base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "SANITIZED": "ON" + } + }, + { + "name": "Default-SanitizedDebug", + "inherits": "Base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "SANITIZED": "ON" + } } ], "buildPresets": [ { "name": "Default-Release", - "description": "Build Release configuration", "configurePreset": "Default-Release" }, { "name": "Default-Debug", - "description": "Build Debug configuration", "configurePreset": "Default-Debug" + }, + { + "name": "Default-RelWithDebInfo", + "configurePreset": "Default-RelWithDebInfo" + }, + { + "name": "Default-Sanitized", + "configurePreset": "Default-Sanitized" + }, + { + "name": "Default-SanitizedDebug", + "configurePreset": "Default-SanitizedDebug" + } + ], + "testPresets": [ + { + "name": "Default-Release", + "configurePreset": "Default-Release", + "execution": { + "jobs": 16 + }, + "output": { + "outputOnFailure": true + } + }, + { + "name": "Default-Debug", + "configurePreset": "Default-Debug", + "execution": { + "jobs": 16 + }, + "output": { + "outputOnFailure": true + } + }, + { + "name": "Default-RelWithDebInfo", + "configurePreset": "Default-RelWithDebInfo", + "execution": { + "jobs": 16 + }, + "output": { + "outputOnFailure": true + } + }, + { + "name": "Default-Sanitized", + "configurePreset": "Default-Sanitized", + "execution": { + "jobs": 16 + }, + "output": { + "outputOnFailure": true + } + }, + { + "name": "Default-SanitizedDebug", + "configurePreset": "Default-SanitizedDebug", + "execution": { + "jobs": 16 + }, + "output": { + "outputOnFailure": true + } } ] } diff --git a/ci-extra/test.sh b/ci-extra/test.sh new file mode 100755 index 0000000..c04a4be --- /dev/null +++ b/ci-extra/test.sh @@ -0,0 +1,11 @@ +PRESET_NAME=$1 + +cmake -S . \ + --preset "${PRESET_NAME}" \ + -DPROTEA_BUILD_TESTS=true \ + -DQEMU_PATH=qemu-riscv32 \ + -G Ninja + +cmake --build --preset "${PRESET_NAME}" --target simtests --parallel 12 + +ctest --preset "${PRESET_NAME}" diff --git a/cmake/CompilerConfig.cmake b/cmake/CompilerConfig.cmake new file mode 100644 index 0000000..e7b2bff --- /dev/null +++ b/cmake/CompilerConfig.cmake @@ -0,0 +1,60 @@ +option(HARDENED "Should the standard library be hardened" OFF) +option(SANITIZED "Should the build be sanitized" OFF) + +function(configure_compiler) + set(isGCC OFF) + set(isClang OFF) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(isGCC ON) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(isClang ON) + endif() + + set(compilerOptions "") + set(compilerDefinitions "") + set(linkerOptions "") + + if(isClang) + list(APPEND compilerOptions -stdlib=libc++) + list(APPEND linkerOptions -stdlib=libc++) + message(STATUS "Using libc++ as a standard library") + endif() + + if(HARDENED) + if(isGCC) + list(APPEND compilerDefinitions _GLIBCXX_DEBUG) + message(STATUS "Enabled debug mode for libstdc++") + elseif(isClang) + list(APPEND compilerDefinitions _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG) + message(STATUS "Enabled hardening mode for libc++") + else() + message(STATUS "Hardening is not supported for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'") + endif() + endif() + + if(SANITIZED) + if(isGCC OR isClang) + list(APPEND compilerOptions + -fsanitize=undefined,address + -fno-sanitize-recover=all + -fno-optimize-sibling-calls + -fno-omit-frame-pointer + ) + list(APPEND linkerOptions + -fsanitize=undefined,address + ) + message(STATUS "Enabled UBSan and ASan") + else() + message(WARNING "Sanitized builds are not supported for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'") + endif() + endif() + + message(STATUS "Setting global compiler options: ${compilerOptions}") + message(STATUS "Setting global compiler definitions: ${compilerDefinitions}") + message(STATUS "Setting global linker options: ${linkerOptions}") + + add_compile_options(${compilerOptions}) + add_compile_definitions(${compilerDefinitions}) + add_link_options(${linkerOptions}) +endfunction() diff --git a/cmake/QEMU.cmake b/cmake/QEMU.cmake new file mode 100644 index 0000000..bdc5122 --- /dev/null +++ b/cmake/QEMU.cmake @@ -0,0 +1,5 @@ +if (NOT DEFINED QEMU_PATH) + set(QEMU_PATH "qemu") +endif() + +message(STATUS "Using QEMU: ${QEMU_PATH}") diff --git a/cmake/discover_generated_tests.cmake.in b/cmake/discover_generated_tests.cmake.in new file mode 100644 index 0000000..455d904 --- /dev/null +++ b/cmake/discover_generated_tests.cmake.in @@ -0,0 +1,23 @@ +if(NOT EXISTS "@OUTPUT_TESTS_DIR@") + message(STATUS "Test directory does not exist yet: @OUTPUT_TESTS_DIR@") + return() +endif() + +file(GLOB discovered_tests "@OUTPUT_TESTS_DIR@/*") + +if(NOT discovered_tests) + message(STATUS "No generated tests found in @OUTPUT_TESTS_DIR@") +endif() + +foreach(test_file IN LISTS discovered_tests) + if(IS_DIRECTORY "${test_file}") + continue() + endif() + + get_filename_component(test_name "${test_file}" NAME) + + add_test( + "@PROJECT_NAME@.${test_name}" + "@GENERATED_SIM_BIN_PATH@" --propagate-exit "${test_file}" + ) +endforeach() diff --git a/cmake/toolchain/riscv.cmake b/cmake/toolchain/riscv.cmake new file mode 100644 index 0000000..67e51d5 --- /dev/null +++ b/cmake/toolchain/riscv.cmake @@ -0,0 +1,65 @@ +# RISC-V Cross Compilation Toolchain File Usage: cmake +# -DCMAKE_TOOLCHAIN_FILE=path/to/this/file.cmake .. + +# Base settings +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR riscv) +set(CMAKE_LINKER_TYPE DEFAULT) + +# Toolchain prefix (modify this according to your toolchain) Common prefixes: +# riscv64-unknown-elf-, riscv64-unknown-linux-gnu-, riscv32-unknown-elf- +set(RISCV_TOOLCHAIN_PREFIX + "riscv32-unknown-elf-" + CACHE STRING "RISC-V toolchain prefix") + +# Target architecture (modify these according to your needs) +set(RISCV_ARCH + "rv32im" + CACHE STRING "RISC-V architecture") +set(RISCV_ABI + "ilp32" + CACHE STRING "RISC-V ABI") + +# Cross-compilation tools +if(DEFINED RISCV_TOOLCHAIN_DIR) + set(CMAKE_C_COMPILER "${RISCV_TOOLCHAIN_DIR}/${RISCV_TOOLCHAIN_PREFIX}gcc") + set(CMAKE_CXX_COMPILER "${RISCV_TOOLCHAIN_DIR}/${RISCV_TOOLCHAIN_PREFIX}g++") + set(CMAKE_ASM_COMPILER "${RISCV_TOOLCHAIN_DIR}/${RISCV_TOOLCHAIN_PREFIX}gcc") + set(CMAKE_AR "${RISCV_TOOLCHAIN_DIR}/${RISCV_TOOLCHAIN_PREFIX}ar") + set(CMAKE_RANLIB "${RISCV_TOOLCHAIN_DIR}/${RISCV_TOOLCHAIN_PREFIX}ranlib") +else() + set(CMAKE_C_COMPILER "${RISCV_TOOLCHAIN_PREFIX}gcc") + set(CMAKE_CXX_COMPILER "${RISCV_TOOLCHAIN_PREFIX}g++") + set(CMAKE_ASM_COMPILER "${RISCV_TOOLCHAIN_PREFIX}gcc") + set(CMAKE_AR "${RISCV_TOOLCHAIN_PREFIX}ar") + set(CMAKE_RANLIB "${RISCV_TOOLCHAIN_PREFIX}ranlib") +endif() + +# Compiler flags Search settings +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Optional: Specify sysroot if needed set(CMAKE_SYSROOT +# "/path/to/riscv/sysroot") + +# Optional: Additional flags for specific use cases +set(COMMON_FLAGS + "-march=${RISCV_ARCH} -mabi=${RISCV_ABI} -Wall -Wextra -nostdlib -nodefaultlibs -nostartfiles -static -fno-builtin" +) +set(CMAKE_C_FLAGS + "${COMMON_FLAGS}" + CACHE STRING "C compiler flags") +set(CMAKE_ASM_FLAGS + "${COMMON_FLAGS}" + CACHE STRING "ASM compiler flags") + +set(CMAKE_EXE_LINKER_FLAGS_INIT + "-nostdlib -nodefaultlibs -nostartfiles -fno-builtin -static" + CACHE STRING "Linker flags") + +# Test compiler +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.6) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif() diff --git a/code_gen/cpp_gen.rb b/code_gen/cpp_gen.rb index 4388b34..388b379 100644 --- a/code_gen/cpp_gen.rb +++ b/code_gen/cpp_gen.rb @@ -52,6 +52,8 @@ def generate_statement(operation) binary_operation(@emitter, operation, '-') when :mul binary_operation(@emitter, operation, '*') + when :rem + binary_operation(@emitter, operation, '%') when :div binary_operation(@emitter, operation, '/') when :shr @@ -83,7 +85,7 @@ def generate_statement(operation) @emitter.emit_line("#{dst} = #{src};") when :new_var var_name = operation[:oprnds][0][:name] - var_type = Utility::HelperCpp.gen_type(operation[:oprnds][0][:type]) + var_type = Utility::HelperCpp.gen_small_type(operation[:oprnds][0][:type]) @emitter.emit_line("#{var_type} #{var_name};") when :cast dst = @mapping[operation[:oprnds][0][:name]] || operation[:oprnds][0][:name] diff --git a/lib/ADL/base.rb b/lib/ADL/base.rb index 8587824..4eb5910 100644 --- a/lib/ADL/base.rb +++ b/lib/ADL/base.rb @@ -9,6 +9,7 @@ def self.serialize(msg= nil) yaml_data = YAML.dump( { regfiles: @@regfiles.map(&:to_h), + interface_functions: @@interface_functions.map(&:to_h), instructions: @@instructions.map(&:to_h), } ) @@ -19,6 +20,7 @@ def self.state yaml_data = YAML.dump( { regfiles: @@regfiles.map(&:to_h), + interface_functions: @@interface_functions.map(&:to_h), instructions: @@instructions.map(&:to_h), } ) diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index 83d0313..36f9c3d 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -129,7 +129,7 @@ def Instruction(name, &block) class InterfaceBuilder include SimInfra - def function(name, output_types = [], input_types = []) + def Function(name, output_types = [], input_types = []) @@interface_functions << {:name => name, :return_types => output_types, :argument_types => input_types} end end diff --git a/lib/ADL/scope.rb b/lib/ADL/scope.rb index 57d4643..2175a7e 100644 --- a/lib/ADL/scope.rb +++ b/lib/ADL/scope.rb @@ -75,6 +75,9 @@ def binOpWType(a, b, op, t) # redefine! add & sub will never be the same def add(a, b) = binOp(a, b, :add) def sub(a, b) = binOp(a, b, :sub) + def mul(a, b) = binOp(a, b, :mul) + def div(a, b) = binOp(a, b, :div) + def rem(a, b) = binOp(a, b, :rem) def shl(a, b) = binOp(a, b, :shl) def lt(a, b) = binOpWType(a, b, :lt, :b1) def gt(a, b) = binOpWType(a, b, :gt, :b1) diff --git a/lib/ADL/var.rb b/lib/ADL/var.rb index 671f258..63321f5 100644 --- a/lib/ADL/var.rb +++ b/lib/ADL/var.rb @@ -42,6 +42,9 @@ module SimInfra class Var def +(other) = @scope.add(self, other) def -(other) = @scope.sub(self, other) + def *(other) = @scope.mul(self, other) + def /(other) = @scope.div(self, other) + def %(other) = @scope.rem(self, other) def <<(other) = @scope.shl(self, other) def <(other) = @scope.lt(self, other) def <=(other) = @scope.le(self, other) diff --git a/lib/Target/RISC-V/32I.rb b/lib/Target/RISC-V/32I.rb index 6a67a7b..3e2d782 100644 --- a/lib/Target/RISC-V/32I.rb +++ b/lib/Target/RISC-V/32I.rb @@ -7,7 +7,7 @@ module RV32I extend SimInfra Interface { - function :sysCall + Function(:sysCall) } RegisterFile(:XRegs) { diff --git a/lib/Target/RISC-V/32ILoops.rb b/lib/Target/RISC-V/32ILoops.rb deleted file mode 100644 index 07b0b06..0000000 --- a/lib/Target/RISC-V/32ILoops.rb +++ /dev/null @@ -1,194 +0,0 @@ -require_relative "encoding" -require_relative "../../Generic/base" -require_relative "../../Generic/builder" - -module Ops - - class Add; def self.op(a, b); a.u + b.u; end; end - class Sub; def self.op(a, b); a.u - b.u; end; end - class Sll; def self.op(a, b); a.u << b.u; end; end - class Slt; def self.op(a, b); (a.s < b.s).b; end; end - class Sltu; def self.op(a, b); (a.u < b.u).b; end; end - class Xor; def self.op(a, b); a ^ b; end; end - class Srl; def self.op(a, b); a.u >> b.u; end; end - class Sra; def self.op(a, b); a.s >> b.u; end; end - class Or; def self.op(a, b); a | b; end; end - class And; def self.op(a, b); a & b; end; end - class Load8; def self.op(rs1, imm); mem[rs1 + imm, :b8].s32; end; end - class Load16; def self.op(rs1, imm); mem[rs1 + imm, :b16].s32; end; end - class Load32; def self.op(rs1, imm); mem[rs1 + imm, :b32]; end; end - class Load8U; def self.op(rs1, imm); mem[rs1 + imm, :b8].u32; end; end - class Load16U; def self.op(rs1, imm); mem[rs1 + imm, :b16].u32; end; end - -end - -module RV32I - include SimInfra - extend SimInfra - - RegisterFile(:XRegs) { - r32 :x0, zero - for x in (1..31); r32 "x" + x.to_s; end - r32 :pc - } - - Instruction(:lui) { - encoding *format_u(0b0110111) - asm { "lui {rd}, {imm}" } - code { rd[]= imm } - } - - Instruction(:auipc) { - encoding *format_u(0b0010111) - asm { "auipc {rd}, {imm}" } - code { rd[]= imm + pc } - } - - TABLE_R_FORMAT_INSTRUCTIONS = [ - [:add, format_r(0b0110011, 0b000, 0b0000000), Ops::Add], - [:sub, format_r(0b0110011, 0b000, 0b0100000), Ops::Sub], - [:sll, format_r(0b0110011, 0b001, 0b0000000), Ops::Sll], - [:slt, format_r(0b0110011, 0b010, 0b0000000), Ops::Slt], - [:sltu, format_r(0b0110011, 0b011, 0b0000000), Ops::Sltu], - [:xor, format_r(0b0110011, 0b100, 0b0000000), Ops::Xor], - [:srl, format_r(0b0110011, 0b101, 0b0000000), Ops::Srl], - [:sra, format_r(0b0110011, 0b101, 0b0100000), Ops::Sra], - [:or, format_r(0b0110011, 0b110, 0b0000000), Ops::Or], - [:and, format_r(0b0110011, 0b111, 0b0000000), Ops::And], - ] - - for insn in TABLE_R_FORMAT_INSTRUCTIONS - Instruction(insn[0]) { - encoding *insn[1] - asm { insn[0].to_s + "{rd}, {rs1}, {rs2}" } - code { rd[]= insn[2].op(rs1, rs2) } - } - end - - TABLE_I_FORMAT_INSTRUCTIONS = [ - [:addi, format_i(0b0010011, 0b000), Ops::Add], - [:xori, format_i(0b0010011, 0b100), Ops::Xor], - [:ori, format_i(0b0010011, 0b110), Ops::Or], - [:andi, format_i(0b0010011, 0b111), Ops::And], - ] - - for insn in TABLE_I_FORMAT_INSTRUCTIONS - Instruction(insn[0]) { - encoding *insn[1] - asm { insn[0].to_s + "{rd}, {rs1}, {imm}" } - code { rd[]= insn[2].op(rs1, imm) } - } - end - - Instruction(:beq) { - encoding *format_b(0b1100011, 0b000) - asm { "beq {rs1}, {rs2}, {imm}" } - code { branch(select(rs1 == rs2, pc + imm, pc + xlen)) } - } - - Instruction(:bne) { - encoding *format_b(0b1100011, 0b001) - asm { "bne {rs1}, {rs2}, {imm}" } - code { branch(select(rs1 != rs2, pc + imm, pc + xlen)) } - } - - Instruction(:blt) { - encoding *format_b(0b1100011, 0b100) - asm { "blt {rs1}, {rs2}, {imm}" } - code { branch(select(rs1 < rs2, pc + imm, pc + xlen)) } - } - - Instruction(:bge) { - encoding *format_b(0b1100011, 0b101) - asm { "bge {rs1}, {rs2}, {imm}" } - code { branch(select(rs1 > rs2, pc + imm, pc + xlen)) } - } - - Instruction(:bltu) { - encoding *format_b(0b1100011, 0b110) - asm { "bltu {rs1}, {rs2}, {imm}" } - code { branch(select(rs1.u < rs2.u, pc + imm, pc + xlen)) } - } - - Instruction(:bgeu) { - encoding *format_b(0b1100011, 0b111) - asm { "bgeu {rs1}, {rs2}, {imm}" } - code { branch(select(rs1.u > rs2.u, pc + imm, pc + xlen)) } - } - - Instruction(:jal) { - encoding *format_j(0b1101111) - asm { "jal {rd}, {imm}" } - code { rd[]= pc + xlen; branch(pc + imm) } - } - - Instruction(:jalr) { - encoding *format_i(0b1101111, 0b000) - asm { "jalr {rd}, {rs1}, {imm}" } - code { - let :t, :b32, pc + xlen - branch((rs1 + imm) & (~1)) - rd[]= t - } - } - - Instruction(:sb) { - encoding *format_s(0b0100011, 0b000) - asm { "sb {rs2}, {imm}({rs1})" } - code { mem[rs1 + imm]= rs2[7, 0] } - } - - Instruction(:sh) { - encoding *format_s(0b0100011, 0b001) - asm { "sh {rs2}, {imm}({rs1})" } - code { mem[rs1 + imm]= rs2[15, 0] } - } - - Instruction(:sw) { - encoding *format_s(0b0100011, 0b010) - asm { "sw {rs2}, {imm}({rs1})" } - code { mem[rs1 + imm]= rs2 } - } - - Instruction(:lb) { - encoding *format_i(0b0100011, 0b000) - asm { "lb {rd}, {imm}({rs1})" } - code { rd[]= mem[rs1 + imm, :b8].s32 } - } - - Instruction(:lh) { - encoding *format_i(0b0100011, 0b001) - asm { "lh {rd}, {imm}({rs1})" } - code { rd[]= mem[rs1 + imm, :b16].s32 } - } - - Instruction(:lw) { - encoding *format_i(0b0100011, 0b010) - asm { "lw {rd}, {imm}({rs1})" } - code { rd[]= mem[rs1 + imm, :b32] } - } - - Instruction(:lbu) { - encoding *format_i(0b0100011, 0b100) - asm { "lbu {rd}, {imm}({rs1})" } - code { rd[]= mem[rs1 + imm, :b8].u32 } - } - - Instruction(:lhu) { - encoding *format_i(0b0100011, 0b101) - asm { "lhu {rd}, {imm}({rs1})" } - code { rd[]= mem[rs1 + imm, :b16].u32 } - } - - Instruction(:ecall) { - encoding :E, [field(:c, 31, 0, 0b1110011)] - asm { "ecall" } - code { } - } - - Instruction(:ebreak) { - encoding :E, [field(:c, 31, 0, 0b100000000000001110011)] - asm { "ebreak" } - code { } - } -end diff --git a/lib/Target/RISC-V/32M.rb b/lib/Target/RISC-V/32M.rb new file mode 100644 index 0000000..2f22a40 --- /dev/null +++ b/lib/Target/RISC-V/32M.rb @@ -0,0 +1,56 @@ +require_relative "encoding" +require_relative "../../ADL/base" +require_relative "../../ADL/builder" + +module RV32M + include SimInfra + extend SimInfra + + Instruction(:mul) { + encoding *format_r(0b0110011, 0b000, 0b0000001) + asm { "mul {rd}, {rs1}, {rs2}" } + code { rd[]= rs1.s * rs2.s } + } + + Instruction(:mulh) { + encoding *format_r(0b0110011, 0b001, 0b0000001) + asm { "mulh {rd}, {rs1}, {rs2}" } + code { rd[]= (rs1.s64 * rs2.s64) >> 32 } + } + + Instruction(:mulhsu) { + encoding *format_r(0b0110011, 0b010, 0b0000001) + asm { "mulhsu {rd}, {rs1}, {rs2}" } + code { rd[]= (rs1.s64 * rs2.u64.s64) >> 32 } + } + + Instruction(:mulhu) { + encoding *format_r(0b0110011, 0b011, 0b0000001) + asm { "mulhu {rd}, {rs1}, {rs2}" } + code { rd[]= (rs1.u64 * rs2.u64) >> 32 } + } + + Instruction(:div) { + encoding *format_r(0b0110011, 0b100, 0b0000001) + asm { "div {rd}, {rs1}, {rs2}" } + code { rd[]= rs1.s / rs2.s } + } + + Instruction(:divu) { + encoding *format_r(0b0110011, 0b101, 0b0000001) + asm { "divu {rd}, {rs1}, {rs2}" } + code { rd[]= rs1.u / rs2.u } + } + + Instruction(:rem) { + encoding *format_r(0b0110011, 0b110, 0b0000001) + asm { "rem {rd}, {rs1}, {rs2}" } + code { rd[]= rs1.s % rs2.s } + } + + Instruction(:remu) { + encoding *format_r(0b0110011, 0b111, 0b0000001) + asm { "remu {rd}, {rs1}, {rs2}" } + code { rd[]= rs1.u % rs2.u } + } +end diff --git a/lib/Utility/helper_cpp.rb b/lib/Utility/helper_cpp.rb index d54f32f..10541c5 100644 --- a/lib/Utility/helper_cpp.rb +++ b/lib/Utility/helper_cpp.rb @@ -15,7 +15,7 @@ def gen_type(type) def gen_small_type(type) actual_type = Utility.get_type(type) - cpp_bitsize = actual_type.bitsize % 8 == 0 ? actual_type.bitsize : (actual_type.bitsize / 8 + 1) * 8 + cpp_bitsize = [8, 1 << (actual_type.bitsize - 1).bit_length].max "#{actual_type.typeof == :s ? 'int' : 'uint'}#{cpp_bitsize}_t" end end diff --git a/lib/ir_gen.rb b/lib/ir_gen.rb index cde48e4..1a66c17 100644 --- a/lib/ir_gen.rb +++ b/lib/ir_gen.rb @@ -4,8 +4,7 @@ require 'ADL/base' require 'ADL/builder' require 'Target/RISC-V/32I' - -require 'yaml' +require 'Target/RISC-V/32M' yaml_data = SimInfra.serialize File.write('IR.yaml', yaml_data) diff --git a/sim_gen/CMakeLists.txt b/sim_gen/CMakeLists.txt index db5540a..adaf7ad 100644 --- a/sim_gen/CMakeLists.txt +++ b/sim_gen/CMakeLists.txt @@ -24,7 +24,7 @@ set(PROTEA_SIMGEN_OUTPUT_FILES set(IR_YAML_FILE ${protea_irgen_BINARY_DIR}/IR.yaml) -add_custom_command( +add_custom_command(DEPENDS OUTPUT ${PROTEA_SIMGEN_OUTPUT_FILES} COMMAND ${BUNDLE_PATH} exec ruby ${CMAKE_CURRENT_SOURCE_DIR}/sim_gen.rb ${IR_YAML_FILE} DEPENDS ${IR_YAML_FILE} @@ -38,7 +38,8 @@ add_executable(sim ${PROTEA_SIMGEN_OUTPUT_SOURCES} ${protea_simlib_SOURCE_DIR}/base_jit.cc ${protea_simlib_SOURCE_DIR}/sim.cc ${protea_simlib_SOURCE_DIR}/jit_factory.cc - ${protea_simlib_SOURCE_DIR}/memory.cc) + ${protea_simlib_SOURCE_DIR}/memory.cc + ${protea_simlib_SOURCE_DIR}/Target/${TARGET_NAME}/cpu_state_ext.cc) target_include_directories(sim PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${protea_simlib_SOURCE_DIR}) target_link_libraries(sim elfio CLI11 fmt) diff --git a/sim_gen/CPUState/cpu_state.rb b/sim_gen/CPUState/cpu_state.rb index d75201f..f7d97c1 100644 --- a/sim_gen/CPUState/cpu_state.rb +++ b/sim_gen/CPUState/cpu_state.rb @@ -121,27 +121,37 @@ def generate_read_reg_functions(regfiles) def generate_do_exit_func emitter = Utility::GenEmitter.new emitter.emit_line('// Function to stop the CPU execution') - emitter.emit_line('void doExit() {') + emitter.emit_line('void doExit(isa::Word code) {') emitter.increase_indent emitter.emit_line('m_finished = true;') + emitter.emit_line('m_code = code;') + emitter.emit_line("fmt::println(\"Exiting with code {}...\", code);") emitter.decrease_indent emitter.emit_line('}') emitter.increase_indent_all(2) emitter end - def generate_dump_func(regfiles) + def gen_input_args(args) + args.map { |arg| Utility::HelperCpp.gen_type(arg) }.join(', ') + end + + def generate_interface_func(interface_functions) emitter = Utility::GenEmitter.new - emitter.emit_line("void CPU::dump(std::ostream &ost) const {") - emitter.increase_indent - emitter.emit_line("fmt::println(ost, \"---CPU STATE DUMP---\");") - regfiles.each do |regfile| - regfile[:regs].each do |register| - emitter.emit_line("fmt::print(ost, \"X[{:02}] = {:#010x} \", effIdx, get#{regfile[:name]}());") + emitter.emit_line('// Interface functions') + interface_functions.each do |ifunc| + + if ifunc[:return_types].size == 0 + emitter.emit_line("void #{ifunc[:name]}(#{gen_input_args(ifunc[:argument_types])});") + elsif ifunc[:return_types].size == 1 + emitter.emit_line("#{gen_input_args(ifunc[:return_types])} #{ifunc[:name]}(#{gen_input_args(ifunc[:argument_types])});") + else + emitter.emit_line("std::tuple<#{gen_input_args(ifunc[:return_types])}> #{ifunc[:name]}(#{gen_input_args(ifunc[:argument_types])});") end end - + emitter.emit_blank_line + emitter.increase_indent_all(2) emitter end end @@ -163,6 +173,7 @@ def generate_cpu_state(input_ir) readreg_funcs = Helper.generate_read_reg_functions(input_ir[:regfiles]) do_exit_func = Helper.generate_do_exit_func increase_icount_func = Helper.increase_icount_func + interface_func = Helper.generate_interface_func(input_ir[:interface_functions]) base_type = Utility::HelperCpp.gen_type input_ir[:regfiles][0][:regs][0][:size] "#ifndef GENERATED_#{input_ir[:isa_name].upcase}_CPUSTATE_HH_INCLUDED @@ -173,6 +184,8 @@ def generate_cpu_state(input_ir) #include #include #include +#include +#include namespace prot::memory { class Memory; @@ -194,16 +207,15 @@ class CPU final { // Finished flag bool m_finished{false}; + // Exit code + isa::Word m_code{0}; + explicit CPU(Memory *mem) : m_memory(mem) {} #{setreg_funcs} #{readreg_funcs} #{pc_functions} - #{base_type} getSysCallNum() const; - #{base_type} getSysCallArg(std::size_t num) const; - #{base_type} getSysCallRet() const; - void emulateSysCall(); - +#{interface_func} #{do_exit_func} #{increase_icount_func} diff --git a/sim_gen/Decoders/decoder.rb b/sim_gen/Decoders/decoder.rb index 4d2689f..e6562fa 100644 --- a/sim_gen/Decoders/decoder.rb +++ b/sim_gen/Decoders/decoder.rb @@ -56,32 +56,35 @@ def get_maj_range(lead_bits) def get_lead_bits(instructions, separ_mask = 0) lead_bits = {} max_len = instructions.map { |insn| insn[:XLEN] * 8 }.max + for bit in 0...max_len - if separ_mask & (1 << bit) != 0 - next - end - + next if (separ_mask & (1 << bit)) != 0 + count_0 = 0 count_1 = 0 - + all_have_bit = true + for insn in instructions insn_mask = calc_insn_mask(insn) insn_value = calc_insn_value(insn) - - if insn_mask & (1 << bit) == 0 - next + + if (insn_mask & (1 << bit)) == 0 + all_have_bit = false + break end - + if (insn_value & (1 << bit)) != 0 count_1 += 1 else count_0 += 1 end end - if count_0 > 0 && count_1 > 0 + + if all_have_bit && count_0 > 0 && count_1 > 0 lead_bits[bit] = [count_0, count_1] end end + lead_bits end diff --git a/sim_gen/ExecEngines/naive_interpreter.rb b/sim_gen/ExecEngines/naive_interpreter.rb index b9fa7d1..cadca79 100644 --- a/sim_gen/ExecEngines/naive_interpreter.rb +++ b/sim_gen/ExecEngines/naive_interpreter.rb @@ -60,7 +60,7 @@ def cpu_read_mem(dst, addr) "cpu.m_memory->read<#{Utility::HelperCpp.gen_small_type(dst[:type])}>(#{addr})" end - def generate_exec_function(instruction) + def generate_exec_function(instruction, funcs) emitter = Utility::GenEmitter.new operand_map = map_operands(instruction) @@ -68,8 +68,13 @@ def generate_exec_function(instruction) emitter.increase_indent gen = CodeGen::CppGenerator.new(emitter, operand_map) + funcs_name = funcs.map { |func| func[:name] } instruction[:code][:tree].each do |node| - gen.generate_statement(node) + if funcs_name.include?(node[:name]) + emitter.emit_line("cpu.#{node[:name]}(#{node[:oprnds].map { |op| op[:name] }.join(', ')});") + else + gen.generate_statement(node) + end end emitter.decrease_indent emitter.emit_line('}') @@ -80,7 +85,7 @@ def generate_exec_function(instruction) def generate_exec_functions(input_ir) emitter = Utility::GenEmitter.new input_ir[:instructions].each do |instruction| - temp_emitter = generate_exec_function(instruction) + temp_emitter = generate_exec_function(instruction, input_ir[:interface_functions]) emitter.concat(temp_emitter) end emitter diff --git a/sim_gen/Hart/hart.rb b/sim_gen/Hart/hart.rb index 8002f12..cb554d1 100644 --- a/sim_gen/Hart/hart.rb +++ b/sim_gen/Hart/hart.rb @@ -52,6 +52,8 @@ class Hart { auto getIcount() const { return m_cpu->m_icount; } + auto getExitCode() const { return m_cpu->m_code; } + public: std::unique_ptr m_mem; std::unique_ptr m_cpu; diff --git a/sim_gen/ISA/isa.rb b/sim_gen/ISA/isa.rb index bed0076..a76067e 100644 --- a/sim_gen/ISA/isa.rb +++ b/sim_gen/ISA/isa.rb @@ -58,7 +58,7 @@ def get_addr_type(instructions) def is_terminator_instruction(insn) insn[:code][:tree].each { |node| - return true if node[:name] == :branch + return true if node[:name] == :branch || node[:name] == :sysCall } false end diff --git a/sim_lib/Target/RISCV/cpu_state_ext.cc b/sim_lib/Target/RISCV/cpu_state_ext.cc new file mode 100644 index 0000000..4389d9e --- /dev/null +++ b/sim_lib/Target/RISCV/cpu_state_ext.cc @@ -0,0 +1,16 @@ +#include "cpu_state.hh" + +namespace prot::state { + +void CPU::sysCall() { + switch (const auto syscallNum = getXRegs(17)) { + case 93: + doExit(getXRegs(10)); + break; + default: + throw std::runtime_error{ + fmt::format("Unknown syscall w/ num {}", syscallNum)}; + } +} + +} // namespace prot::state diff --git a/sim_lib/base_jit.cc b/sim_lib/base_jit.cc index 247b993..f2f8d2e 100644 --- a/sim_lib/base_jit.cc +++ b/sim_lib/base_jit.cc @@ -8,12 +8,13 @@ extern "C" { } namespace prot::engine { + using namespace prot::isa; using namespace prot::decoder; void JitEngine::step(CPU &cpu) { while (!cpu.m_finished) [[likely]] { - // colllect bb + // collect bb const auto pc = cpu.getPC(); auto found = m_tbCache.lookup(pc); if (found != nullptr) [[likely]] { @@ -30,7 +31,8 @@ void JitEngine::step(CPU &cpu) { auto bytes = cpu.m_memory->read(curAddr); auto inst = decode(bytes); if (!inst.has_value()) { - throw std::runtime_error{"Cannot decode bytes"}; + throw std::runtime_error{"Cannot decode bytes: " + + std::to_string(bytes)}; } bb.insns.push_back(*inst); @@ -51,6 +53,7 @@ void JitEngine::step(CPU &cpu) { interpret(cpu, bbIt->second); } } + void JitEngine::interpret(CPU &cpu, BBInfo &info) { for (const auto &insn : info.insns) { execute(cpu, insn); @@ -94,4 +97,5 @@ CodeHolder::CodeHolder(std::span src) throw std::runtime_error{"Failed to change protection"}; } } + } // namespace prot::engine diff --git a/sim_lib/base_jit.hh b/sim_lib/base_jit.hh index 637a27b..e75e0a1 100644 --- a/sim_lib/base_jit.hh +++ b/sim_lib/base_jit.hh @@ -12,7 +12,9 @@ #include namespace prot::engine { + using JitFunction = void (*)(CPU &); + class JitEngine : public Interpreter { static constexpr std::size_t kExecThreshold = 10; @@ -35,12 +37,14 @@ protected: const auto &entry = get(gpa); return entry.gpa == gpa ? entry.func : nullptr; } + void insert(std::uint32_t gpa, JitFunction func) { get(gpa) = Entry{.func = func, .gpa = gpa}; } private: const Entry &get(std::uint32_t gpa) const { return m_cache[getHash(gpa)]; } + Entry &get(std::uint32_t gpa) { return m_cache[getHash(gpa)]; } [[nodiscard]] static constexpr std::uint32_t getHash(std::uint32_t gpa) { @@ -55,10 +59,12 @@ protected: std::vector insns; std::size_t num_exec{}; }; + [[nodiscard]] const BBInfo *getBBInfo(isa::Addr pc) const; private: void interpret(CPU &cpu, BBInfo &info); + void execute(CPU &cpu, const isa::Instruction &insn) final { Interpreter::execute(cpu, insn); } @@ -94,11 +100,13 @@ public: template [[nodiscard]] auto as() const { return reinterpret_cast(m_data.get()); } + void operator()(CPU &state) const { as()(state); } private: std::unique_ptr m_data; }; + } // namespace prot::engine #endif // INCLUDE_JIT_BASE_HH_INCLUDED diff --git a/sim_lib/elf_loader.cc b/sim_lib/elf_loader.cc index 950cafa..d653ed0 100644 --- a/sim_lib/elf_loader.cc +++ b/sim_lib/elf_loader.cc @@ -1,10 +1,11 @@ #include "elf_loader.hh" -#include - #include +#include + namespace prot::elf_loader { + using namespace prot::memory; ElfLoader::~ElfLoader() = default; @@ -58,4 +59,5 @@ void ElfLoader::loadMemory(Memory &mem) const { std::byte(), seg->get_memory_size() - seg->get_file_size()); } } + } // namespace prot::elf_loader diff --git a/sim_lib/elf_loader.hh b/sim_lib/elf_loader.hh index a75a702..0dee5cc 100644 --- a/sim_lib/elf_loader.hh +++ b/sim_lib/elf_loader.hh @@ -12,11 +12,14 @@ // NOLINTNEXTLINE namespace ELFIO { + // forward decl class elfio; + } // namespace ELFIO namespace prot::elf_loader { + class ElfLoader { public: explicit ElfLoader(std::istream &stream); @@ -35,6 +38,7 @@ private: std::unique_ptr m_elf; }; + } // namespace prot::elf_loader #endif // PROT_ELF_LOADER_HH_INCLUDED diff --git a/sim_lib/jit_factory.cc b/sim_lib/jit_factory.cc index c3c3742..92590f9 100644 --- a/sim_lib/jit_factory.cc +++ b/sim_lib/jit_factory.cc @@ -1,10 +1,12 @@ #include "jit_factory.hh" + #include "base_jit.hh" #include #include namespace prot::engine { + const std::unordered_map()>> JitFactory::kFactories = { @@ -21,8 +23,9 @@ std::vector JitFactory::backends() { std::unique_ptr JitFactory::createEngine(const std::string &backend) { auto it = kFactories.find(backend); - if (it != kFactories.end()) + if (it != kFactories.end()) { return it->second(); + } throw std::invalid_argument("Undefined JIT backend: " + backend); } @@ -30,4 +33,5 @@ JitFactory::createEngine(const std::string &backend) { bool JitFactory::exist(const std::string &backend) { return kFactories.contains(backend); } + } // namespace prot::engine diff --git a/sim_lib/memory.cc b/sim_lib/memory.cc index ec37fdc..a16f3cb 100644 --- a/sim_lib/memory.cc +++ b/sim_lib/memory.cc @@ -1,4 +1,5 @@ #include "memory.hh" + #include "isa.hh" #include @@ -46,9 +47,11 @@ class PlainMemory : public Memory { uint8_t read8(isa::Addr addr) const override { return *reinterpret_cast(translateAddr(addr)); } + uint16_t read16(isa::Addr addr) const override { return *reinterpret_cast(translateAddr(addr)); } + uint32_t read32(isa::Addr addr) const override { return *reinterpret_cast(translateAddr(addr)); } @@ -56,9 +59,11 @@ class PlainMemory : public Memory { void write8(isa::Addr addr, uint8_t val) override { *reinterpret_cast(translateAddr(addr)) = val; } + void write16(isa::Addr addr, uint16_t val) override { *reinterpret_cast(translateAddr(addr)) = val; } + void write32(isa::Addr addr, uint32_t val) override { *reinterpret_cast(translateAddr(addr)) = val; } diff --git a/sim_lib/memory.hh b/sim_lib/memory.hh index 40b1cfc..a8265d9 100644 --- a/sim_lib/memory.hh +++ b/sim_lib/memory.hh @@ -2,6 +2,7 @@ #define PROT_MEMORY_HH_INCLUDED_MEMORY_HH_INCLUDED #include "isa.hh" + #include #include #include @@ -59,14 +60,19 @@ public: } virtual uint8_t read8(isa::Addr addr) const { return read(addr); } + virtual uint16_t read16(isa::Addr addr) const { return read(addr); } + virtual uint32_t read32(isa::Addr addr) const { return read(addr); } + virtual void write8(isa::Addr addr, uint8_t val) { write(addr, val); } + virtual void write16(isa::Addr addr, uint16_t val) { write(addr, val); } + virtual void write32(isa::Addr addr, uint32_t val) { write(addr, val); } diff --git a/sim_lib/sim.cc b/sim_lib/sim.cc index cc6c9a0..95628d0 100644 --- a/sim_lib/sim.cc +++ b/sim_lib/sim.cc @@ -1,10 +1,3 @@ -#include -#include -#include -#include -#include -#include - #include "base_jit.hh" #include "elf_loader.hh" #include "hart.hh" @@ -12,17 +5,28 @@ #include "memory.hh" #include "naive_interpreter.hh" +#include +#include +#include + +#include +#include +#include + int main(int argc, const char *argv[]) try { std::filesystem::path elfPath; constexpr prot::isa::Addr kDefaultStack = 0x7fffffff; prot::isa::Addr stackTop = kDefaultStack; std::string jitBackend; + bool propagateExit = false; CLI::App app{"Generated simulator with JIT support"}; app.add_option("elf", elfPath, "Path to executable ELF file") ->required() ->check(CLI::ExistingFile); + app.add_flag("--propagate-exit", propagateExit, + "Propagate exit code from guest to host"); app.add_option("--jit", jitBackend, "Use JIT with specified backend") ->check(CLI::IsMember(prot::engine::JitFactory::backends())); @@ -56,7 +60,7 @@ int main(int argc, const char *argv[]) try { fmt::println("MIPS: {:.2f}", hart.getIcount() / (duration.count() * 1'000'000)); - return EXIT_SUCCESS; + return propagateExit ? hart.getExitCode() : EXIT_SUCCESS; } catch (const std::exception &ex) { fmt::println(std::cerr, "Caught exception of type {}: {}", typeid(ex).name(), ex.what()); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..9f280e3 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(SimTests) diff --git a/tests/SemaTests/simple_tests.rb b/test/CodeGenTests/simple_tests.rb similarity index 100% rename from tests/SemaTests/simple_tests.rb rename to test/CodeGenTests/simple_tests.rb diff --git a/test/SimTests/C/CImpl/CMakeLists.txt b/test/SimTests/C/CImpl/CMakeLists.txt new file mode 100644 index 0000000..dbcd372 --- /dev/null +++ b/test/SimTests/C/CImpl/CMakeLists.txt @@ -0,0 +1,13 @@ +project(tests LANGUAGES C ASM) + +add_subdirectory(Target) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +macro(protea_add_test tar) + add_executable(${tar} ${ARGN}) + target_link_libraries(${tar} PRIVATE tests_startup) +endmacro() + +add_subdirectory(fib) +add_subdirectory(qsort) diff --git a/test/SimTests/C/CImpl/Target/CMakeLists.txt b/test/SimTests/C/CImpl/Target/CMakeLists.txt new file mode 100644 index 0000000..529c48f --- /dev/null +++ b/test/SimTests/C/CImpl/Target/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(${TARGET_NAME}) diff --git a/test/SimTests/C/CImpl/Target/RISCV/CMakeLists.txt b/test/SimTests/C/CImpl/Target/RISCV/CMakeLists.txt new file mode 100644 index 0000000..777f189 --- /dev/null +++ b/test/SimTests/C/CImpl/Target/RISCV/CMakeLists.txt @@ -0,0 +1 @@ +add_library(tests_startup OBJECT start.s) diff --git a/test/SimTests/C/CImpl/Target/RISCV/start.s b/test/SimTests/C/CImpl/Target/RISCV/start.s new file mode 100644 index 0000000..a9b0814 --- /dev/null +++ b/test/SimTests/C/CImpl/Target/RISCV/start.s @@ -0,0 +1,39 @@ +.global _start +.section .text +_start: + li x1, 0 + # li x2, 0 set via sim + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + jal main + + li a7, 93 + ecall diff --git a/test/SimTests/C/CImpl/fib/CMakeLists.txt b/test/SimTests/C/CImpl/fib/CMakeLists.txt new file mode 100644 index 0000000..feb9aaf --- /dev/null +++ b/test/SimTests/C/CImpl/fib/CMakeLists.txt @@ -0,0 +1 @@ +protea_add_test(protea_test_fib fib.c) diff --git a/test/SimTests/C/CImpl/fib/fib.c b/test/SimTests/C/CImpl/fib/fib.c new file mode 100644 index 0000000..7e56ac6 --- /dev/null +++ b/test/SimTests/C/CImpl/fib/fib.c @@ -0,0 +1,30 @@ +int verify(unsigned r, unsigned n) { + static const unsigned calculated[] = { + 1, 1, 2, 3, 5, 8, + 13, 21, 34, 55, 89, 144, + 233, 377, 610, 987, 1597, 2584, + 4181, 6765, 10946, 17711, 28657, 46368, + 75025, 121393, 196418, 317811, 514229, 832040, + 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, + 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, + 433494437, 701408733, 1134903170, 1836311903, 2971215073, 512559680, + 3483774753, 3996334433, 3185141890, 2886509027, 1776683621, 368225352, + 2144908973, 2513134325, 363076002, 2876210327, 3239286329, 1820529360, + 764848393, 2585377753, 3350226146, 1640636603, + }; + if (r == calculated[n]) { + return 0; + } + return 1; +} + +unsigned fib(unsigned n) { + if (n <= 1) { + return 1; + } + return fib(n - 1) + fib(n - 2); +} + +int main() { + return verify(fib(16), 16) || verify(fib(20), 20) || verify(fib(31), 31); +} diff --git a/test/SimTests/C/CImpl/qsort/CMakeLists.txt b/test/SimTests/C/CImpl/qsort/CMakeLists.txt new file mode 100644 index 0000000..e3ccb86 --- /dev/null +++ b/test/SimTests/C/CImpl/qsort/CMakeLists.txt @@ -0,0 +1 @@ +protea_add_test(protea_test_qsort qsort.c) diff --git a/test/SimTests/C/CImpl/qsort/dataset1.h b/test/SimTests/C/CImpl/qsort/dataset1.h new file mode 100644 index 0000000..8d28ed9 --- /dev/null +++ b/test/SimTests/C/CImpl/qsort/dataset1.h @@ -0,0 +1,691 @@ + + +#define DATA_SIZE 2048 + +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, + 2055783490, 980863365, 1308872551, 1010427073, 1399854717, 1217804021, + 934700736, 878744414}; + +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, + 2140756121, 2141591317, 2142357746, 2143324534, 2143343312, 2143968639, + 2145073408, 2145930822}; diff --git a/test/SimTests/C/CImpl/qsort/qsort.c b/test/SimTests/C/CImpl/qsort/qsort.c new file mode 100644 index 0000000..e8ffebd --- /dev/null +++ b/test/SimTests/C/CImpl/qsort/qsort.c @@ -0,0 +1,179 @@ +// See LICENSE for license details. + +//************************************************************************** +// Quicksort benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses quicksort to sort an array of integers. The +// implementation is largely adapted from Numerical Recipes for C. The +// input data (and reference data) should be generated using the +// qsort_gendata.pl perl script and dumped to a file named +// dataset1.h. + +// The INSERTION_THRESHOLD is the size of the subarray when the +// algorithm switches to using an insertion sort instead of +// quick sort. + +typedef unsigned size_t; + +#define INSERTION_THRESHOLD 10 + +// NSTACK is the required auxiliary storage. +// It must be at least 2*lg(DATA_SIZE) + +#define NSTACK 50 + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#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) + +//-------------------------------------------------------------------------- +// Quicksort function + +static void insertion_sort(size_t n, type arr[]) { + type *i, *j; + type value; + for (i = arr + 1; i < arr + n; i++) { + value = *i; + 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); + } + } +} + +void sort(size_t n, type arr[]) { + type *ir = arr + n; + type *l = arr + 1; + type *stack[NSTACK]; + type **stackp = stack; + + for (;;) { + // Insertion sort when subarray small enough. + if (ir - l < INSERTION_THRESHOLD) { + insertion_sort(ir - l + 1, l - 1); + + if (stackp == stack) { + break; + } + + // Pop stack and begin a new round of partitioning. + ir = *stackp--; + 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]); + + // Initialize pointers for partitioning. + 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. + + // Insert partitioning element. + 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; + stackp[-1] = i; + ir = j - 1; + } else { + stackp[0] = j - 1; + stackp[-1] = l; + l = i; + } + } + } +} + +//-------------------------------------------------------------------------- +// Main + +static int verify(int n, const int *test, const int *verify) { + int i; + // Unrolled for faster verification + for (i = 0; i < n / 2 * 2; i += 2) { + int t0 = test[i], t1 = test[i + 1]; + int v0 = verify[i], v1 = verify[i + 1]; + if (t0 != v0) { + return i + 1; + } + if (t1 != v1) { + return i + 2; + } + } + if (n % 2 != 0 && test[n - 1] != verify[n - 1]) { + return n; + } + return 0; +} + +int start() { +#if PREALLOCATE + // If needed we preallocate everything in the caches + sort(DATA_SIZE, verify_data); + if (verify(DATA_SIZE, input_data, input_data)) { + return 1; + } +#endif + + // Do the sort + // setStats(1); + sort(DATA_SIZE, input_data); + // setStats(0); + + // Check the results + return verify(DATA_SIZE, input_data, verify_data); +} + +int main() { start(); } diff --git a/test/SimTests/C/CMakeLists.txt b/test/SimTests/C/CMakeLists.txt new file mode 100644 index 0000000..b66f30a --- /dev/null +++ b/test/SimTests/C/CMakeLists.txt @@ -0,0 +1,38 @@ +project(c-simtests) + +if(PROTEA_BUILD_TESTS) + string(TOLOWER ${TARGET_NAME} TARGET_NAME_LOWER) + set(TARGET_TOOLCHAIN_FILE ${protea_SOURCE_DIR}/cmake/toolchain/${TARGET_NAME_LOWER}.cmake) + set(DEFAULT_ARGS + -DTARGET_NAME=${TARGET_NAME} + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} + -DCMAKE_BUILD_TYPE:STRING=Release + -DCMAKE_TOOLCHAIN_FILE:PATH=${TARGET_TOOLCHAIN_FILE}) + if (DEFINED ${TARGET_NAME}_TOOLCHAIN_DIR) + list(APPEND DEFAULT_ARGS -D${TARGET_NAME}_TOOLCHAIN_DIR:PATH=${${TARGET_NAME}_TOOLCHAIN_DIR}) + endif() + + set(TESTS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/CImpl) + set(OUTPUT_TESTS_DIR ${CMAKE_CURRENT_BINARY_DIR}/CImpl/bin) + set(GENERATED_SIM_BIN_PATH ${protea_simgen_BINARY_DIR}/sim) + + ExternalProject_Add( + c-simtestsimpl + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CImpl + BINARY_DIR ${TESTS_BINARY_DIR} + CONFIGURE_HANDLED_BY_BUILD True + BUILD_ALWAYS True + CMAKE_ARGS ${DEFAULT_ARGS} + INSTALL_COMMAND "") + + set(RunTests ${tests-common_SOURCE_DIR}/RunTests.py) + + set(DISCOVER_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/discover_generated_tests.cmake") + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/discover_generated_tests.cmake.in" + "${DISCOVER_SCRIPT}" + @ONLY + ) + + set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${DISCOVER_SCRIPT}") +endif() diff --git a/test/SimTests/CMakeLists.txt b/test/SimTests/CMakeLists.txt new file mode 100644 index 0000000..6593b78 --- /dev/null +++ b/test/SimTests/CMakeLists.txt @@ -0,0 +1,9 @@ +project(simtests) + +add_subdirectory(C) +add_subdirectory(SnippetBased) + +if(PROTEA_BUILD_TESTS) + add_custom_target(${PROJECT_NAME}) + add_dependencies(${PROJECT_NAME} sim c-simtestsimpl snippetbased-simtestsimpl) +endif() diff --git a/test/SimTests/SnippetBased/CMakeLists.txt b/test/SimTests/SnippetBased/CMakeLists.txt new file mode 100644 index 0000000..7a837b8 --- /dev/null +++ b/test/SimTests/SnippetBased/CMakeLists.txt @@ -0,0 +1,41 @@ +project(snippetbased-simtests) + +if(PROTEA_BUILD_TESTS) + string(TOLOWER ${TARGET_NAME} TARGET_NAME_LOWER) + set(TARGET_TOOLCHAIN_FILE ${protea_SOURCE_DIR}/cmake/toolchain/${TARGET_NAME_LOWER}.cmake) + set(DEFAULT_ARGS + -DTARGET_NAME=${TARGET_NAME} + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} + -DCMAKE_BUILD_TYPE:STRING=Release + -DCMAKE_TOOLCHAIN_FILE:PATH=${TARGET_TOOLCHAIN_FILE}) + if (DEFINED ${TARGET_NAME}_TOOLCHAIN_DIR) + list(APPEND DEFAULT_ARGS -D${TARGET_NAME}_TOOLCHAIN_DIR:PATH=${${TARGET_NAME}_TOOLCHAIN_DIR}) + endif() + + set(TESTS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/SnippetBasedImpl) + set(OUTPUT_TESTS_DIR ${CMAKE_CURRENT_BINARY_DIR}/compiled_tests) + + set(RunTests ${tests-common_SOURCE_DIR}/RunTests.py) + set(GENERATED_SIM_BIN_PATH ${protea_simgen_BINARY_DIR}/sim) + + ExternalProject_Add( + snippetbased-simtestsimpl + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SnippetBasedImpl + BINARY_DIR ${TESTS_BINARY_DIR} + CONFIGURE_HANDLED_BY_BUILD True + BUILD_ALWAYS True + CMAKE_ARGS ${DEFAULT_ARGS} -DQEMU_PATH=${QEMU_PATH} -DBUNDLE_PATH=${BUNDLE_PATH} -DIR_PATH=${protea_irgen_BINARY_DIR}/IR.yaml -DTARGET_NAME=${TARGET_NAME} -DOUTPUT_TESTS_DIR=${OUTPUT_TESTS_DIR} + INSTALL_COMMAND "") + + add_dependencies(snippetbased-simtestsimpl protea_irgen sim) + + set(DISCOVER_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/discover_generated_tests.cmake") + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/discover_generated_tests.cmake.in" + "${DISCOVER_SCRIPT}" + @ONLY + ) + + set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${DISCOVER_SCRIPT}") +endif() + diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/CMakeLists.txt b/test/SimTests/SnippetBased/SnippetBasedImpl/CMakeLists.txt new file mode 100644 index 0000000..6a99b5f --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.22 FATAL_ERROR) + +project(tests LANGUAGES CXX C ASM) + +set(INIT_DIR "${CMAKE_CURRENT_BINARY_DIR}/init") +set(BIN_DIR "${CMAKE_CURRENT_BINARY_DIR}/init_bin") +set(QEMU_LOG_DIR "${CMAKE_CURRENT_BINARY_DIR}/qemu_log") +set(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/tests") + +add_custom_target(init-tests + ALL + COMMAND ${CMAKE_COMMAND} -E make_directory "${INIT_DIR}" + COMMAND ${BUNDLE_PATH} exec ruby ${CMAKE_CURRENT_SOURCE_DIR}/InitTestGen.rb + ${IR_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/Target/${TARGET_NAME}/Snippets ${INIT_DIR} + COMMENT "Generating test .s files" +) + +set(COMPILER "${CMAKE_C_COMPILER}") +set(COMPILER_FLAGS + "${CMAKE_C_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" + CACHE INTERNAL "Compiler flags for assembling and linking" +) + +set(SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/compile-and-run.sh") +set(COMPILE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/compile-dir.sh") + +add_custom_target(run-qemu-tests + ALL + DEPENDS init-tests + COMMAND ${CMAKE_COMMAND} -E make_directory "${BIN_DIR}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${QEMU_LOG_DIR}" + COMMAND "${SCRIPT_PATH}" + "${INIT_DIR}" + "${BIN_DIR}" + "${COMPILER}" + "${QEMU_PATH}" + "${QEMU_LOG_DIR}" + "${COMPILER_FLAGS}" + COMMENT "Compile all .s files and run each with QEMU" + VERBATIM +) + +add_custom_target(gen-tests + ALL + DEPENDS run-qemu-tests + COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_DIR}" + COMMAND ${BUNDLE_PATH} exec ruby "${CMAKE_CURRENT_SOURCE_DIR}/TestGen.rb" + "${IR_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/Target/${TARGET_NAME}/Snippets" "${INIT_DIR}" "${QEMU_LOG_DIR}" "${OUTPUT_DIR}") + +add_custom_target(compile-tests + ALL + DEPENDS gen-tests + COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_TESTS_DIR}" + COMMAND ${COMPILE_SCRIPT_PATH} "${OUTPUT_DIR}" "${OUTPUT_TESTS_DIR}" "${COMPILER}" "${COMPILER_FLAGS}") diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/InitTestGen.rb b/test/SimTests/SnippetBased/SnippetBasedImpl/InitTestGen.rb new file mode 100644 index 0000000..6d1aa4a --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/InitTestGen.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +require 'optparse' +require 'yaml' +require 'etc' +require 'parallel' +require 'Utility/gen_emitter' +require_relative 'Target/RISCV/Formatter' + +module SimTest + class InitAsmGen + attr_reader :ir, :reg2value, :rng + + def initialize(ir, seed: nil) + @ir = ir + @seed = seed || Random.new_seed + @rng = Random.new(@seed) + end + + def seed; @seed; end + + def generate_random_values + values = {} + ir[:regfiles].each do |regfile| + regfile[:regs].each do |reg| + attrs = reg[:attrs] || [] + next if attrs.include?(:zero) || attrs.include?(:pc) + size = reg[:size] || 32 + max = (1 << size) - 1 + values[reg[:name]] = @rng.rand(0..max) + end + end + values + end + + def generate(formatter, snippet_content, output_file) + emitter = Utility::GenEmitter.new() + @reg2value = generate_random_values + + formatter.prologue(emitter) + formatter.init_register(emitter, ir, @reg2value) + + emitter.emit_line 'j _snippet' + emitter.decrease_indent + emitter.emit_line '_snippet:' + emitter.increase_indent + formatter.insert_snippet(emitter, snippet_content) + emitter.emit_line 'j _exit_snippet' + emitter.decrease_indent + emitter.emit_line '_exit_snippet:' + emitter.increase_indent + + formatter.epilogue(emitter) + + File.write("#{output_file}yaml", @reg2value.to_yaml) + File.write("#{output_file}s", emitter.to_s) + end + end +end + +if __FILE__ == $PROGRAM_NAME + options = { + num_tests: 4, + seed: 42, + jobs: Etc.nprocessors + } + + parser = OptionParser.new do |opts| + opts.banner = "Usage: #{$PROGRAM_NAME} [options] " + + opts.on('-n', '--num-tests NUM', Integer, 'Number of tests per snippet (default: 4)') do |n| + options[:num_tests] = n + end + + opts.on('-s', '--seed SEED', Integer, 'Random seed for reproducibility') do |s| + options[:seed] = s + end + + opts.on('-j', '--jobs NUM', Integer, 'Number of parallel workers (default: CPU count)') do |j| + options[:jobs] = j + end + + opts.on('-h', '--help', 'Show this help message') do + puts opts + exit + end + end + + parser.parse! + + if ARGV.size != 3 + puts parser + exit 1 + end + + ir_file, snippets_dir, output_directory = ARGV + + ir = YAML.load_file(ir_file, symbolize_names: true) + + snippet_paths = Dir.glob(File.join(snippets_dir, '*')).select { |p| File.file?(p) } + + jobs = snippet_paths.each_with_index.flat_map do |snippet_path, snippet_idx| + snippet_content = File.read(snippet_path) + base = File.basename(snippet_path, '.*') + + options[:num_tests].times.map do |i| + { + ir: ir, + snippet_content: snippet_content, + base: base, + i: i, + num_tests: options[:num_tests], + seed: options[:seed] + snippet_idx * options[:num_tests] + i, + output_directory: output_directory + } + end + end + + Parallel.each(jobs, in_processes: options[:jobs]) do |job| + formatter = SimTest::RiscVFormatter.new + generator = SimTest::InitAsmGen.new(job[:ir], seed: job[:seed]) + + output_file = File.join(job[:output_directory], "#{job[:base]}_#{job[:i]}.init.") + generator.generate(formatter, job[:snippet_content], output_file) + + puts "Generated: #{output_file}s (seed: #{generator.seed}, test #{job[:i] + 1}/#{job[:num_tests]})" + end +end diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/Parsers/QEMUParser.rb b/test/SimTests/SnippetBased/SnippetBasedImpl/Parsers/QEMUParser.rb new file mode 100644 index 0000000..827e82a --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/Parsers/QEMUParser.rb @@ -0,0 +1,28 @@ +module SimTest + module QEMULogParser + # Parses a QEMU log file and returns the last register snapshot. + # The returned hash contains keys like "pc", "x0", "x1", ... "x31" + # with their 8‑digit hexadecimal values as strings. + def self.parse(log_file) + last_snapshot = nil + current_snapshot = nil + + File.readlines(log_file).each do |line| + line.strip! + next if line.empty? + if line.start_with?('pc') + last_snapshot = current_snapshot if current_snapshot + current_snapshot = {} + else + line.scan(/([^\s]+)\s+(\h+)/) do |name, value| + simple_name = name.split('/').first + current_snapshot[simple_name.to_sym] = value.to_i(16) + end + end + end + last_snapshot = current_snapshot if current_snapshot + + last_snapshot || {} + end + end +end diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Formatter.rb b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Formatter.rb new file mode 100644 index 0000000..7d53a43 --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Formatter.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module SimTest + class RiscVFormatter + def prologue(emitter) + emitter.emit_line '.global _start' + emitter.emit_line '.section .text' + emitter.emit_line '_start:' + emitter.increase_indent + end + + def init_register(emitter, ir, values) + ir[:regfiles].each do |regfile| + regfile[:regs].each do |reg| + attrs = reg[:attrs] || [] + next if attrs.include?(:zero) || attrs.include?(:pc) || reg[:name] == :x2 + + emitter.emit_line "li #{reg[:name]}, 0x#{values[reg[:name]].to_s(16)}" + end + end + end + + def insert_snippet(emitter, snippet_content) + snippet_content.each_line do |line| + emitter.emit_line line.chomp + end + end + + def insert_check(emitter, ir, ref_values) + emitter.emit_line 'addi sp, sp, -4' + emitter.emit_line 'sw x1, 4(sp)' + ir[:regfiles].each do |regfile| + regfile[:regs].each do |reg| + attrs = reg[:attrs] || [] + next if attrs.include?(:zero) || attrs.include?(:pc) || reg[:name] == :x1 || reg[:name] == :x2 + + emitter.emit_line "li x1, 0x#{ref_values[reg[:name]].to_s(16)}" + emitter.emit_line "bne x1, #{reg[:name]}, _fail" + end + end + emitter.emit_line 'lw x3, 4(sp)' + emitter.emit_line "li x1, 0x#{ref_values[:x1].to_s(16)}" + emitter.emit_line 'addi sp, sp, 4' + emitter.emit_line 'bne x1, x3, _fail' + end + + def epilogue(emitter) + emitter.emit_line 'li a0, 0' + emitter.emit_line 'li a7, 93' + emitter.emit_line 'ecall' + emitter.emit_blank_line + emitter.decrease_indent + emitter.emit_line '_fail:' + emitter.increase_indent + emitter.emit_line 'li a0, 1' + emitter.emit_line 'li a7, 93' + emitter.emit_line 'ecall' + emitter.decrease_indent + emitter.emit_blank_line + end + end +end diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/add-1.s b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/add-1.s new file mode 100644 index 0000000..d74fb1a --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/add-1.s @@ -0,0 +1 @@ +add x10, x6, x5 diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/addi-1.s b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/addi-1.s new file mode 100644 index 0000000..cd32b26 --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/addi-1.s @@ -0,0 +1 @@ +addi x3, x6, 10 diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/mul.s b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/mul.s new file mode 100644 index 0000000..2cbf877 --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/Target/RISCV/Snippets/mul.s @@ -0,0 +1,11 @@ +li a0, 200 +li a1, 300 +mul a2, a0, a1 +mulh a3, a0, a1 +mulhsu a4, a0, a1 +mulhu a5, a0, a1 +li a1, 2 +div a6, a0, a1 +divu a7, a0, a1 +rem t0, a0, a1 +remu t1, a0, a1 diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/TestGen.rb b/test/SimTests/SnippetBased/SnippetBasedImpl/TestGen.rb new file mode 100644 index 0000000..1d274d2 --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/TestGen.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true + +require 'yaml' +require 'etc' +require 'parallel' +require 'optparse' +require 'Utility/gen_emitter' +require_relative 'Target/RISCV/Formatter' +require_relative 'Parsers/QEMUParser' + +module SimTest + class FinalAsmGen + attr_reader :ir + + def initialize(ir) + @ir = ir + end + + def generate(formatter, snippet_content, init_yaml_file, ref_log_file, output_file) + emitter = Utility::GenEmitter.new + + initreg2value = YAML.load_file(init_yaml_file) + refreg2value = QEMULogParser.parse(ref_log_file) + + formatter.prologue(emitter) + formatter.init_register(emitter, @ir, initreg2value) + + emitter.emit_line 'j _snippet' + emitter.decrease_indent + emitter.emit_line '_snippet:' + emitter.increase_indent + formatter.insert_snippet(emitter, snippet_content) + emitter.emit_line 'j _exit_snippet' + emitter.decrease_indent + emitter.emit_line '_exit_snippet:' + emitter.increase_indent + + formatter.insert_check(emitter, @ir, refreg2value) + + formatter.epilogue(emitter) + File.write(output_file, emitter.to_s) + end + end +end + +if __FILE__ == $0 + options = { + jobs: Etc.nprocessors + } + + parser = OptionParser.new do |opts| + opts.banner = "Usage: #{$0} [options] " + + opts.on('-j', '--jobs NUM', Integer, 'Number of parallel workers (default: CPU count)') do |j| + options[:jobs] = j + end + + opts.on('-h', '--help', 'Show this help message') do + puts opts + exit + end + end + + parser.parse! + + if ARGV.size != 5 + puts parser + exit 1 + end + + ir_file = ARGV[0] + snippets_dir = ARGV[1] + init_yaml_dir = ARGV[2] + log_dir = ARGV[3] + output_dir = ARGV[4] + + ir = YAML.load_file(ir_file, symbolize_names: true) + + snippet_map = Dir.glob(File.join(snippets_dir, '*')) + .select { |f| File.file?(f) } + .each_with_object({}) do |path, map| + map[File.basename(path, '.*')] = path + end + + log_files = Dir.glob(File.join(log_dir, '*')).select { |f| File.file?(f) } + + jobs = log_files.filter_map do |log_path| + log_basename = File.basename(log_path) + match = log_basename.match(/^(.*)_(\d+)\.init\.log$/) + + snippet = match[1] + index = match[2].to_i + + snippet_path = snippet_map[snippet] + + init_yaml_file = File.join(init_yaml_dir, "#{snippet}_#{index}.init.yaml") + + { + ir: ir, + snippet: snippet, + index: index, + snippet_path: snippet_path, + init_yaml_file: init_yaml_file, + log_path: log_path, + output_file: File.join(output_dir, "#{snippet}_#{index}.s") + } + end + + Parallel.each(jobs, in_processes: options[:jobs]) do |job| + generator = SimTest::FinalAsmGen.new(job[:ir]) + formatter = SimTest::RiscVFormatter.new + snippet_content = File.read(job[:snippet_path]) + + generator.generate( + formatter, + snippet_content, + job[:init_yaml_file], + job[:log_path], + job[:output_file] + ) + + puts "Generated: #{job[:output_file]}" + end +end diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/compile-and-run.sh b/test/SimTests/SnippetBased/SnippetBasedImpl/compile-and-run.sh new file mode 100755 index 0000000..7765bca --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/compile-and-run.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +if [ $# -lt 6 ]; then + echo "Usage: $0 " + exit 1 +fi + +SRC_DIR="$1" +BIN_DIR="$2" +COMPILER="$3" +QEMU="$4" +QEMU_LOG_DIR="$5" +COMPILER_FLAGS="$6" + +# Compile each .s file +for s_file in "$SRC_DIR"/*.s; do + if [ -f "$s_file" ]; then + base=$(basename "$s_file" .s) + out_file="$BIN_DIR/$base.elf" + echo "Compiling $s_file -> $out_file" + $COMPILER $COMPILER_FLAGS "$s_file" -o "$out_file" + if [ $? -ne 0 ]; then + echo "Compilation failed for $s_file" + exit 1 + fi + fi +done + +# Run QEMU on each compiled binary +for bin_file in "$BIN_DIR"/*.elf; do + if [ -f "$bin_file" ]; then + echo "Running QEMU on $bin_file" + base_name="${bin_file##*/}" + base_name="${base_name%.elf}" + $QEMU -D "$QEMU_LOG_DIR/$base_name.log" -d cpu "$bin_file" + if [ $? -ne 0 ]; then + echo "QEMU failed on $bin_file" + exit 1 + fi + fi +done diff --git a/test/SimTests/SnippetBased/SnippetBasedImpl/compile-dir.sh b/test/SimTests/SnippetBased/SnippetBasedImpl/compile-dir.sh new file mode 100755 index 0000000..2968116 --- /dev/null +++ b/test/SimTests/SnippetBased/SnippetBasedImpl/compile-dir.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +if [ $# -ne 4 ]; then + echo "Usage: $0 " + exit 1 +fi + +SRC_DIR="$1" +BIN_DIR="$2" +COMPILER="$3" +COMPILER_FLAGS="$4" + +for s_file in "$SRC_DIR"/*.s; do + if [ -f "$s_file" ]; then + base=$(basename "$s_file" .s) + out_file="$BIN_DIR/$base.elf" + echo "Compiling $s_file -> $out_file" + $COMPILER $COMPILER_FLAGS "$s_file" -o "$out_file" + if [ $? -ne 0 ]; then + echo "Compilation failed for $s_file" + exit 1 + fi + fi +done