MAKEFLAGS      += -R -r

PROJECT		= max80
REVISIONS	= v1 v2 v2boot
QU        	= quartus

# Common options for all Quartus tools
QPRI    	= --lower_priority
QCPF		= $(QU)_cpf $(QPRI)
QSH		= $(QU)_sh  $(QPRI)
QSTA		= $(QU)_sta $(QPRI)
QPGM    	= $(QU)_pgm $(QPRI)

# Common options for Quartus in-flow tools
QOPT    	= --write_settings_files=off $(QPRI)
QMAP    	= $(QU)_map $(QOPT)
QFIT    	= $(QU)_fit $(QOPT)
QCDB    	= $(QU)_cdb $(QOPT)
QASM    	= $(QU)_asm $(QOPT)
QPOW    	= $(QU)_pow $(QOPT)

outdir		= output

PERL		= perl
PYTHON		= python
SED		= sed
GZIP		= gzip

SUBDIRS     = usb
PREREQFILES = $(outdir)/sram.mif \
	      $(foreach rev,$(REVISIONS),$(foreach coffmt,jic pof, \
		$(outdir)/$(rev).$(coffmt).cof))

alltarg := sof pof jic svf svf.gz xsvf xsvf.gz rbf rbf.gz \
	   rpd rpd.gz pow.rpt sta.rpt
allout   = $(foreach o,$(alltarg),$(outdir)/$(1).$(o))

sram_src = ../rv32/boot.bin

.SUFFIXES:

.SECONDARY:

.DELETE_ON_ERROR:

all:
	$(MAKE) prereq
	$(MAKE) $(foreach rev,$(REVISIONS),$(rev).targets)

-include $(foreach rev,$(REVISIONS),$(rev).deps)

.PHONY: $(REVISIONS)
$(REVISIONS):
	$(MAKE) prereq
	$(MAKE) $@.targets

.PHONY: %.targets
%.targets:
	$(MAKE) $(call allout,$*)

$(outdir)/%.map.rpt: %.qsf | $(outdir)/sram.bin
	$(QMAP) $(PROJECT) -c $*

$(outdir)/%.fit.rpt: $(outdir)/%.map.rpt
	$(QFIT) $(PROJECT) -c $*

$(outdir)/sram.bin: $(sram_src) $(all_map_deps)
	LC_ALL=C date | tr '\n' '\0' | cat $< - > $@

sram_depth  := 8192
sram_width  := 32
sram_stride := 1
$(outdir)/%.mif: $(outdir)/%.bin ../tools/bin2mif.pl
	$(PERL) ../tools/bin2mif.pl $< $@ $($*_depth) $($*_width) $($*_stride)

$(outdir)/%.mif_update.rpt: $(outdir)/%.fit.rpt
	[ -z '$($*_asm_deps)' ] || $(QCDB) --update_mif $(PROJECT) -c $*

$(outdir)/%.sof: $(outdir)/%.mif_update.rpt
	$(QASM) $(PROJECT) -c $*

$(outdir)/%.sta.rpt: $(outdir)/%.fit.rpt | $(outdir)/%.sof
	$(QSTA) $(PROJECT) -c $*

$(outdir)/%.pow.rpt: $(outdir)/%.sta.rpt
	$(QPOW) $(PROJECT) -c $*

$(foreach rev,$(REVISIONS),$(outdir)/$(rev).%.cof): %.cof.xml
	$(SED) -e 's/@@PROJECT@@/$(@F:.$*.cof=)/g' $< > $@

$(outdir)/%.jic: $(outdir)/%.jic.cof $(outdir)/%.sof ../rv32/dram.hex
	$(QCPF) -c $<

$(outdir)/%.pof: $(outdir)/%.pof.cof $(outdir)/%.sof
	$(QCPF) -c $<

# This produces a transient-load .svf file
$(outdir)/%.svf: $(outdir)/%.sof
	$(QCPF) -c -q 12.0MHz -g 3.3 -n p $< $@

# xsvf: compact representation of .svf; more or less a wrapper around
# the raw binary file.
$(outdir)/%.xsvf: $(outdir)/%.svf ../tools/svf2xsvf.py
	$(PYTHON) ../tools/svf2xsvf.py $< $@

# Raw Binary File, compact data for transient programming or for loading
# into flash (address 0); does *not* include the non-FPGA code; load
# ../rv32/dram.{bin,bin.gz,hex} for that.
$(outdir)/%.rbf: $(outdir)/%.sof
	$(QCPF) -c $< $@

# Raw Programmer Data, for loading into flash, includes all contents
# but is rather large if not compressed.
$(outdir)/%.rpd: $(outdir)/%.pof
	$(QCPF) -c $< $@

$(outdir)/%.gz: $(outdir)/%
	$(GZIP) -9 < $< > $@

# Prerequisite directories and files
prereq:
	mkdir -p $(outdir)
	$(MAKE) $(PREREQFILES)
	for d in $(SUBDIRS); do $(MAKE) -C $$d; done

# Clean out SignalTap
signalclean:
	for f in *.qsf; do \
		$(PERL) -ne 'print unless (/(SIGNALTAP_FILE\b|\bENABLE_SIGNALTAP\b|\bSLD_FILE\b|SLD_NODE_)/);' < $$f > $$f.tmp && \
		mv -f $$f.tmp $$f ; \
	done

# Programming targets. Environment JTAG_CABLE can override the default,
# which is otherwise the first cable found.
rpar := )
JTAG_CABLE ?= $(shell jtagconfig --enum | sed -ne 's/^1$(rpar) //p')

# Transient programming
program-%: $(outdir)/%.sof
	$(QPGM) -c '$(JTAG_CABLE)' -m JTAG -o 'p;$(outdir)/$*.sof'

# Permanent programming in flash
flash-%: $(outdir)/%.jic
	$(QPGM) -c '$(JTAG_CABLE)' -m JTAG -i -o 'pvbi;$(outdir)/$*.jic'

%.deps: %.qsf scripts/qsfdeps.pl
	$(PERL) scripts/qsfdeps.pl $* $@ $<

clean:
	for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done
	rm -rf db incremental_db simulation/modelsim \
	greybox_tmp */greybox_tmp iodevs.vh output_files
	for d in $(REVISIONS); do \
		$$d/*.rpt $$d/*.rpt $$d/*.summary $$d/*.smsg  \
		$$d/*.htm $$d/*.htm_files $$d/*.map $$d/*.eqn $$d/*.sld \
		$$d/*.done ; \
	done

spotless:
	for d in $(SUBDIRS); do $(MAKE) -C $$d spotless; done
	rm -rf $(outdir) *.deps *~ \#*~

iodevs.vh: ../iodevs.conf ../tools/iodevs.pl
	$(PERL) ../tools/iodevs.pl v $< $@

deps: Makefile

# Verilog header dependencies
max80.sv: iodevs.vh
