# #############################################################################
# Copyright (c) 2013 Benjamin Krill <benjamin@krll.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# #############################################################################
PROJECT_DEFAULT = atlys_sig
PROJECT_NAME   ?= $(PROJECT_DEFAULT)
PROJECT_DIR     = $(PROJECT_NAME)_build
PROJECT_SRC     = ../src
PROJECT_SRC_TOP = $(PROJECT_SRC)/top
PROJECT_UCF     = $(PROJECT_SRC_TOP)/$(PROJECT_NAME).ucf

##### BUILD FLAGS #############################
FPGA_PART       = $(shell grep FPGA_PART $(PROJECT_UCF) | cut -d'=' -f2)
XST_FLAGS       = -intstyle silent
NGDBUILD_FLAGS  = -intstyle silent -dd _ngo
NGDBUILD_FLAGS += $(if $(PROJECT_UCF),-uc ../,)$(PROJECT_UCF)
MAP_FLAGS       = -intstyle silent -w -logic_opt off -ol high -t 1 -xt 0 -register_duplication off -r 4 \
                  -global_opt off -mt off -ir off -pr off -lc off -power off
PAR_FLAGS       = -w -intstyle silent -ol high -mt off
TRCE_FLAGS      = -intstyle silent -v 3 -s 3 -n 3 -fastpaths
BITGEN_FLAGS    = -intstyle silent

##### SOURCE FILES ############################
COMMON_SRCS =  $(PROJECT_SRC)/snippets/vhdl/rrarbiter.vhd

FX2_TOP_DIR = ../../fx2/fpga
USB_NGCS = $(FX2_TOP_DIR)/vendor/xilinx/usb_fifo_tx.ngc $(FX2_TOP_DIR)/vendor/xilinx/usb_fifo_rx.ngc \
           $(FX2_TOP_DIR)/vendor/xilinx/usb_fifo_tx_fin.ngc
USB_SRCS = $(FX2_TOP_DIR)/f2p/strm_package.vhd $(FX2_TOP_DIR)/f2p/f2p_master.vhd \
           $(FX2_TOP_DIR)/f2p/f2p_strm_top.vhd $(FX2_TOP_DIR)/strm_ddr2/strm_ddr2.vhd \
	   $(FX2_TOP_DIR)/strm_regfile/strm_regfile.vhd

DVI_TOP_DIR = $(PROJECT_SRC)/dvi
DVI_SRCS = $(DVI_TOP_DIR)/dvi_package.vhd $(DVI_TOP_DIR)/serdes_1_to_5_diff_data.vhd $(DVI_TOP_DIR)/DRAM16XN.vhd \
           $(DVI_TOP_DIR)/phsaligner.vhd $(DVI_TOP_DIR)/chnlbond.vhd $(DVI_TOP_DIR)/serdes_n_to_1.vhd \
           $(DVI_TOP_DIR)/encoder.vhd $(DVI_TOP_DIR)/decoder.vhd $(DVI_TOP_DIR)/convert_30to15_fifo.vhd \
           $(DVI_TOP_DIR)/dvi_encoder.vhd $(DVI_TOP_DIR)/dvi_decoder.vhd

I2C_TOP_DIR = $(PROJECT_SRC)/i2c
I2C_SRCS = $(I2C_TOP_DIR)/slave/i2c_slave.vhd $(I2C_TOP_DIR)/slave/i2c_rom.vhd

DDR2_TOP_DIR = $(PROJECT_SRC)/vendor/xilinx/atlys_ddr2/ddr2/user_design/rtl/
DDR2_SRCS = $(DDR2_TOP_DIR)/iodrp_controller.vhd $(DDR2_TOP_DIR)/mcb_raw_wrapper.vhd \
            $(DDR2_TOP_DIR)/iodrp_mcb_controller.vhd $(DDR2_TOP_DIR)/mcb_soft_calibration_top.vhd \
            $(DDR2_TOP_DIR)/mcb_soft_calibration.vhd $(DDR2_TOP_DIR)/memc3_infrastructure.vhd \
            $(DDR2_TOP_DIR)/memc3_wrapper.vhd $(DDR2_TOP_DIR)/ddr2.vhd

SIG_TOP_DIR = $(PROJECT_SRC)/sig
SIG_NGCS = $(PROJECT_SRC)/vendor/xilinx/px_fifo.ngc
SIG_SRCS = $(SIG_TOP_DIR)/sig_read.vhd $(SIG_TOP_DIR)/sig_write.vhd $(SIG_TOP_DIR)/sig.vhd \
           $(SIG_TOP_DIR)/ddr2dvi.vhd $(SIG_TOP_DIR)/dvi2ddr.vhd

