Skip to content

Instantly share code, notes, and snippets.

@benmezger
Created July 21, 2019 17:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benmezger/697118613191b469d4a1c6b8559faee1 to your computer and use it in GitHub Desktop.
Save benmezger/697118613191b469d4a1c6b8559faee1 to your computer and use it in GitHub Desktop.
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