# Copyright (c) 2013, 2018 Potential Ventures Ltd
# Copyright (c) 2013 SolarFlare Communications Inc
# Licensed under the Revised BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-3-Clause

# Questa compatibility flow using the vlog and vsim commands with the +acc
# switch for design access.

CMD_BIN := vsim

ifdef MODELSIM_BIN_DIR
    CMD := $(shell :; command -v $(MODELSIM_BIN_DIR)/$(CMD_BIN) 2>/dev/null)
else
    # auto-detect bin dir from system path
    CMD := $(shell :; command -v $(CMD_BIN) 2>/dev/null)
	MODELSIM_BIN_DIR := $(shell dirname $(CMD))
endif

ifdef RTL_LIBRARY
    $(warning Using RTL_LIBRARY is deprecated, please use TOPLEVEL_LIBRARY instead.)
    TOPLEVEL_LIBRARY ?= $(RTL_LIBRARY)
else
    TOPLEVEL_LIBRARY ?= work
endif
COCOTB_TOPLEVEL := "$(TOPLEVEL_LIBRARY).$(COCOTB_TOPLEVEL)"

ifndef VLOG_ARGS
    VLOG_ARGS = -timescale $(COCOTB_HDL_TIMEUNIT)/$(COCOTB_HDL_TIMEPRECISION) -mfcu
endif

COMPILE_ARGS += +acc

ifdef VERILOG_INCLUDE_DIRS
    VLOG_ARGS += $(addprefix +incdir+, $(VERILOG_INCLUDE_DIRS))
endif

# below allows for maintaining legacy syntax as well as enables using cross-simulator vars COMPILE_ARGS/SIM_ARGS
VLOG_ARGS += $(COMPILE_ARGS)
VCOM_ARGS += $(COMPILE_ARGS)
VSIM_ARGS += $(SIM_ARGS)

ifeq ($(GUI),1)
    CMD += -gui
    VSIM_ARGS += -onfinish stop
else
    CMD += -c
    VSIM_ARGS += -onfinish exit
endif

FLI_LIB := $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path fli questa)
VHPI_LIB := $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vhpi questa)

GPI_EXTRA :=

VHDL_GPI_INTERFACE ?= fli

ifeq ($(filter vhpi fli,$(VHDL_GPI_INTERFACE)),)
    $(error A valid value (fli or vhpi) was not provided for VHDL_GPI_INTERFACE=$(VHDL_GPI_INTERFACE))
endif

ifeq ($(TOPLEVEL_LANG),vhdl)
    VSIM_ARGS += -t $(COCOTB_HDL_TIMEPRECISION)
ifeq ($(VHDL_GPI_INTERFACE),fli)
    CUSTOM_COMPILE_DEPS += $(FLI_LIB)
    VSIM_ARGS += -foreign \"cocotb_init $(FLI_LIB)\"
else
    VSIM_ARGS += -voptargs="-access=rw+/." -foreign \"vhpi_startup_routines_bootstrap $(call to_tcl_path,$(VHPI_LIB))\"
endif
ifneq ($(VERILOG_SOURCES),)
    GPI_EXTRA :=  $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi questa):cocotbvpi_entry_point
endif

else ifeq ($(TOPLEVEL_LANG),verilog)
    VSIM_ARGS += -pli $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi questa)
ifneq ($(VHDL_SOURCES),)
    GPI_EXTRA := $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path $(VHDL_GPI_INTERFACE) questa):cocotb$(VHDL_GPI_INTERFACE)_entry_point
endif

else
   $(error A valid value (verilog or vhdl) was not provided for TOPLEVEL_LANG=$(TOPLEVEL_LANG))
endif

