# -*- Makefile -*-
#*****************************************************************************
#
# DESCRIPTION: Verilator: Makefile for verilog source
#
# Code available from: https://verilator.org
#
#*****************************************************************************
#
# Copyright 2003-2025 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
#
#****************************************************************************/

#### Start of system configuration section. ####

# Unfortunately configure uses relative paths, and this makefile is called
# from a level lower, so we need to move up if it's relative, not if absolute.
config_srcdir = @srcdir@
ifeq ($(config_srcdir),.)
 srcdir = ..
else  # Run an experiment
 ifeq ($(wildcard $(config_srcdir)/../Makefile_obj.in),)
   srcdir = $(config_srcdir)
 else
   srcdir = $(config_srcdir)/..
 endif
endif

incdir = $(srcdir)/../include
# Bldsrc may differ from srcdir if configure wan't run from the kit top
bldsrc = ..

# Programs
CC = @CC@
CXX = @CXX@
LINK = @CXX@
LEX = @LEX@
LFLAGS = -d
PYTHON3 = @PYTHON3@
YACC = @YACC@
OBJCACHE ?= @OBJCACHE@

prefix = @prefix@

# Directory in which to install data across multiple architectures
datarootdir = @datarootdir@

# Directory in which to install package-specific files
# Generally ${prefix}/share/verilator
pkgdatadir = @pkgdatadir@

# Compile options
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CFG_WITH_SOLVER = @CFG_WITH_SOLVER@
CPPFLAGS += @CPPFLAGS@
CFLAGS += @CFLAGS@
CXXFLAGS += @CXXFLAGS@
LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@
CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
# Compiler flags that turn on extra warnings
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
CFG_LDFLAGS_SRC = @CFG_LDFLAGS_SRC@
CFG_LIBS = @CFG_LIBS@
CFG_CXXFLAGS_PCH = -x c++-header
# Compiler option to put in front of filename to read precompiled header
CFG_CXXFLAGS_PCH_I = @CFG_CXXFLAGS_PCH_I@
# Compiler's filename prefix for precompiled headers, .gch if clang, empty if GCC
CFG_GCH_IF_CLANG = @CFG_GCH_IF_CLANG@

#### End of system configuration section. ####

VPATH += . $(bldsrc) $(srcdir)
TGT = ../../verilator_bin$(EXEEXT)

#################
ifeq ($(VL_NOOPT),1)
CPPFLAGS += -O0
else ifeq ($(VL_DEBUG),)
# Optimize
CPPFLAGS += -O3
else
# Debug
CPPFLAGS += @CFG_CXXFLAGS_DEBUG@ -DVL_DEBUG -D_GLIBCXX_DEBUG
LDFLAGS += @CFG_LDFLAGS_DEBUG@
endif
#################

#LIBS += -ldl
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl

# -lfl not needed as Flex invoked with %nowrap option
LIBS = $(CFG_LIBS) -lm

CPPFLAGS += -DVERILATOR_INTERNAL_
CPPFLAGS += -MMD
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) -I../../include
#CPPFLAGS += -DVL_LEAK_CHECKS  # If running valgrind or other hunting tool
CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(CFG_WITH_CCWARN),yes)  # Local... Else don't burden users
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_WEXTRA) $(CFG_CXXFLAGS_SRC) -Werror
#CPPFLAGS += -pedantic-errors
else
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
endif
LDFLAGS += $(CFG_LDFLAGS_SRC)

CPPFLAGSWALL   = $(CPPFLAGS)
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)

# Allow RPM builds to specify hardcoded data directories
# To do this:
ifeq ($(CFG_WITH_DEFENV),yes)
 CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
 CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
 CPPFLAGS += -DDEFENV_SYSTEMC_INCLUDE=\"$(SYSTEMC_INCLUDE)\"
 CPPFLAGS += -DDEFENV_SYSTEMC_LIBDIR=\"$(SYSTEMC_LIBDIR)\"
 ifeq ($(VERILATOR_ROOT),)  # Use what we're given, or intuit
  CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
 else
  CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(VERILATOR_ROOT)\"
 endif
 ifneq ($(CFG_WITH_SOLVER),no)
  CPPFLAGS += -DDEFENV_VERILATOR_SOLVER='"$(CFG_WITH_SOLVER)"'
 else
  ifneq ($(VERILATOR_SOLVER),)
   CPPFLAGS += -DDEFENV_VERILATOR_SOLVER='"$(VERILATOR_SOLVER)"'
  endif
 endif
endif

HEADERS = $(wildcard V*.h v*.h)

ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre
FLEXFIX = $(srcdir)/flexfix
VLCOVGEN = $(srcdir)/vlcovgen

# BISON_DEBUG = -Wcounterexamples

######################################################################
# CCACHE flags (via environment as no command line option available)
CCACHE_SLOPPINESS ?= pch_defines,time_macros
export CCACHE_SLOPPINESS

