# the name of the program we're going to build
PROJECT = program
# this is a list of object files to generate.  Make will work out which to build from C and which from assembly
OBJECT_FILES = main.o init.o
# name of the Quartus program
FPGA_PROJECT = yarvi_fpga

# directory for output Memory Initialization Files
MIF_DIR = ..

# settings for the compilers
CC = riscv32-unknown-elf-gcc
AS = riscv32-unknown-elf-as
TARGET_ARCH = -m32 -march=RV32I
CFLAGS = -O0 $(TARGET_ARCH)
ASFLAGS =

# Lists of rules: the name of a file, followed by the files it depends on.
# When typing 'make' not followed by a rule name, the first rule is followed.  This rule depends on 
# everything, causing all the parts to be built

all: ${OBJECT_FILES} ${PROJECT} ${PROJECT}/${PROJECT}.bin \
	${MIF_DIR}/imem.mif  \
	${MIF_DIR}/dmem.0.mif ${MIF_DIR}/dmem.1.mif ${MIF_DIR}/dmem.2.mif ${MIF_DIR}/dmem.3.mif \
	${PROJECT}/${PROJECT}.dump

# how to build a .o file from a .c file
%.o: %.c
	$(CC) -c -o $@ $< $(CFLAGS)

# how to build a .o file from a .s file
%.o: %.s
	$(AS) -c -o $@ $< $(ASFLAGS)

${MIF_DIR}/imem.mif: ${PROJECT}/${PROJECT}.imem
	hexdump -v -e '"%08x\n"' $< | python txt2mif.py - $@ 32 1024
	
${PROJECT}/dmem.txt: ${PROJECT}/${PROJECT}.dmem
	hexdump -v -e '"%08x\n"' $< > $@
	
	
# Yarvi is little endian: in the simulation makefile the data memory
# was being generated as big endian
${MIF_DIR}/dmem.3.mif: ${PROJECT}/dmem.txt
	cut -b 1-2 $< | python txt2mif.py - $@ 8 1024

${MIF_DIR}/dmem.2.mif: ${PROJECT}/dmem.txt
	cut -b 3-4 $< | python txt2mif.py - $@ 8 1024

${MIF_DIR}/dmem.1.mif: ${PROJECT}/dmem.txt
	cut -b 5-6 $< | python txt2mif.py - $@ 8 1024

${MIF_DIR}/dmem.0.mif: ${PROJECT}/dmem.txt
	cut -b 7-8 $< | python txt2mif.py - $@ 8 1024


${PROJECT}:
	if [ ! -d "$@" ]; then \
		mkdir ${PROJECT}; \
	fi

${PROJECT}/${PROJECT}.imem: ${PROJECT}/${PROJECT}.bin
	riscv32-unknown-elf-objcopy -O binary --only-section=.text $< $@
	
${PROJECT}/${PROJECT}.dmem: ${PROJECT}/${PROJECT}.bin
	riscv32-unknown-elf-objcopy -O binary --pad-to=0x10001000 --only-section=DATA $< $@

${PROJECT}/${PROJECT}.bin: ${OBJECT_FILES}
	riscv32-unknown-elf-ld -o $@ -T prog-link.ld $^

${PROJECT}/${PROJECT}.dump: ${PROJECT}/${PROJECT}.bin
	riscv32-unknown-elf-objdump -S $< > $@

# update the memory files inside the FPGA bitfile
updatemif:	all
	cd ../.. && quartus_cdb ${FPGA_PROJECT} -c ${FPGA_PROJECT} --update_mif
	cd ../.. && quartus_asm --read_settings_files=on --write_settings_files=off ${FPGA_PROJECT} -c ${FPGA_PROJECT}

# download the bitfile to your board
download:
	cd ../../ && quartus_pgm -m jtag -o P\;output_files/${FPGA_PROJECT}.sof@2

# build the whole FPGA from the command line
# not that it's harder to spot warnings in this output compared with the GUI
build_fpga:
	cd ../.. && quartus_sh --flow compile ${FPGA_PROJECT}

# perform timing analysis.  This isn't that helpful since there isn't a nice GUI to navigate the results
timequest:
	cd ../.. && quartus_sta --read_settings_files=on --write_settings_files=off ${FPGA_PROJECT} -c ${FPGA_PROJECT}


# 'clean' rule: delete all the files so we can start afresh
clean:
	rm -rf ${PROJECT} ${PROJECT}.bin *.o ${MIF_DIR}/imem.mif ${MIF_DIR}/dmem.*.mif