define make_lib
  echo "if [file exists $(SIM_BUILD)/$(LIB)] {vdel -lib $(SIM_BUILD)/$(LIB) -all}" >> $@;
  echo "vlib $(SIM_BUILD)/$(LIB)" >> $@;
  echo "vmap $(LIB) $(SIM_BUILD)/$(LIB)" >> $@;
  echo "vcom -work $(LIB) $(VCOM_ARGS) $(call to_tcl_path,$(VHDL_SOURCES_$(LIB)))" >> $@;
endef

$(SIM_BUILD)/runsim.do : $(VHDL_SOURCES) $(VERILOG_SOURCES) $(CUSTOM_COMPILE_DEPS) $(CUSTOM_SIM_DEPS) | $(SIM_BUILD)
	# Make sure all libs in SOURCES_VHDL_* are mentioned in VHDL_LIB_ORDER and vice versa
	$(foreach LIB, $(VHDL_LIB_ORDER), $(check_vhdl_sources))
	$(foreach SOURCES_VAR, $(filter VHDL_SOURCES_%, $(.VARIABLES)), $(check_lib_order))

	@echo "# Autogenerated file" > $@
	@echo "onerror {" >> $@
	@echo "	quit -f -code 1" >> $@
	@echo "}" >> $@
	@echo "vmap -c" >> $@
	$(foreach LIB, $(VHDL_LIB_ORDER), $(make_lib))
	@echo "if [file exists $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)] {vdel -lib $(SIM_BUILD)/$(TOPLEVEL_LIBRARY) -all}" >> $@
	@echo "vlib $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)" >> $@
	@echo "vmap $(TOPLEVEL_LIBRARY) $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)" >> $@
ifneq ($(VHDL_SOURCES),)
	@echo "vcom -work $(TOPLEVEL_LIBRARY) $(VCOM_ARGS) $(call to_tcl_path,$(VHDL_SOURCES))" >> $@
endif
ifneq ($(VERILOG_SOURCES),)
	@echo "vlog -work $(TOPLEVEL_LIBRARY) -sv $(VLOG_ARGS) $(EXTRA_ARGS) $(call to_tcl_path,$(VERILOG_SOURCES))" >> $@
endif
ifdef SCRIPT_FILE
	@echo "do $(SCRIPT_FILE)" >> $@
endif
	@echo "vsim $(VSIM_ARGS) $(EXTRA_ARGS) $(call deprecate,PLUSARGS,COCOTB_PLUSARGS) $(COCOTB_TOPLEVEL)" >> $@
ifeq ($(WAVES),1)
	@echo "log -recursive /*" >> $@
endif
ifeq ($(GUI),1)
	@echo "add log -r *" >> $@
else
	@echo "onbreak resume" >> $@
	@echo "run -all" >> $@
	@echo "quit" >> $@
endif

ifeq ($(PYTHON_ARCH),64bit)
    CMD += -64
endif

$(COCOTB_RESULTS_FILE): $(SIM_BUILD)/runsim.do
	$(RM) $(COCOTB_RESULTS_FILE)

	set -o pipefail; \
	  COCOTB_TEST_MODULES=$(call deprecate,MODULE,COCOTB_TEST_MODULES) \
	  COCOTB_TESTCASE=$(call deprecate,TESTCASE,COCOTB_TESTCASE) \
	  COCOTB_TEST_FILTER=$(COCOTB_TEST_FILTER) \
	  COCOTB_TOPLEVEL=$(call deprecate,TOPLEVEL,COCOTB_TOPLEVEL) \
	  GPI_EXTRA=$(GPI_EXTRA) \
	  TOPLEVEL_LANG=$(TOPLEVEL_LANG) \
	  VHDL_GPI_INTERFACE=$(VHDL_GPI_INTERFACE) \
	  COCOTB__QUESTA_MODE=compat \
	$(SIM_CMD_PREFIX) $(CMD) $(RUN_ARGS) -do $(SIM_BUILD)/runsim.do $(call deprecate,PLUSARGS,COCOTB_PLUSARGS) $(SIM_CMD_SUFFIX)

	$(call check_results)
