# Copyright cocotb contributors
# Copyright (c) 2013 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

# Common Makefile for Aldec Riviera-PRO simulator

ifeq ($(GUI),1)
    CMD_BIN := riviera
else
    CMD_BIN := vsimsa
endif

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

ifeq ($(GUI),1)
    CMD += -nosplash
endif

ALOG_ARGS += -timescale $(COCOTB_HDL_TIMEUNIT)/$(COCOTB_HDL_TIMEPRECISION)

ifdef VERILOG_INCLUDE_DIRS
    ALOG_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
ALOG_ARGS += $(COMPILE_ARGS)
ACOM_ARGS += $(COMPILE_ARGS)
ASIM_ARGS += $(SIM_ARGS)

# Plusargs need to be passed to ASIM command not vsimsa
ASIM_ARGS += $(call deprecate,PLUSARGS,COCOTB_PLUSARGS)

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

# Pass the VPI library to the Verilog compilation to get extended checking.
ALOG_ARGS += -pli $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi riviera)

# Aldec-specific coverage types:
# - (s)tatement
# - (b)ranch
# - (e)xpression
# - (c)ondition
# - (a)ssertion
# - (p)ath
# - finite state (m)achine
# Documentation: Riviera Pro 2017.02 Documentation - Page 359
COVERAGE_TYPES ?= sb
ifeq ($(COCOTB_USER_COVERAGE),1)
    ALOG_ARGS += -dbg -coverage $(COVERAGE_TYPES)
    ACOM_ARGS += -dbg -coverage $(COVERAGE_TYPES)

    ASIM_ARGS += -dbg -acdb -acdb_cov $(COVERAGE_TYPES)
endif

GPI_EXTRA:=
ifeq ($(TOPLEVEL_LANG),verilog)
    GPI_ARGS = -pli $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi riviera)
ifneq ($(VHDL_SOURCES),)
    GPI_EXTRA = $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vhpi riviera):cocotbvhpi_entry_point
endif

else ifeq ($(TOPLEVEL_LANG),vhdl)
    GPI_ARGS = -loadvhpi $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vhpi riviera):vhpi_startup_routines_bootstrap
ifneq ($(VERILOG_SOURCES),)
    GPI_EXTRA = $(shell $(PYTHON_BIN) -m cocotb_tools.config --lib-name-path vpi riviera):cocotbvpi_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)] {adel -lib $(SIM_BUILD)/$(LIB) -all}" >> $@;
  echo "alib $(SIM_BUILD)/$(LIB)" >> $@;
  echo "amap $(LIB) $(SIM_BUILD)/$(LIB)" >> $@;
  echo "acom -work $(LIB) $(ACOM_ARGS) $(call to_tcl_path,$(VHDL_SOURCES_$(LIB)))" >> $@;
endef

# Create a TCL script based on the list of $(VERILOG_SOURCES)
$(SIM_BUILD)/runsim.tcl : $(VERILOG_SOURCES) $(VHDL_SOURCES) | $(SIM_BUILD)
	@echo "onerror {" > $@
	@echo "	puts [read [open sim.log r]]" >> $@
	@echo "	quit -code 1" >> $@
	@echo "}" >> $@
	@echo "amap -c" >> $@
	$(foreach LIB, $(VHDL_LIB_ORDER), $(make_lib))
	@echo "@if [string length [array get env LICENSE_QUEUE]] {" >> $@
	@echo " set LICENSE_QUEUE $$::env(LICENSE_QUEUE)" >> $@
	@echo "}" >> $@
	@echo "if [file exists $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)] {adel -lib $(SIM_BUILD)/$(TOPLEVEL_LIBRARYRTL_LIBRARY) -all}" >> $@;
	@echo "alib $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)" >> $@
	@echo "amap $(TOPLEVEL_LIBRARY) $(SIM_BUILD)/$(TOPLEVEL_LIBRARY)" >> $@;
	@echo "set worklib $(TOPLEVEL_LIBRARY)" >> $@;
ifneq ($(VHDL_SOURCES),)
	@echo "acom -work $(TOPLEVEL_LIBRARY) $(ACOM_ARGS) $(call to_tcl_path,$(VHDL_SOURCES))" >> $@
endif
ifneq ($(VERILOG_SOURCES),)
	@echo "alog -work $(TOPLEVEL_LIBRARY) $(ALOG_ARGS) $(call to_tcl_path,$(VERILOG_SOURCES))" >> $@
endif
ifdef SCRIPT_FILE
	@echo "do $(SCRIPT_FILE)" >> $@
endif
ifneq ($(CFG_TOPLEVEL),)
	@echo "asim $(ASIM_ARGS) +access +w_nets -interceptcoutput $(GPI_ARGS) $(CFG_TOPLEVEL) $(EXTRA_TOPS)" >> $@
else
	@echo "asim $(ASIM_ARGS) +access +w_nets -interceptcoutput $(GPI_ARGS) $(COCOTB_TOPLEVEL) $(EXTRA_TOPS)" >> $@
endif
ifeq ($(WAVES),1)
	@echo "log -recursive *" >> $@
endif
ifeq ($(GUI),1)
	@echo "wave -rec *" >> $@
else
	@echo "run -all" >> $@
	@echo "endsim" >> $@
ifeq ($(COCOTB_USER_COVERAGE),1)
	@echo "acdb report -cov $(COVERAGE_TYPES) -db $(TOPLEVEL_LIBRARY).acdb -html -o coverage/acdb_report.html" >> $@
	@echo "acdb report -cov $(COVERAGE_TYPES) -db $(TOPLEVEL_LIBRARY).acdb -txt -o coverage/acdb_report.txt" >> $@
endif
	@echo "exit" >> $@
endif

# Note it's the redirection of the output rather than the 'do' command
# that turns on batch mode (i.e. exit on completion/error)
$(COCOTB_RESULTS_FILE): $(SIM_BUILD)/runsim.tcl $(CUSTOM_COMPILE_DEPS) $(CUSTOM_SIM_DEPS)
	$(RM) $(COCOTB_RESULTS_FILE)

	set -o pipefail; GPI_EXTRA=$(GPI_EXTRA) TOPLEVEL_LANG=$(TOPLEVEL_LANG) \
	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) $(SIM_CMD_PREFIX) $(CMD) $(RUN_ARGS) -do $(SIM_BUILD)/runsim.tcl $(SIM_CMD_SUFFIX)

	$(call check_results)
