# Servant inside a FPGA inside a FPGA -- a Gowin FPGA modelled tile by tile, built for a Digilent Arty A7-100T,
# configured over the USB-UART with a Gowin bitstream: SERV (a RISC-V) prints "Hi, I'm Servant!".  README.md says more.
#
#   make run          the menu: program the Arty, then load "Hi, I'm Servant!" or the LED blinker into the
#                     emulated Gowin (another choice is loaded into the running fabric); DESIGN=servtiny|blinky
#   make prog-arty    step 1: program the Arty's FPGA with the emulated Gowin FPGA (bit/top.bit; = make prog)
#   make prog-gowin   step 2: program the Gowin FPGA inside it -- DESIGN=servtiny|blinky, or FS=x.fs PNR=pnr.json;
#                     repeatable: each one resets the emulated Gowin first (the SYNC word) and loads anew
#   make reset-gowin  reset the emulated Gowin to a blank chip (an empty configuration); then prog-gowin again
#   make load         shift a configuration into the fabric and listen  (CFG=cfg/servtiny: the shipped one)
#   make listen       only listen on the USB-UART at the design's baud rate
#   make bit          rebuild bit/top.bit with Vivado from vivado/  (about 40 minutes)
#
# NEW BITSTREAMS (the open Gowin toolchain, built from source and patched -- README "Your own designs"):
#   make toolchain    build yosys, nextpnr, apycula into $(TOOLS) from source, with the patches in chipdb/patches
#   make servtiny     build designs/servant's servtiny.fs again (SERV is cloned at its pinned commit)
#   make cfg FS=x.fs PNR=pnr.json   turn a .fs for GW1NZ-1-trim10-s2 into a configuration in cfg/<name>/ (PNR:
#                     nextpnr's routed json -- opens the unused default connections that ring in the emulation)
#   make load-fs FS=x.fs   both: cfg, then load it
#
# SERIAL=<ftdi serial> picks one Arty of several, TTY=/dev/ttyUSBn its port, SECS= how long to listen.
TOOLS  ?= $(HOME)/opt/gowin-tools
TSRC   ?= $(HOME)/git/gowin-tools
SERV   ?= $(CURDIR)/designs/serv
CFG    ?= cfg/servtiny
DESIGN ?=
SECS   ?= 20
FS     ?=
PNR    ?=
GEN    := gen/gw1nz_1_trim10_s2_c
NF     := $(shell wc -l < $(GEN)/fuses.txt)
PY     ?= $(if $(wildcard $(TOOLS)/venv/bin/python),$(TOOLS)/venv/bin/python,python3)
export SERIAL TTY

help:
	@sed -n '1,/^TOOLS/p' Makefile | grep '^#' | sed 's/^# \{0,1\}//'
run:
	@sh scripts/run.sh . $(DESIGN)
prog:
	@sh scripts/prog.sh .
# the two layers by name: the Arty's FPGA first (once), then the Gowin FPGA inside it (as often as you like)
prog-arty: prog
reset-gowin:
	@sh scripts/load.sh . --reset $(NF) 0
prog-gowin:
	@if [ -n "$(FS)" ]; then $(MAKE) --no-print-directory load-fs FS=$(FS) PNR=$(PNR); \
	 else sh scripts/load.sh . cfg/$(or $(DESIGN),servtiny) $(NF) $(SECS); fi
load:
	@sh scripts/load.sh . $(CFG) $(NF) $(SECS)
listen:
	@sh scripts/load.sh . - $(NF) $(SECS)
bit:
	$(MAKE) -C vivado synth
	cp vivado/top.bit bit/top.bit
toolchain:
	sh toolchain/build.sh $(TSRC) $(TOOLS)
servtiny:
	@[ -d $(SERV) ] || git clone -q https://github.com/olofk/serv.git $(SERV)
	git -C $(SERV) checkout -q f200eb2
	$(MAKE) -C designs/servant servtiny TOOLS=$(TOOLS) SERV=$(SERV) OUT=$(CURDIR)/out/servtiny \
	  FAMILY=GW1NZ-1-trim10-s2 CST=servant_crop.cst MEMSIZE=1024 SEED=2
	@echo "== out/servtiny/servant_gw1nz.fs -- make load-fs FS=out/servtiny/servant_gw1nz.fs PNR=out/servtiny/pnr.json"
cfg:
	@[ -n "$(FS)" ] || { echo "make cfg FS=design.fs"; exit 1; }
	@mkdir -p cfg/$(basename $(notdir $(FS)))
	$(PY) -I chipdb/fs_to_fuses.py $(if $(PNR),--pnr $(PNR)) $(GEN) $(FS) cfg/$(basename $(notdir $(FS)))/$(basename $(notdir $(FS))).hex
	@echo "== cfg/$(basename $(notdir $(FS)))/: the configuration bits and the block RAM rows"
load-fs: cfg
	@sh scripts/load.sh . cfg/$(basename $(notdir $(FS))) $(NF) $(SECS)
.PHONY: help run prog prog-arty prog-gowin reset-gowin load listen bit toolchain servtiny cfg load-fs
