# Copyright cocotb contributors
# Copyright (c) 2014 Potential Ventures Ltd
# Licensed under the Revised BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-3-Clause

TOPLEVEL_LANG ?= vhdl

ifneq ($(or $(filter-out $(TOPLEVEL_LANG),vhdl),$(VERILOG_SOURCES)),)

$(COCOTB_RESULTS_FILE):
	@echo "Skipping simulation as only VHDL is supported on simulator=$(SIM)"

else

CMD_BIN := ghdl

ifdef GHDL_BIN_DIR
    CMD := $(shell :; command -v $(GHDL_BIN_DIR)/$(CMD_BIN) 2>/dev/null)
else
    # auto-detect bin dir from system path
    CMD := $(shell :; command -v $(CMD_BIN) 2>/dev/null)
    GHDL_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
GHDL_ARGS ?=
GHDL_ARGS += $(EXTRA_ARGS)

# On Windows add GHDL lib folder to PATH to find libraries
ifeq ($(OS),Msys)
    export PATH := $(GHDL_BIN_DIR)/../lib:$(PATH)
endif

GHDL_RUN_ARGS ?=

ifeq ($(shell $(CMD) --version | grep -q mcode; echo $$?),0)
    ifneq ($(COCOTB_HDL_TIMEPRECISION),)
        # Convert the time precision to a format string supported by GHDL, if
        # possible.
        # GHDL only supports setting the time precision if the mcode backend is
        # used, using the --time-resolution argument causes GHDL to error out
        # otherwise.
        # https://ghdl.github.io/ghdl/using/InvokingGHDL.html#cmdoption-ghdl-time-resolution
        ifeq ($(COCOTB_HDL_TIMEPRECISION),1fs)
            GHDL_TIME_RESOLUTION=fs
        else ifeq ($(COCOTB_HDL_TIMEPRECISION),1ps)
            GHDL_TIME_RESOLUTION=ps
        else ifeq ($(COCOTB_HDL_TIMEPRECISION),1us)
            GHDL_TIME_RESOLUTION=us
        else ifeq ($(COCOTB_HDL_TIMEPRECISION),1ms)
            GHDL_TIME_RESOLUTION=ms
        else ifeq ($(COCOTB_HDL_TIMEPRECISION),1s)
            GHDL_TIME_RESOLUTION=sec
        else
            $(error GHDL only supports the following values for COCOTB_HDL_TIMEPRECISION: 1fs, 1ps, 1us, 1ms, 1s)
        endif

        GHDL_RUN_ARGS += --time-resolution=$(GHDL_TIME_RESOLUTION)
    endif
endif

.PHONY: analyse

# Compilation phase
analyse: $(VHDL_SOURCES) $(CUSTOM_COMPILE_DEPS) | $(SIM_BUILD)
	$(foreach SOURCES_VAR, $(filter VHDL_SOURCES_%, $(.VARIABLES)), \
		$(CMD) -i $(GHDL_ARGS) $(COMPILE_ARGS) --workdir=$(SIM_BUILD) --work=$(SOURCES_VAR:VHDL_SOURCES_%=%) $($(SOURCES_VAR)) && ) \
	$(CMD) -i $(GHDL_ARGS) $(COMPILE_ARGS) --workdir=$(SIM_BUILD) --work=$(TOPLEVEL_LIBRARY) $(VHDL_SOURCES) && \
	$(CMD) -m $(GHDL_ARGS) $(COMPILE_ARGS) --workdir=$(SIM_BUILD) -P$(SIM_BUILD) --work=$(TOPLEVEL_LIBRARY) $(COCOTB_TOPLEVEL) $(ARCH)

$(COCOTB_RESULTS_FILE): analyse $(CUSTOM_SIM_DEPS)
	$(RM) $(COCOTB_RESULTS_FILE)

	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) TOPLEVEL_LANG=$(TOPLEVEL_LANG) \
	$(SIM_CMD_PREFIX) $(CMD) -r $(GHDL_ARGS) $(GHDL_RUN_ARGS) --workdir=$(SIM_BUILD) -P$(SIM_BUILD) --work=$(TOPLEVEL_LIBRARY) $(COCOTB_TOPLEVEL) $(ARCH) --vpi=$(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi ghdl) $(SIM_ARGS) $(call deprecate,PLUSARGS,COCOTB_PLUSARGS) $(SIM_CMD_SUFFIX)

	$(call check_results)

endif
