RISCV_PREFIX ?= riscv64-unknown-elf- CC := $(RISCV_PREFIX)gcc OBJCOPY := $(RISCV_PREFIX)objcopy OBJDUMP := $(RISCV_PREFIX)objdump READELF := $(RISCV_PREFIX)readelf NM := $(RISCV_PREFIX)nm SIZE := $(RISCV_PREFIX)size HOST_CC ?= cc LOCAL_RV_ENV := $(abspath ../../../../../edu/rv32i-hazard3-student-env) ifneq ($(wildcard /opt/rv-env/vendor/Hazard3/test/sim/common/init.S),) RV_ENV_ROOT ?= /opt/rv-env else RV_ENV_ROOT ?= $(LOCAL_RV_ENV) endif H3_ROOT ?= $(RV_ENV_ROOT)/vendor/Hazard3 H3_COMMON ?= $(H3_ROOT)/test/sim/common H3_INIT ?= $(H3_COMMON)/init.S LOCAL_H3_TB := $(H3_ROOT)/test/sim/tb_verilator/tb PREBUILT_H3_TB := $(abspath ../../freertos/lab-rv32i-freertos-c-scheduler/vendor/Hazard3/test/sim/tb_verilator/tb) H3_TB ?= $(if $(wildcard $(LOCAL_H3_TB)),$(LOCAL_H3_TB),$(if $(wildcard $(PREBUILT_H3_TB)),$(PREBUILT_H3_TB),$(LOCAL_H3_TB))) H3_TB_DIR ?= $(dir $(H3_TB)) PROFILE ?= observe ifeq ($(PROFILE),observe) OPTFLAGS := -O0 -fno-omit-frame-pointer -fno-inline -fno-optimize-sibling-calls DBGFLAGS := -g3 -ggdb else ifeq ($(PROFILE),debug) OPTFLAGS := -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls DBGFLAGS := -g3 -ggdb else ifeq ($(PROFILE),release) OPTFLAGS := -Os DBGFLAGS := else $(error PROFILE must be observe, debug or release) endif ARCH ?= rv32i_zicsr_zifencei ABI ?= ilp32 BUILD_ROOT ?= build HOST_BUILD_ROOT ?= host-build LINKER_SCRIPT := link/hazard3_c09.ld TASK01 := task01_libc_without_heap TASK02 := task02_malloc_requires_sbrk TASK03 := task03_bounded_sbrk TASK04 := task04_smalloc TASK05 := task05_picolibc_malloc SUCCESS_TASKS := $(TASK01) $(TASK03) $(TASK04) $(TASK05) RV_CFLAGS := -std=c11 -march=$(ARCH) -mabi=$(ABI) -nostdlib -nostartfiles \ -ffreestanding -fno-builtin -fno-stack-protector \ -ffunction-sections -fdata-sections $(OPTFLAGS) $(DBGFLAGS) \ -Wall -Wextra -Wpedantic -Werror -Isrc/runtime RV_LDFLAGS := -Wl,--no-relax -Wl,--gc-sections -T$(LINKER_SCRIPT) RV_LIBS := -Wl,--start-group -lc -lgcc -Wl,--end-group HOST_CFLAGS := -std=c11 -DC09_HOST=1 -DHOST_PRINTF=1 -fno-builtin \ $(OPTFLAGS) $(DBGFLAGS) -Wall -Wextra -Wpedantic -Werror -Isrc/runtime .PHONY: all tasks host check full-check clean check-support \ task1 task2 task3 task4 task5 t1 t2 t3 t4 t5 \ host-test expected-fail archive-map check-elf testbench hazard3-test card card-check all: tasks tasks: $(SUCCESS_TASKS) host: $(addprefix $(HOST_BUILD_ROOT)/,$(addsuffix /prog,$(SUCCESS_TASKS))) task1 t1: $(TASK01) task2 t2: expected-fail task3 t3: $(TASK03) task4 t4: $(TASK04) task5 t5: $(TASK05) check-support: @test -f "$(H3_INIT)" || { echo "Missing Hazard3 init.S: $(H3_INIT)" >&2; exit 1; } @test -f "$(LINKER_SCRIPT)" || { echo "Missing $(LINKER_SCRIPT)" >&2; exit 1; } define rv_task_rules $(1): $(BUILD_ROOT)/$(1)/prog.bin $(BUILD_ROOT)/$(1)/prog.lst $(BUILD_ROOT)/$(1)/prog.elf: crt0.S $(H3_INIT) $(LINKER_SCRIPT) $(2) | check-support mkdir -p $$(@D) $(CC) $(RV_CFLAGS) $(RV_LDFLAGS) -Wl,-Map,$(BUILD_ROOT)/$(1)/prog.map \ -o $$@ $(H3_INIT) crt0.S $(2) $(RV_LIBS) $(SIZE) -A -x $$@ $(BUILD_ROOT)/$(1)/prog.bin: $(BUILD_ROOT)/$(1)/prog.elf $(OBJCOPY) -O binary $$< $$@ $(BUILD_ROOT)/$(1)/prog.lst: $(BUILD_ROOT)/$(1)/prog.elf $(OBJDUMP) -d -S -M no-aliases,numeric $$< > $$@ $(HOST_BUILD_ROOT)/$(1)/prog: $(2) mkdir -p $$(@D) $(HOST_CC) $(HOST_CFLAGS) -o $$@ $(2) endef $(eval $(call rv_task_rules,$(TASK01),src/tasks/$(TASK01).c)) $(eval $(call rv_task_rules,$(TASK03),src/tasks/$(TASK03).c src/runtime/c09_bounded_sbrk.c)) $(eval $(call rv_task_rules,$(TASK04),src/tasks/$(TASK04).c src/runtime/c09_bounded_sbrk.c src/runtime/c09_smalloc.c)) $(eval $(call rv_task_rules,$(TASK05),src/tasks/$(TASK05).c)) $(BUILD_ROOT)/$(TASK02)/task.o: src/tasks/$(TASK02).c mkdir -p $(@D) $(CC) $(RV_CFLAGS) -c -o $@ $< expected-fail: $(BUILD_ROOT)/$(TASK02)/task.o | check-support @set -eu; \ log="$(BUILD_ROOT)/$(TASK02)/expected-link-failure.log"; \ elf="$(BUILD_ROOT)/$(TASK02)/must-not-exist.elf"; \ rm -f "$$elf" "$$log"; \ set +e; \ $(CC) $(RV_CFLAGS) $(RV_LDFLAGS) -Wl,--wrap=sbrk \ -Wl,-Map,$(BUILD_ROOT)/$(TASK02)/expected-link-failure.map \ -o "$$elf" $(H3_INIT) crt0.S $(BUILD_ROOT)/$(TASK02)/task.o \ $(RV_LIBS) >"$$log" 2>&1; \ status=$$?; \ set -e; \ if [ "$$status" -eq 0 ]; then \ echo "FAIL: Task02 unexpectedly linked" >&2; rm -f "$$elf"; exit 1; \ fi; \ test ! -e "$$elf"; \ grep -q "undefined reference to.*__wrap_sbrk" "$$log"; \ grep -q "libc_stdlib_malloc.c.o" "$$log"; \ echo "PASS Task02: controlled link failure (__wrap_sbrk missing)" host-test: host ./tests/test_host.sh --already-built archive-map: $(BUILD_ROOT)/$(TASK01)/prog.elf $(BUILD_ROOT)/$(TASK05)/prog.elf ./tests/check_archive_maps.sh check-elf: tasks ./tests/check_elf.sh testbench: @if [ ! -x "$(H3_TB)" ]; then $(MAKE) -C "$(H3_TB_DIR)"; fi @test -x "$(H3_TB)" hazard3-test: tasks testbench @set -eu; \ for task in $(SUCCESS_TASKS); do \ echo "RUN Hazard3 $$task"; \ "$(H3_TB)" --bin "$(abspath $(BUILD_ROOT))/$$task/prog.bin" \ --cycles 1000000 --cpuret; \ done card: ./scripts/build_new_card.sh GITEA_SHA=$${GITEA_SHA:-0000000000000000000000000000000000000000} \ ./scripts/render_new_pdf.sh card-check: card ./tests/check_card.sh check: host-test expected-fail archive-map check-elf full-check: check hazard3-test card-check clean: rm -rf $(BUILD_ROOT) $(HOST_BUILD_ROOT)