######################################################################
#### Top level

all: make_info $(TGT)

make_info:
	@echo "      Compile flags: " $(CXX) ${CFLAGS} ${CXXFLAGS} ${CPPFLAGS}

clean mostlyclean distclean maintainer-clean::
	-rm -f *.o *.d *_gen_*
	-rm -f *__gen*
	-rm -f obj_* .objcache*

distclean maintainer-clean:: clean

maintainer-clean::

maintainer-copy::

#### Top executable

RAW_OBJS = \
	V3Const__gen.o \
	V3Error.o \
	V3FileLine.o \
	V3Graph.o \
	V3GraphAcyc.o \
	V3GraphAlg.o \
	V3GraphPathChecker.o \
	V3GraphTest.o \
	V3Hash.o \
	V3OptionParser.o \
	V3Os.o \
	V3ParseGrammar.o \
	V3ParseImp.o \
	V3ParseLex.o \
	V3PreProc.o \
	V3PreShell.o \
	V3String.o \
	V3ThreadPool.o \
	V3Waiver.o \
	Verilator.o \

RAW_OBJS_PCH_ASTMT = \
	V3Ast.o \
	V3AstNodes.o \
	V3Broken.o \
	V3Config.o \
	V3EmitCBase.o \
	V3EmitCConstPool.o \
	V3EmitCFunc.o \
	V3EmitCHeaders.o \
	V3EmitCImp.o \
	V3EmitCInlines.o \
	V3EmitCPch.o \
	V3EmitV.o \
	V3File.o \
	V3FuncOpt.o \
	V3Global.o \
	V3Hasher.o \
	V3Number.o \
	V3Options.o \
	V3Stats.o \
	V3StatsReport.o \
	V3VariableOrder.o \

RAW_OBJS_PCH_ASTNOMT = \
	V3Active.o \
	V3ActiveTop.o \
	V3Assert.o \
	V3AssertPre.o \
	V3Begin.o \
	V3Branch.o \
	V3CCtors.o \
	V3CUse.o \
	V3Case.o \
	V3Cast.o \
	V3Class.o \
	V3Clean.o \
	V3Clock.o \
	V3Combine.o \
	V3Common.o \
	V3Coverage.o \
	V3CoverageJoin.o \
	V3Dead.o \
	V3Delayed.o \
	V3Depth.o \
	V3DepthBlock.o \
	V3Descope.o \
	V3Dfg.o \
	V3DfgAstToDfg.o \
	V3DfgCache.o \
	V3DfgDecomposition.o \
	V3DfgDfgToAst.o \
	V3DfgOptimizer.o \
	V3DfgPasses.o \
	V3DfgPeephole.o \
	V3DfgRegularize.o \
	V3DupFinder.o \
	V3EmitCMain.o \
	V3EmitCMake.o \
	V3EmitCModel.o \
	V3EmitCSyms.o \
	V3EmitMk.o \
	V3EmitXml.o \
	V3ExecGraph.o \
	V3Expand.o \
	V3Force.o \
	V3Fork.o \
	V3Gate.o \
	V3HierBlock.o \
	V3Inline.o \
	V3Inst.o \
	V3InstrCount.o \
	V3Interface.o \
	V3Life.o \
	V3LifePost.o \
	V3LinkCells.o \
	V3LinkDot.o \
	V3LinkInc.o \
	V3LinkJump.o \
	V3LinkLValue.o \
	V3LinkLevel.o \
	V3LinkParse.o \
	V3LinkResolve.o \
	V3Localize.o \
	V3MergeCond.o \
	V3Name.o \
	V3Order.o \
	V3OrderGraphBuilder.o \
	V3OrderMoveGraph.o \
	V3OrderParallel.o \
	V3OrderProcessDomains.o \
	V3OrderSerial.o \
	V3Param.o \
	V3Premit.o \
	V3ProtectLib.o \
	V3Randomize.o \
	V3Reloop.o \
	V3Sampled.o \
	V3Sched.o \
	V3SchedAcyclic.o \
	V3SchedPartition.o \
	V3SchedReplicate.o \
	V3SchedTiming.o \
	V3SchedVirtIface.o \
	V3Scope.o \
	V3Scoreboard.o \
	V3Slice.o \
	V3Split.o \
	V3SplitAs.o \
	V3SplitVar.o \
	V3StackCount.o \
	V3Subst.o \
	V3TSP.o \
	V3Table.o \
	V3Task.o \
	V3Timing.o \
	V3Trace.o \
	V3TraceDecl.o \
	V3Tristate.o \
	V3Undriven.o \
	V3Unknown.o \
	V3Unroll.o \
	V3Width.o \
	V3WidthCommit.o \
	V3WidthSel.o \

# verilator_coverage
VLCOV_OBJS = \
	VlcMain.o \

