# ================================================================================ # # NEORV32 Application Software Makefile # # -------------------------------------------------------------------------------- # # Do not edit this file! Use the re-defines in the project-local makefile instead. # # -------------------------------------------------------------------------------- # # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 # # Copyright (c) NEORV32 contributors. # # Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. # # Licensed under the BSD-3-Clause license, see LICENSE for details. # # SPDX-License-Identifier: BSD-3-Clause # # ================================================================================ # # ----------------------------------------------------------------------------- # Default configuration (DO NOT EDIT THIS FILE! REDEFINE / OVERRIDE THE DEFAULT # CONFIGURATION WHEN INCLUDING THIS MAKEFILE IN THE PROJECT-SPECIFIC MAKEFILE) # ----------------------------------------------------------------------------- # User's application sources (*.c, *.cpp, *.s, *.S); add additional files here APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S) # User's application object files (*.o, *.cpp, *.s, *.S); add additional files here APP_OBJ ?= # User's application include folders (don't forget the '-I' before each entry) APP_INC ?= -I . # User's application include folders - for assembly files only (don't forget the '-I' before each entry) ASM_INC ?= -I . # Build folder for output BUILD_DIR ?= build # Optimization EFFORT ?= -Os # Compiler toolchain prefix RISCV_PREFIX ?= riscv-none-elf- # CPU architecture and ABI MARCH ?= rv32i_zicsr_zifencei MABI ?= ilp32 # User flags for additional configuration (will be added to compiler flags) USER_FLAGS ?= # Relative or absolute path to the NEORV32 home folder NEORV32_HOME ?= ../../.. # GDB arguments GDB_ARGS ?= -ex "target extended-remote localhost:3333" # GHDL simulation run arguments GHDL_RUN_FLAGS ?= # ----------------------------------------------------------------------------- # NEORV32 framework # ----------------------------------------------------------------------------- # Path to NEORV32 linker script and startup file NEORV32_COM_PATH = $(NEORV32_HOME)/sw/common # Path to main NEORV32 library include files NEORV32_INC_PATH = $(NEORV32_HOME)/sw/lib/include # Path to main NEORV32 library source files NEORV32_SRC_PATH = $(NEORV32_HOME)/sw/lib/source # Path to NEORV32 executable generator NEORV32_EXG_PATH = $(NEORV32_HOME)/sw/image_gen # Path to NEORV32 rtl folder NEORV32_RTL_PATH = $(NEORV32_HOME)/rtl # Path to NEORV32 sim folder NEORV32_SIM_PATH = $(NEORV32_HOME)/sim # Core libraries (peripheral and CPU drivers) CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c) # Application start-up code CORE_SRC += $(NEORV32_COM_PATH)/crt0.S # Linker script LD_SCRIPT ?= $(NEORV32_COM_PATH)/neorv32.ld # Main output files APP_EXE = neorv32_exe.bin APP_ELF = main.elf APP_HEX = neorv32_raw_exe.hex APP_BIN = neorv32_raw_exe.bin APP_COE = neorv32_raw_exe.coe APP_MEM = neorv32_raw_exe.mem APP_MIF = neorv32_raw_exe.mif APP_ASM = main.asm APP_VHD = neorv32_application_image.vhd BOOT_VHD = neorv32_bootloader_image.vhd # Binary main file BIN_MAIN = $(BUILD_DIR)/main.bin # Define all sources SRC = $(APP_SRC) SRC += $(CORE_SRC) # Define search path for prerequisites VPATH = $(sort $(dir $(SRC))) # Define all object files OBJ := $(patsubst %,$(BUILD_DIR)/%.o,$(notdir $(SRC))) OBJ += $(APP_OBJ) # ----------------------------------------------------------------------------- # Tools and flags # ----------------------------------------------------------------------------- # Compiler tools CC = $(RISCV_PREFIX)gcc OBJDUMP = $(RISCV_PREFIX)objdump OBJCOPY = $(RISCV_PREFIX)objcopy READELF = $(RISCV_PREFIX)readelf SIZE = $(RISCV_PREFIX)size GDB = $(RISCV_PREFIX)gdb # Host's native compiler CC_HOST = gcc -Wall -O -g # System tools ECHO = @echo SET = set CP = cp RM = rm MKDIR = mkdir SH = sh WC = wc # NEORV32 executable image generator IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen ifeq ($(OS),Windows_NT) IMAGE_GEN := $(IMAGE_GEN).exe endif # Compiler & linker flags CC_FLAGS = -march=$(MARCH) -mabi=$(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv CC_FLAGS += -mstrict-align -mbranch-cost=10 -Wl,--gc-sections -ffp-contract=off -g CC_FLAGS += $(USER_FLAGS) LD_LIBS = -lm -lc -lgcc LD_LIBS += $(USER_LIBS) # Allow users to use tool-specific flags # Uses naming from https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html NEO_CFLAGS = $(CC_FLAGS) $(CFLAGS) NEO_CXXFLAGS = $(CC_FLAGS) $(CXXFLAGS) NEO_LDFLAGS = $(CC_FLAGS) $(LDFLAGS) NEO_ASFLAGS = $(CC_FLAGS) $(ASFLAGS) # ----------------------------------------------------------------------------- # Application output definitions # ----------------------------------------------------------------------------- .PHONY: check info help elf_info clean clean_all .DEFAULT_GOAL := help elf: $(APP_ELF) asm: $(APP_ASM) exe: $(APP_EXE) hex: $(APP_HEX) bin: $(APP_BIN) coe: $(APP_COE) mem: $(APP_MEM) mif: $(APP_MIF) image: $(APP_VHD) install: image install-$(APP_VHD) all: $(APP_ELF) $(APP_ASM) $(APP_EXE) $(APP_HEX) $(APP_BIN) $(APP_COE) $(APP_MEM) $(APP_MIF) $(APP_VHD) install hex bin # ----------------------------------------------------------------------------- # Verbosity # ----------------------------------------------------------------------------- ifeq ("$(origin V)", "command line") BUILD_VERBOSE=$(V) endif ifndef BUILD_VERBOSE BUILD_VERBOSE = 0 endif ifeq ($(BUILD_VERBOSE),0) Q = @ else Q = endif # ----------------------------------------------------------------------------- # Git tag and commit hash # ----------------------------------------------------------------------------- NEORV32_GIT_TAG = "unknown" # check if git is available at all ifneq (, $(shell git 2>/dev/null)) $(eval NEORV32_GIT_TAG = $(shell git describe --tags)) endif # add short commit hash as C define NEO_CFLAGS += -DNEORV32_GIT_TAG="\"$(NEORV32_GIT_TAG)\"" # ----------------------------------------------------------------------------- # Image generator targets # ----------------------------------------------------------------------------- # Compile image generator $(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.c $(ECHO) Compiling image generator... $(Q)$(CC_HOST) $< -o $(IMAGE_GEN) # ----------------------------------------------------------------------------- # General targets: Assemble, compile, link, dump # ----------------------------------------------------------------------------- # Create the build directories if they don't exist $(BUILD_DIR): $(Q)$(MKDIR) -p $(BUILD_DIR) # Compile app *.s sources (assembly) $(BUILD_DIR)/%.s.o: %.s | $(BUILD_DIR) $(Q)$(CC) -c $(NEO_ASFLAGS) -MMD -MP -MF $(BUILD_DIR)/$*.s.d -MT $(BUILD_DIR)/$*.s.o -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ # Compile app *.S sources (assembly + C pre-processor) $(BUILD_DIR)/%.S.o: %.S | $(BUILD_DIR) $(Q)$(CC) -c $(NEO_ASFLAGS) -MMD -MP -MF $(BUILD_DIR)/$*.S.d -MT $(BUILD_DIR)/$*.S.o -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ # Compile app *.c sources $(BUILD_DIR)/%.c.o: %.c | $(BUILD_DIR) $(Q)$(CC) -c $(NEO_CFLAGS) -MMD -MP -MF $(BUILD_DIR)/$*.c.d -MT $(BUILD_DIR)/$*.c.o -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ # Compile app *.cpp sources $(BUILD_DIR)/%.cpp.o: %.cpp | $(BUILD_DIR) $(Q)$(CC) -c $(NEO_CXXFLAGS) -MMD -MP -MF $(BUILD_DIR)/$*.cpp.d -MT $(BUILD_DIR)/$*.cpp.o -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ # Link object files and show memory utilization -include $(OBJ:.o=.d) $(APP_ELF): $(OBJ) $(Q)$(CC) $(NEO_LDFLAGS) -T $(LD_SCRIPT) $^ $(LD_LIBS) -o $@ $(ECHO) "Memory utilization:" $(Q)$(SIZE) $(APP_ELF) # Assembly listing file (for debugging) $(APP_ASM): $(APP_ELF) $(Q)$(OBJDUMP) -d -S -z $< > $@ # Generate final executable from .text + .rodata + .data (in THIS order!) $(BIN_MAIN): $(APP_ELF) | $(BUILD_DIR) $(Q)$(OBJCOPY) -I elf32-little $< -j .text -j .rodata -j .data -O binary $@ # ----------------------------------------------------------------------------- # Application targets: Generate executable formats # ----------------------------------------------------------------------------- # Generate NEORV32 executable image for upload via bootloader $(APP_EXE): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_EXE)" $(Q)$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR)) $(ECHO) "Executable size in bytes:" $(Q)$(WC) -c < $(APP_EXE) # Generate NEORV32 executable VHDL boot image $(APP_VHD): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_VHD)" $(Q)$(IMAGE_GEN) -app_vhd $< $@ $(shell basename $(CURDIR)) # Generate NEORV32 RAW executable image in plain hex format $(APP_HEX): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_HEX)" $(Q)$(IMAGE_GEN) -raw_hex $< $@ $(shell basename $(CURDIR)) # Generate NEORV32 RAW executable image in binary format $(APP_BIN): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_BIN)" $(Q)$(IMAGE_GEN) -raw_bin $< $@ $(shell basename $(CURDIR)) # Generate NEORV32 RAW executable image in COE format $(APP_COE): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_COE)" $(Q)$(IMAGE_GEN) -raw_coe $< $@ $(shell basename $(CURDIR)) # Generate NEORV32 RAW executable image in MIF format $(APP_MIF): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_MIF)" $(Q)$(IMAGE_GEN) -raw_mif $< $@ $(shell basename $(CURDIR)) # Generate NEORV32 RAW executable image in MEM format $(APP_MEM): $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(APP_MEM)" $(Q)$(IMAGE_GEN) -raw_mem $< $@ $(shell basename $(CURDIR)) # ----------------------------------------------------------------------------- # BOOTROM / bootloader image targets # ----------------------------------------------------------------------------- # Create local VHDL BOOTROM image bl_image: $(BIN_MAIN) $(IMAGE_GEN) $(Q)$(SET) -e $(ECHO) "Generating $(BOOT_VHD)" $(Q)$(IMAGE_GEN) -bld_vhd $< $(BOOT_VHD) $(shell basename $(CURDIR)) # Install BOOTROM image to VHDL source directory bootloader: bl_image $(Q)$(SET) -e $(ECHO) "Installing bootloader image to $(NEORV32_RTL_PATH)/core/$(BOOT_VHD)" $(Q)$(CP) $(BOOT_VHD) $(NEORV32_RTL_PATH)/core/. # ----------------------------------------------------------------------------- # In-console simulation using default testbench and GHDL # ----------------------------------------------------------------------------- sim: $(APP_VHD) $(ECHO) "Simulating processor using default testbench..." $(Q)$(SH) $(NEORV32_SIM_PATH)/ghdl.sh $(GHDL_RUN_FLAGS) # Install VHDL memory initialization file install-$(APP_VHD): $(APP_VHD) $(Q)$(SET) -e $(ECHO) "Installing application image to $(NEORV32_RTL_PATH)/core/$(APP_VHD)" $(Q)$(CP) $(APP_VHD) $(NEORV32_RTL_PATH)/core/. # ----------------------------------------------------------------------------- # Regenerate HDL file list file(s) # ----------------------------------------------------------------------------- hdl_lists: $(Q)$(SH) $(NEORV32_RTL_PATH)/generate_file_lists.sh # ----------------------------------------------------------------------------- # Show final ELF details (just for debugging) # ----------------------------------------------------------------------------- elf_info: $(APP_ELF) $(Q)$(OBJDUMP) -x $(APP_ELF) elf_sections: $(APP_ELF) $(Q)$(READELF) -S $(APP_ELF) # ----------------------------------------------------------------------------- # Run GDB # ----------------------------------------------------------------------------- gdb: $(APP_ELF) $(Q)$(GDB) $(APP_ELF) $(GDB_ARGS) # ----------------------------------------------------------------------------- # Clean up # ----------------------------------------------------------------------------- # remove all build artifacts clean: $(Q)$(RM) -rf $(BUILD_DIR) $(Q)$(RM) -f $(APP_EXE) $(APP_ELF) $(APP_HEX) $(APP_BIN) $(APP_COE) $(APP_MEM) $(APP_MIF) $(APP_ASM) $(APP_VHD) $(BOOT_VHD) $(Q)$(RM) -f .gdb_history # also remove image generator clean_all: clean $(Q)$(RM) -f $(IMAGE_GEN) $(Q)$(RM) -rf $(NEORV32_SIM_PATH)/build # ----------------------------------------------------------------------------- # Check toolchain # ----------------------------------------------------------------------------- check: $(IMAGE_GEN) $(ECHO) "---------------- $(CC) ----------------" $(Q)$(CC) -v $(ECHO) "---------------- $(OBJDUMP) ----------------" $(Q)$(OBJDUMP) -V $(ECHO) "---------------- $(OBJCOPY) ----------------" $(Q)$(OBJCOPY) -V $(ECHO) "---------------- $(READELF) ----------------" $(Q)$(READELF) -v $(ECHO) "---------------- $(SIZE) ----------------" $(Q)$(SIZE) -V $(ECHO) "---------------- NEORV32 image_gen ----------------" $(Q)$(IMAGE_GEN) -help $(ECHO) "---------------- Native GCC ----------------" $(Q)$(CC_HOST) -v $(ECHO) "" $(ECHO) "Toolchain check OK" # ----------------------------------------------------------------------------- # Show configuration # ----------------------------------------------------------------------------- info: $(ECHO) "******************************************************" $(ECHO) "Project / Makefile Configuration" $(ECHO) "******************************************************" $(ECHO) "Git tag: $(NEORV32_GIT_TAG)" $(ECHO) "Project folder: $(shell basename $(CURDIR))" $(ECHO) "Source files: $(APP_SRC)" $(ECHO) "Include folder(s): $(APP_INC)" $(ECHO) "ASM include folder(s): $(ASM_INC)" $(ECHO) "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)" $(ECHO) "IMAGE_GEN: $(IMAGE_GEN)" $(ECHO) "Core source files:" $(ECHO) "$(CORE_SRC)" $(ECHO) "Core include folder:" $(ECHO) "$(NEORV32_INC_PATH)" $(ECHO) "Search path (VPATH)" $(ECHO) "$(VPATH)" $(ECHO) "Project object files:" $(ECHO) "$(OBJ)" $(ECHO) "LIBGCC:" $(Q)$(CC) -print-libgcc-file-name $(ECHO) "SEARCH-DIRS:" $(Q)$(CC) -print-search-dirs $(ECHO) "USER_LIBS: $(USER_LIBS)" $(ECHO) "LD_LIBS: $(LD_LIBS)" $(ECHO) "MARCH: $(MARCH)" $(ECHO) "MABI: $(MABI)" $(ECHO) "CC: $(CC)" $(ECHO) "OBJDUMP: $(OBJDUMP)" $(ECHO) "OBJCOPY: $(OBJCOPY)" $(ECHO) "SIZE: $(SIZE)" $(ECHO) "DEBUGGER: $(GDB)" $(ECHO) "GDB_ARGS: $(GDB_ARGS)" $(ECHO) "GHDL_RUN_FLAGS: $(GHDL_RUN_FLAGS)" $(ECHO) "USER_FLAGS: $(USER_FLAGS)" $(ECHO) "CC_FLAGS: $(CC_FLAGS)" # ----------------------------------------------------------------------------- # Help # ----------------------------------------------------------------------------- help: $(ECHO) "NEORV32 Software Makefile" $(ECHO) "Find more information at https://github.com/stnolting/neorv32" $(ECHO) "Use make V=1 or set BUILD_VERBOSE to increase build verbosity" $(ECHO) "" $(ECHO) "Targets:" $(ECHO) "" $(ECHO) " help show this text" $(ECHO) " check check toolchain" $(ECHO) " info show makefile/toolchain configuration" $(ECHO) " gdb start GNU debugging session" $(ECHO) " asm compile and generate <$(APP_ASM)> assembly listing file for manual debugging" $(ECHO) " elf compile and generate <$(APP_ELF)> ELF file" $(ECHO) " exe compile and generate <$(APP_EXE)> executable image file for bootloader upload (includes a HEADER!)" $(ECHO) " bin compile and generate <$(APP_BIN)> executable memory image" $(ECHO) " hex compile and generate <$(APP_HEX)> executable memory image" $(ECHO) " coe compile and generate <$(APP_COE)> executable memory image" $(ECHO) " mem compile and generate <$(APP_MEM)> executable memory image" $(ECHO) " mif compile and generate <$(APP_MIF)> executable memory image" $(ECHO) " image compile and generate VHDL IMEM application boot image <$(APP_VHD)> in local folder" $(ECHO) " install compile, generate and install VHDL IMEM application boot image <$(APP_VHD)>" $(ECHO) " sim in-console simulation using default testbench (sim folder) and GHDL" $(ECHO) " hdl_lists regenerate HDL file-lists (*.f) in NEORV32_HOME/rtl" $(ECHO) " all exe + install + hex + bin + asm" $(ECHO) " elf_info show ELF layout info" $(ECHO) " elf_sections show ELF sections" $(ECHO) " clean clean up project home folder" $(ECHO) " clean_all clean up project home folder and image generator" $(ECHO) " bl_image compile and generate VHDL BOOTROM bootloader boot image <$(BOOT_VHD)> in local folder" $(ECHO) " bootloader compile, generate and install VHDL BOOTROM bootloader boot image <$(BOOT_VHD)>" $(ECHO) "" $(ECHO) "Variables:" $(ECHO) "" $(ECHO) " BUILD_VERBOSE Set to increase build verbosity: \"$(BUILD_VERBOSE)\"" $(ECHO) " USER_FLAGS Custom toolchain flags [append only]: \"$(USER_FLAGS)\"" $(ECHO) " USER_LIBS Custom libraries [append only]: \"$(USER_LIBS)\"" $(ECHO) " EFFORT Optimization level: \"$(EFFORT)\"" $(ECHO) " MARCH Machine architecture: \"$(MARCH)\"" $(ECHO) " MABI Machine binary interface: \"$(MABI)\"" $(ECHO) " APP_INC C include folder(s) [append only]: \"$(APP_INC)\"" $(ECHO) " APP_SRC C source folder(s) [append only]: \"$(APP_SRC)\"" $(ECHO) " APP_OBJ Object file(s) [append only]: \"$(APP_OBJ)\"" $(ECHO) " ASM_INC ASM include folder(s) [append only]: \"$(ASM_INC)\"" $(ECHO) " RISCV_PREFIX Toolchain prefix: \"$(RISCV_PREFIX)\"" $(ECHO) " NEORV32_HOME NEORV32 home folder: \"$(NEORV32_HOME)\"" $(ECHO) " GDB_ARGS GDB (connection) arguments: \"$(GDB_ARGS)\"" $(ECHO) " GHDL_RUN_FLAGS GHDL simulation run arguments: \"$(GHDL_RUN_FLAGS)\"" $(ECHO) ""