From 6cf506c2c79a28ebc1677abc487acbb9390f4aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Denkinger?= Date: Wed, 27 Mar 2024 14:16:55 +0100 Subject: [PATCH 01/24] Removed SignalType and created a clock and reset property. Cleaned unused properties. --- .../peakrdl_socgen/common/socgen_props.rdl | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/cmake/peakrdl/peakrdl_socgen/common/socgen_props.rdl b/cmake/peakrdl/peakrdl_socgen/common/socgen_props.rdl index 6a7ad85..6f838f2 100644 --- a/cmake/peakrdl/peakrdl_socgen/common/socgen_props.rdl +++ b/cmake/peakrdl/peakrdl_socgen/common/socgen_props.rdl @@ -1,33 +1,30 @@ `ifndef COMMON_RDL `define COMMON_RDL -enum SignalType { - output = 0; - input = 1; - bidir = 2; - tri = 3; - clk = 4; - rst = 5; - wire = 6; - blank = 7; -}; - +// input or output property is needed to be detected by socgen property output { type = boolean; component = signal; }; + property input { type = boolean; component = signal; }; -property datatype { - type = string; +property clock { + type = boolean; component = signal; }; -property signal_type { - type = SignalType; +// reset property is a a built-in SystemRDL property but not for signals +property reset_signal { + type = boolean; + component = signal; +}; + +property datatype { + type = string; component = signal; }; @@ -61,12 +58,6 @@ property path { component = signal; }; -property propagate { - type = boolean; - component = signal; -}; - - struct intc { string name; string slv_ports[]; @@ -78,7 +69,6 @@ property intc_l { component = addrmap; }; - // desc = "Slave select signal, should not be shared between slaves"; property ss { type = boolean; @@ -100,25 +90,28 @@ property miso { component = signal; }; -signal clk { +signal clk { + input; + clock; signalwidth=1; desc = "Input clock"; - signal_type = SignalType::clk; - }; +}; signal rstn { + input; + reset_signal; signalwidth=1; desc = "Input reset, active low"; activelow = true; - signal_type = SignalType::rst; - }; +}; signal rst { + input; + reset_signal; signalwidth=1; desc = "Input reset, active high"; activehigh = true; - signal_type = SignalType::rst; - }; +}; property intf { type = boolean; @@ -150,8 +143,6 @@ struct addr_intf : data_intf { longint unsigned ADDR_WIDTH; }; - - property intf_inst{ component = addrmap; type = base_intf; From 218ee1baed8674ef9bff43242c39104daa398697 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Tue, 16 Apr 2024 16:52:47 +0200 Subject: [PATCH 02/24] Commented and cleaned lds generatation scripts. --- SoCMakeConfig.cmake | 1 + cmake/firmware/linker_script/gen_lds.cmake | 33 ++- .../linker_script/src/gen_linker_script.py | 55 ++++- .../linker_script/src/template/linker.lds.j2 | 230 ++++++++++++++++++ 4 files changed, 302 insertions(+), 17 deletions(-) create mode 100644 cmake/firmware/linker_script/src/template/linker.lds.j2 diff --git a/SoCMakeConfig.cmake b/SoCMakeConfig.cmake index a200e0e..02a359a 100644 --- a/SoCMakeConfig.cmake +++ b/SoCMakeConfig.cmake @@ -80,6 +80,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/tmrg/tmrv/tmrv.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/fw_utils.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/add_tests.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/gen_lds.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/src/lds_props.cmake") set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") set(IBEX_TOOLCHAIN_BASE "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain_base.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN_BASE") diff --git a/cmake/firmware/linker_script/gen_lds.cmake b/cmake/firmware/linker_script/gen_lds.cmake index 6485e87..4e7472d 100644 --- a/cmake/firmware/linker_script/gen_lds.cmake +++ b/cmake/firmware/linker_script/gen_lds.cmake @@ -1,52 +1,76 @@ +#[[[ +# This function generates linker script (LDS) file for the specified IP library. +# +# :param IP_LIB: The name of the IP library target. +# :type IP_LIB: str +#]] function(gen_lds IP_LIB) - cmake_parse_arguments(ARG "NODEBUG" "OUTDIR" "PARAMETERS" ${ARGN}) + # Parse the arguments passed to the function + cmake_parse_arguments(ARG "NODEBUG" "OUTDIR;PARAMETERS" ${ARGN}) + # Check for any unrecognized arguments if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") endif() + # Include necessary CMake files include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../hwip.cmake") include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../fw_utils.cmake") include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../utils/find_python.cmake") find_python3() + # Define the path to the linker script generation tool set(LDS_GEN_TOOL "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/src/gen_linker_script.py") + # Set the IP library to the last specified ip_assume_last(IP_LIB ${IP_LIB}) + # Get the binary directory of the IP library get_target_property(BINARY_DIR ${IP_LIB} BINARY_DIR) + # Set the output directory for the linker script if(NOT ARG_OUTDIR) set(OUTDIR ${BINARY_DIR}/lds) else() set(OUTDIR ${ARG_OUTDIR}) endif() + # Set the debug flag if NODEBUG is not specified if(ARG_NODEBUG) set(ARG_NODEBUG) else() set(ARG_NODEBUG --debug) endif() - # Used to overwrite the top level parameters + # Initialize string to store overwritten parameters set(OVERWRITTEN_PARAMETERS "") + # Process any specified parameters to overwrite if(ARG_PARAMETERS) foreach(PARAM ${ARG_PARAMETERS}) string(APPEND OVERWRITTEN_PARAMETERS "-p${PARAM}") endforeach() endif() + # Create the output directory if it does not exist execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTDIR}) + # Get the system RDL files for the IP library get_ip_sources(RDL_FILES ${IP_LIB} SYSTEMRDL) + # Check if system RDL files exist if(NOT RDL_FILES) message(FATAL_ERROR "Library ${IP_LIB} does not have RDL_FILES property set, unable to run ${CMAKE_CURRENT_FUNCTION}") endif() + + # Set the path to the generated linker script file set(LDS_FILE "${OUTDIR}/${IP_LIB}.lds") + # Mark the linker script file as generated set_source_files_properties(${LDS_FILE} PROPERTIES GENERATED TRUE) + # Set linker script file as IP library source ip_sources(${IP_LIB} LINKER_SCRIPT ${LDS_FILE}) + # Set the stamp file path set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") + # Add custom command to generate linker script add_custom_command( OUTPUT ${LDS_FILE} ${STAMP_FILE} COMMAND ${Python3_EXECUTABLE} ${LDS_GEN_TOOL} @@ -60,13 +84,12 @@ function(gen_lds IP_LIB) COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" ) + # Add custom target for generating linker script add_custom_target( ${IP_LIB}_lds DEPENDS ${RDL_FILES} ${STAMP_FILE} ) + # Add dependency on the custom target for the IP library add_dependencies(${IP_LIB} ${IP_LIB}_lds) - endfunction() - -include("${CMAKE_CURRENT_LIST_DIR}/src/lds_props.cmake") diff --git a/cmake/firmware/linker_script/src/gen_linker_script.py b/cmake/firmware/linker_script/src/gen_linker_script.py index b1f8414..0c90c4d 100644 --- a/cmake/firmware/linker_script/src/gen_linker_script.py +++ b/cmake/firmware/linker_script/src/gen_linker_script.py @@ -1,11 +1,35 @@ -from systemrdl import RDLCompiler, RDLCompileError, RDLListener, RDLWalker -from systemrdl.node import FieldNode, MemNode, Node, RootNode, AddressableNode, RegNode, SignalNode from typing import List import sys, os import jinja2 import argparse +from systemrdl import RDLCompiler, RDLCompileError, RDLListener, RDLWalker +from systemrdl.node import MemNode, Node + class RDL2LdsExporter(RDLListener): + """Export SystemRDL to Linker Description Script (LDS). + + Class methods: + + - :func:`enter_Mem` + - :func:`enter_Reg` + - :func:`isSwEx` + - :func:`isSwWr` + - :func:`isBoot` + - :func:`isStack` + - :func:`isData` + - :func:`isBss` + - :func:`get_sections_prop` + - :func:`getStackMem` + - :func:`getProgramMem` + - :func:`getDataMem` + - :func:`getBssMem` + - :func:`getBootMem` + - :func:`getSwAcc` + - :func:`write_sections` + - :func:`export` + - :func:`process_template`` + """ def __init__(self): self.memories = [] self.regs = [] @@ -16,47 +40,57 @@ def enter_Mem(self, node): def enter_Reg(self, node): if node.get_property("linker_symbol", default=False): - assert not any(reg.inst_name == node.inst_name for reg in self.regs), f"Only one register with linker_symbol property and the same instance name can exist, you probably instantiated \"{node.parent.orig_type_name}\" Addrmap multiple times" + assert (not any(reg.inst_name == node.inst_name for reg in self.regs), + f"Only one register with linker_symbol property and the same instance + name can exist, you probably instantiated \"{node.parent.orig_type_name}\" + Addrmap multiple times") self.regs.append(node) def isSwEx(self, mem : MemNode) -> bool: + """Returns True if the section contains executable code.""" sections = self.get_sections_prop(mem) if "text" in sections: return True return False def isSwWr(self, mem : MemNode) -> bool: + """Returns True if section is writable by software.""" sections = self.get_sections_prop(mem) if any(item in sections for item in ["data", "bss", "stack"]): return True return False def isBoot(self, mem : MemNode) -> bool: + """Returns True if section is contains the bootloader.""" sections = self.get_sections_prop(mem) if "boot" in sections: return True return False def isStack(self, mem : MemNode) -> bool: + """Returns True if section contains the stack.""" sections = self.get_sections_prop(mem) if "stack" in sections: return True return False def isData(self, mem : MemNode) -> bool: + """Returns True if section contains data.""" sections = self.get_sections_prop(mem) if "data" in sections: return True return False def isBss(self, mem : MemNode) -> bool: + """Returns True if section contains the bss (uninitialized global or static variables).""" sections = self.get_sections_prop(mem) if "bss" in sections: return True return False - def get_sections_prop(self, m : MemNode): + def get_sections_prop(self, m : MemNode) -> List[str]: + """Returns a list of string corresponding to the section properties.""" sections = m.get_property('sections').split('|') for s in sections: assert_m = f"Illegal property for sections: {s} of memory: {m.inst_name} in addrmap: {m.parent.inst_name}" @@ -75,6 +109,7 @@ def getStackMem(self, mems: List[MemNode]) -> MemNode: def getProgramMem(self, mems: List[MemNode]) -> MemNode: + """Returns the program/instruction/text MemNode.""" prog_mems = [] for m in mems: if self.isSwEx(m) and not self.isBoot(m): @@ -84,6 +119,7 @@ def getProgramMem(self, mems: List[MemNode]) -> MemNode: return prog_mems[0] def getDataMem(self, mems: List[MemNode]) -> MemNode: + """Returns the data MemNode.""" data_mems = [] for m in mems: if self.isData(m): @@ -93,6 +129,7 @@ def getDataMem(self, mems: List[MemNode]) -> MemNode: return data_mems[0] def getBssMem(self, mems: List[MemNode]) -> MemNode: + """Returns the bss MemNode.""" data_mems = [] for m in mems: if self.isData(m): @@ -102,6 +139,7 @@ def getBssMem(self, mems: List[MemNode]) -> MemNode: return data_mems[0] def getBootMem(self, mems: List[MemNode]) -> "MemNode | None": + """Returns the boot MemNode.""" boot_mems = [] for m in mems: if self.isBoot(m): @@ -111,6 +149,7 @@ def getBootMem(self, mems: List[MemNode]) -> "MemNode | None": return boot_mems[0] if len(boot_mems) > 0 else None def getSwAcc(self, mem : MemNode) -> str: + """Returns the software access rights to the MemNode.""" out = "r" if self.isSwWr(mem): out = out + "w" @@ -118,17 +157,11 @@ def getSwAcc(self, mem : MemNode) -> str: out = out + "x" return out - def write_sections(self, mems : List[MemNode]) -> str: - out = "" - - return out - def export(self, node: Node, outfile : str, debug : bool = True, ): - # self.memories = self.find_memories(node) context = {'mems' : self.memories, 'debug' : debug, @@ -215,5 +248,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/cmake/firmware/linker_script/src/template/linker.lds.j2 b/cmake/firmware/linker_script/src/template/linker.lds.j2 new file mode 100644 index 0000000..a7893eb --- /dev/null +++ b/cmake/firmware/linker_script/src/template/linker.lds.j2 @@ -0,0 +1,230 @@ +/* Copyright (c) 2024 CERN */ +/* SPDX-License-Identifier: Apache-2.0 */ + +OUTPUT_ARCH(riscv) + +ENTRY(_start) + +MEMORY { +{% for m in mems %} + {{ m.parent.inst_name }} ({{ m|getSwAcc }}): ORIGIN = 0x{{ '%08x' % m.absolute_address }}, LENGTH = 0x{{ '%08x' % m.size }} +{% endfor %} +} + +{% set stack_mem = mems|getStackMem %} +{% set prog_mem = mems|getProgramMem %} +{% set boot_mem = mems|getBootMem %} +{% set data_mem = mems|getDataMem %} +{% set bss_mem = mems|getBssMem %} + +PROVIDE(_estack = ORIGIN( {{ stack_mem.parent.inst_name }}) + LENGTH( {{ stack_mem.parent.inst_name }} )); + +PROVIDE(_stext = ORIGIN( {{ prog_mem.parent.inst_name }} )); +PROVIDE(_start = ORIGIN( {{ prog_mem.parent.inst_name }} )); +PROVIDE(_program_memory = ORIGIN( {{ prog_mem.parent.inst_name }} )); + +PROVIDE (__executable_start = SEGMENT_START("text-segment", _start)); . = SEGMENT_START("text-segment", _start) + SIZEOF_HEADERS; + +{% for reg in regs %} +PROVIDE({{reg.inst_name}} = 0x{{ '%08x' % reg.absolute_address }}); +{% endfor %} + + +SECTIONS { + + {% if boot_mem is not none %} + .bootloader : { + *bootloader.S.o(.vectors); + *bootloader.S.o*(*); + *bootloader.cpp.o*(*); + . = ALIGN(4); + } > {{ boot_mem.parent.inst_name }} + {% endif %} + + .text : + { + . = ALIGN(4); + *crt0.S.o(.vectors); + *crt0.S.o(.start_section); + *crt0.S.o(.text); + + /* TODO maybe more relaxed garbage collection */ + KEEP (*crt0.S.o(*)) + + KEEP (*(SORT_NONE(.init))) + + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + + KEEP (*(SORT_NONE(.fini))) + } > {{ prog_mem.parent.inst_name }} + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > {{ data_mem.parent.inst_name }} + + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } > {{ data_mem.parent.inst_name }} + + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > {{ data_mem.parent.inst_name }} + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } > {{ data_mem.parent.inst_name }} + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > {{ data_mem.parent.inst_name }} + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > {{ data_mem.parent.inst_name }} + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > {{ data_mem.parent.inst_name }} + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } > {{ data_mem.parent.inst_name }} + .dynamic : { *(.dynamic) } > {{ data_mem.parent.inst_name }} + . = DATA_SEGMENT_RELRO_END (0, .); + .data : + { + __DATA_BEGIN__ = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + *(.data1) + *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } > {{ data_mem.parent.inst_name }} + _edata = .; PROVIDE (edata = .); + + + + + __bss_start = .; + __BSS_START__ = .; + _bss_start = .; + .sbss : + { + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } > {{ bss_mem.parent.inst_name }} + .bss : ALIGN(4) + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } > {{ bss_mem.parent.inst_name }} + . = ALIGN(32 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(32 / 8); + __BSS_END__ = .; + _bss_end = .; + _align_begin = .; + .align_mem0 : { + . = ALIGN(3); + } > {{ bss_mem.parent.inst_name }} + __global_pointer$ = 0x{{ '%08x' % data_mem.absolute_address }} + 0x{{ '%08x' % (data_mem.size/2)|int }}; + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + + {% if debug %} + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } > {{ data_mem.parent.inst_name }} + .stabstr 0 : { *(.stabstr) } > {{ data_mem.parent.inst_name }} + .stab.excl 0 : { *(.stab.excl) } > {{ data_mem.parent.inst_name }} + .stab.exclstr 0 : { *(.stab.exclstr) } > {{ data_mem.parent.inst_name }} + .stab.index 0 : { *(.stab.index) } > {{ data_mem.parent.inst_name }} + .stab.indexstr 0 : { *(.stab.indexstr) } > {{ data_mem.parent.inst_name }} + .comment 0 : { *(.comment) } > {{ data_mem.parent.inst_name }} + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } > {{ data_mem.parent.inst_name }} + .line 0 : { *(.line) } > {{ data_mem.parent.inst_name }} + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } > {{ data_mem.parent.inst_name }} + .debug_sfnames 0 : { *(.debug_sfnames) } > {{ data_mem.parent.inst_name }} + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } > {{ data_mem.parent.inst_name }} + .debug_pubnames 0 : { *(.debug_pubnames) } > {{ data_mem.parent.inst_name }} + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } > {{ data_mem.parent.inst_name }} + .debug_abbrev 0 : { *(.debug_abbrev) } > {{ data_mem.parent.inst_name }} + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } > {{ data_mem.parent.inst_name }} + .debug_frame 0 : { *(.debug_frame) } > {{ data_mem.parent.inst_name }} + .debug_str 0 : { *(.debug_str) } > {{ data_mem.parent.inst_name }} + .debug_loc 0 : { *(.debug_loc) } > {{ data_mem.parent.inst_name }} + .debug_macinfo 0 : { *(.debug_macinfo) } > {{ data_mem.parent.inst_name }} + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } > {{ data_mem.parent.inst_name }} + .debug_funcnames 0 : { *(.debug_funcnames) } > {{ data_mem.parent.inst_name }} + .debug_typenames 0 : { *(.debug_typenames) } > {{ data_mem.parent.inst_name }} + .debug_varnames 0 : { *(.debug_varnames) } > {{ data_mem.parent.inst_name }} + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } > {{ data_mem.parent.inst_name }} + .debug_ranges 0 : { *(.debug_ranges) } > {{ data_mem.parent.inst_name }} + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } > {{ data_mem.parent.inst_name }} + .debug_addr 0 : { *(.debug_addr) } > {{ data_mem.parent.inst_name }} + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } > {{ data_mem.parent.inst_name }} + {% endif %} + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(*) } > {{ data_mem.parent.inst_name }} +}; + From c189262cf4ca2012b101fd9aacb712a133ad4948 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Wed, 17 Apr 2024 09:14:36 +0200 Subject: [PATCH 03/24] Reverted bug introduction with NODEBUG flag. --- cmake/firmware/linker_script/gen_lds.cmake | 2 +- cmake/firmware/linker_script/src/gen_linker_script.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmake/firmware/linker_script/gen_lds.cmake b/cmake/firmware/linker_script/gen_lds.cmake index 4e7472d..eccc505 100644 --- a/cmake/firmware/linker_script/gen_lds.cmake +++ b/cmake/firmware/linker_script/gen_lds.cmake @@ -6,7 +6,7 @@ #]] function(gen_lds IP_LIB) # Parse the arguments passed to the function - cmake_parse_arguments(ARG "NODEBUG" "OUTDIR;PARAMETERS" ${ARGN}) + cmake_parse_arguments(ARG "NODEBUG" "OUTDIR" "PARAMETERS" ${ARGN}) # Check for any unrecognized arguments if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") diff --git a/cmake/firmware/linker_script/src/gen_linker_script.py b/cmake/firmware/linker_script/src/gen_linker_script.py index 0c90c4d..1a7a3ad 100644 --- a/cmake/firmware/linker_script/src/gen_linker_script.py +++ b/cmake/firmware/linker_script/src/gen_linker_script.py @@ -40,10 +40,10 @@ def enter_Mem(self, node): def enter_Reg(self, node): if node.get_property("linker_symbol", default=False): - assert (not any(reg.inst_name == node.inst_name for reg in self.regs), - f"Only one register with linker_symbol property and the same instance - name can exist, you probably instantiated \"{node.parent.orig_type_name}\" - Addrmap multiple times") + assert not any(reg.inst_name == node.inst_name for reg in self.regs), \ + f"Only one register with linker_symbol property and the same \ + instance name can exist, you probably instantiated \ + {node.parent.orig_type_name} Addrmap multiple times" self.regs.append(node) @@ -207,7 +207,7 @@ def main(): parser.add_argument('--rdlfiles', nargs="+", help='RDL input files') parser.add_argument('--outfile', required=True, help='Output lds file') - parser.add_argument('--debug', type=bool, default=False, help='Include debug section in the lds or discard it') + parser.add_argument('--debug', default=False, action="store_true", help='Include debug section in the lds or discard it') parser.add_argument('-p', '--param', nargs='+', help="Parameter to overwrite on top RDL module in the format 'PARAM=VALUE'") args = parser.parse_args() @@ -228,6 +228,7 @@ def main(): sys.exit(1) top_gen = root.children(unroll=True) + # Is this really needed? top = None for top in top_gen: top = top From f0522ffc6e4d6658ead23748f9e2fbf2955f1436 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Wed, 17 Apr 2024 17:06:24 +0200 Subject: [PATCH 04/24] New linker script implementation started. --- .../linker_script/src/gen_linker_script.py | 21 +- .../linker_script/src/template/linker.lds.j2 | 259 ++++++++++-------- 2 files changed, 164 insertions(+), 116 deletions(-) diff --git a/cmake/firmware/linker_script/src/gen_linker_script.py b/cmake/firmware/linker_script/src/gen_linker_script.py index 1a7a3ad..36618b4 100644 --- a/cmake/firmware/linker_script/src/gen_linker_script.py +++ b/cmake/firmware/linker_script/src/gen_linker_script.py @@ -75,6 +75,13 @@ def isStack(self, mem : MemNode) -> bool: return True return False + def isHeap(self, mem : MemNode) -> bool: + """Returns True if section contains the heap.""" + sections = self.get_sections_prop(mem) + if "heap" in sections: + return True + return False + def isData(self, mem : MemNode) -> bool: """Returns True if section contains data.""" sections = self.get_sections_prop(mem) @@ -94,7 +101,7 @@ def get_sections_prop(self, m : MemNode) -> List[str]: sections = m.get_property('sections').split('|') for s in sections: assert_m = f"Illegal property for sections: {s} of memory: {m.inst_name} in addrmap: {m.parent.inst_name}" - assert s in ['text', 'data', 'bss', 'boot', 'stack'], assert_m + assert s in ['text', 'data', 'bss', 'boot', 'stack', 'heap'], assert_m return sections @@ -107,6 +114,15 @@ def getStackMem(self, mems: List[MemNode]) -> MemNode: return stack_mems[0] + def getHeapMem(self, mems: List[MemNode]) -> MemNode: + heap_mems = [] + for m in mems: + if self.isHeap(m): + heap_mems.append(m) + assert len(heap_mems) == 1, f"Exactly 1 memory with section heap is allowed and required {heap_mems}" # TODO + + return heap_mems[0] + def getProgramMem(self, mems: List[MemNode]) -> MemNode: """Returns the program/instruction/text MemNode.""" @@ -168,7 +184,8 @@ def export(self, 'regs' : self.regs } - text = self.process_template(context, "lds.j2") + # text = self.process_template(context, "lds.j2") + text = self.process_template(context, "linker.lds.j2") # assert(node.type_name is not None) # out_file = os.path.join(outfile, node.type_name + ".lds") diff --git a/cmake/firmware/linker_script/src/template/linker.lds.j2 b/cmake/firmware/linker_script/src/template/linker.lds.j2 index a7893eb..da7cdab 100644 --- a/cmake/firmware/linker_script/src/template/linker.lds.j2 +++ b/cmake/firmware/linker_script/src/template/linker.lds.j2 @@ -3,7 +3,7 @@ OUTPUT_ARCH(riscv) -ENTRY(_start) +ENTRY(_entry) MEMORY { {% for m in mems %} @@ -11,99 +11,102 @@ MEMORY { {% endfor %} } -{% set stack_mem = mems|getStackMem %} +{# {% set stack_mem = mems|getStackMem %} +{% set heap_mem = mems|getHeapMem %} #} {% set prog_mem = mems|getProgramMem %} {% set boot_mem = mems|getBootMem %} {% set data_mem = mems|getDataMem %} {% set bss_mem = mems|getBssMem %} -PROVIDE(_estack = ORIGIN( {{ stack_mem.parent.inst_name }}) + LENGTH( {{ stack_mem.parent.inst_name }} )); - -PROVIDE(_stext = ORIGIN( {{ prog_mem.parent.inst_name }} )); -PROVIDE(_start = ORIGIN( {{ prog_mem.parent.inst_name }} )); -PROVIDE(_program_memory = ORIGIN( {{ prog_mem.parent.inst_name }} )); - -PROVIDE (__executable_start = SEGMENT_START("text-segment", _start)); . = SEGMENT_START("text-segment", _start) + SIZEOF_HEADERS; - {% for reg in regs %} PROVIDE({{reg.inst_name}} = 0x{{ '%08x' % reg.absolute_address }}); {% endfor %} +SECTIONS +{ + /* we want a fixed boot point */ + PROVIDE(__boot_address = ORIGIN( {{ boot_mem.parent.inst_name }} )); -SECTIONS { + {% if boot_mem is not none %} + .bootloader : { + *bootloader.S.o*(*); + *bootloader.cpp.o*(*); + . = ALIGN(4); + } > {{ boot_mem.parent.inst_name }} + {% endif %} - {% if boot_mem is not none %} - .bootloader : { - *bootloader.S.o(.vectors); - *bootloader.S.o*(*); - *bootloader.cpp.o*(*); - . = ALIGN(4); - } > {{ boot_mem.parent.inst_name }} - {% endif %} + /* we want a fixed entry point */ + PROVIDE(__entry_address = ORIGIN( {{ prog_mem.parent.inst_name }} ) + 0x180); - .text : - { - . = ALIGN(4); - *crt0.S.o(.vectors); - *crt0.S.o(.start_section); - *crt0.S.o(.text); + /* stack and heap related settings */ + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x800; + PROVIDE(__stack_size = __stack_size); + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; - /* TODO maybe more relaxed garbage collection */ - KEEP (*crt0.S.o(*)) + /***************************************/ + /* PROGRAM / TEXT / READ-ONLY SECTIONS */ + /***************************************/ - KEEP (*(SORT_NONE(.init))) + /* interrupt vectors */ + .vectors (ORIGIN( {{ prog_mem.parent.inst_name }} )): + { + PROVIDE(__vector_start = .); + KEEP(*(.vectors)); + } > {{ prog_mem.parent.inst_name }} - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) + /* crt0 init code */ + .init (__entry_address): + { + /* The _enter symbol is placed in the .text.entry section + * and must be placed at the beginning of the program */ + KEEP (*(.text.entry)) + KEEP (*(SORT_NONE(.init))) + } > {{ prog_mem.parent.inst_name }} + /* not used by RISC-V */ + .fini : + { KEEP (*(SORT_NONE(.fini))) } > {{ prog_mem.parent.inst_name }} - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - .rodata : + .text : { - *(.rodata .rodata.* .gnu.linkonce.r.*) - *(.rodata1) - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - } > {{ data_mem.parent.inst_name }} - - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } > {{ data_mem.parent.inst_name }} + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } > {{ prog_mem.parent.inst_name }} + /*****************/ + /* DATA SECTIONS */ + /*****************/ - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); - /* Exception handling */ - .preinit_array : + /* initialization and termination routines */ + .preinit_array : ALIGN(8) { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); - } > {{ data_mem.parent.inst_name }} - .init_array : - { + } > {{ data_mem.parent.inst_name }} + + .init_array : ALIGN(8) + { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); - } > {{ data_mem.parent.inst_name }} - .fini_array : - { + } > {{ data_mem.parent.inst_name }} + + .fini_array : ALIGN(8) + { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); - } > {{ data_mem.parent.inst_name }} - .ctors : - { + } > {{ data_mem.parent.inst_name }} + + .ctors : + { /* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it @@ -112,7 +115,7 @@ SECTIONS { linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o - is in. */ + is in. */ KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section from @@ -122,66 +125,93 @@ SECTIONS { KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) - } > {{ data_mem.parent.inst_name }} + } > {{ data_mem.parent.inst_name }} + .dtors : - { + { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) - } > {{ data_mem.parent.inst_name }} - .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } > {{ data_mem.parent.inst_name }} - .dynamic : { *(.dynamic) } > {{ data_mem.parent.inst_name }} - . = DATA_SEGMENT_RELRO_END (0, .); - .data : - { - __DATA_BEGIN__ = .; - *(.data .data.* .gnu.linkonce.d.*) + } > {{ data_mem.parent.inst_name }} + + .rodata : { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } > {{ data_mem.parent.inst_name }} + + /* data sections for initalized data */ + .data : ALIGN(8) + { + *(.data .data.*) + *(.gnu.linkonce.d.*) SORT(CONSTRUCTORS) - *(.data1) - *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) - *(.sdata .sdata.* .gnu.linkonce.s.*) - . = ALIGN(4); - } > {{ data_mem.parent.inst_name }} - _edata = .; PROVIDE (edata = .); - - - - - __bss_start = .; - __BSS_START__ = .; - _bss_start = .; - .sbss : - { - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - } > {{ bss_mem.parent.inst_name }} - .bss : ALIGN(4) - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 32 / 8 : 1); - } > {{ bss_mem.parent.inst_name }} - . = ALIGN(32 / 8); - . = SEGMENT_START("ldata-segment", .); - . = ALIGN(32 / 8); - __BSS_END__ = .; - _bss_end = .; - _align_begin = .; - .align_mem0 : { - . = ALIGN(3); - } > {{ bss_mem.parent.inst_name }} - __global_pointer$ = 0x{{ '%08x' % data_mem.absolute_address }} + 0x{{ '%08x' % (data_mem.size/2)|int }}; - _end = .; PROVIDE (end = .); - . = DATA_SEGMENT_END (.); + /* The compiler uses this to access data in the .sdata, .data, .sbss and .bss + sections with fewer instructions (relaxation). This reduces code size. + */ + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + } > {{ data_mem.parent.inst_name }} + + /* Thread Local Storage sections */ + .tdata : ALIGN(8) + { + PROVIDE_HIDDEN ( __tdata_start = . ); + *(.tdata .tdata.*) + *(.gnu.linkonce.td.*) + } > {{ data_mem.parent.inst_name }} + + PROVIDE ( __edata = . ); + + /* zero initialized sections */ + .tbss : ALIGN(8) + { + PROVIDE( __bss_start = . ); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + } > {{ data_mem.parent.inst_name }} + + .bss (NOLOAD): ALIGN(8) { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + PROVIDE( __bss_end = . ); + } > {{ data_mem.parent.inst_name }} + + /* second level sbss and sdata, not needed for now */ + /* .sdata2 : {*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)} */ + /* .sbss2 : {*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } */ + + .stack (NOLOAD) : ALIGN(16) /* This is a requirement of the ABI */ + { + PROVIDE( __stack_start = . ); + . = __stack_size; + PROVIDE( _sp = . ); + PROVIDE( __stack_end = . ); + } > {{ data_mem.parent.inst_name }} + + .heap (NOLOAD) : ALIGN(8) + { + PROVIDE( __end = . ); + PROVIDE( __heap_start = . ); + . = __heap_size; + PROVIDE( __heap_end = . ); + } > {{ data_mem.parent.inst_name }} + + /******************/ + /* DEBUG SECTIONS */ + /******************/ {% if debug %} /* Stabs debugging sections. */ @@ -226,5 +256,6 @@ SECTIONS { .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } > {{ data_mem.parent.inst_name }} {% endif %} /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(*) } > {{ data_mem.parent.inst_name }} + }; From 5dcdd33e49b94d7d4ee615f292f0fe727df6ab96 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Sun, 21 Apr 2024 21:35:43 +0200 Subject: [PATCH 05/24] RISCV toolchain update. --- SoCMakeConfig.cmake | 4 +- cmake/firmware/fw_utils.cmake | 4 +- .../linker_script/src/template/linker.lds.j2 | 1 + .../toolchains/ibex_toolchain_base.cmake | 31 ---- .../firmware/toolchains/riscv_toolchain.cmake | 137 ++++++++++++++++++ 5 files changed, 142 insertions(+), 35 deletions(-) delete mode 100644 cmake/firmware/toolchains/ibex_toolchain_base.cmake create mode 100644 cmake/firmware/toolchains/riscv_toolchain.cmake diff --git a/SoCMakeConfig.cmake b/SoCMakeConfig.cmake index 02a359a..e80dd14 100644 --- a/SoCMakeConfig.cmake +++ b/SoCMakeConfig.cmake @@ -82,8 +82,8 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/add_tests.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/gen_lds.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/src/lds_props.cmake") -set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") -set(IBEX_TOOLCHAIN_BASE "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain_base.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN_BASE") +# set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") +set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/riscv_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") # ==================================== # ======== Documentation ============= diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index 6b5f61d..2298ede 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -1,6 +1,6 @@ function(print_link_map EXE) get_target_property(BINARY_DIR ${EXE} BINARY_DIR) - + add_custom_command(TARGET ${EXE} POST_BUILD COMMAND cat ${BINARY_DIR}/map_file.map # TODO find where it is @@ -108,7 +108,7 @@ function(set_linker_scripts EXE) message(FATAL_ERROR "Must provide one or more linker_scripts: LDS [fn,...]") endif() - set(LINKER_SCRIPT_ARG "-Wl") + # set(LINKER_SCRIPT_ARG "-Wl") foreach(lds ${ARG_LDS}) target_link_options(${PROJECT_NAME} PUBLIC -T${lds} diff --git a/cmake/firmware/linker_script/src/template/linker.lds.j2 b/cmake/firmware/linker_script/src/template/linker.lds.j2 index da7cdab..fa0df58 100644 --- a/cmake/firmware/linker_script/src/template/linker.lds.j2 +++ b/cmake/firmware/linker_script/src/template/linker.lds.j2 @@ -1,6 +1,7 @@ /* Copyright (c) 2024 CERN */ /* SPDX-License-Identifier: Apache-2.0 */ +OUTPUT_FORMAT("elf32-littleriscv") OUTPUT_ARCH(riscv) ENTRY(_entry) diff --git a/cmake/firmware/toolchains/ibex_toolchain_base.cmake b/cmake/firmware/toolchains/ibex_toolchain_base.cmake deleted file mode 100644 index b1d99d9..0000000 --- a/cmake/firmware/toolchains/ibex_toolchain_base.cmake +++ /dev/null @@ -1,31 +0,0 @@ -set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) - -set(CMAKE_SYSTEM_PROCESSOR riscv32) -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_ABI elf) - -set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}-") - -set(CMAKE_AR "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}ar") -set(CMAKE_ASM "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}g++") -set(CMAKE_C_COMPILER "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}gcc") -set(CMAKE_CXX_COMPILER "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}g++") -set(CMAKE_LINKER "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}ld") -set(CMAKE_OBJCOPY "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}objcopy") -set(CMAKE_OBJDUMP "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}objdump") -set(CMAKE_RANLIB "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}ranlib") -set(CMAKE_SIZE "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}size") -set(CMAKE_STRIP "${RISCV_GNU_PATH}/bin/${TOOLCHAIN_PREFIX}strip") - -set(CMAKE_CXX_STANDARD 17) -set(CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - - -set(CMAKE_CXX_FLAGS "") -set(CMAKE_C_FLAGS "") -set(CMAKE_EXE_LINKER_FLAGS "") - -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") # Print memory usage -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") - diff --git a/cmake/firmware/toolchains/riscv_toolchain.cmake b/cmake/firmware/toolchains/riscv_toolchain.cmake new file mode 100644 index 0000000..0410984 --- /dev/null +++ b/cmake/firmware/toolchains/riscv_toolchain.cmake @@ -0,0 +1,137 @@ +if(ENV{RISCV_TOOLCHAIN}) + message("TOOLCHAIN: ENV DETECTED") + set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) +elseif(RISCV_TOOLCHAIN) + set(RISCV_GNU_PATH ${RISCV_TOOLCHAIN}) + message("TOOLCHAIN: VAR DETECTED") +else() + message("TOOLCHAIN: GETTING CPM PACKAGE (ENV: $ENV{RISCV_TOOLCHAIN})") + CPMAddPackage( + NAME toolchain + URL "https://github.com/lowRISC/lowrisc-toolchains/releases/download/20230427-1/lowrisc-toolchain-gcc-rv32imcb-20230427-1.tar.xz" + ) + # set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) + message("TOOLCHAIN: NOVAR DETECTED") + set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) +endif() + +set(CMAKE_SYSTEM_PROCESSOR riscv32) +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_ABI elf) + +set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}") + +find_program(RISCV_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++ HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_AR ${TOOLCHAIN_PREFIX}-ar HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_ASM ${TOOLCHAIN_PREFIX}-as HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_LINKER ${TOOLCHAIN_PREFIX}-ld HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_OBJCOPY ${TOOLCHAIN_PREFIX}-objcopy HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_OBJDUMP ${TOOLCHAIN_PREFIX}-objdump HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_RANLIB ${TOOLCHAIN_PREFIX}-ranlib HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_SIZE ${TOOLCHAIN_PREFIX}-size HINTS ${RISCV_GNU_PATH}/bin) +find_program(RISCV_STRIP ${TOOLCHAIN_PREFIX}-strip HINTS ${RISCV_GNU_PATH}/bin) + +set(CMAKE_C_COMPILER ${RISCV_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${RISCV_CXX_COMPILER}) +set(CMAKE_ASM ${RISCV_ASM}) +# set(CMAKE_ASM /home/bdenking/CERN/projects/triglav/deps/_deps/toolchain-src/bin/riscv32-unknown-elf-as) +set(CMAKE_AR ${RISCV_AR}) +set(CMAKE_LINKER ${RISCV_LINKER}) +set(CMAKE_OBJCOPY ${RISCV_OBJCOPY}) +set(CMAKE_OBJDUMP ${RISCV_OBJDUMP}) +set(CMAKE_RANLIB ${RISCV_RANLIB}) +set(CMAKE_SIZE ${RISCV_SIZE}) +set(CMAKE_STRIP ${RISCV_STRIP}) + + +get_filename_component(RISCV_TOOLCHAIN_PATH ${RISCV_CXX_COMPILER} DIRECTORY CACHE) +set(RISCV_TOOLCHAIN_PREFIX "${TOOLCHAIN_PREFIX}-" CACHE STRING "") + +# set(CMAKE_C_FLAGS ) # TODO write based on CXX FLAGS + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_STANDARD 17) + +set(CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_CXX_FLAGS "") +set(CMAKE_C_FLAGS "") +set(CMAKE_EXE_LINKER_FLAGS "") + +string(APPEND CMAKE_CXX_FLAGS " -march=rv32imac_zicsr") # RV32 Integer, Compressed instruction set # rv32imac_zicsr +string(APPEND CMAKE_CXX_FLAGS " -mabi=ilp32") # int and pointers are 32bit, long 64bit, char 8bit, short 16bit + +# string(APPEND CMAKE_CXX_FLAGS " -static") +# string(APPEND CMAKE_CXX_FLAGS " -mcmodel=medany") +# string(APPEND CMAKE_CXX_FLAGS " -nostartfiles") +string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ +# string(APPEND CMAKE_CXX_FLAGS " -ffreestanding") # Standard library may not exist and program startup may not be at main, do not assume that standard function use usual definitions + +if(DEBUG) + string(APPEND CMAKE_CXX_FLAGS " -g -O0") # Debug flags + string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-g") +else() + string(APPEND CMAKE_CXX_FLAGS " -Os") # Optimize for code size TODO move to release + # string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--strip-debug") # https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld + # string(APPEND CMAKE_EXE_LINKER_FLAGS " --strip-debug") # https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld +endif() + +string(APPEND CMAKE_CXX_FLAGS " -DHOST_BUILD") + +string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include/") +string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include") + +# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/runtime") +# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/base") +# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/hal") + +string(APPEND CMAKE_CXX_FLAGS " -specs=nano.specs") + +# Until now both C and C++ and Linker have common flag settings +set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS}) +# set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_CXX_FLAGS}) + +# string(APPEND CMAKE_CXX_FLAGS " -fpermissive") + +# C specific flags + +# CXX specific flags +# string(APPEND CMAKE_CXX_FLAGS " -fno-delete-null-pointer-checks") # Avoid gcc delete NULL pointer accesses, because something might be at 0 address on CPU +# string(APPEND CMAKE_CXX_FLAGS " -fverbose-asm") +# string(APPEND CMAKE_CXX_FLAGS " -fno-rtti") +# string(APPEND CMAKE_CXX_FLAGS " -save-temps") +# string(APPEND CMAKE_CXX_FLAGS " -fdevirtualize") +# string(APPEND CMAKE_CXX_FLAGS " -fstack-usage") # Create stack usage reports .su files +# string(APPEND CMAKE_CXX_FLAGS " -Wstack-usage=128") # Create warning if a function is using more than 128 bytes +# string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wredundant-decls -pedantic") +# string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ +# string(APPEND CMAKE_CXX_FLAGS " -nodefaultlibs") # Do not use the standard system libraries when linking +# string(APPEND CMAKE_CXX_FLAGS " -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables") # Remove eh_frame sections and rest + + +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -mabi=ilp32 -march=rv32ic -ffreestanding -nostdlib -lgcc") +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=none") # Don't include build-id in the output (should be disabled by default?), saves 160bits https://interrupt.memfault.com/blog/gnu-build-id-for-firmware +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Bstatic") # Use only static libraries https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld + +string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") # Print memory usage +string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") + +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -nostdlib") +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -static") + +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/lib") # TODO Is this needed? +string(APPEND CMAKE_EXE_LINKER_FLAGS " -lc -lm -lgcc -flto") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -ffunction-sections -fdata-sections") + + +# set(CMAKE_C_FLAGS_DEBUG ) # TODO +# set(CMAKE_C_FLAGS_RELEASE ) +# set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS}) +# set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS}) + + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) From 4983af3e7109506066456397b8d2942f7824aab0 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 22 Apr 2024 08:04:46 +0200 Subject: [PATCH 06/24] Changed riscv toolchain url. --- cmake/firmware/toolchains/riscv_toolchain.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/firmware/toolchains/riscv_toolchain.cmake b/cmake/firmware/toolchains/riscv_toolchain.cmake index 0410984..942121e 100644 --- a/cmake/firmware/toolchains/riscv_toolchain.cmake +++ b/cmake/firmware/toolchains/riscv_toolchain.cmake @@ -8,11 +8,11 @@ else() message("TOOLCHAIN: GETTING CPM PACKAGE (ENV: $ENV{RISCV_TOOLCHAIN})") CPMAddPackage( NAME toolchain - URL "https://github.com/lowRISC/lowrisc-toolchains/releases/download/20230427-1/lowrisc-toolchain-gcc-rv32imcb-20230427-1.tar.xz" + URL "https://github.com/HEP-SoC/riscv-gnu-toolchain/releases/download/2024.04.18/riscv_toolchain-rv32imac_zicsr-ilp32.tar.xz" ) - # set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) + set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) message("TOOLCHAIN: NOVAR DETECTED") - set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) + # set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) endif() set(CMAKE_SYSTEM_PROCESSOR riscv32) @@ -20,6 +20,7 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_ABI elf) set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}") +set(TOOLCHAIN_PREFIX "riscv64-unknown-${CMAKE_SYSTEM_ABI}") find_program(RISCV_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc HINTS ${RISCV_GNU_PATH}/bin) find_program(RISCV_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++ HINTS ${RISCV_GNU_PATH}/bin) From 83ff40eb7747375fca58e399281db8cb8f36b5f3 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Tue, 23 Apr 2024 14:32:35 +0200 Subject: [PATCH 07/24] Removed useless flag for riscv toolchain. --- .../firmware/toolchains/riscv_toolchain.cmake | 49 ++----------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/cmake/firmware/toolchains/riscv_toolchain.cmake b/cmake/firmware/toolchains/riscv_toolchain.cmake index 942121e..dd136b0 100644 --- a/cmake/firmware/toolchains/riscv_toolchain.cmake +++ b/cmake/firmware/toolchains/riscv_toolchain.cmake @@ -1,18 +1,13 @@ if(ENV{RISCV_TOOLCHAIN}) - message("TOOLCHAIN: ENV DETECTED") set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) elseif(RISCV_TOOLCHAIN) set(RISCV_GNU_PATH ${RISCV_TOOLCHAIN}) - message("TOOLCHAIN: VAR DETECTED") else() - message("TOOLCHAIN: GETTING CPM PACKAGE (ENV: $ENV{RISCV_TOOLCHAIN})") CPMAddPackage( NAME toolchain URL "https://github.com/HEP-SoC/riscv-gnu-toolchain/releases/download/2024.04.18/riscv_toolchain-rv32imac_zicsr-ilp32.tar.xz" ) set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) - message("TOOLCHAIN: NOVAR DETECTED") - # set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) endif() set(CMAKE_SYSTEM_PROCESSOR riscv32) @@ -20,7 +15,6 @@ set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_ABI elf) set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}") -set(TOOLCHAIN_PREFIX "riscv64-unknown-${CMAKE_SYSTEM_ABI}") find_program(RISCV_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc HINTS ${RISCV_GNU_PATH}/bin) find_program(RISCV_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++ HINTS ${RISCV_GNU_PATH}/bin) @@ -36,7 +30,6 @@ find_program(RISCV_STRIP ${TOOLCHAIN_PREFIX}-strip HINTS ${RISCV_GNU_PA set(CMAKE_C_COMPILER ${RISCV_C_COMPILER}) set(CMAKE_CXX_COMPILER ${RISCV_CXX_COMPILER}) set(CMAKE_ASM ${RISCV_ASM}) -# set(CMAKE_ASM /home/bdenking/CERN/projects/triglav/deps/_deps/toolchain-src/bin/riscv32-unknown-elf-as) set(CMAKE_AR ${RISCV_AR}) set(CMAKE_LINKER ${RISCV_LINKER}) set(CMAKE_OBJCOPY ${RISCV_OBJCOPY}) @@ -49,8 +42,6 @@ set(CMAKE_STRIP ${RISCV_STRIP}) get_filename_component(RISCV_TOOLCHAIN_PATH ${RISCV_CXX_COMPILER} DIRECTORY CACHE) set(RISCV_TOOLCHAIN_PREFIX "${TOOLCHAIN_PREFIX}-" CACHE STRING "") -# set(CMAKE_C_FLAGS ) # TODO write based on CXX FLAGS - set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 17) @@ -61,14 +52,12 @@ set(CMAKE_CXX_FLAGS "") set(CMAKE_C_FLAGS "") set(CMAKE_EXE_LINKER_FLAGS "") -string(APPEND CMAKE_CXX_FLAGS " -march=rv32imac_zicsr") # RV32 Integer, Compressed instruction set # rv32imac_zicsr +string(APPEND CMAKE_CXX_FLAGS " -march=rv32imac_zicsr") # RV32 Integer, Compressed instruction set string(APPEND CMAKE_CXX_FLAGS " -mabi=ilp32") # int and pointers are 32bit, long 64bit, char 8bit, short 16bit -# string(APPEND CMAKE_CXX_FLAGS " -static") -# string(APPEND CMAKE_CXX_FLAGS " -mcmodel=medany") -# string(APPEND CMAKE_CXX_FLAGS " -nostartfiles") +string(APPEND CMAKE_CXX_FLAGS " -static") +string(APPEND CMAKE_CXX_FLAGS " -nostartfiles") string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ -# string(APPEND CMAKE_CXX_FLAGS " -ffreestanding") # Standard library may not exist and program startup may not be at main, do not assume that standard function use usual definitions if(DEBUG) string(APPEND CMAKE_CXX_FLAGS " -g -O0") # Debug flags @@ -84,44 +73,15 @@ string(APPEND CMAKE_CXX_FLAGS " -DHOST_BUILD") string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include/") string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include") -# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/runtime") -# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/base") -# string(APPEND CMAKE_CXX_FLAGS " -I/home/bdenking/CERN/projects/triglav/firmware/lib/hal") - string(APPEND CMAKE_CXX_FLAGS " -specs=nano.specs") # Until now both C and C++ and Linker have common flag settings set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS}) -# set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_CXX_FLAGS}) - -# string(APPEND CMAKE_CXX_FLAGS " -fpermissive") - -# C specific flags - -# CXX specific flags -# string(APPEND CMAKE_CXX_FLAGS " -fno-delete-null-pointer-checks") # Avoid gcc delete NULL pointer accesses, because something might be at 0 address on CPU -# string(APPEND CMAKE_CXX_FLAGS " -fverbose-asm") -# string(APPEND CMAKE_CXX_FLAGS " -fno-rtti") -# string(APPEND CMAKE_CXX_FLAGS " -save-temps") -# string(APPEND CMAKE_CXX_FLAGS " -fdevirtualize") -# string(APPEND CMAKE_CXX_FLAGS " -fstack-usage") # Create stack usage reports .su files -# string(APPEND CMAKE_CXX_FLAGS " -Wstack-usage=128") # Create warning if a function is using more than 128 bytes -# string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wredundant-decls -pedantic") -# string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ -# string(APPEND CMAKE_CXX_FLAGS " -nodefaultlibs") # Do not use the standard system libraries when linking -# string(APPEND CMAKE_CXX_FLAGS " -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables") # Remove eh_frame sections and rest - - -# string(APPEND CMAKE_EXE_LINKER_FLAGS " -mabi=ilp32 -march=rv32ic -ffreestanding -nostdlib -lgcc") -# string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=none") # Don't include build-id in the output (should be disabled by default?), saves 160bits https://interrupt.memfault.com/blog/gnu-build-id-for-firmware -# string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Bstatic") # Use only static libraries https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld +# Linker specific flags string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") # Print memory usage string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") -# string(APPEND CMAKE_EXE_LINKER_FLAGS " -nostdlib") -# string(APPEND CMAKE_EXE_LINKER_FLAGS " -static") - string(APPEND CMAKE_EXE_LINKER_FLAGS " -L${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/lib") # TODO Is this needed? string(APPEND CMAKE_EXE_LINKER_FLAGS " -lc -lm -lgcc -flto") string(APPEND CMAKE_EXE_LINKER_FLAGS " -ffunction-sections -fdata-sections") @@ -132,7 +92,6 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS " -ffunction-sections -fdata-sections") # set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS}) # set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) From ffbf9dc9e9478ea8d0a102e2770c177b2080c949 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Tue, 23 Apr 2024 15:57:01 +0200 Subject: [PATCH 08/24] Using toolchain to generate hex file much faster. --- cmake/firmware/fw_utils.cmake | 70 +++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index 2298ede..72dc98c 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -13,7 +13,7 @@ endfunction() function(disassemble EXE) get_target_property(BINARY_DIR ${EXE} BINARY_DIR) set(EXECUTABLE ${BINARY_DIR}/${EXE}) - set(OUT_ASM_FILE "${BINARY_DIR}/${EXE}_asm.S") + set(OUT_ASM_FILE "${BINARY_DIR}/${EXE}_disasm.S") add_custom_command(TARGET ${EXE} POST_BUILD @@ -28,32 +28,32 @@ function(disassemble EXE) ) endfunction() -function(gen_bin EXE) - get_target_property(BINARY_DIR ${EXE} BINARY_DIR) - set(EXECUTABLE ${BINARY_DIR}/${EXE}) - set(BIN_FILE "${BINARY_DIR}/${EXE}.bin") - set(BIN_TEXT_FILE "${BINARY_DIR}/${EXE}_text.bin") - set(BIN_DATA_FILE "${BINARY_DIR}/${EXE}_data.bin") - - get_target_property(BOOTLOADER ${EXE} BOOTLOADER) - if(BOOTLOADER) - set(TEXT_SECTION .bootloader) - else() - set(TEXT_SECTION .text) - endif() - add_custom_command(TARGET ${EXE} - POST_BUILD - BYPRODUCTS ${BIN_FILE} ${BIN_TEXT_FILE} ${BIN_DATA_FILE} - COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${BIN_FILE} - COMMAND ${CMAKE_OBJCOPY} -O binary --only-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_TEXT_FILE} - COMMAND ${CMAKE_OBJCOPY} -O binary --remove-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_DATA_FILE} - COMMENT "Generating bin file from ${EXE}" - ) +# function(gen_bin EXE) +# get_target_property(BINARY_DIR ${EXE} BINARY_DIR) +# set(EXECUTABLE ${BINARY_DIR}/${EXE}) +# set(BIN_FILE "${BINARY_DIR}/${EXE}.bin") +# set(BIN_TEXT_FILE "${BINARY_DIR}/${EXE}_text.bin") +# set(BIN_DATA_FILE "${BINARY_DIR}/${EXE}_data.bin") + +# get_target_property(BOOTLOADER ${EXE} BOOTLOADER) +# if(BOOTLOADER) +# set(TEXT_SECTION .bootloader) +# else() +# set(TEXT_SECTION .text) +# endif() +# add_custom_command(TARGET ${EXE} +# POST_BUILD +# BYPRODUCTS ${BIN_FILE} ${BIN_TEXT_FILE} ${BIN_DATA_FILE} +# COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${BIN_FILE} +# COMMAND ${CMAKE_OBJCOPY} -O binary --only-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_TEXT_FILE} +# COMMAND ${CMAKE_OBJCOPY} -O binary --remove-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_DATA_FILE} +# COMMENT "Generating bin file from ${EXE}" +# ) - set_property(TARGET ${EXE} PROPERTY BIN_FILE ${BIN_FILE}) - set_property(TARGET ${EXE} PROPERTY BIN_TEXT_FILE ${BIN_TEXT_FILE}) - set_property(TARGET ${EXE} PROPERTY BIN_DATA_FILE ${BIN_DATA_FILE}) -endfunction() +# set_property(TARGET ${EXE} PROPERTY BIN_FILE ${BIN_FILE}) +# set_property(TARGET ${EXE} PROPERTY BIN_TEXT_FILE ${BIN_TEXT_FILE}) +# set_property(TARGET ${EXE} PROPERTY BIN_DATA_FILE ${BIN_DATA_FILE}) +# endfunction() function(gen_hex_files EXE) get_target_property(BINARY_DIR ${EXE} BINARY_DIR) @@ -64,8 +64,7 @@ function(gen_hex_files EXE) find_python3() set(EXECUTABLE ${BINARY_DIR}/${EXE}) - set(SOCMAKE_MAKEHEX_TOOL "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/scripts/makehex.py" CACHE STRING "Makehex tool") - gen_bin(${EXE}) + get_property(BIN_FILE TARGET ${EXE} PROPERTY BIN_FILE) get_property(BIN_TEXT_FILE TARGET ${EXE} PROPERTY BIN_TEXT_FILE) get_property(BIN_DATA_FILE TARGET ${EXE} PROPERTY BIN_DATA_FILE) @@ -74,6 +73,15 @@ function(gen_hex_files EXE) set(ARG_WIDTHS 32) endif() + get_target_property(BOOTLOADER ${EXE} BOOTLOADER) + if(BOOTLOADER) + set(TEXT_SECTION .bootloader) + else() + set(TEXT_SECTION .text) + endif() + + set(DATA_SECTION .data) + set(ALLOWED_WIDTHS 8 16 32 64) foreach(width ${ARG_WIDTHS}) list(FIND ALLOWED_WIDTHS ${width} WIDTH_FIND) @@ -85,9 +93,9 @@ function(gen_hex_files EXE) add_custom_command(TARGET ${EXE} POST_BUILD BYPRODUCTS ${HEX_FILE} ${HEX_TEXT_FILE} ${HEX_DATA_FILE} - COMMAND ${Python3_EXECUTABLE} ${SOCMAKE_MAKEHEX_TOOL} --width ${width} ${BIN_FILE} ${HEX_FILE} # TODO this is slowing down - COMMAND ${Python3_EXECUTABLE} ${SOCMAKE_MAKEHEX_TOOL} --width ${width} ${BIN_TEXT_FILE} ${HEX_TEXT_FILE} - COMMAND ${Python3_EXECUTABLE} ${SOCMAKE_MAKEHEX_TOOL} --width ${width} ${BIN_DATA_FILE} ${HEX_DATA_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog ${EXECUTABLE} ${HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog --only-section=${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog --only-section=${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} COMMENT "Generating ${width} bit hex file file for ${EXE}" ) From 94c362a1ad4827a66d43588aaf5e40ccc52cc279 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Tue, 23 Apr 2024 16:09:00 +0200 Subject: [PATCH 09/24] Explicitely named section for text and data memories. --- cmake/firmware/fw_utils.cmake | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index 72dc98c..66d7b1c 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -75,12 +75,23 @@ function(gen_hex_files EXE) get_target_property(BOOTLOADER ${EXE} BOOTLOADER) if(BOOTLOADER) - set(TEXT_SECTION .bootloader) + set(TEXT_SECTION --only-section=.bootloader) else() - set(TEXT_SECTION .text) + set(TEXT_SECTION + --only-section=.vectors + --only-section=.init + --only-section=.fini + --only-section=.text + ) endif() - set(DATA_SECTION .data) + set(DATA_SECTION + --remove-section=.bootloader + --remove-section=.vectors + --remove-section=.init + --remove-section=.fini + --remove-section=.text + ) set(ALLOWED_WIDTHS 8 16 32 64) foreach(width ${ARG_WIDTHS}) @@ -94,8 +105,8 @@ function(gen_hex_files EXE) POST_BUILD BYPRODUCTS ${HEX_FILE} ${HEX_TEXT_FILE} ${HEX_DATA_FILE} COMMAND ${CMAKE_OBJCOPY} -O verilog ${EXECUTABLE} ${HEX_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog --only-section=${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog --only-section=${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog ${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} COMMENT "Generating ${width} bit hex file file for ${EXE}" ) From ada84e1fdeb62af611d3f620183aacf196fc4227 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Sat, 27 Apr 2024 15:30:25 +0200 Subject: [PATCH 10/24] Adjust data memory (tmp fix). --- cmake/firmware/fw_utils.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index 66d7b1c..b241eae 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -106,7 +106,7 @@ function(gen_hex_files EXE) BYPRODUCTS ${HEX_FILE} ${HEX_TEXT_FILE} ${HEX_DATA_FILE} COMMAND ${CMAKE_OBJCOPY} -O verilog ${EXECUTABLE} ${HEX_FILE} COMMAND ${CMAKE_OBJCOPY} -O verilog ${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog --adjust-vma=-0x10000000 ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} COMMENT "Generating ${width} bit hex file file for ${EXE}" ) From b8faf447bcf2b3c927a7f486236ae524349d09d8 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 3 May 2024 11:44:46 +0200 Subject: [PATCH 11/24] File formating. --- cmake/sim/verilator/verilate.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/sim/verilator/verilate.cmake b/cmake/sim/verilator/verilate.cmake index 810900f..3b7c65c 100644 --- a/cmake/sim/verilator/verilate.cmake +++ b/cmake/sim/verilator/verilate.cmake @@ -3,7 +3,7 @@ function(verilate IP_LIB) set(ONE_PARAM_ARGS "PREFIX;TOP_MODULE;THREADS;TRACE_THREADS;DIRECTORY;EXECUTABLE_NAME") set(MULTI_PARAM_ARGS "VERILATOR_ARGS;OPT_SLOW;OPT_FAST;OPT_GLOBAL") - cmake_parse_arguments(ARG + cmake_parse_arguments(ARG "${OPTIONS}" "${ONE_PARAM_ARGS}" "${MULTI_PARAM_ARGS}" @@ -161,11 +161,11 @@ function(verilate IP_LIB) INSTALL_COMMAND "" DEPENDS ${IP_LIB} EXCLUDE_FROM_ALL 1 - ) + ) set_property( TARGET ${VERILATE_TARGET} - APPEND PROPERTY ADDITIONAL_CLEAN_FILES + APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${DIRECTORY} ${EXECUTABLE_PATH} ) From 3ca540e1ec808875422a28c596de75e8523beedb Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 6 May 2024 15:11:16 +0200 Subject: [PATCH 12/24] RISCV toolchain update compatible with mic cluster. --- cmake/firmware/toolchains/riscv_toolchain.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/firmware/toolchains/riscv_toolchain.cmake b/cmake/firmware/toolchains/riscv_toolchain.cmake index dd136b0..d631958 100644 --- a/cmake/firmware/toolchains/riscv_toolchain.cmake +++ b/cmake/firmware/toolchains/riscv_toolchain.cmake @@ -1,3 +1,5 @@ + +# GET THE RISCV TOOLCHAIN if(ENV{RISCV_TOOLCHAIN}) set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) elseif(RISCV_TOOLCHAIN) @@ -5,16 +7,16 @@ elseif(RISCV_TOOLCHAIN) else() CPMAddPackage( NAME toolchain - URL "https://github.com/HEP-SoC/riscv-gnu-toolchain/releases/download/2024.04.18/riscv_toolchain-rv32imac_zicsr-ilp32.tar.xz" + URL "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" ) set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) endif() -set(CMAKE_SYSTEM_PROCESSOR riscv32) +set(CMAKE_SYSTEM_PROCESSOR riscv) set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_ABI elf) -set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}") +set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-none-${CMAKE_SYSTEM_ABI}") find_program(RISCV_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc HINTS ${RISCV_GNU_PATH}/bin) find_program(RISCV_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++ HINTS ${RISCV_GNU_PATH}/bin) From a4af95423c4e8ca2b50ae58faa59a5f9514a4d12 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Wed, 8 May 2024 09:51:58 +0200 Subject: [PATCH 13/24] xcelium no default value for parameter as warning. --- cmake/sim/cadence/xcelium.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/sim/cadence/xcelium.cmake b/cmake/sim/cadence/xcelium.cmake index d39bf2b..5f71432 100644 --- a/cmake/sim/cadence/xcelium.cmake +++ b/cmake/sim/cadence/xcelium.cmake @@ -55,13 +55,14 @@ function(xcelium IP_LIB) add_custom_target( run_${IP_LIB}_${CMAKE_CURRENT_FUNCTION} COMMAND xrun - ${V_FILES} + # Enable parameters without default value + -setenv CADENCE_ENABLE_AVSREQ_44905_PHASE_1=1 -setenv CADENCE_ENABLE_AVSREQ_63188_PHASE_1=1 + ${SOURCES} ${ARG_INCDIRS} ${CMP_DEFS_ARG} ${ARG_GUI} - DEPENDS ${V_FILES} COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" - DEPENDS ${V_FILES} ${IP_LIB} + DEPENDS ${SOURCES} ${IP_LIB} ) # add_dependencies(${IP_LIB}_${CMAKE_CURRENT_FUNCTION} ${IP_LIB}) From 810380f50286823d96712b2cf774b39d6a6ac898 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Wed, 8 May 2024 10:11:09 +0200 Subject: [PATCH 14/24] Peakrdl-socgen plugin generting sv files. --- cmake/peakrdl/peakrdl_socgen/peakrdl_socgen.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/peakrdl/peakrdl_socgen/peakrdl_socgen.cmake b/cmake/peakrdl/peakrdl_socgen/peakrdl_socgen.cmake index 89f3d74..54d7526 100644 --- a/cmake/peakrdl/peakrdl_socgen/peakrdl_socgen.cmake +++ b/cmake/peakrdl/peakrdl_socgen/peakrdl_socgen.cmake @@ -148,7 +148,7 @@ function(peakrdl_socgen IP_LIB) endif() set_source_files_properties(${V_GEN} PROPERTIES GENERATED TRUE) - ip_sources(${IP_LIB} VERILOG ${V_GEN}) + ip_sources(${IP_LIB} SYSTEMVERILOG ${V_GEN}) set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") add_custom_command( From 3b0bd189f438adeed35ae25a2d9ab2544d7cc879 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Wed, 8 May 2024 17:12:45 +0200 Subject: [PATCH 15/24] Save commit scelium test. --- cmake/sim/cadence/xcelium.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/sim/cadence/xcelium.cmake b/cmake/sim/cadence/xcelium.cmake index 5f71432..6854625 100644 --- a/cmake/sim/cadence/xcelium.cmake +++ b/cmake/sim/cadence/xcelium.cmake @@ -57,6 +57,7 @@ function(xcelium IP_LIB) COMMAND xrun # Enable parameters without default value -setenv CADENCE_ENABLE_AVSREQ_44905_PHASE_1=1 -setenv CADENCE_ENABLE_AVSREQ_63188_PHASE_1=1 + -define COMMON_CELLS_ASSERTS_OFF ${SOURCES} ${ARG_INCDIRS} ${CMP_DEFS_ARG} From 759b90a83cb51595df76fe1c7a803e3a146d3cd6 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 13 May 2024 13:58:15 +0200 Subject: [PATCH 16/24] hex file modified to match new sram block. --- cmake/firmware/fw_utils.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index b241eae..61a42c8 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -104,9 +104,10 @@ function(gen_hex_files EXE) add_custom_command(TARGET ${EXE} POST_BUILD BYPRODUCTS ${HEX_FILE} ${HEX_TEXT_FILE} ${HEX_DATA_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog ${EXECUTABLE} ${HEX_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog ${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} - COMMAND ${CMAKE_OBJCOPY} -O verilog --adjust-vma=-0x10000000 ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 ${EXECUTABLE} ${HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 --gap-fill 0x0000 ${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} + # TODO find an automatic way to 'correct' the vma for loading during simulation + COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 --gap-fill 0x0000 --adjust-vma=-0x10000000 ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} COMMENT "Generating ${width} bit hex file file for ${EXE}" ) From c6eeef60dee3caa95195315745976928bd27d339 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 17 May 2024 15:58:17 +0200 Subject: [PATCH 17/24] Added reset option for regblock generation. --- cmake/peakrdl/peakrdl_regblock.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/peakrdl/peakrdl_regblock.cmake b/cmake/peakrdl/peakrdl_regblock.cmake index 29e88aa..0624194 100644 --- a/cmake/peakrdl/peakrdl_regblock.cmake +++ b/cmake/peakrdl/peakrdl_regblock.cmake @@ -35,7 +35,7 @@ #]] function(peakrdl_regblock IP_LIB) # Parse keyword arguments - cmake_parse_arguments(ARG "" "OUTDIR;RENAME;INTF" "" ${ARGN}) + cmake_parse_arguments(ARG "" "OUTDIR;RENAME;INTF;RESET" "" ${ARGN}) # Check for any unknown argument if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " @@ -71,6 +71,12 @@ function(peakrdl_regblock IP_LIB) if(ARG_INTF) set(INTF_ARG --cpuif ${ARG_INTF}) endif() + + # The default reset is active-high and synchronous + if(ARG_RESET) + set(RESET_ARG --default-reset ${ARG_RESET}) + endif() + # Get the SystemRDL sources to generate the register block # This function gets the IP sources and the deps get_ip_sources(RDL_SOURCES ${IP_LIB} SYSTEMRDL) @@ -84,6 +90,7 @@ function(peakrdl_regblock IP_LIB) set(__CMD ${Python3_EXECUTABLE} -m peakrdl regblock --rename ${REGBLOCK_NAME} ${INTF_ARG} + ${RESET_ARG} -o ${OUTDIR} ${RDL_SOURCES} ) From b9eb32c843b71c0c6a65197fd0147264e1ba5844 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 27 May 2024 10:57:57 +0200 Subject: [PATCH 18/24] init and finit section filled on 4 bytes alignement to match hex generation required alignement. --- cmake/firmware/linker_script/src/template/linker.lds.j2 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/firmware/linker_script/src/template/linker.lds.j2 b/cmake/firmware/linker_script/src/template/linker.lds.j2 index fa0df58..3ff1fc1 100644 --- a/cmake/firmware/linker_script/src/template/linker.lds.j2 +++ b/cmake/firmware/linker_script/src/template/linker.lds.j2 @@ -62,12 +62,18 @@ SECTIONS * and must be placed at the beginning of the program */ KEEP (*(.text.entry)) KEEP (*(SORT_NONE(.init))) + /* Align on 4 bytes to avoid errors during hex generation */ + FILL(0xDEAD) + . = ALIGN(4); } > {{ prog_mem.parent.inst_name }} /* not used by RISC-V */ .fini : { KEEP (*(SORT_NONE(.fini))) + /* Align on 4 bytes to avoid errors during hex generation */ + FILL(0xDEAD) + . = ALIGN(4); } > {{ prog_mem.parent.inst_name }} .text : From e57b9ca81db0316bbbba0b0ef241e49f26833813 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 31 May 2024 14:03:23 +0200 Subject: [PATCH 19/24] riscv toolchain file udpated and commented. --- .../firmware/toolchains/riscv_toolchain.cmake | 90 ++++++++++++------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/cmake/firmware/toolchains/riscv_toolchain.cmake b/cmake/firmware/toolchains/riscv_toolchain.cmake index d631958..f490b49 100644 --- a/cmake/firmware/toolchains/riscv_toolchain.cmake +++ b/cmake/firmware/toolchains/riscv_toolchain.cmake @@ -50,43 +50,71 @@ set(CMAKE_C_STANDARD 17) set(CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "") set(CMAKE_C_FLAGS "") +set(CMAKE_CXX_FLAGS "") set(CMAKE_EXE_LINKER_FLAGS "") -string(APPEND CMAKE_CXX_FLAGS " -march=rv32imac_zicsr") # RV32 Integer, Compressed instruction set -string(APPEND CMAKE_CXX_FLAGS " -mabi=ilp32") # int and pointers are 32bit, long 64bit, char 8bit, short 16bit - -string(APPEND CMAKE_CXX_FLAGS " -static") -string(APPEND CMAKE_CXX_FLAGS " -nostartfiles") -string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ - -if(DEBUG) - string(APPEND CMAKE_CXX_FLAGS " -g -O0") # Debug flags - string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-g") -else() - string(APPEND CMAKE_CXX_FLAGS " -Os") # Optimize for code size TODO move to release - # string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--strip-debug") # https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld - # string(APPEND CMAKE_EXE_LINKER_FLAGS " --strip-debug") # https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld -endif() - -string(APPEND CMAKE_CXX_FLAGS " -DHOST_BUILD") - -string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include/") -string(APPEND CMAKE_CXX_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include") - -string(APPEND CMAKE_CXX_FLAGS " -specs=nano.specs") +############################# +# Machine-Dependent Options # +############################# +# RV32 +# i : Integer +# m : Integer Multiplication and Division +# a : Atomic instructions +# c : Compressed instructions +# zicsr : CSR Instructions (explicitely required with latest specs) +string(APPEND CMAKE_C_FLAGS " -march=rv32imac_zicsr") +# int and pointers are 32bit, long 64bit, char 8bit, short 16bit +string(APPEND CMAKE_C_FLAGS " -mabi=ilp32") + +################################ +# Options for Directory Search # +################################ +# Add the directory dir to the list of directories to be searched for header files during preprocessing +# string(APPEND CMAKE_C_FLAGS " -I${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/include/") + +##################################### +# Options that Control Optimization # +##################################### +# Place each function or data item into its own section in the output file +# if the target supports arbitrary sections. The name of the function or +# the name of the data item determines the section’s name in the output file. +# string(APPEND CMAKE_C_FLAGS " -ffunction-sections") +# string(APPEND CMAKE_C_FLAGS " -fdata-sections") + +# Optimize for size by default +string(APPEND CMAKE_C_FLAGS " -Os") + +# Pass common flags for c++ compilation flow +set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) + +####################### +# Options for Linking # +####################### +# Do not use the standard system startup +string(APPEND CMAKE_EXE_LINKER_FLAGS " -nostartfiles") +# Prevents linking with the shared libraries +string(APPEND CMAKE_EXE_LINKER_FLAGS " -static") + +# Print memory usage +string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") +# Generate executable map file +string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") -# Until now both C and C++ and Linker have common flag settings -set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS}) +########################################## +# Options Controlling the Kind of Output # +########################################## +# Use embedded class libnano_c +string(APPEND CMAKE_EXE_LINKER_FLAGS " -specs=nano.specs") -# Linker specific flags -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") # Print memory usage -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") +################################ +# Options for Directory Search # +################################ +# Add directory dir to the list of directories to be searched for -l +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -L${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/lib") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L${RISCV_GNU_PATH}/${TOOLCHAIN_PREFIX}/lib") # TODO Is this needed? -string(APPEND CMAKE_EXE_LINKER_FLAGS " -lc -lm -lgcc -flto") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -ffunction-sections -fdata-sections") +# Search the library named library when linking. +# string(APPEND CMAKE_EXE_LINKER_FLAGS " -lc -lgcc -lm") # set(CMAKE_C_FLAGS_DEBUG ) # TODO From e7a22b71eafbcc372b51acc41e6aa25a53406ded Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 31 May 2024 14:40:18 +0200 Subject: [PATCH 20/24] Added SKIP_BUSES argument for peakrdl-halcpp target. --- cmake/peakrdl/peakrdl_halcpp.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/peakrdl/peakrdl_halcpp.cmake b/cmake/peakrdl/peakrdl_halcpp.cmake index 17e1d83..4fce40e 100644 --- a/cmake/peakrdl/peakrdl_halcpp.cmake +++ b/cmake/peakrdl/peakrdl_halcpp.cmake @@ -39,7 +39,7 @@ # :type OUTDIR: string path #]] function(peakrdl_halcpp IP_LIB) - cmake_parse_arguments(ARG "" "OUTDIR" "PARAMETERS" ${ARGN}) + cmake_parse_arguments(ARG "SKIP_BUSES" "OUTDIR" "PARAMETERS" ${ARGN}) if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") endif() @@ -72,6 +72,10 @@ function(peakrdl_halcpp IP_LIB) set(EXT_ARG --ext ${libs}) endif() + if(ARG_SKIP_BUSES) + set(SKIB_BUSES_ARG --skip-buses) + endif() + if(NOT RDL_FILES) message(FATAL_ERROR "Library ${IP_LIB} does not have RDL_FILES property set, unable to run ${CMAKE_CURRENT_FUNCTION}") @@ -79,7 +83,7 @@ function(peakrdl_halcpp IP_LIB) find_python3() set(__CMD ${Python3_EXECUTABLE} -m peakrdl halcpp - ${RDL_FILES} ${EXT_ARG} -o ${OUTDIR} ${OVERWRITTEN_PARAMETERS} + ${RDL_FILES} ${EXT_ARG} ${SKIB_BUSES_ARG} -o ${OUTDIR} ${OVERWRITTEN_PARAMETERS} ) target_include_directories(${IP_LIB} INTERFACE ${OUTDIR} ${OUTDIR}/include) From 4e8c3664dc6b27eb15eb8a1ccb7093ad0640db85 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 31 May 2024 15:14:02 +0200 Subject: [PATCH 21/24] Files cleaned and commented. --- SoCMakeConfig.cmake | 1 - cmake/firmware/fw_utils.cmake | 122 ++++++++---------- .../firmware/toolchains/ibex_toolchain.cmake | 92 ------------- 3 files changed, 56 insertions(+), 159 deletions(-) delete mode 100644 cmake/firmware/toolchains/ibex_toolchain.cmake diff --git a/SoCMakeConfig.cmake b/SoCMakeConfig.cmake index e80dd14..5770d8d 100644 --- a/SoCMakeConfig.cmake +++ b/SoCMakeConfig.cmake @@ -82,7 +82,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/add_tests.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/gen_lds.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/linker_script/src/lds_props.cmake") -# set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/ibex_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") set(IBEX_TOOLCHAIN "${CMAKE_CURRENT_LIST_DIR}/cmake/firmware/toolchains/riscv_toolchain.cmake" CACHE INTERNAL "IBEX_TOOLCHAIN") # ==================================== diff --git a/cmake/firmware/fw_utils.cmake b/cmake/firmware/fw_utils.cmake index 61a42c8..9a0f957 100644 --- a/cmake/firmware/fw_utils.cmake +++ b/cmake/firmware/fw_utils.cmake @@ -1,78 +1,71 @@ -function(print_link_map EXE) - get_target_property(BINARY_DIR ${EXE} BINARY_DIR) - - add_custom_command(TARGET ${EXE} - POST_BUILD - COMMAND cat ${BINARY_DIR}/map_file.map # TODO find where it is - COMMAND ${CMAKE_SIZE} "${BINARY_DIR}/${EXE}" - COMMENT "Printing the Map file from the linker for ${EXE}" - ) - -endfunction() - +#[[[ +# This function disassembles the given executable target to generate an assembly file. +# +# The function retrieves the binary directory of the target, sets the output assembly file name, +# and adds a custom command to disassemble the executable and store the result in the specified file. +# +# :param EXE: The executable target. +# :type EXE: string +#]] function(disassemble EXE) + # Retrieve the binary directory of the target get_target_property(BINARY_DIR ${EXE} BINARY_DIR) + + # Set the paths for the executable and output assembly file set(EXECUTABLE ${BINARY_DIR}/${EXE}) set(OUT_ASM_FILE "${BINARY_DIR}/${EXE}_disasm.S") + # Add a custom command to disassemble the executable and generate the assembly file add_custom_command(TARGET ${EXE} POST_BUILD BYPRODUCTS ${OUT_ASM_FILE} COMMAND ${CMAKE_OBJDUMP} -DgrwCS ${EXECUTABLE} > ${OUT_ASM_FILE} COMMENT "Dumping assembly from ${EXE}" - ) + ) + # Set a property on the target to store the path of the generated assembly file set_property(TARGET ${EXE} PROPERTY DISASM_FILE ${OUT_ASM_FILE} - ) + ) endfunction() -# function(gen_bin EXE) -# get_target_property(BINARY_DIR ${EXE} BINARY_DIR) -# set(EXECUTABLE ${BINARY_DIR}/${EXE}) -# set(BIN_FILE "${BINARY_DIR}/${EXE}.bin") -# set(BIN_TEXT_FILE "${BINARY_DIR}/${EXE}_text.bin") -# set(BIN_DATA_FILE "${BINARY_DIR}/${EXE}_data.bin") - -# get_target_property(BOOTLOADER ${EXE} BOOTLOADER) -# if(BOOTLOADER) -# set(TEXT_SECTION .bootloader) -# else() -# set(TEXT_SECTION .text) -# endif() -# add_custom_command(TARGET ${EXE} -# POST_BUILD -# BYPRODUCTS ${BIN_FILE} ${BIN_TEXT_FILE} ${BIN_DATA_FILE} -# COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${BIN_FILE} -# COMMAND ${CMAKE_OBJCOPY} -O binary --only-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_TEXT_FILE} -# COMMAND ${CMAKE_OBJCOPY} -O binary --remove-section=${TEXT_SECTION} ${EXECUTABLE} ${BIN_DATA_FILE} -# COMMENT "Generating bin file from ${EXE}" -# ) - -# set_property(TARGET ${EXE} PROPERTY BIN_FILE ${BIN_FILE}) -# set_property(TARGET ${EXE} PROPERTY BIN_TEXT_FILE ${BIN_TEXT_FILE}) -# set_property(TARGET ${EXE} PROPERTY BIN_DATA_FILE ${BIN_DATA_FILE}) -# endfunction() - +#[[[ +# This function generates hex files for the given executable target. +# +# The function retrieves the binary directory of the target, parses the width arguments, +# and includes a utility script to find Python. It then retrieves binary file properties +# from the target, sets the appropriate sections for the bootloader, and generates hex files +# for each specified width. +# +# :param EXE: The executable target. +# :type EXE: string +#]] function(gen_hex_files EXE) + # Retrieve the binary directory of the target get_target_property(BINARY_DIR ${EXE} BINARY_DIR) + # Parse the width arguments cmake_parse_arguments(ARG "" "" "WIDTHS" ${ARGN}) + # Include the utility script to find Python include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../utils/find_python.cmake") find_python3() + # Set the path for the executable set(EXECUTABLE ${BINARY_DIR}/${EXE}) + # Retrieve binary file properties from the target get_property(BIN_FILE TARGET ${EXE} PROPERTY BIN_FILE) get_property(BIN_TEXT_FILE TARGET ${EXE} PROPERTY BIN_TEXT_FILE) get_property(BIN_DATA_FILE TARGET ${EXE} PROPERTY BIN_DATA_FILE) + # Set default width to 32 if not specified if(NOT ARG_WIDTHS) set(ARG_WIDTHS 32) endif() + # Determine the sections based on whether the target is a bootloader get_target_property(BOOTLOADER ${EXE} BOOTLOADER) if(BOOTLOADER) set(TEXT_SECTION --only-section=.bootloader) @@ -85,6 +78,7 @@ function(gen_hex_files EXE) ) endif() + # Set the sections to be excluded for the data section set(DATA_SECTION --remove-section=.bootloader --remove-section=.vectors @@ -93,6 +87,7 @@ function(gen_hex_files EXE) --remove-section=.text ) + # Define allowed widths and iterate over specified widths to generate hex files set(ALLOWED_WIDTHS 8 16 32 64) foreach(width ${ARG_WIDTHS}) list(FIND ALLOWED_WIDTHS ${width} WIDTH_FIND) @@ -101,16 +96,19 @@ function(gen_hex_files EXE) set(HEX_FILE "${BINARY_DIR}/${EXE}_${width}bit.hex") set(HEX_TEXT_FILE "${BINARY_DIR}/${EXE}_text_${width}bit.hex") set(HEX_DATA_FILE "${BINARY_DIR}/${EXE}_data_${width}bit.hex") + + # Add custom commands to generate hex files for the specified width add_custom_command(TARGET ${EXE} POST_BUILD BYPRODUCTS ${HEX_FILE} ${HEX_TEXT_FILE} ${HEX_DATA_FILE} COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 ${EXECUTABLE} ${HEX_FILE} COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 --gap-fill 0x0000 ${TEXT_SECTION} ${EXECUTABLE} ${HEX_TEXT_FILE} - # TODO find an automatic way to 'correct' the vma for loading during simulation + # TODO: find an automatic way to 'correct' the VMA for loading during simulation COMMAND ${CMAKE_OBJCOPY} -O verilog --verilog-data-width=4 --gap-fill 0x0000 --adjust-vma=-0x10000000 ${DATA_SECTION} ${EXECUTABLE} ${HEX_DATA_FILE} - COMMENT "Generating ${width} bit hex file file for ${EXE}" - ) + COMMENT "Generating ${width} bit hex file for ${EXE}" + ) + # Set properties on the target to store the paths of the generated hex files set_property(TARGET ${EXE} PROPERTY HEX_${width}bit_FILE ${HEX_FILE}) set_property(TARGET ${EXE} PROPERTY HEX_TEXT_${width}bit_FILE ${HEX_TEXT_FILE}) set_property(TARGET ${EXE} PROPERTY HEX_DATA_${width}bit_FILE ${HEX_DATA_FILE}) @@ -118,41 +116,33 @@ function(gen_hex_files EXE) message(FATAL_ERROR "\nWidth ${width} not allowed in gen_hex_files(), allowed values ${ALLOWED_WIDTHS}\n") endif() endforeach() - endfunction() +#[[[ +# This function sets linker scripts for the given executable target. +# +# The function parses the linker script arguments and sets them as link options for the target. +# It also sets a property on the target to store the list of linker scripts. +# +# :param EXE: The executable target. +# :type EXE: string +#]] function(set_linker_scripts EXE) + # Parse the linker script arguments cmake_parse_arguments(ARG "" "" "LDS" ${ARGN}) + # Ensure linker scripts are provided if(NOT ARG_LDS) message(FATAL_ERROR "Must provide one or more linker_scripts: LDS [fn,...]") endif() - # set(LINKER_SCRIPT_ARG "-Wl") + # Iterate over linker scripts and set them as link options for the target foreach(lds ${ARG_LDS}) target_link_options(${PROJECT_NAME} PUBLIC -T${lds} - ) + ) endforeach() + # Set a property on the target to store the list of linker scripts set_property(TARGET ${EXE} PROPERTY LINK_DEPENDS ${ARG_LDS}) endfunction() - -# function(static_stack_analysis EXE) -# set(SSA_TOOL "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/scripts/ssa.py") -# get_target_property(BINARY_DIR ${EXE} BINARY_DIR) -# set(CFLOW_CALLSTACK "${BINARY_DIR}/${EXE}_cflow_callstack.txt") -# -# get_target_property(CPP_SOURCES ${EXE} SOURCES) -# list(FILTER CPP_SOURCES EXCLUDE REGEX "\\.[S|s]$") # Exclude asm files -# -# add_custom_command(TARGET ${EXE} -# POST_BUILD -# BYPRODUCTS ${CFLOW_CALLSTACK} -# COMMAND cflow ${CPP_SOURCES} > ${CFLOW_CALLSTACK} || (exit 0) -# COMMAND ${Python3_EXECUTABLE} ${SSA_TOOL} -f ${CFLOW_CALLSTACK} -d ${BINARY_DIR}/CMakeFiles/${EXE}.dir/ || (exit 0) -# COMMENT "Running static stack analysis on ${EXE}, error on this command can be ignored" -# ) -# -# endfunction() -# diff --git a/cmake/firmware/toolchains/ibex_toolchain.cmake b/cmake/firmware/toolchains/ibex_toolchain.cmake deleted file mode 100644 index 53e3692..0000000 --- a/cmake/firmware/toolchains/ibex_toolchain.cmake +++ /dev/null @@ -1,92 +0,0 @@ -if(ENV{RISCV_TOOLCHAIN}) - set(RISCV_GNU_PATH $ENV{RISCV_TOOLCHAIN}) -elseif(RISCV_TOOLCHAIN) - set(RISCV_GNU_PATH ${RISCV_TOOLCHAIN}) -else() - CPMAddPackage( - NAME toolchain - URL "https://github.com/lowRISC/lowrisc-toolchains/releases/download/20230427-1/lowrisc-toolchain-gcc-rv32imcb-20230427-1.tar.xz" - ) - set(RISCV_GNU_PATH ${toolchain_SOURCE_DIR}) -endif() - -set(CMAKE_SYSTEM_PROCESSOR riscv32) -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_ABI elf) - -set(TOOLCHAIN_PREFIX "${CMAKE_SYSTEM_PROCESSOR}-unknown-${CMAKE_SYSTEM_ABI}-") - -find_program(RISCV_C_COMPILER ${TOOLCHAIN_PREFIX}gcc HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_AR ${TOOLCHAIN_PREFIX}ar HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_ASM ${TOOLCHAIN_PREFIX}g++ HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_LINKER ${TOOLCHAIN_PREFIX}ld HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_OBJDUMP ${TOOLCHAIN_PREFIX}objdump HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_RANLIB ${TOOLCHAIN_PREFIX}ranlib HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_SIZE ${TOOLCHAIN_PREFIX}size HINTS ${RISCV_GNU_PATH}/bin) -find_program(RISCV_STRIP ${TOOLCHAIN_PREFIX}strip HINTS ${RISCV_GNU_PATH}/bin) - -set(CMAKE_C_COMPILER ${RISCV_C_COMPILER}) -set(CMAKE_CXX_COMPILER ${RISCV_CXX_COMPILER}) -set(CMAKE_ASM ${RISCV_ASM}) -set(CMAKE_AR ${RISCV_AR}) -set(CMAKE_LINKER ${RISCV_LINKER}) -set(CMAKE_OBJCOPY ${RISCV_OBJCOPY}) -set(CMAKE_OBJDUMP ${RISCV_OBJDUMP}) -set(CMAKE_RANLIB ${RISCV_RANLIB}) -set(CMAKE_SIZE ${RISCV_SIZE}) -set(CMAKE_STRIP ${RISCV_STRIP}) - - -get_filename_component(RISCV_TOOLCHAIN_PATH ${RISCV_CXX_COMPILER} DIRECTORY CACHE) -set(RISCV_TOOLCHAIN_PREFIX ${TOOLCHAIN_PREFIX} CACHE STRING "") - -# set(CMAKE_C_FLAGS ) # TODO write based on CXX FLAGS - -set(CMAKE_CXX_STANDARD 17) -set(CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_CXX_FLAGS "") -set(CMAKE_C_FLAGS "") -set(CMAKE_EXE_LINKER_FLAGS "") - -string(APPEND CMAKE_CXX_FLAGS " -mabi=ilp32") # int and pointers are 32bit, long 64bit, char 8bit, short 16bit -string(APPEND CMAKE_CXX_FLAGS " -march=rv32ic") # RV32 Integer, Compressed instruction set -if(DEBUG) - string(APPEND CMAKE_CXX_FLAGS " -g -O0") # Debug flags - string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-g") -else() - string(APPEND CMAKE_CXX_FLAGS " -Os") # Optimize for code size TODO move to release - string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--strip-debug") # https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld -endif() -string(APPEND CMAKE_CXX_FLAGS " -fno-delete-null-pointer-checks") # Avoid gcc delete NULL pointer accesses, because something might be at 0 address on CPU -string(APPEND CMAKE_CXX_FLAGS " -fverbose-asm") -string(APPEND CMAKE_CXX_FLAGS " -fno-rtti") -string(APPEND CMAKE_CXX_FLAGS " -save-temps") -string(APPEND CMAKE_CXX_FLAGS " -fdevirtualize") -string(APPEND CMAKE_CXX_FLAGS " -fstack-usage") # Create stack usage reports .su files -string(APPEND CMAKE_CXX_FLAGS " -Wstack-usage=128") # Create warning if a function is using more than 128 bytes -string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wredundant-decls -pedantic") -string(APPEND CMAKE_CXX_FLAGS " -ffreestanding") # Standard library may not exist and program startup may not be at main, do not assume that standard function use usual definitions -string(APPEND CMAKE_CXX_FLAGS " -nostdlib") # Do not use the standard system startup files or libraries when linking https://cs107e.github.io/guides/gcc/ -string(APPEND CMAKE_CXX_FLAGS " -nodefaultlibs") # Do not use the standard system libraries when linking -# string(APPEND CMAKE_CXX_FLAGS " -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables") # Remove eh_frame sections and rest - - -string(APPEND CMAKE_EXE_LINKER_FLAGS " -mabi=ilp32 -march=rv32ic -ffreestanding -nostdlib -lgcc") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=none") # Don't include build-id in the output (should be disabled by default?), saves 160bits https://interrupt.memfault.com/blog/gnu-build-id-for-firmware -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Bstatic") # Use only static libraries https://web.archive.org/web/20220530212919/https://linux.die.net/man/1/ld -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--print-memory-usage") # Print memory usage -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-Map=map_file.map") - -# set(CMAKE_C_FLAGS_DEBUG ) # TODO -# set(CMAKE_C_FLAGS_RELEASE ) -# set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS}) -# set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS}) -set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS}) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) From 3e3933553a9d9d9baf33c67a9edb6b417bb9b1ec Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Fri, 31 May 2024 15:24:00 +0200 Subject: [PATCH 22/24] old linker template removed. --- .../linker_script/src/template/lds.j2 | 225 ------------------ 1 file changed, 225 deletions(-) delete mode 100644 cmake/firmware/linker_script/src/template/lds.j2 diff --git a/cmake/firmware/linker_script/src/template/lds.j2 b/cmake/firmware/linker_script/src/template/lds.j2 deleted file mode 100644 index 6229a2e..0000000 --- a/cmake/firmware/linker_script/src/template/lds.j2 +++ /dev/null @@ -1,225 +0,0 @@ -OUTPUT_ARCH(riscv) /* TODO allow other architectures */ - -MEMORY { -{% for m in mems %} - {{ m.parent.inst_name }} ({{ m|getSwAcc }}): ORIGIN = 0x{{ '%08x' % m.absolute_address }}, LENGTH = 0x{{ '%08x' % m.size }} -{% endfor %} -} - -{% set stack_mem = mems|getStackMem %} -{% set prog_mem = mems|getProgramMem %} -{% set boot_mem = mems|getBootMem %} -{% set data_mem = mems|getDataMem %} -{% set bss_mem = mems|getBssMem %} - -PROVIDE(_estack = ORIGIN( {{ stack_mem.parent.inst_name }}) + LENGTH( {{ stack_mem.parent.inst_name }} )); - -PROVIDE(_stext = ORIGIN( {{ prog_mem.parent.inst_name }} )); -PROVIDE(_start = ORIGIN( {{ prog_mem.parent.inst_name }} )); -PROVIDE(_program_memory = ORIGIN( {{ prog_mem.parent.inst_name }} )); - -PROVIDE (__executable_start = SEGMENT_START("text-segment", _start)); . = SEGMENT_START("text-segment", _start) + SIZEOF_HEADERS; - -{% for reg in regs %} -PROVIDE({{reg.inst_name}} = 0x{{ '%08x' % reg.absolute_address }}); -{% endfor %} - - -SECTIONS { - - {% if boot_mem is not none %} - .bootloader : { - *bootloader.S.o(.vectors); - *bootloader.S.o*(*); - *bootloader.cpp.o*(*); - . = ALIGN(4); - } > {{ boot_mem.parent.inst_name }} - {% endif %} - - .text : - { - . = ALIGN(4); - *crt0.S.o(.vectors); - *crt0.S.o(.start_section); - *crt0.S.o(.text); - - /* TODO maybe more relaxed garbage collection */ - KEEP (*crt0.S.o(*)) - - KEEP (*(SORT_NONE(.init))) - - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - - KEEP (*(SORT_NONE(.fini))) - } > {{ prog_mem.parent.inst_name }} - - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - - .rodata : - { - *(.rodata .rodata.* .gnu.linkonce.r.*) - *(.rodata1) - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - } > {{ data_mem.parent.inst_name }} - - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } > {{ data_mem.parent.inst_name }} - - - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); - /* Exception handling */ - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } > {{ data_mem.parent.inst_name }} - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } > {{ data_mem.parent.inst_name }} - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } > {{ data_mem.parent.inst_name }} - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } > {{ data_mem.parent.inst_name }} - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } > {{ data_mem.parent.inst_name }} - .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } > {{ data_mem.parent.inst_name }} - .dynamic : { *(.dynamic) } > {{ data_mem.parent.inst_name }} - . = DATA_SEGMENT_RELRO_END (0, .); - .data : - { - __DATA_BEGIN__ = .; - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - *(.data1) - *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) - *(.sdata .sdata.* .gnu.linkonce.s.*) - . = ALIGN(4); - } > {{ data_mem.parent.inst_name }} - _edata = .; PROVIDE (edata = .); - - - - - __bss_start = .; - __BSS_START__ = .; - _bss_start = .; - .sbss : - { - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - } > {{ bss_mem.parent.inst_name }} - .bss : ALIGN(4) - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 32 / 8 : 1); - } > {{ bss_mem.parent.inst_name }} - . = ALIGN(32 / 8); - . = SEGMENT_START("ldata-segment", .); - . = ALIGN(32 / 8); - __BSS_END__ = .; - _bss_end = .; - _align_begin = .; - .align_mem0 : { - . = ALIGN(3); - } > {{ bss_mem.parent.inst_name }} - __global_pointer$ = 0x{{ '%08x' % data_mem.absolute_address }} + 0x{{ '%08x' % (data_mem.size/2)|int }}; - _end = .; PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - - {% if debug %} - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } > {{ data_mem.parent.inst_name }} - .stabstr 0 : { *(.stabstr) } > {{ data_mem.parent.inst_name }} - .stab.excl 0 : { *(.stab.excl) } > {{ data_mem.parent.inst_name }} - .stab.exclstr 0 : { *(.stab.exclstr) } > {{ data_mem.parent.inst_name }} - .stab.index 0 : { *(.stab.index) } > {{ data_mem.parent.inst_name }} - .stab.indexstr 0 : { *(.stab.indexstr) } > {{ data_mem.parent.inst_name }} - .comment 0 : { *(.comment) } > {{ data_mem.parent.inst_name }} - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } > {{ data_mem.parent.inst_name }} - .line 0 : { *(.line) } > {{ data_mem.parent.inst_name }} - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } > {{ data_mem.parent.inst_name }} - .debug_sfnames 0 : { *(.debug_sfnames) } > {{ data_mem.parent.inst_name }} - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } > {{ data_mem.parent.inst_name }} - .debug_pubnames 0 : { *(.debug_pubnames) } > {{ data_mem.parent.inst_name }} - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } > {{ data_mem.parent.inst_name }} - .debug_abbrev 0 : { *(.debug_abbrev) } > {{ data_mem.parent.inst_name }} - .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } > {{ data_mem.parent.inst_name }} - .debug_frame 0 : { *(.debug_frame) } > {{ data_mem.parent.inst_name }} - .debug_str 0 : { *(.debug_str) } > {{ data_mem.parent.inst_name }} - .debug_loc 0 : { *(.debug_loc) } > {{ data_mem.parent.inst_name }} - .debug_macinfo 0 : { *(.debug_macinfo) } > {{ data_mem.parent.inst_name }} - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } > {{ data_mem.parent.inst_name }} - .debug_funcnames 0 : { *(.debug_funcnames) } > {{ data_mem.parent.inst_name }} - .debug_typenames 0 : { *(.debug_typenames) } > {{ data_mem.parent.inst_name }} - .debug_varnames 0 : { *(.debug_varnames) } > {{ data_mem.parent.inst_name }} - /* DWARF 3 */ - .debug_pubtypes 0 : { *(.debug_pubtypes) } > {{ data_mem.parent.inst_name }} - .debug_ranges 0 : { *(.debug_ranges) } > {{ data_mem.parent.inst_name }} - /* DWARF Extension. */ - .debug_macro 0 : { *(.debug_macro) } > {{ data_mem.parent.inst_name }} - .debug_addr 0 : { *(.debug_addr) } > {{ data_mem.parent.inst_name }} - .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } > {{ data_mem.parent.inst_name }} - {% endif %} - /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(*) } > {{ data_mem.parent.inst_name }} -}; - From e5f42da93bdc2d0e8c7a68588e26a06ade46e77d Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 3 Jun 2024 16:35:46 +0200 Subject: [PATCH 23/24] regblock wrap function updated with reset option and reverted to previous renaming flow. --- cmake/peakrdl/peakrdl_regblock_wrap.cmake | 50 +++++++++++++++++++---- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/cmake/peakrdl/peakrdl_regblock_wrap.cmake b/cmake/peakrdl/peakrdl_regblock_wrap.cmake index 58fbe9b..0fb14d5 100644 --- a/cmake/peakrdl/peakrdl_regblock_wrap.cmake +++ b/cmake/peakrdl/peakrdl_regblock_wrap.cmake @@ -1,6 +1,6 @@ function(peakrdl_regblock_wrap IP_LIB) # Parse keyword arguments - cmake_parse_arguments(ARG "TMR" "OUTDIR;RENAME;INTF" "" ${ARGN}) + cmake_parse_arguments(ARG "TMR" "OUTDIR;RENAME;INTF;RESET" "" ${ARGN}) # Check for any unknown argument if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " @@ -35,6 +35,29 @@ function(peakrdl_regblock_wrap IP_LIB) if(ARG_INTF) set(INTF_ARG --cpuif ${ARG_INTF}) endif() + + # The default reset is active-high and synchronous + if(ARG_RESET) + set(RESET_ARG --default-reset ${ARG_RESET}) + endif() + + # Activate the triplication if TMR option is passed + if(ARG_TMR) + set(TMR_OPT "--tmr") + endif() + + if(NOT ARG_RENAME) + # The default name is the IP name + get_target_property(REGBLOCK_NAME ${IP_LIB} IP_NAME) + if(NOT REGBLOCK_NAME) + message(FATAL_ERROR "IP_NAME not set for ${IP_LIB}, check if the IP was added with + add_ip function from SoCMake") + endif() + set(REGBLOCK_NAME ${REGBLOCK_NAME}_regblock) + else() + set(REGBLOCK_NAME ${ARG_RENAME}) + endif() + # Get the SystemRDL sources to generate the register block # This function gets the IP sources and the deps get_ip_sources(RDL_SOURCES ${IP_LIB} SYSTEMRDL) @@ -46,21 +69,30 @@ function(peakrdl_regblock_wrap IP_LIB) # Generate the regblock and wrapper find_python3() - if(ARG_TMR) - set(TMR_OPT "--tmr") - endif() + + # Create the reblog_wrap python command set(__CMD ${Python3_EXECUTABLE} -m peakrdl regblock_wrap + --rename ${REGBLOCK_NAME} + ${INTF_ARG} + ${RESET_ARG} ${TMR_OPT} - # --rename ${IP_NAME} - # ${INTF_ARG} -o ${OUTDIR} ${RDL_SOURCES} ) - set(REGBLOCK_SV_GEN ${OUTDIR}/${IP_NAME}_regblock_pkg.sv ${OUTDIR}/${IP_NAME}_regblock.sv) + set(REGBLOCK_SV_GEN ${OUTDIR}/${IP_NAME}_pkg.sv ${OUTDIR}/${IP_NAME}.sv) set(WRAP_SV_GEN ${OUTDIR}/${IP_NAME}.sv) set(STAMP_FILE "${BINARY_DIR}/${IP_LIB}_${CMAKE_CURRENT_FUNCTION}.stamp") + # Regblock generated files (pkg + logic) + set(REGBLOCK_SV_GEN + ${OUTDIR}/${REGBLOCK_NAME}_pkg.sv + ${OUTDIR}/${REGBLOCK_NAME}.sv + ) + # Top module wraper file generate + set(WRAP_SV_GEN ${OUTDIR}/${IP_NAME}.sv) + + # Add the custom command to call the peakrdl regblock_wrap plugin add_custom_command( # The output files are automtically marked as GENERATED (deleted by make clean among other things) OUTPUT ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN} ${STAMP_FILE} @@ -70,12 +102,14 @@ function(peakrdl_regblock_wrap IP_LIB) COMMENT "Running ${CMAKE_CURRENT_FUNCTION} on ${IP_LIB}" ) - # This target triggers the systemverilog register block generation using peakRDL regblock tool (_CMD) + # This target triggers the custom command generating the top wrapper and the register file block set(TNAME ${IP_LIB}_regblock_wrap) add_custom_target( ${TNAME} DEPENDS ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN} ${STAMP_FILE} ) + + # Add the generated sources to the IP sources ip_sources(${IP_LIB} SYSTEMVERILOG PREPEND ${REGBLOCK_SV_GEN} ${WRAP_SV_GEN}) if(ARG_TMR) From 0077cf1776d096810465c2b67a30335f9f832774 Mon Sep 17 00:00:00 2001 From: Benoit Denkinger Date: Mon, 3 Jun 2024 23:02:36 +0200 Subject: [PATCH 24/24] regblock path corrected. --- cmake/synth/sv2v.cmake | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cmake/synth/sv2v.cmake b/cmake/synth/sv2v.cmake index dbfaddd..22a88e4 100644 --- a/cmake/synth/sv2v.cmake +++ b/cmake/synth/sv2v.cmake @@ -24,7 +24,7 @@ function(get_sv2v_sources OUT_VAR IP_LIB) endfunction() function(sv2v IP_LIB) - cmake_parse_arguments(ARG "REPLACE;TMR;HWIF_WIRE" "OUTDIR" "" ${ARGN}) + cmake_parse_arguments(ARG "REPLACE;TMR;HWIF_WIRE" "OUTDIR;REGBLOCK_OUTDIR" "" ${ARGN}) if(ARG_UNPARSED_ARGUMENTS) message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}") endif() @@ -39,6 +39,18 @@ function(sv2v IP_LIB) endif() execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTDIR}) + # Default regblock output directory is regblock/ + if(NOT ARG_REGBLOCK_OUTDIR) + if(NOT ARG_TMR) + set(REGBLOCK_OUTDIR_ARG regblock) + else() + set(REGBLOCK_OUTDIR_ARG regblock_tmr) + endif() + else() + set(REGBLOCK_OUTDIR_ARG ${ARG_REGBLOCK_OUTDIR}) + endif() + + get_sv2v_sources(SV2V_SRC ${IP_LIB}) foreach(vfile ${SV2V_SRC}) get_filename_component(V_SOURCE_WO_EXT ${vfile} NAME_WE) @@ -66,7 +78,7 @@ function(sv2v IP_LIB) if(ARG_HWIF_WIRE) get_target_property(TOP_MODULE ${IP_LIB} IP_NAME) set(SED_COMMAND - COMMAND ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hwif_sed.sh ${OUTDIR}/${TOP_MODULE}_regblock.v ${OUTDIR}/../regblock/${TOP_MODULE}.sv + COMMAND ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/hwif_sed.sh ${OUTDIR}/${TOP_MODULE}_regblock.v ${OUTDIR}/../${REGBLOCK_OUTDIR_ARG}/${TOP_MODULE}.sv ) endif()