.PHONY: default clean lint

# =========================
# DIRECTORIES
# =========================
RTL_DIR  = ../rtl
OBJ_DIR  = obj_dir
LOG_DIR  = logs

VERILATOR = verilator
VERILATOR_FLAGS = -Wall -Wno-fatal -trace -cc -I$(RTL_DIR)

# =========================
# COMMON RTL LIST
# =========================
RTL_COMMON = \
    $(RTL_DIR)/buffer.sv \
    $(RTL_DIR)/control_regs.sv \
    $(RTL_DIR)/debounce.sv \
    $(RTL_DIR)/font8x16_rom.sv \
    $(RTL_DIR)/frame_buffer_avmm.sv \
    $(RTL_DIR)/meta_buffer_avmm.sv \
    $(RTL_DIR)/vga_display.sv \
    $(RTL_DIR)/vga_counters.sv \
    $(RTL_DIR)/hex7seg.sv \
    $(RTL_DIR)/ov7670_top.sv \
    $(RTL_DIR)/ov7670_config.sv \
    $(RTL_DIR)/ov7670_SCCB.sv \
    $(RTL_DIR)/ov7670_CommandSet.sv \
    $(RTL_DIR)/ov7670_RGBRcrv.sv \
    $(RTL_DIR)/vga_ball.sv \
    $(RTL_DIR)/soc_system_bb.v

# =========================
# DEFAULT
# =========================
default:
	@echo "Targets:"
	@echo "  make buffer.vcd"
	@echo "  make control_regs.vcd"
	@echo "  make frame_buffer_avmm.vcd"
	@echo "  make meta_buffer_avmm.vcd"
	@echo "  make debounce.vcd"
	@echo "  make font8x16_rom.vcd"
	@echo "  make vga_display.vcd"
	@echo "  make lint"
	@echo "  make clean"

# =========================
# LINT
# =========================
lint:
	@mkdir -p $(LOG_DIR)
	$(VERILATOR) --lint-only -Wall $(RTL_COMMON) \
		2>&1 | tee $(LOG_DIR)/lint.log

# ============================================================
# BUFFER
# ============================================================
$(OBJ_DIR)/Vbuffer: buffer.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/buffer.sv \
		--top-module buffer \
		--exe buffer.cpp \
		2>&1 | tee $(LOG_DIR)/build_buffer.log
	cd $(OBJ_DIR) && make -f Vbuffer.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_buffer.log

buffer.vcd: $(OBJ_DIR)/Vbuffer
	$(OBJ_DIR)/Vbuffer \
		2>&1 | tee $(LOG_DIR)/run_buffer.log

# ============================================================
# CONTROL REGISTERS
# ============================================================
$(OBJ_DIR)/Vcontrol_regs: control_regs.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/control_regs.sv \
		--top-module control_regs \
		--exe control_regs.cpp \
		2>&1 | tee $(LOG_DIR)/build_control_regs.log
	cd $(OBJ_DIR) && make -f Vcontrol_regs.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_control_regs.log

control_regs.vcd: $(OBJ_DIR)/Vcontrol_regs
	$(OBJ_DIR)/Vcontrol_regs \
		2>&1 | tee $(LOG_DIR)/run_control_regs.log

# ============================================================
# FRAME BUFFER
# ============================================================
$(OBJ_DIR)/Vframe_buffer_avmm: frame_buffer_avmm.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/frame_buffer_avmm.sv \
		$(RTL_DIR)/buffer.sv \
		--top-module frame_buffer_avmm \
		--exe frame_buffer_avmm.cpp \
		2>&1 | tee $(LOG_DIR)/build_frame_buffer.log
	cd $(OBJ_DIR) && make -f Vframe_buffer_avmm.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_frame_buffer.log

frame_buffer_avmm.vcd: $(OBJ_DIR)/Vframe_buffer_avmm
	$(OBJ_DIR)/Vframe_buffer_avmm \
		2>&1 | tee $(LOG_DIR)/run_frame_buffer.log

# ============================================================
# META BUFFER
# ============================================================
$(OBJ_DIR)/Vmeta_buffer_avmm: meta_buffer_avmm.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/meta_buffer_avmm.sv \
		$(RTL_DIR)/buffer.sv \
		--top-module meta_buffer_avmm \
		--exe meta_buffer_avmm.cpp \
		2>&1 | tee $(LOG_DIR)/build_meta_buffer.log
	cd $(OBJ_DIR) && make -f Vmeta_buffer_avmm.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_meta_buffer.log

meta_buffer_avmm.vcd: $(OBJ_DIR)/Vmeta_buffer_avmm
	$(OBJ_DIR)/Vmeta_buffer_avmm \
		2>&1 | tee $(LOG_DIR)/run_meta_buffer.log

# ============================================================
# DEBOUNCE
# ============================================================
$(OBJ_DIR)/Vdebounce: debounce.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/debounce.sv \
		--top-module debounce \
		--exe debounce.cpp \
		2>&1 | tee $(LOG_DIR)/build_debounce.log
	cd $(OBJ_DIR) && make -f Vdebounce.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_debounce.log

debounce.vcd: $(OBJ_DIR)/Vdebounce
	$(OBJ_DIR)/Vdebounce \
		2>&1 | tee $(LOG_DIR)/run_debounce.log

# ============================================================
# FONT ROM
# ============================================================
$(OBJ_DIR)/Vfont8x16_rom: font8x16_rom.cpp
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_DIR)/font8x16_rom.sv \
		--top-module font8x16_rom \
		--exe font8x16_rom.cpp \
		2>&1 | tee $(LOG_DIR)/build_font.log
	cd $(OBJ_DIR) && make -f Vfont8x16_rom.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_font.log

font8x16_rom.vcd: $(OBJ_DIR)/Vfont8x16_rom
	$(OBJ_DIR)/Vfont8x16_rom \
		2>&1 | tee $(LOG_DIR)/run_font.log

# ============================================================
# VGA DISPLAY 
# ============================================================
$(OBJ_DIR)/Vov7670_top: vga_display.cpp $(RTL_COMMON)
	@mkdir -p $(OBJ_DIR) $(LOG_DIR)
	$(VERILATOR) $(VERILATOR_FLAGS) \
		$(RTL_COMMON) \
		--top-module ov7670_top \
		--exe vga_display.cpp \
		2>&1 | tee $(LOG_DIR)/build_vga_display.log
	cd $(OBJ_DIR) && make -f Vov7670_top.mk \
		2>&1 | tee ../$(LOG_DIR)/compile_vga_display.log

vga_display.vcd: $(OBJ_DIR)/Vov7670_top
	$(OBJ_DIR)/Vov7670_top \
		2>&1 | tee $(LOG_DIR)/run_vga_display.log

# =========================
# CLEAN
# =========================
clean:
	rm -rf $(OBJ_DIR) $(LOG_DIR) *.vcd