NGCS = $(USB_NGCS) $(SIG_NGCS)
SRCS = $(NGCS:%.ngc=%.vhd) \
       $(COMMON_SRCS) \
       $(DVI_SRCS) \
       $(I2C_SRCS) \
       $(DDR2_SRCS) \
       $(USB_SRCS) \
       $(SIG_SRCS) \
       $(PROJECT_SRC_TOP)/$(PROJECT_NAME).vhd

##### RUN SCRIPTS #############################
define XST_SCRIPT
set -tmpdir "tmp"
set -xsthdpdir "xst"
run
-ifn $(PROJECT_NAME).prj
-ofn $(PROJECT_NAME)
-ofmt NGC
-p $(FPGA_PART)
-top $(PROJECT_NAME)
-opt_mode Speed
-opt_level 1
-power NO
-iuc NO
-keep_hierarchy No
-netlist_hierarchy As_Optimized
-rtlview Yes
-glob_opt AllClockNets
-read_cores YES
-write_timing_constraints NO
-cross_clock_analysis NO
-hierarchy_separator /
-bus_delimiter <>
-case Maintain
-slice_utilization_ratio 100
-bram_utilization_ratio 100
-dsp_utilization_ratio 100
-lc Auto
-reduce_control_sets Auto
-fsm_extract YES -fsm_encoding Auto
-safe_implementation No
-fsm_style LUT
-ram_extract Yes
-ram_style Auto
-rom_extract Yes
-shreg_extract YES
-rom_style Auto
-auto_bram_packing NO
-resource_sharing YES
-async_to_sync NO
-shreg_min_size 2
-use_dsp48 Auto
-iobuf YES
-max_fanout 100000
-bufg 16
-register_duplication YES
-register_balancing NO
-optimize_primitives NO
-use_clock_enable Auto
-use_sync_set Auto
-use_sync_reset Auto
-iob Auto
-equivalent_register_removal YES
-slice_utilization_ratio_maxmargin 5
endef
export XST_SCRIPT

define BITGEN_FILE
-w
-g DebugBitstream:No
-g Binary:no
-g CRC:Enable
-g Reset_on_err:No
-g ConfigRate:2
-g ProgPin:PullUp
-g TckPin:PullUp
-g TdiPin:PullUp
-g TdoPin:PullUp
-g TmsPin:PullUp
-g UnusedPin:PullDown
-g UserID:0xFFFFFFFF
-g ExtMasterCclk_en:No
-g SPI_buswidth:1
-g TIMER_CFG:0xFFFF
-g multipin_wakeup:No
-g StartUpClk:CClk
-g DONE_cycle:4
-g GTS_cycle:5
-g GWE_cycle:6
-g LCK_cycle:NoWait
-g Security:None
-g DonePipe:Yes
-g DriveDone:No
-g en_sw_gsr:No
-g drive_awake:No
-g sw_clk:Startupclk
-g sw_gwe_cycle:5
-g sw_gts_cycle:4
endef
export BITGEN_FILE

