diff --git a/targets/CMakeLists.txt b/targets/CMakeLists.txt index ddc5b82..f9fbbdd 100644 --- a/targets/CMakeLists.txt +++ b/targets/CMakeLists.txt @@ -6,7 +6,7 @@ # Viviane Potocnik set(AVAILABLE_TARGETS - "cheshire" + "chimera-host" "chimera-open" CACHE STRING "Available Targets" ) @@ -17,8 +17,8 @@ if(NOT TARGET_PLATFORM IN_LIST AVAILABLE_TARGETS) message(FATAL_ERROR "Wrong value for TARGET_PLATFORM: Got ${TARGET_PLATFORM}. Available targets are: ${AVAILABLE_TARGETS}") endif() -if (TARGET_PLATFORM STREQUAL "cheshire") - add_subdirectory(cheshire) +if (TARGET_PLATFORM STREQUAL "chimera-host") + add_subdirectory(chimera-host) endif() if (TARGET_PLATFORM STREQUAL "chimera-open") diff --git a/targets/chimera-host/CMakeLists.txt b/targets/chimera-host/CMakeLists.txt new file mode 100644 index 0000000..ea4c692 --- /dev/null +++ b/targets/chimera-host/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Moritz Scherer +# Viviane Potocnik + +file(GLOB_RECURSE ASM_SOURCES + "src/crt0.S" +) + +file(GLOB_RECURSE C_SOURCES + "src/*.c" +) + +set_property(SOURCE ${ASM_SOURCES} PROPERTY LANGUAGE ASM) +add_library(runtime OBJECT ${ASM_SOURCES} ${C_SOURCES}) + +target_include_directories(runtime + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/include +) + +set(ISA rv32imc) +set(ABI ilp32) + +target_compile_options(runtime + PUBLIC + -march=${ISA} + -mabi=${ABI} +) + +target_link_options(runtime + PUBLIC + -march=${ISA} + -mabi=${ABI} + -nostartfiles + -nostdlib + -L${CMAKE_CURRENT_LIST_DIR} + -Tlink.ld +) diff --git a/targets/chimera-host/common.ldh b/targets/chimera-host/common.ldh new file mode 100644 index 0000000..cff6ed2 --- /dev/null +++ b/targets/chimera-host/common.ldh @@ -0,0 +1,55 @@ +/* Copyright 2022 ETH Zurich and University of Bologna. */ +/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* Nicole Narr */ +/* Christopher Reinwardt */ +/* Paul Scheffler */ + +/* This header defines symbols and rules universal to bare-metal execution */ + +ENTRY(_start) + +MEMORY { + bootrom (rx) : ORIGIN = 0x02000000, LENGTH = 16K + /* We assume at least 64 KiB SPM, same minus stack for ROMs. */ + /* If more SPM is available, CRT0 repoints the stack. */ + extrom (rx) : ORIGIN = 0x00000000, LENGTH = 48K + spm (rwx) : ORIGIN = 0x10000000, LENGTH = 64K + memisl (rwx) : ORIGIN = 0x48000000, LENGTH = 64K + /* We assume at least 8 MiB of DRAM (minimum for Linux). */ + dram (rwx) : ORIGIN = 0x80000000, LENGTH = 8M +} + +SECTIONS { + /* Keep binaries lean */ + /DISCARD/ : { *(.riscv.attributes) *(.comment) } + + /* Global and stack pointer */ + /* By default, keep the calling context (boot ROM) stack pointer */ + __global_pointer$ = ADDR(.misc) + SIZEOF(.misc) / 2; + __stack_pointer$ = __stack_start - 8; + + /* Further addresses */ + __base_dma = 0x01000000; + __base_bootrom = 0x02000000; + __base_clint = 0x02040000; + __base_axirt = 0x020C0000; + __base_axirtgrd = 0x020C1ffc; + __base_regs = 0x03000000; + __base_llc = 0x03001000; + __base_uart = 0x03002000; + __base_i2c = 0x03003000; + __base_spih = 0x03004000; + __base_gpio = 0x03005000; + __base_slink = 0x03006000; + __base_vga = 0x03007000; + __base_usb = 0x03008000; + __base_bus_err = 0x03009000; + __base_plic = 0x04000000; + __base_clic = 0x08000000; + __base_spm = ORIGIN(spm); + __base_dram = ORIGIN(dram); + __base_memisl = ORIGIN(memisl); + __stack_start = ORIGIN(memisl) + LENGTH(memisl); +} diff --git a/targets/chimera-host/link.ld b/targets/chimera-host/link.ld new file mode 100644 index 0000000..6dcf16c --- /dev/null +++ b/targets/chimera-host/link.ld @@ -0,0 +1,46 @@ +/* Copyright 2022 ETH Zurich and University of Bologna. */ +/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* Nicole Narr */ +/* Christopher Reinwardt */ +/* Paul Scheffler */ +/* Lorenzo Leone */ + + +INCLUDE common.ldh + +SECTIONS { + .text : { + *(.text._start) + *(.text) + *(.text.*) + } > memisl + + .misc : ALIGN(16) { + *(.rodata) + *(.rodata.*) + *(.data) + *(.data.*) + *(.srodata) + *(.srodata.*) + *(.sdata) + *(.sdata.*) + } > memisl + + . = ALIGN(32); + __bss_start = .; + .bss : { + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + } > memisl + . = ALIGN(32); + __bss_end = .; + + .bulk : ALIGN(16) { + *(.bulk) + *(.bulk.*) + } > memisl +} diff --git a/targets/chimera-host/src/crt0.S b/targets/chimera-host/src/crt0.S new file mode 100644 index 0000000..5e44ab5 --- /dev/null +++ b/targets/chimera-host/src/crt0.S @@ -0,0 +1,133 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Viviane Potocnik + +.section .text._start +// Minimal CRT0 +.global _start +_start: + // Globally disable Machine and Supervisor interrupts + csrrc x0, mstatus, 10 + + // Park SMP harts + csrr t0, mhartid + beqz t0, 2f +1: + wfi + j 1b +2: + // Init stack and global pointer iff linked as nonzero + mv t1, sp + la t0, __stack_pointer$ + beqz t0, 1f + mv sp, t0 +1: .option push + .option norelax + la t0, __global_pointer$ + beqz t0, 1f + mv gp, t0 +1: .option pop + + // Store existing stack, global, return pointers on new stack + addi sp, sp, -12 + sw t1, 0(sp) + sw gp, 4(sp) + sw ra, 8(sp) + + // Set trap vector + la t0, _trap_handler_wrap + csrrw x0, mtvec, t0 + + // Zero the .bss section + la t0, __bss_start // t0 = bss start address + la t1, __bss_end // t1 = bss end address + sub t2, t1, t0 // t2 = #bytes to zero + li a0, 0 + +_zero_bss_loop: + addi t4, t2, -16 + blez t2, _fp_init // t2 <= 0? => No bss to zero + blt t4, x0, _zero_bss_rem // t4 < 0? => Less than 4 words left + sw a0, 0(t0) + sw a0, 4(t0) + sw a0, 8(t0) + sw a0, 12(t0) + addi t2, t2, -16 + addi t0, t0, 16 + bgt t2, x0, _zero_bss_loop // Still more to go + j _fp_init + +_zero_bss_rem: + sb a0, 0(t0) + addi t2, t2, -1 + addi t0, t0, 1 + bgt t2, x0, _zero_bss_rem + +_fp_init: + // Full fence, then jump to main + call main + +// If main returns, we end up here +.global _exit +_exit: + // Restore the original context registers (sp last) + lw ra, 8(sp) + lw gp, 4(sp) + lw sp, 0(sp) + // Save the return value to scratch register 2 and wait forever. + slli t0, a0, 1 + ori t0, t0, 1 + la t1, __base_regs + sw t0, 8(t1) // regs.SCRATCH[2] + // Hand over to whatever called us, passing return + ret + +// This wraps the C trap handler to save the (integer-only) caller-save +// registers and perform a proper machine-mode exception return. +.align 4 +_trap_handler_wrap: + addi sp, sp, -64 + sw ra, 60(sp) + sw t0, 56(sp) + sw t1, 52(sp) + sw t2, 48(sp) + sw a0, 44(sp) + sw a1, 40(sp) + sw a2, 36(sp) + sw a3, 32(sp) + sw a4, 28(sp) + sw a5, 24(sp) + sw a6, 20(sp) + sw a7, 16(sp) + sw t3, 12(sp) + sw t4, 8(sp) + sw t5, 4(sp) + sw t6, 0(sp) + + jal trap_vector + + lw ra, 60(sp) + lw t0, 56(sp) + lw t1, 52(sp) + lw t2, 48(sp) + lw a0, 44(sp) + lw a1, 40(sp) + lw a2, 36(sp) + lw a3, 32(sp) + lw a4, 28(sp) + lw a5, 24(sp) + lw a6, 20(sp) + lw a7, 16(sp) + lw t3, 12(sp) + lw t4, 8(sp) + lw t5, 4(sp) + lw t6, 0(sp) + addi sp, sp, 128 + mret + +.global trap_vector +.weak trap_vector +trap_vector: + j trap_vector