2

所以我正在尝试编写一个与 QuestaSim 和 systemverilog 文件一起使用的 Makefile。如果您不知道那是什么(大多数人不会),请不要担心,这与我的问题无关。

我有一个项目主管,其中包含:src/work/Makefile

src/ 目录包含几个目录,每个目录都包含源文件。

work/ 目录最初并不存在,而是由 makefile 创建的。

当我调用称为 vlog 的“编译器”时,在 .sv 文件上会在工作文件夹中创建一个目录,该目录与 .sv 文件的名称相同,但没有后缀。在该目录中有三个文件,我将用作“对象”文件的文件是_primary.dat。

例如,调用“vlog src/interface/my_interface.sv”会创建(如果成功)work/my_interface/_primary.dat

我的 .sv 文件也需要按特定顺序编译,并且我只想在源文件或其依赖项之一发生更改时编译它们。

我可以使用“$(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR)/, $(basename $(notdir $(SRC))”将 .sv 文件的路径转换为相关 _primary.dat 文件的路径)))" 但是反过来是不可能的,因为我们失去了目录结构。

所以我想我想要的是来自对象-> src 的某种映射。所以在我的 $(OBJ): 目标中,我可以做“vlog $(getsrc $@)”。

之后我必须处理编译顺序和依赖关系,但我可能可以解决这个问题。

有什么建议么?

4

1 回答 1

0

我找到了一个可行的解决方案。我不确定它是不是最整洁的,但我会在此处发布以帮助遇到此问题的其他人。

基本上,我创建了一个带有两个参数的宏:.sv 源文件路径和名称,以及依赖项列表。这会将源文件路径转换为目标文件路径并将其创建为目标。依赖源文件和任何传入的依赖项。然后我创建一个变量,其中包含我所有来源的列表。最后我做了: $(foreach src,$(SRCS),$(eval $(call create_target_for, $(src)))) 它创建了我所有的目标。

此外,我将每个子目录作为虚假目标,具有相关的依赖项,使我能够在目录上获得正确的编译顺序。

唯一缺少的是如果我需要确保单个目录中的文件具有正确的编译顺序。

我的制作文件:

# Makefile for use in building all my UVM components
# ----------------------------------------------------------------------------------
# Requirements:
#   QuestaSim - We use the vlog compiler packaged with QuestaSim.
#     ModelSim also comes with vlog, but doesn't really support UVM.
#   UVM_INCLUDE_DIR environment var - This should point to the UVM src directory.
#     For me this is: C:\questasim_10.0b\verilog_src\uvm-1.0p1\src
# ----------------------------------------------------------------------------------
# Notes:
#   The vlog compiler creates an output folder in the VLIB_DIR directors
#   per package/module/interface with the same name as the entity
#   Any capitals are replace with @ followed by the lower case letter
#   IE. FooBar -> @foo@bar
#   This makefile requires that:
#     All interfaces end in _if
#     All packages end in _pkg
#     Each file can only contain a single interface, package or module
#     No capitals in package/module/interface naems
#     The package/module/interface has the same name as the file

# some variabls to use later
VLIB_DIR    = ./work
VLOG_FLAGS  = +incdir+$(UVM_INCLUDE_DIR)

# src files - per directory for use with compile orders
#             ie. transactions have to be compiled before drivers
INTERFACE_SRCS      = $(wildcard src/interfaces/*.sv)
CONFIG_SRCS         = $(wildcard src/configs/*.sv)
TRANSACTION_SRCS    = $(wildcard src/transactions/*.sv)
SEQUENCE_SRCS       = $(wildcard src/sequences/*.sv)
DRIVER_SRCS         = $(wildcard src/drivers/*.sv)
MONITOR_SRCS        = $(wildcard src/monitors/*.sv)
AGENT_SRCS          = $(wildcard src/agents/*.sv)
SCOREBOARD_SRCS     = $(wildcard src/scoreboards/*.sv)

# all source files - for use with creating makefile targets
SRCS                = $(INTERFACE_SRCS) \
                      $(CONFIG_SRCS) \
                      $(TRANSACTION_SRCS) \
                      $(SEQUENCE_SRCS) \
                      $(DRIVER_SRCS) \
                      $(MONITOR_SRCS) \
                      $(AGENT_SRCS) \
                      $(SCOREBOARD_SRCS)

# list of all the components
COMPONENTS  = interfaces \
              configs \
              transactions \
              sequences \
              drivers \
              monitors \
              agents \
              scoreboards

# colours for use in echo commands for highlighting
COLOUR_NONE     = \x1b[0m
COLOUR_RED      = \x1b[31;01m
COLOUR_BLUE     = \x1b[34;01m
COLOUR_GREEN    = \x1b[32;01m

# macros to turn a .sv file into the compiled file in the relevant VLIB_DIR subdirectory
# src/abc/def.sv -> $(VLIB_DIR)/def/_primary.dat
src2obj     = $(addsuffix /_primary.dat, $(addprefix $(VLIB_DIR)/, $(basename $(notdir $(1)))))

# macro to create a target for a given source file
# it takes two arguments:
# 1) the path and name of the source file
# 2) any dependencies
# It then creates a traget on the relevant _primary.dat (questaSim created object)
# with a dependency on the source file, and any other passed in dependencies
define create_target_for

$$(info $COLOUR_GREEN create_target_for called on $(1))
$$(info creating target $(call src2obj, $(1)))
$$(info with dependencies $(VLIB_DIR) $(1) $(2))
$$(info )
$(call src2obj, $(1)): $(1) $(2)
    @echo -e "$(COLOUR_BLUE)compiling $(1) because of changes in: $$? $(COLOUR_NONE)\n"
    vlog $(VLOG_FLAGS) $(1)

endef

# default rule is to create the library, compile the UVM pkg and all the components
all: $(VLIB_DIR) UVM $(COMPONENTS)

# create the questaSim library if it's not already there
$(VLIB_DIR):
    vlib $(VLIB_DIR)
    @echo -e "$(COLOUR_GREEN)Created the $(VLIB_DIR) library$(COLOUR_NONE)\n"

# compile the UVM library
$(VLIB_DIR)/uvm_pkg/_primary.dat:
    vlog +incdir+$(UVM_INCLUDE_DIR) $(UVM_INCLUDE_DIR)/uvm.sv
    @echo -e "$(COLOUR_GREEN)Compiled the UVM package$(COLOUR_NONE)\n"

# simple alias
UVM: $(VLIB_DIR) $(VLIB_DIR)/uvm_pkg/_primary.dat

# create targets for all our sources
# note with this method we can't set dependencies within a single directory
$(foreach src,$(SRCS),$(eval $(call create_target_for, $(src))))

# define a phony target per directory so we can specify compile order
interfaces: $(VLIB_DIR) UVM \
            $(call src2obj, $(INTERFACE_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

configs: $(VLIB_DIR) UVM \
         $(call src2obj, $(CONFIG_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

transactions: $(VLIB_DIR) UVM \
              $(call src2obj, $(TRANSACTION_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

sequences: $(VLIB_DIR) UVM \
           transactions \
           $(call src2obj, $(SEQUENCE_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

drivers: $(VLIB_DIR) UVM \
         transactions interfaces \
         $(call src2obj, $(DRIVER_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

monitors: $(VLIB_DIR) UVM \
          transactions interfaces \
          $(call src2obj, $(MONITOR_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

agents: $(VLIB_DIR) UVM \
        drivers monitors transactions configs interfaces \
        $(call src2obj, $(AGENT_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

scoreboards: $(call src2obj, $(SCOREBOARD_SRCS))
    @echo -e "$(COLOUR_GREEN)Compiled all $@$(COLOUR_NONE)\n"

# delete the library and all compiled files
clean:
    if [ -d $(VLIB_DIR) ]; then vdel -lib $(VLIB_DIR) -all; fi;

.PHONY: clean UVM $(COMPONENTS)
于 2016-07-21T23:38:42.607 回答