macro(import_binary_as_elf Path Symbol Target)
set(objcopy_flags -I binary -O default -B riscv)
string(MAKE_C_IDENTIFIER ${Path} unstripped)
add_custom_command(
OUTPUT ${Path}.elf
DEPENDS ${Target}
COMMAND
${CMAKE_OBJCOPY} ${objcopy_flags}
${Path} ${Path}.elf
COMMAND
${CMAKE_OBJCOPY} -N
_binary_${unstripped}_end ${Path}.elf
COMMAND
${CMAKE_OBJCOPY} --redefine-sym
_binary_${unstripped}_start=${Symbol}_start
${Path}.elf
COMMAND
${CMAKE_OBJCOPY} --redefine-sym
_binary_${unstripped}_size=${Symbol}_size
${Path}.elf
)
add_custom_target(${Symbol}_elf DEPENDS ${Path}.elf)
endmacro()
Some learnings of RISC-V, at least from CVA6 perspective:
sfence.vma together with fence.i. It is not optimal but usually ensures stability. Once things are functionally together sync points can be reduced.W PTE’s created without having also D, causing odd crashes. So again, I’ve taken the habit of first binding these together and later on reduce.I’ve yet use ASIC boards, have only used FPGA so far and development versions of CPU’s. I guess these sort of fail-safe practices are more important in early development
I nailed the Keystone SATP change bug on CVA6 after only 1.5 months of constant debugging:
I try to learn at least one RISC-V opcode a day to get more familiar. Today’s opcode was auipc which stores to a register a PC-relative address from an immediate offset. The offset is given as number of pages.
It is e.g. used to set the gp (which is mnemonic for x3), which is the base address for global variables.
Not trying to teach anyone. Writing things down like this just works for my memory :-)