NON_STANDALONE_HEADERS = \
	V3AstInlines.h \
	V3AstNodeDType.h \
	V3AstNodeExpr.h \
	V3AstNodeOther.h \
	V3DfgVertices.h \
	V3ThreadPool.h \
	V3WidthRemove.h \

AST_DEFS := \
	V3AstNodeDType.h \
	V3AstNodeExpr.h \
	V3AstNodeOther.h \

DFG_DEFS := \
	V3DfgVertices.h

#### astgen common flags

ASTGENFLAGS = -I $(srcdir)
ASTGENFLAGS += $(foreach f,$(AST_DEFS),--astdef $f)
ASTGENFLAGS += $(foreach f,$(DFG_DEFS),--dfgdef $f)

#### Linking

ifeq ($(VL_VLCOV),)
PREDEP_H = V3Ast__gen_forward_class_decls.h
OBJS += $(RAW_OBJS) $(RAW_OBJS_PCH_ASTMT) $(RAW_OBJS_PCH_ASTNOMT)
else
PREDEP_H =
OBJS += $(VLCOV_OBJS)
endif

$(TGT): $(PREDEP_H) $(OBJS)
	@echo "      Linking $@..."
	${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}

#### Modules

%__gen.cpp: %.cpp $(ASTGEN) $(AST_DEFS) $(DFG_DEFS)
	$(PYTHON3) $(ASTGEN) $(ASTGENFLAGS) $*.cpp

.SECONDARY:

%.gch: %
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} ${CFG_CXXFLAGS_PCH} -c $< -o $@
%.o: %.cpp
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} -c $< -o $@
%.o: %.c
	$(OBJCACHE) ${CC}  ${CFLAGS} ${CPPFLAGSWALL} -c $< -o $@

V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSPARSER} -c $< -o $@

V3ParseGrammar.o: V3ParseGrammar.cpp V3ParseBison.c
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSPARSER} -c $< -o $@

V3ParseImp.o: V3ParseImp.cpp V3ParseBison.c
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSPARSER} -c $< -o $@

V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSPARSER} -c $< -o $@

define CXX_ASTMT_template
$(1): $(basename $(1)).cpp V3PchAstMT.h.gch
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} ${CFG_CXXFLAGS_PCH_I} V3PchAstMT.h${CFG_GCH_IF_CLANG} -c $(srcdir)/$(basename $(1)).cpp -o $(1)

endef

$(foreach obj,$(RAW_OBJS_PCH_ASTMT),$(eval $(call CXX_ASTMT_template,$(obj))))

define CXX_ASTNOMT_template
$(1): $(basename $(1)).cpp V3PchAstNoMT.h.gch
	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} ${CFG_CXXFLAGS_PCH_I} V3PchAstNoMT.h${CFG_GCH_IF_CLANG} -c $(srcdir)/$(basename $(1)).cpp -o $(1)

endef

$(foreach obj,$(RAW_OBJS_PCH_ASTNOMT),$(eval $(call CXX_ASTNOMT_template,$(obj))))

#### Generated files

# Target rule called before parallel build to make generated files
serial:: V3Ast__gen_forward_class_decls.h V3ParseBison.c

serial_vlcov:: vlcovgen.d

vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h
	$(PYTHON3) $(VLCOVGEN) --srcdir $(srcdir)
	touch $@

V3Ast__gen_forward_class_decls.h: $(ASTGEN) $(AST_DEFS) $(DFG_DEFS)
	$(PYTHON3) $(ASTGEN) $(ASTGENFLAGS) --classes

V3ParseBison.h: V3ParseBison.c

# Have only one output file in this rule to prevent parallel make issues
V3ParseBison.c: verilog.y $(BISONPRE)
	@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
	$(PYTHON3) $(BISONPRE) --yacc ${YACC} -d -v -o V3ParseBison.c $(BISON_DEBUG) $<

V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
	${LEX} --version
	${LEX} ${LFLAGS} -o$@ $<

V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX)
	$(PYTHON3) $(FLEXFIX) V3Lexer <$< >$@

V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
	${LEX} --version
	${LEX} ${LFLAGS} -o$@ $<

V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
	$(PYTHON3) $(FLEXFIX) V3PreLex <$< >$@

# For t_dist_header_cc
HEADER_CC_H := $(filter-out $(NON_STANDALONE_HEADERS), $(notdir $(wildcard $(srcdir)/*.h)))

.PHONY: header_cc
header_cc: $(addsuffix __header_cc.o, $(basename $(HEADER_CC_H)))

%__header_cc.cpp: %.h
	$(PYTHON3) $(srcdir)/../bin/verilator_includer -DVL_MT_DISABLED_CODE_UNIT=1 $^ > $@

.SUFFIXES:

######################################################################
######################################################################

DEPS := $(wildcard *.d)
ifneq ($(DEPS),)
include $(DEPS)
endif
