在 Verilog 模拟器和 VPI 代码中使用 make 的最佳实践是啥

Posted

技术标签:

【中文标题】在 Verilog 模拟器和 VPI 代码中使用 make 的最佳实践是啥【英文标题】:What is the best practice of using make with Verilog simulators and VPI code在 Verilog 模拟器和 VPI 代码中使用 make 的最佳实践是什么 【发布时间】:2011-06-27 12:43:23 【问题描述】:

我的第一个 VPI 项目已经进入了一个合理的阶段,这是打算 帮助数字滤波器设计。此刻我正在和伊卡洛斯一起工作,虽然 我也想测试 Verilator 和其他模拟器。

到目前为止,我有这个makefile,虽然这是为了构建 C 代码和 一个简单的测试平台。我希望能够包含一个生成文件并构建/模拟 不同的新 Verilog 项目。

我在网上没有找到很多用于 HDL 项目的 Makefile 示例。 在某种程度上,我对我的实施感到非常满意,并且可以继续进行 滚动我自己的,虽然希望看到任何组织良好的更大规模 项目。我还没有看过 OpenRISC 中的 Makefile ...

我真正在寻找的一个例子是 VPI 测试平台项目,例如你 已经完成了你的 VPI 代码,现在想围绕它建立一个小型生态系统 使用 Makefile 的层次结构。

假设我们只使用了两个模拟器 - Icarus 和 Verilator。

【问题讨论】:

查看“boldport flow”FPGA 构建 Makefile 生成器...可能对您有用boldport.com @saar 很有趣。很努力!我明白了,这是你的项目;)它应该是仅限网络的吗?我很高兴以 Tk 或 QT 应用程序的形式看到这一点……甚至是 ncurses/dialog(对于控制台怪胎)!让我知道,atm 我正在准备各种项目 :)~ 是的,这是我的;不是故意隐瞒的,应该提一下。让这个讨论“脱机”。 【参考方案1】:

这似乎是一个不同的基本 makefile。在我们的生成文件中,我们通常有更多的目标,其中还包括综合、标准和模拟。遗憾的是,它们包含非常特定于供应商(Xilinx 和 Synopsys)的东西,这使得它不是很通用。此外,我们通常有一个生成文件的层次结构。我们有一个通用的,一些模块细节,还有一些子项目(例如内存系统)。

但如果你有兴趣,我在这里发布一个,让你印象一个是什么样子的:

.PHONY: default
default: rtlsim

.PHONY: help
help:
    @echo "Syntax:"
    @echo "-------"
    @echo "make [make_target] [options]"
    @echo ""
    @echo "Arguments:"
    @echo "----------"
    @echo "make_target = [bits], timing, rtlsim, rtlsimgui, laysim, laysimgui"
    @echo "  bits:       Generate bitstream (includes P&R)"
    @echo "  timing:     Generate timing report using timing analyzer (includes P&R)"
    @echo "  rtlsim:     VCS RTL simulation (text mode)"
    @echo "  rtlsimgui:  VCS RTL simulation (interactive gui mode)"
    @echo "  laysim:     VCS post-place-and-route simulation (text mode)"
    @echo "  laysimgui:  VCS post-place-and-route simulation (interactive gui mode)"
    @echo ""
    @echo "Options:"
    @echo "----------"
    @echo "target = [ml507], ml310"
    @echo "  ml507: Use Virtex-5 xc5vfx70t-1 as target FPGA (Xilinx ML507)"
    @echo "  ml310: Use Virtex-II Pro xc2vp30-6 as target FPGA (Xilinx ML310)"
    @echo "disregard_cache_stalls = [0], 1"
    @echo "  0: for normal simulation"
    @echo "  1: to disregard cache stalls (results may then be incorrect, but the simulation time without cache stalls is obtained)"
    @echo "physical_synthesis = [0], 1"
    @echo "  0: run Synplify without physical synthesis"
    @echo "  1: run Synplify with physical synthesis"
    @echo "BATCH_GUI = [default], GUI"
    @echo "  default: run Synplify in batch mode"
    @echo "  GUI:     start Synplify GUI instead"
    @echo "toplevel = [fpga], datapath, sequencer, hw_kernel, user, plb_marc, mci_marc"
    @echo "  Sets the toplevel file in the HW design hierarchy; relevant for area / timing reports"
    @echo "marc = [1], 2"
    @echo "  Chooses between usage of MARC1 and MARC2 (use the latter for 256 bit LPU transfers)"

# defaults
ifndef target
  target=ml507
endif
ifndef toplevel
  toplevel=fpga
endif
ifndef disregard_cache_stalls
  disregard_cache_stalls=0
endif
ifndef marc
  marc=1
endif

ifeq "$(target)" "ml507"
  TECHNOLOGY_NAME=VIRTEX5
  TECHNOLOGY_PART=XC5VFX70T
  TECHNOLOGY_PACKAGE=FF1136
  TECHNOLOGY_SPEED_GRADE=-1
  FREQUENCY=100.000
else
  TECHNOLOGY_NAME=VIRTEX2P
  TECHNOLOGY_PART=XC2VP30
  TECHNOLOGY_PACKAGE=FF896
  TECHNOLOGY_SPEED_GRADE=-6
  FREQUENCY=100.000
endif

ifndef physical_synthesis
  physical_synthesis=0
endif

ifndef BATCH_GUI
  BATCH_GUI=default
endif

ifeq "$(BATCH_GUI)" "default"
  BATCH_TCL=batch
else
  BATCH_TCL=tcl
endif

ifdef area_timing_result_file
  AREA_TIMING_RESULT_FILE=$(area_timing_result_file)
else
  AREA_TIMING_RESULT_FILE=area_timing_results.$(target).$(toplevel).txt
endif

ifeq ($(disregard_cache_stalls),1)
  DISREGARD_CACHE_STALLS=+define+DISREGARD_CACHE_STALLS
else
  DISREGARD_CACHE_STALLS=
endif

# base directory for MARC, SimEnv, AddOns, etc.
ifeq "$(target)" "ml507"
  PRAKTIKUM_BASE=$(COMRADE_ROOT_DIR)/COMRADE/sim_synth/v5
else
  PRAKTIKUM_BASE=$(COMRADE_ROOT_DIR)/COMRADE/sim_synth/v2p
endif

BRAM_VERILOG=$(COMRADE_ROOT_DIR)/COMRADE/sim_synth/platform_independent/bram

# command to get the directory of the current test example,
# relative to Comrade's "tests" directory
TEST_EXAMPLE=$(shell pwd | sed 's/.*tests\///g' | sed 's/\/sim_env_acem3//g')

# name of target RC executable
PROG=main

# Modlib path
MODLIB=$(COMRADE_ROOT_DIR)/modlib

# path to the instantiated verilog modules
MODULES=..

# path to the instantiated verilog blackboxes
BLACKBOXES=../blackboxes

ifeq "$(target)" "ml507"
DESIGN=user.v mci_marc.tcl
else
DESIGN=user.v plb_marc.tcl
endif

# base name of synthesis-related files
ifeq "$(target)" "ml507"
NETLIST=mci_marc
else
NETLIST=plb_marc
endif

# base name of toplevel after synthesis
TOPLEVEL=system

# current directory (which is in some cases != $(PWD)...)
CURRENT_DIR=$(shell pwd)

# "HOME" on local /scratch
SCRHOME=/scratch/$(USER)/private/tmp/$(TEST_EXAMPLE)

# directory containing MARC
ifeq ($(marc),2)
MARC=$(PRAKTIKUM_BASE)/MARC_marc2
else
MARC=$(PRAKTIKUM_BASE)/MARC
endif

# directory containing the simulation environment
ifeq ($(marc),2)
SIMENV=$(PRAKTIKUM_BASE)/SimEnv_marc2
else
SIMENV=$(PRAKTIKUM_BASE)/SimEnv
endif

# directory containing additional files (IP cores, SW, ...)
ifeq ($(marc),2)
ADDONS=$(PRAKTIKUM_BASE)/AddOns_marc2
else
ADDONS=$(PRAKTIKUM_BASE)/AddOns
endif

# ML310 Linux kernel image
VMLINUX=$(ADDONS)/zImage.elf

# TTY for serial console
CONSOLETTY=/dev/ttyS0

# path to xilinx's simulation primitives
SIMPRIMS=$(XILINX)/verilog/src/simprims
UNISIMS=$(XILINX)/verilog/src/unisims

# RC definitions
ifeq "$(target)" "ml507"
  DEVICE=xc5vfx70t
  PARTTYPE=$(DEVICE)-ff1136-1
  DEVDES=$(TOPLEVEL)-$(DEVICE)
else
  DEVICE=xc2vp30
  PARTTYPE=$(DEVICE)-ff896-6
  DEVDES=$(TOPLEVEL)-$(DEVICE)
endif


# this is the name of synplify target subdirectory
IMPL=Simple.$(target).fpga

# configuration files for $(VIRSIM)
CFGRTL=default-rtl
VPDRTL=$(SCRHOME)/vcdplus-rtl-$(notdir $(PWD))
CFGLAY=default-lay
VPDLAY=$(SCRHOME)/vcdplus-lay-$(notdir $(PWD))
CFGSYN=default-syn
VPDSYN=$(SCRHOME)/vcdplus-syn-$(notdir $(PWD))
MDIRRTL=csrc.rtl
MDIRLAY=csrc.lay
MDIRSYN=csrc.syn

# path to the cross OS installation directory
#CROSS=/acs/ace/rtems
#CROSS=/images/ml310/ml310_rootfs_gentoo
CROSS=/cad/tools/acs-prak/ACS07/Cross
#CROSSBIN=$(CROSS)/bin
CROSSBIN=/cad/tools/crosscompiler/powerpc-405-linux/bin

# the RTEMS/ACE2 IO server
SERVER=$(CROSSBIN)/rtemsserver -l

# the compile-flow tools
#CC=$(CROSSBIN)/sparc-rtems-gcc
CC=$(CROSSBIN)/powerpc-405-linux-gnu-gcc
#LD=$(CROSSBIN)/sparc-rtems-gcc
LD=$(CROSSBIN)/powerpc-405-linux-gnu-gcc
COPY=$(CROSSBIN)/sparc-rtems-objcopy
BIT2O=$(CROSSBIN)/bit2o
VPP=vpp
SED=sed
XC=xc
ifeq ($(SYNPLIFY_VERSION),8.8)
SYNPLIFY=synplify_pro
else
SYNPLIFY=synplify_premier_dp
endif
NGDBUILD=ngdbuild
MAP=map
PAR=par
NETGEN=netgen
BITGEN=bitgen
TRCE=trce
IMPACT=impact
XMD=xmd
VCS=vcs
SIMVRTL=simv.rtl
SIMVLAY=simv.lay
SIMVSYN=simv.syn
VIRSIM=virsim
XPOWER=xpwr

# the compile options

#CCOPTS=-fasm -specs bsp_specs -qrtems -O3 -I include -I $(CROSS)/sparc-rtems/include/rtems-ace2
CCOPTS=-O3 -I $(CROSS)/usr/include
#LDOPTS=-fasm -specs bsp_specs -qrtems -O3
LDOPTS=-O3
COPYOPTS=-O binary
SYNPLIFYOPTS=$(filter %.tcl,$(DESIGN))
NGDBUILDOPTS=-uc $(ADDONS)/$(TOPLEVEL).ucf -sd $(ADDONS) -sd $(MODLIB) -sd $(MODLIB)/$(target)
MAPOPTS=-pr b -detail -timing -ol high -xe c -w
PAROPTS=-ol high -xe c -w
BITGENOPTS=
TRCEOPTS=-v 10
TRCEOPTS_HG=-v 10 -u 10
VCSOPTS=+v2k +notimingchecks -y . -y .. -y $(MARC) +incdir+$(MARC) -y $(SIMENV) +incdir+$(SIMENV) -y $(ADDONS) +incdir+$(ADDONS) -y $(MODLIB) +incdir+$(MODLIB) -y $(BRAM_VERILOG) +incdir+$(BRAM_VERILOG) $(DISREGARD_CACHE_STALLS)

# Don't change these

ifeq ($(target),ml507)
  ifeq ($(disregard_cache_stalls),1)
    VCSRTLOPTS=+define+TESTBENCH=testbench_rtl -v ../simdefs.v -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_rtl.v
  else
    VCSRTLOPTS=+define+TESTBENCH=testbench_rtl -v ../simdefs.v -v marc.v -v $(SIMENV)/ppc440.v -v $(SIMENV)/temac.v -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_rtl.v
  endif
  VCSSYNOPTS=+define+TESTBENCH=testbench_syn -v ../simdefs.v -v $(SIMENV)/ppc440.v -v $(SIMENV)/temac.v -v $(IMPL)/$(NETLIST).vm -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_syn.v
  VCSLAYOPTS=+define+TESTBENCH=testbench_lay -v ../simdefs.v -v $(SIMENV)/ppc440.v -v $(IMPL)/$(DEVDES).v -v $(SIMPRIMS)/../glbl.v $(VCSOPTS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_lay.v
else
  ifeq ($(disregard_cache_stalls),1)
    VCSRTLOPTS=+define+TESTBENCH=testbench_rtl -v ../simdefs.v -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_rtl.v
  else
    VCSRTLOPTS=+define+TESTBENCH=testbench_rtl -v ../simdefs.v -v marc.v -v $(SIMENV)/ppc405.v -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_rtl.v
  endif
  VCSSYNOPTS=+define+TESTBENCH=testbench_syn -v ../simdefs.v -v $(SIMENV)/ppc405.v -v $(IMPL)/$(NETLIST).vm -v $(UNISIMS)/../glbl.v $(VCSOPTS) -y $(UNISIMS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_syn.v
  VCSLAYOPTS=+define+TESTBENCH=testbench_lay -v ../simdefs.v -v $(SIMENV)/ppc405.v -v $(IMPL)/$(DEVDES).v -v $(SIMPRIMS)/../glbl.v $(VCSOPTS) -y $(SIMPRIMS) +libext+.v $(SIMENV)/testbench_lay.v
endif

# make rules

default: all

.c.o:
        $(CC) -c $(CCOPTS) $<

$(PROG).exe:  $(PROG).o $(DEVDES).o
        $(LD) -o $(PROG).exe $(PROG).o  $(DEVDES).o $(LDOPTS) $(CROSS)/sparc-rtems/lib/libacevapi.a -lm
$(PROG).bin: $(PROG).exe
        $(COPY) $(COPYOPTS) $(PROG).exe $(PROG).bin

$(PROG): $(PROG).o
        $(LD) -o $(PROG) $(PROG).o $(LDOPTS) $(CROSS)/usr/lib/libadmxrc2.so.2


# build hardware objects

#$(SIMENV)/%.v: $(ADDONS)/%.ngc
#       $(NETGEN) -w -sim -ofmt verilog $< $@
#       rm $(basename $@).nlf

$(DEVDES).o: $(IMPL)/$(DEVDES).o
        cp $(IMPL)/$(DEVDES).o .

$(IMPL)/$(DEVDES).o: $(IMPL)/$(DEVDES).bit
        cd $(IMPL); \
        $(BIT2O) $(DEVDES).bit $(DEVDES).o config_$(TOPLEVEL) ;\
        cd ..

$(VPDRTL).vpd: $(MARC)/*.v marc.v $(SIMENV)/*.v $(patsubst $(ADDONS)/%.ngc,$(SIMENV)/%.v,$(wildcard $(ADDONS)/*.ngc)) $(filter %.v,$(DESIGN))
        mkdir -p -m 700 $(dir $(VPDRTL))
        $(VCS) -line -PP +define+BATCH -Mupdate -Mdir=$(MDIRRTL) -o $(SIMVRTL) $(VCSRTLOPTS)
        ./$(SIMVRTL) +vpddrivers +vpdfile+$(VPDRTL).vpd

$(VPDLAY).vpd: $(SIMENV)/*.v $(IMPL)/$(DEVDES).v
        mkdir -p -m 700 $(dir $(VPDLAY))
        $(VCS) -line -PP +define+BATCH -Mupdate -Mdir=$(MDIRLAY) -o $(SIMVLAY) $(VCSLAYOPTS)
        ./$(SIMVLAY) +vpddrivers +vpdfile+$(VPDLAY).vpd

$(VPDSYN).vpd: $(SIMENV)/*.v $(patsubst $(ADDONS)/%.ngc,$(SIMENV)/%.v,$(wildcard $(ADDONS)/*.ngc)) $(IMPL)/$(NETLIST).vm
        mkdir -p -m 700 $(dir $(VPDSYN))
        $(VCS) -line -PP +define+BATCH -Mupdate -Mdir=$(MDIRSYN) -o $(SIMVSYN) $(VCSSYNOPTS)
        ./$(SIMVSYN) +vpddrivers +vpdfile+$(VPDSYN).vpd

$(IMPL)/$(DEVDES).v: $(IMPL)/$(DEVDES).ncd
        cd $(IMPL); \
        $(NETGEN) -w -sim -ofmt verilog -sdf_path ../$(IMPL)/$(DEVDES).sdf $(DEVDES) -pcf $(DEVDES).pcf; \
        $(SED) -i -e 's/SIM_COLLISION_CHECK = "ALL"/SIM_COLLISION_CHECK = "GENERATE_X_ONLY"/g' $(DEVDES).v ;\
        cd ..

$(IMPL)/$(DEVDES).hg.twr: $(IMPL)/$(DEVDES).ncd
        cd $(IMPL); \
        $(TRCE) $(TRCEOPTS_HG) $(DEVDES).ncd ;\
        mv $(DEVDES).twr $(DEVDES).hg.twr
        cd ..

$(IMPL)/$(DEVDES).twr: $(IMPL)/$(DEVDES).ncd
        cd $(IMPL); \
        $(TRCE) $(TRCEOPTS) $(DEVDES).ncd ;\
        cd ..

$(IMPL)/$(DEVDES).bit: $(IMPL)/$(DEVDES).ncd
        cd $(IMPL); \
        $(BITGEN) -w $(BITGENOPTS) $(DEVDES) $(DEVDES);\
        cd ..

$(IMPL)/$(DEVDES).ncd: $(IMPL)/$(DEVDES)_map.ncd
        cd $(IMPL); \
        $(PAR) $(PAROPTS) $(DEVDES)_map.ncd $(DEVDES).ncd $(DEVDES).pcf ;\
        cd ..

$(IMPL)/$(DEVDES)_map.ncd: $(IMPL)/$(DEVDES).ngd
        cd $(IMPL); \
        XIL_TIMING_ALLOW_IMPOSSIBLE=1 $(MAP) $(MAPOPTS) -o $(DEVDES)_map.ncd $(DEVDES).ngd $(DEVDES).pcf ; \
        cd ..

$(IMPL)/$(DEVDES).ngd: $(IMPL)/$(NETLIST).edf $(wildcard $(ADDONS)/*.ngc) $(wildcard $(ADDONS)/*.edf)
        cd $(IMPL); \
        $(NGDBUILD) $(NGDBUILDOPTS) -p $(PARTTYPE) $(TOPLEVEL) $(DEVDES).ngd; \
        cd ..

$(IMPL)/$(NETLIST).edf $(IMPL)/$(NETLIST).vm: $(MARC)/*.v marc.v $(wildcard $(ADDONS)/*.v) $(filter %.v,$(DESIGN)) $(filter %.tcl,$(DESIGN))
        DESIGN=$(CURRENT_DIR) IMPL=$(IMPL) NETLIST=$(NETLIST) MARC=$(MARC) \
        ADDONS=$(ADDONS) MODULES=$(MODULES) MODLIB=$(MODLIB) BRAM_VERILOG=$(BRAM_VERILOG) BLACKBOXES=$(BLACKBOXES) \
        TECHNOLOGY_NAME=$(TECHNOLOGY_NAME) TECHNOLOGY_PART=$(TECHNOLOGY_PART) \
        TECHNOLOGY_PACKAGE=$(TECHNOLOGY_PACKAGE) TECHNOLOGY_SPEED_GRADE=$(TECHNOLOGY_SPEED_GRADE) \
        FREQUENCY=$(FREQUENCY) PHYSICAL_SYNTHESIS=$(physical_synthesis) \
        BATCH_GUI=$(BATCH_GUI) $(SYNPLIFY) -$(BATCH_TCL) $(SYNPLIFYOPTS)

# if link_marcdefs_v_$(target)_created does not exist, the marcdefs.v link is (re-)created
link_marcdefs_v_$(target)_created:
        -rm -f link_marcdefs_v_ml310_created link_marcdefs_v_ml507_created 2>/dev/null
        @touch link_marcdefs_v_$(target)_created

marcdefs.v: marcdefs.$(target).v link_marcdefs_v_$(target)_created
        -rm -f marcdefs.v 2>/dev/null
        ln -s marcdefs.$(target).v marcdefs.v
        @touch marcdefs.v

marc.v: $(MARC)/marc.vpp marcdefs.v
        $(VPP) $(MARC)/marc.vpp > marc.v 2>/dev/null

.PHONY: all
all:    $(PROG) bits
        @echo -e "OK, ML310 Linux executable for $(PROG) built. Run it using \n\tmake linux\nand after logging in, execute \n\t$(SCRHOME)/$(PROG)"

.PHONY: rtlsimbatch
rtlsimbatch: $(VPDRTL).vpd
        $(VIRSIM) +define+RTLSIM +vpdfile+$(VPDRTL).vpd +cfgfile+$(CFGRTL).cfg $(VCSRTLOPTS)

.PHONY: rtlsimgui
ifeq ($(disregard_cache_stalls),1)
rtlsimgui: $(MARC)/*.v ../simdefs.v ../stimulus.v $(SIMENV)/*.v $(filter %.v,$(DESIGN))
        mkdir -p -m 700 $(dir $(VPDRTL))
        $(VCS) -line -RI -Mupdate -Mdir=$(MDIRRTL) -o $(SIMVRTL) +define+RTLSIM +vpdfile+$(VPDRTL).vpd +cfgfile+$(CFGRTL).cfg $(VCSRTLOPTS)
else
rtlsimgui: $(MARC)/*.v ../simdefs.v ../stimulus.v marc.v $(SIMENV)/*.v $(patsubst $(ADDONS)/%.ngc,$(SIMENV)/%.v,$(wildcard $(ADDONS)/*.ngc)) $(filter %.v,$(DESIGN))
        mkdir -p -m 700 $(dir $(VPDRTL))
        $(VCS) -line -RI -Mupdate -Mdir=$(MDIRRTL) -o $(SIMVRTL) +define+RTLSIM +vpdfile+$(VPDRTL).vpd +cfgfile+$(CFGRTL).cfg $(VCSRTLOPTS)
endif

.PHONY: rtlsim
ifeq ($(disregard_cache_stalls),1)
rtlsim: marcdefs.v ../simdefs.v ../stimulus.v $(SIMENV)/*.v $(filter %.v,$(DESIGN))
        mkdir -p -m 700 $(dir $(VPDRTL))
        $(VCS) -line -PP -Mupdate -Mdir=$(MDIRRTL) -o $(SIMVRTL) +define+RTLSIM +vpdfile+$(VPDRTL).vpd +cfgfile+$(CFGRTL).cfg $(VCSRTLOPTS)
        ./$(SIMVRTL)
else
rtlsim: $(MARC)/*.v ../simdefs.v ../stimulus.v marc.v $(SIMENV)/*.v $(patsubst $(ADDONS)/%.ngc,$(SIMENV)/%.v,$(wildcard $(ADDONS)/*.ngc)) $(filter %.v,$(DESIGN))
        mkdir -p -m 700 $(dir $(VPDRTL))
        $(VCS) -line -PP -Mupdate -Mdir=$(MDIRRTL) -o $(SIMVRTL) +define+RTLSIM +vpdfile+$(VPDRTL).vpd +cfgfile+$(CFGRTL).cfg $(VCSRTLOPTS)
        ./$(SIMVRTL)
endif

.PHONY: laysimbatch
laysimbatch: $(VPDLAY).vpd
        $(VIRSIM) +vpdfile+$(VPDLAY).vpd +cfgfile+$(CFGLAY).cfg $(VCSLAYOPTS)

.PHONY: laysimgui
laysimgui: $(SIMENV)/*.v $(IMPL)/$(DEVDES).v
        mkdir -p -m 700 $(dir $(VPDLAY))
        $(VCS) -line -RI -Mupdate -Mdir=$(MDIRLAY) -o $(SIMVLAY) +vpdfile+$(VPDLAY).vpd +cfgfile+$(CFGLAY).cfg $(VCSLAYOPTS)

.PHONY: laysim
laysim: $(SIMENV)/*.v ../simdefs.v ../stimulus.v $(IMPL)/$(DEVDES).v
        mkdir -p -m 700 $(dir $(VPDLAY))
        $(VCS) -line -PP -Mupdate -Mdir=$(MDIRLAY) -o $(SIMVLAY) +vpdfile+$(VPDLAY).vpd +cfgfile+$(CFGLAY).cfg $(VCSLAYOPTS)
        ./$(SIMVLAY)

.PHONY: synsimbatch
synsimbatch: $(VPDSYN).vpd
        $(VIRSIM) +vpdfile+$(VPDSYN).vpd +cfgfile+$(CFGSYN).cfg $(VCSSYNOPTS)

.PHONY: synsim
synsim: $(SIMENV)/*.v ../simdefs.v ../stimulus.v $(patsubst $(ADDONS)/%.ngc,$(SIMENV)/%.v,$(wildcard $(ADDONS)/*.ngc)) $(IMPL)/$(NETLIST).vm
        mkdir -p -m 700 $(dir $(VPDSYN))
        $(VCS) -line -RI -Mupdate -Mdir=$(MDIRSYN) -o $(SIMVSYN) +vpdfile+$(VPDSYN).vpd +cfgfile+$(CFGSYN).cfg $(VCSSYNOPTS)

.PHONY: timing
ifeq "$(physical_synthesis)" "1"
# Synplify creates .edf, .ncd and .twr in one call!
timing: $(IMPL)/$(NETLIST).edf
        cat $(IMPL)/par_1/$(NETLIST).twr
        $(COMRADE_ROOT_DIR)/COMRADE/scripts/XilinxReportReader/xrr $(TECHNOLOGY_NAME) \
                $(IMPL)/par_1/$(NETLIST)_map.mrp $(IMPL)/par_1/$(NETLIST).twr >$(AREA_TIMING_RESULT_FILE)
else
# Create only .edf by Synplify, rest using Makefile
timing: $(IMPL)/$(DEVDES).twr
        cat $(IMPL)/$(DEVDES).twr
        $(COMRADE_ROOT_DIR)/COMRADE/scripts/XilinxReportReader/xrr $(TECHNOLOGY_NAME) \
                $(IMPL)/$(DEVDES)_map.mrp $(IMPL)/$(DEVDES).twr >$(AREA_TIMING_RESULT_FILE)
endif

# create .vcd from .vpd for power analysis
$(VPDLAY).vcd: $(VPDLAY).vpd
        vpd2vcd $(VPDLAY).vpd $(VPDLAY).vcd

# create .xad from .vcd for power analysis
$(VPDLAY).xad: $(VPDLAY).vcd
        /cad/tools/ise-9.2/bin/lin/vcd2xad.pl -f $(VPDLAY).vcd

# create .saif from .vcd
$(VPDLAY).saif: $(VPDLAY).vcd
        vcd2saif -i $(VPDLAY).vcd -o $(VPDLAY).saif

# power analysis
.PHONY: power
power: $(IMPL)/$(DEVDES).ncd $(VPDLAY).saif
        $(XPOWER) -v -a $(IMPL)/$(DEVDES).ncd $(IMPL)/$(DEVDES).pcf -s $(VPDLAY).vcd
        @echo "Power results written to file \"$(IMPL)/$(DEVDES).pwr\"."

# area results
.PHONY: area
area: $(IMPL)/$(DEVDES)_map.ncd

.PHONY: area_all
area_all:
        # V2P
        make area_datapath toplevel=datapath
        make area_sequencer toplevel=sequencer
        make area_hw_kernel toplevel=hw_kernel
        make area_plb_marc toplevel=plb_marc
        make area
        # V5
        make area_datapath toplevel=datapath target=ml507
        make area_sequencer toplevel=sequencer target=ml507
        make area_hw_kernel toplevel=hw_kernel target=ml507

.PHONY: timing_all
timing_all:
        # V2P
        make timing_datapath toplevel=datapath
        make timing_sequencer toplevel=sequencer
        make timing_hw_kernel toplevel=hw_kernel
        make timing_plb_marc toplevel=plb_marc
        make timing
        # V5
        make timing_datapath toplevel=datapath target=ml507
        make timing_sequencer toplevel=sequencer target=ml507
        make timing_hw_kernel toplevel=hw_kernel target=ml507

.PHONY: bits
bits: $(IMPL)/$(DEVDES).bit

.PHONY: download
download: bits
        cd $(IMPL); \
        echo -e "setMode    -bscan \
               \nsetCable   -p lpt1 \
               \naddDevice  -p 1 -part xccace \
               \naddDevice  -p 2 -file $(DEVDES).bit \
               \nprogram    -p 2 \
               \nquit" > download.cmd ; \
        $(IMPACT) -batch download.cmd ; \
        cd ..

.PHONY: linux
linux: $(PROG) $(VMLINUX) download
        mkdir -p -m 700 $(SCRHOME)
        cp -a $(PROG) $(SCRHOME)
        cd $(IMPL); \
        echo -e "connect ppc hw \
               \nrst \
               \nafter 1700 set end 1 \
               \nvwait end \
               \ndow $(VMLINUX) \
               \ncon \
               \nexit" > download.tcl ; \
        echo -e "set bps 115200 \
               \nset msdos "off" \
               \nset del2bs "off" \
               \nbind_function 1 \"quitchr\" \
               \nshell \"$(XMD) -tcl download.tcl\" \
               \necho \"Linux wird auf der seriellen Konsole gestartet...\" \
               \n" > download.xc ; \
        $(XC) -l $(CONSOLETTY) -s download.xc ; \
        cd ..

.PHONY: cosim
cosim:
        make -C cosimulation/
        cosimulation/simv

.PHONY: cosim_gui
cosim_gui:
        make -C cosimulation/
        cosimulation/simv -gui

.PHONY: cosim_clean
cosim_clean:
        make clean -C cosimulation/

.PHONY: clean
clean:
        rm -f $(PROG).exe $(PROG).bin $(PROG).run $(PROG).o $(PROG) $(DEVDES).o $(VPDRTL).vpd $(VPDLAY).vpd $(VPDSYN).vpd $(SIMVRTL) $(SIMVLAY) $(SIMVSYN) marc.v stdout.log vcs.key
        rm -rf Simple.ml310.* Simple.ml507.* $(IMPL) $(IMPL).datapath $(IMPL).sequencer $(IMPL).user $(IMPL).plb_marc
        rm -rf $(SIMVRTL).daidir $(SIMVLAY).daidir $(SIMVSYN).daidir $(MDIRRTL) $(MDIRLAY) $(MDIRSYN)

# Switch between different top-level modules
ifeq "$(toplevel)" "datapath"
  include Makefile.datapath
endif
ifeq "$(toplevel)" "sequencer"
  include Makefile.sequencer
endif
ifeq "$(toplevel)" "hw_kernel"
  include Makefile.hw_kernel
endif
ifeq "$(toplevel)" "user"
  include Makefile.user
endif
ifeq "$(toplevel)" "plb_marc"
  include Makefile.plb_marc
endif
ifeq "$(toplevel)" "mci_marc"
  include Makefile.mci_marc
endif

【讨论】:

这是一个很好的答案,尽管我所看到的只是 DPS 算法的模拟。我得到了一些 VPI 代码,它只能用于测试平台。嗯...我最终可能会想出一个解决方案...

以上是关于在 Verilog 模拟器和 VPI 代码中使用 make 的最佳实践是啥的主要内容,如果未能解决你的问题,请参考以下文章

如何在verilog中制作VPI?

使用 Verilator 和 VPI 读取 regs 数组

SV通过DPI调用C

verilog hdl中啥是综合?啥是模拟?

RTL基本知识:Verilog常见错误

NVIDIA VPI架构解析