##### PRINT ###################################
PW=\033[1m\033[0m
GR=\E[40;32m
WH=\E[40;37m
B=\033[1m
pr_info = "$(B) $(GR)[$(1)]\t $(WH)$(2)$(PW)"

TARGETS = build help prep syn ngd map par trce bit flash clean
VAR_TARGETS = $(PROJECT_DIR)/tmp  $(PROJECT_DIR)/$(PROJECT_NAME).ngc $(PROJECT_DIR)/$(PROJECT_NAME).ngd \
	       $(PROJECT_DIR)/$(PROJECT_NAME)_map.ncd $(PROJECT_DIR)/$(PROJECT_NAME).pcf \
	       $(PROJECT_DIR)/$(PROJECT_NAME).ncd $(PROJECT_DIR)/$(PROJECT_NAME).twr \
	       $(PROJECT_DIR)/$(PROJECT_NAME).bit
##### BUILD RULES #############################
.SILENT: help $(if $(V),,$(TARGETS) $(VAR_TARGETS))
.PHONY: $(TARGETS)

help:
	echo -e "$$ make PROJECT_NAME=<top-file> <rule> [V=1]"
	echo -e "\tprojects (*=default) .. : $(subst $(PROJECT_DEFAULT),*$(PROJECT_DEFAULT),$(subst $(PROJECT_SRC_TOP)/,,$(subst .ucf,,$(wildcard $(PROJECT_SRC_TOP)/*.ucf))))"
	echo -e "\trule .................. : $(TARGETS)"
	echo -e "\tV ..................... : verbose"

prep $(PROJECT_DIR)/tmp: $(SRCS)
	echo -e $(call pr_info,PREP,Build ENV for $(PROJECT_NAME))
	mkdir -p $(PROJECT_DIR)/tmp
	rm -f $(PROJECT_DIR)/$(PROJECT_NAME).prj
	for s in $(SRCS); do \
		if [ "$${s##*.}" = "vhd" ]; then echo "vhdl work \"../$$s\"" >> $(PROJECT_DIR)/$(PROJECT_NAME).prj; fi; \
		if [ "$${s##*.}" = "v"   ]; then echo "verilog work \"../$$s\"" >> $(PROJECT_DIR)/$(PROJECT_NAME).prj; fi; \
	done
	echo "$$XST_SCRIPT" > $(PROJECT_DIR)/$(PROJECT_NAME).xst

syn $(PROJECT_DIR)/$(PROJECT_NAME).ngc: $(PROJECT_DIR)/tmp
	echo -e $(call pr_info,NGC,Link prebuild IP Cores)
	for n in $(NGCS); do ln -sf ../$$n $(PROJECT_DIR)/${n##*/}; done
	echo -e $(call pr_info,XST,Synthesis)
	cd $(PROJECT_DIR) && xst $(XST_FLAGS) -ifn $(PROJECT_NAME).xst -ofn $(PROJECT_NAME).syr

ngd $(PROJECT_DIR)/$(PROJECT_NAME).ngd: $(PROJECT_DIR)/$(PROJECT_NAME).ngc $(PROJECT_UCF)
	echo -e $(call pr_info,NGD,Native Generic Database)
	cd $(PROJECT_DIR) && ngdbuild $(NGDBUILD_FLAGS) -p $(FPGA_PART) $(PROJECT_NAME).ngc $(PROJECT_NAME).ngd

map $(PROJECT_DIR)/$(PROJECT_NAME)_map.ncd $(PROJECT_DIR)/$(PROJECT_NAME).pcf: $(PROJECT_DIR)/$(PROJECT_NAME).ngd
	echo -e $(call pr_info,MAP,Mapping Logic)
	cd $(PROJECT_DIR) && map $(MAP_FLAGS) -p $(FPGA_PART) -o $(PROJECT_NAME)_map.ncd $(PROJECT_NAME).ngd $(PROJECT_NAME).pcf

par $(PROJECT_DIR)/$(PROJECT_NAME).ncd: $(PROJECT_DIR)/$(PROJECT_NAME)_map.ncd $(PROJECT_DIR)/$(PROJECT_NAME).pcf
	echo -e $(call pr_info,PAR,Place and Route)
	cd $(PROJECT_DIR) && par $(PAR_FLAGS) $(PROJECT_NAME)_map.ncd $(PROJECT_NAME).ncd $(PROJECT_NAME).pcf

trce $(PROJECT_DIR)/$(PROJECT_NAME).twr: $(PROJECT_DIR)/$(PROJECT_NAME).ncd
	echo -e $(call pr_info,TRCE,Timing analyzes)
	cd $(PROJECT_DIR) && trce $(TRCE_FLAGS) -xml $(PROJECT_NAME).twx $(PROJECT_NAME).ncd -o $(PROJECT_NAME).twr $(PROJECT_NAME).pcf

bit build $(PROJECT_DIR)/$(PROJECT_NAME).bit: $(PROJECT_DIR)/$(PROJECT_NAME).ncd $(PROJECT_DIR)/$(PROJECT_NAME).twr
	echo -e $(call pr_info,BITG,Bitfile Generation)
	echo "$$BITGEN_FILE" > $(PROJECT_DIR)/$(PROJECT_NAME).ut
	cd $(PROJECT_DIR) && bitgen $(BITGEN_FLAGS) -f $(PROJECT_NAME).ut $(PROJECT_NAME).ncd

flash: $(PROJECT_DIR)/$(PROJECT_NAME).bit
	echo -e "setmode -bs\nsetCable -p auto\nIdentify -inferir\nidentifyMPM\nassignFile -p 1 -file "$$PWD/$(PROJECT_DIR)/$(PROJECT_NAME).bit"\nprogram -p 1\nquit\n" | impact -batch

clean:
	echo -e $(call pr_info,RM,delete project directory)
	rm -rf $(PROJECT_DIR)
