PROGRAM = main | |
############################################################# | |
# Makefile Arguments | |
############################################################# | |
# BSP_DIR sets the path to the target-specific board support package. | |
BSP_DIR ?= $(abspath bsp) | |
# SRC_DIR sets the path to the program source directory | |
SRC_DIR ?= $(abspath kernel) | |
# The configuration defaults to Debug. Valid choices are: | |
# - debug | |
# - release | |
CONFIGURATION ?= debug | |
############################################################# | |
# BSP loading | |
############################################################# | |
# There must be a settings makefile fragment in the BSP's board directory. | |
ifeq ($(wildcard $(BSP_DIR)/settings.mk),) | |
$(error Unable to find BSP for $(TARGET), expected to find $(BSP_DIR)/settings.mk) | |
endif | |
# Include the BSP settings | |
include $(BSP_DIR)/settings.mk | |
# Check that settings.mk sets RISCV_ARCH and RISCV_ABI | |
ifeq ($(RISCV_ARCH),) | |
$(error $(BSP_DIR)/board.mk must set RISCV_ARCH, the RISC-V ISA string to target) | |
endif | |
ifeq ($(RISCV_ABI),) | |
$(error $(BSP_DIR)/board.mk must set RISCV_ABI, the ABI to target) | |
endif | |
ifeq ($(RISCV_CMODEL),) | |
RISCV_CMODEL = medany | |
endif | |
ifeq ($(PROGRAM),dhrystone) | |
ifeq ($(LINK_TARGET),) | |
ifneq ($(TARGET),freedom-e310-arty) | |
ifneq ($(TARGET),sifive-hifive1) | |
ifneq ($(TARGET),sifive-hifive1-revb) | |
LINK_TARGET = ramrodata | |
endif | |
endif | |
endif | |
endif | |
endif | |
ifeq ($(PROGRAM),coremark) | |
ifeq ($(LINK_TARGET),) | |
LINK_TARGET = ramrodata | |
endif | |
endif | |
ifeq ($(LINK_TARGET),) | |
LINK_TARGET = default | |
endif | |
# Determines the XLEN from the toolchain tuple | |
ifeq ($(patsubst rv32%,rv32,$(RISCV_ARCH)),rv32) | |
RISCV_XLEN := 32 | |
else ifeq ($(patsubst rv64%,rv64,$(RISCV_ARCH)),rv64) | |
RISCV_XLEN := 64 | |
else | |
$(error Unable to determine XLEN from $(RISCV_ARCH)) | |
endif | |
############################################################# | |
# Toolchain | |
############################################################# | |
# Allow users to select a different cross compiler. | |
CROSS_COMPILE ?= riscv64-unknown-elf | |
# If users don't specify RISCV_PATH then assume that the tools will just be in | |
# their path. | |
ifeq ($(RISCV_PATH),) | |
RISCV_GCC := $(CROSS_COMPILE)-gcc | |
RISCV_GXX := $(CROSS_COMPILE)-g++ | |
RISCV_OBJDUMP := $(CROSS_COMPILE)-objdump | |
RISCV_OBJCOPY := $(CROSS_COMPILE)-objcopy | |
RISCV_GDB := $(CROSS_COMPILE)-gdb | |
RISCV_AR := $(CROSS_COMPILE)-ar | |
RISCV_SIZE := $(CROSS_COMPILE)-size | |
else | |
RISCV_GCC := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-gcc) | |
RISCV_GXX := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-g++) | |
RISCV_OBJDUMP := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-objdump) | |
RISCV_OBJCOPY := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-objcopy) | |
RISCV_GDB := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-gdb) | |
RISCV_AR := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-ar) | |
RISCV_SIZE := $(abspath $(RISCV_PATH)/bin/$(CROSS_COMPILE)-size) | |
PATH := $(abspath $(RISCV_PATH)/bin):$(PATH) | |
endif | |
SEGGER_JLINK_EXE := JLinkExe | |
SEGGER_JLINK_GDB_SERVER := JLinkGDBServer | |
############################################################# | |
# Software Flags | |
############################################################# | |
# Set the arch, ABI, and code model | |
RISCV_CCASFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=$(RISCV_CMODEL) | |
RISCV_CFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=$(RISCV_CMODEL) | |
RISCV_CXXFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=$(RISCV_CMODEL) | |
RISCV_ASFLAGS += -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=$(RISCV_CMODEL) | |
# Prune unused functions and data | |
RISCV_CFLAGS += -ffunction-sections -fdata-sections | |
RISCV_CXXFLAGS += -ffunction-sections -fdata-sections | |
# Include the Metal headers | |
RISCV_CCASFLAGS += -I$(abspath $(BSP_DIR)/install/include/) | |
RISCV_CFLAGS += -I$(abspath $(BSP_DIR)/install/include/) | |
RISCV_CXXFLAGS += -I$(abspath $(BSP_DIR)/install/include/) | |
# Use newlib-nano | |
RISCV_CCASFLAGS += --specs=nano.specs | |
RISCV_CFLAGS += --specs=nano.specs | |
RISCV_CXXFLAGS += --specs=nano.specs | |
# Turn on garbage collection for unused sections | |
RISCV_LDFLAGS += -Wl,--gc-sections | |
# Turn on linker map file generation | |
RISCV_LDFLAGS += -Wl,-Map,$(PROGRAM).map | |
# Turn off the C standard library | |
RISCV_LDFLAGS += -nostartfiles -nostdlib | |
# Find the archive files and linker scripts | |
RISCV_LDFLAGS += -L$(sort $(dir $(abspath $(filter %.a,$^)))) -T$(abspath $(filter %.lds,$^)) | |
# Link to the relevant libraries | |
RISCV_LDLIBS += -Wl,--start-group -lc -lgcc -lmetal -lmetal-gloss -Wl,--end-group | |
# Load the configuration Makefile | |
CONFIGURATION_FILE = $(wildcard $(CONFIGURATION).mk) | |
ifeq ($(words $(CONFIGURATION_FILE)),0) | |
$(error Unable to find the Makefile $(CONFIGURATION).mk for CONFIGURATION=$(CONFIGURATION)) | |
endif | |
include $(CONFIGURATION).mk | |
# Benchmark CFLAGS go after loading the CONFIGURATION so that they can override the optimization level | |
ifeq ($(PROGRAM),dhrystone) | |
ifeq ($(DHRY_OPTION),) | |
# Ground rules (default) | |
RISCV_XCFLAGS += -mexplicit-relocs -fno-inline | |
else ifeq ($(DHRY_OPTION),fast) | |
# With inline and without lto | |
RISCV_XCFLAGS += -mexplicit-relocs -finline | |
else ifeq ($(DHRY_OPTION),best) | |
# Best Score | |
RISCV_XCFLAGS += -finline -flto -fwhole-program | |
endif | |
RISCV_XCFLAGS += -DDHRY_ITERS=$(TARGET_DHRY_ITERS) | |
endif | |
ifeq ($(PROGRAM),coremark) | |
ifeq ($(RISCV_SERIES),sifive-7-series) | |
RISCV_XCFLAGS += -O2 -fno-common -funroll-loops -finline-functions -funroll-all-loops --param max-inline-insns-auto=20 -falign-functions=8 -falign-jumps=8 -falign-loops=8 --param inline-min-speedup=10 -mtune=sifive-7-series -ffast-math | |
else | |
RISCV_XCFLAGS += -O2 -fno-common -funroll-loops -finline-functions --param max-inline-insns-auto=20 -falign-functions=4 -falign-jumps=4 -falign-loops=4 --param inline-min-speedup=10 | |
endif | |
RISCV_XCFLAGS += -DITERATIONS=$(TARGET_CORE_ITERS) | |
endif | |
############################################################# | |
# Software | |
############################################################# | |
PROGRAM_ELF ?= $(SRC_DIR)/$(CONFIGURATION)/$(PROGRAM).elf | |
PROGRAM_HEX ?= $(SRC_DIR)/$(CONFIGURATION)/$(PROGRAM).hex | |
PROGRAM_LST ?= $(SRC_DIR)/$(CONFIGURATION)/$(PROGRAM).lst | |
.PHONY: all | |
all: software | |
.PHONY: software | |
software: $(PROGRAM_ELF) | |
software: $(PROGRAM_HEX) | |
PROGRAM_SRCS = $(wildcard $(SRC_DIR)/*.c) $(wildcard $(SRC_DIR)/*.h) $(wildcard $(SRC_DIR)/*.S) | |
$(PROGRAM_ELF): \ | |
$(PROGRAM_SRCS) \ | |
$(BSP_DIR)/install/lib/$(CONFIGURATION)/libmetal.a \ | |
$(BSP_DIR)/install/lib/$(CONFIGURATION)/libmetal-gloss.a \ | |
$(BSP_DIR)/metal.$(LINK_TARGET).lds | |
mkdir -p $(dir $@) | |
$(MAKE) -C $(SRC_DIR) $(basename $(notdir $@)) \ | |
PORT_DIR=$(PORT_DIR) \ | |
AR=$(RISCV_AR) \ | |
CC=$(RISCV_GCC) \ | |
CXX=$(RISCV_GXX) \ | |
ASFLAGS="$(RISCV_ASFLAGS)" \ | |
CCASFLAGS="$(RISCV_CCASFLAGS)" \ | |
CFLAGS="$(RISCV_CFLAGS)" \ | |
CXXFLAGS="$(RISCV_CXXFLAGS)" \ | |
XCFLAGS="$(RISCV_XCFLAGS)" \ | |
LDFLAGS="$(RISCV_LDFLAGS)" \ | |
LDLIBS="$(RISCV_LDLIBS)" | |
mv $(SRC_DIR)/$(basename $(notdir $@)).map $(dir $@) | |
mv $(SRC_DIR)/$(basename $(notdir $@)) $@ | |
touch -c $@ | |
$(RISCV_OBJDUMP) --source --all-headers --demangle --line-numbers --wide $@ > $(PROGRAM_LST) | |
$(RISCV_SIZE) $@ | |
# Use elf2hex if we're creating a hex file for RTL simulation | |
ifneq ($(filter rtl,$(TARGET_TAGS)),) | |
.PHONY: software | |
$(PROGRAM_HEX): \ | |
scripts/elf2hex/install/bin/$(CROSS_COMPILE)-elf2hex \ | |
$(PROGRAM_ELF) | |
$< --output $@ --input $(PROGRAM_ELF) --bit-width $(COREIP_MEM_WIDTH) | |
else | |
$(PROGRAM_HEX): \ | |
$(PROGRAM_ELF) | |
$(RISCV_OBJCOPY) -O ihex $(PROGRAM_ELF) $@ | |
endif | |
.PHONY: clean-kernel | |
clean-kernel: | |
rm -rf $(SRC_DIR)/$(CONFIGURATION) | |
rm -rf $(SRC_DIR)/$(PROGRAM) $(PROGRAM).hex | |
.PHONY: clean | |
clean: clean-kernel | |
############################################################# | |
# elf2hex | |
############################################################# | |
scripts/elf2hex/build/Makefile: scripts/elf2hex/configure | |
@rm -rf $(dir $@) | |
@mkdir -p $(dir $@) | |
cd $(dir $@); \ | |
$(abspath $<) \ | |
--prefix=$(abspath $(dir $<))/install \ | |
--target=$(CROSS_COMPILE) | |
scripts/elf2hex/install/bin/$(CROSS_COMPILE)-elf2hex: scripts/elf2hex/build/Makefile | |
$(MAKE) -C $(dir $<) install | |
touch -c $@ | |
.PHONY: clean-elf2hex | |
clean-elf2hex: | |
rm -rf scripts/elf2hex/build scripts/elf2hex/install | |
clean: clean-elf2hex | |
############################################################# | |
# Compiles an instance of Metal targeted at $(TARGET) | |
############################################################# | |
METAL_SOURCE_PATH ?= freedom-metal | |
METAL_LDSCRIPT = $(BSP_DIR)/metal.$(LINK_TARGET).lds | |
METAL_HEADER = $(BSP_DIR)/metal.h | |
METAL_INLINE = $(BSP_DIR)/metal-inline.h | |
PLATFORM_HEADER = $(BSP_DIR)/metal-platform.h | |
METAL_PREFIX = $(abspath $(BSP_DIR)/install) | |
METAL_BUILD_DIR = $(abspath $(BSP_DIR)/build/$(CONFIGURATION)) | |
METAL_LIB_DIR = $(abspath $(BSP_DIR)/install/lib/$(CONFIGURATION)) | |
.PHONY: metal | |
metal: $(METAL_LIB_DIR)/stamp | |
$(METAL_BUILD_DIR)/Makefile: | |
@rm -rf $(dir $@) | |
@mkdir -p $(dir $@) | |
cd $(dir $@) && \ | |
CFLAGS="$(RISCV_CFLAGS)" \ | |
$(abspath $(METAL_SOURCE_PATH)/configure) \ | |
--host=$(CROSS_COMPILE) \ | |
--prefix=$(METAL_PREFIX) \ | |
--libdir=$(METAL_LIB_DIR) \ | |
--disable-maintainer-mode \ | |
--with-preconfigured \ | |
--with-machine-name=$(TARGET) \ | |
--with-machine-header=$(abspath $(METAL_HEADER)) \ | |
--with-machine-inline=$(abspath $(METAL_INLINE)) \ | |
--with-platform-header=$(abspath $(PLATFORM_HEADER)) \ | |
--with-machine-ldscript=$(abspath $(METAL_LDSCRIPT)) \ | |
--with-builtin-libgloss | |
touch -c $@ | |
$(METAL_LIB_DIR)/stamp: $(BSP_DIR)/build/$(CONFIGURATION)/Makefile | |
$(MAKE) -C $(abspath $(BSP_DIR)/build/$(CONFIGURATION)) install | |
date > $@ | |
$(METAL_LIB_DIR)/libriscv%.a: $(METAL_LIB_DIR)/stamp ;@: | |
$(METAL_LIB_DIR)/libmetal.a: $(METAL_LIB_DIR)/libriscv__mmachine__$(TARGET).a | |
cp $< $@ | |
$(METAL_LIB_DIR)/libmetal-gloss.a: $(METAL_LIB_DIR)/libriscv__menv__metal.a | |
cp $< $@ | |
# If we're cleaning the last Metal library for a TARGET, then remove | |
# the install directory, otherwise just remove the built libs for that | |
# CONFIGURATION. | |
ifeq ($(words $(wildcard $(METAL_PREFIX)/lib/*)),1) | |
METAL_CLEAN = $(METAL_PREFIX) | |
else | |
METAL_CLEAN = $(METAL_LIB_DIR) | |
endif | |
.PHONY: clean-metal | |
clean-metal: | |
rm -rf $(METAL_CLEAN) | |
rm -rf $(METAL_BUILD_DIR) | |
clean: clean-metal | |
metal_install: metal | |
$(MAKE) -C $(METAL_SOURCE_PATH) install | |
upload: | |
$(FREEDOME_SDK)/scripts/upload --hex $(SRC_DIR)/debug/main.hex --jlink JLinkExe | |
ifneq ($(filter jlink,$(TARGET_TAGS)),) | |
debug: $(PROGRAM_ELF) | |
$(FREEDOME_SDK)/scripts/debug --elf $(PROGRAM_ELF) --jlink $(SEGGER_JLINK_GDB_SERVER) --gdb $(RISCV_GDB) | |
upload_debug: $(PROGRAM_ELF) | |
$(FREEDOME_SDK)/scripts/debug --elf $(PROGRAM_ELF) --jlink $(SEGGER_JLINK_GDB_SERVER) --gdb $(RISCV_GDB) | |
else | |
debug: $(PROGRAM_ELF) | |
$(FREEDOME_SDK)/scripts/debug --elf $(PROGRAM_ELF) --openocd $(RISCV_OPENOCD) --gdb $(RISCV_GDB) --openocd-config bsp/$(TARGET)/openocd.cfg | |
upload_debug: $(PROGRAM_ELF) | |
$(FREEDOME_SDK)/scripts/debug --elf $(PROGRAM_ELF) --openocd $(RISCV_OPENOCD) --gdb $(RISCV_GDB) --openocd-config bsp/$(TARGET)/openocd.cfg | |
endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment