Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
Copy link
Copy Markdown
Member

@derzhavin3016 derzhavin3016 Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes to clang format should be discussed, this change is not related to this PR. Consider using either minimal default clang format (e.g. LLVM), or remove this file completely

Copy link
Copy Markdown
Contributor Author

@egorshamshura egorshamshura Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Started to use LLVM format

BasedOnStyle: LLVM
17 changes: 8 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the image contain? Add more info

strategy:
fail-fast: false
matrix:
Expand All @@ -44,11 +46,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"
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@ 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
PROPERTY VALUE "${CMAKE_BINARY_DIR}/install")
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)
92 changes: 87 additions & 5 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,119 @@
"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"
}
},
{
"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
}
}
]
}
11 changes: 11 additions & 0 deletions ci-extra/test.sh
Original file line number Diff line number Diff line change
@@ -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}"
60 changes: 60 additions & 0 deletions cmake/CompilerConfig.cmake
Original file line number Diff line number Diff line change
@@ -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()
5 changes: 5 additions & 0 deletions cmake/QEMU.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (NOT DEFINED QEMU_PATH)
set(QEMU_PATH "qemu")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add message

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added status message

endif()

message(STATUS "Using QEMU: ${QEMU_PATH}")
23 changes: 23 additions & 0 deletions cmake/discover_generated_tests.cmake.in
Original file line number Diff line number Diff line change
@@ -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()
65 changes: 65 additions & 0 deletions cmake/toolchain/riscv.cmake
Original file line number Diff line number Diff line change
@@ -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
"rv32i"
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()
2 changes: 1 addition & 1 deletion code_gen/cpp_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,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]
Expand Down
2 changes: 2 additions & 0 deletions lib/ADL/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
)
Expand All @@ -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),
}
)
Expand Down
2 changes: 1 addition & 1 deletion lib/ADL/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading