2016-07-21 3 views
1

Donc j'essaye d'écrire un Makefile à utiliser avec les fichiers QuestaSim et systemverilog. Si vous ne savez pas ce que c'est (et la plupart des gens ne le feront pas) alors ne vous inquiétez pas, ce n'est pas pertinent pour mon problème.Comment écrire un fichier makefile où les fichiers objet compilés sont dans un répertoire différent avec un nom différent?

J'ai un directeur de projet contenant: src/travail/Makefile

le répertoire src/contient plusieurs répertoires qui contiennent chacun des fichiers source.

Le répertoire travail/n'existe pas initialement et est créé par le fichier makefile. Lorsque j'appelle mon "compilateur" qui s'appelle vlog, sur un fichier .sv un répertoire est créé dans le dossier de travail avec le même nom que le fichier .sv sans le suffixe

Dans ce répertoire sont trois fichiers celui que je vais utiliser comme mon "objet" fichier est _primary.dat

Ainsi par exemple, appelant "vlog src/interface/mon_interface.sv" crée (si elle réussit) le travail /my_interface/_primary.dat

Mes fichiers .SV doivent également être compilés dans un ordre précis, et je veux que les compiler si le fichier source ou un de leurs dépendances a changé.

Je peux tourner le chemin d'accès au fichier .sv dans le chemin d'accès au fichier _primary.dat correspondant en utilisant "$ (addsuffix /_primary.dat, $ (addprefix $ (VLIB_DIR) /, $ (basename $ (notdir $ (SRC))))) "mais l'inverse est impossible, car nous perdons la structure du répertoire."

Donc je pense que ce que je veux, c'est une sorte de carte de l'objet -> src. Alors que dans ma cible $ (OBJ):, je peux faire "vlog $ (getsrc $ @)". Après cela, je dois gérer l'ordre de compilation et les dépendances, mais je peux probablement le faire.

Des suggestions?

+0

1) Y at-il un risque de collision de nom de la source? Autrement dit, s'il y a un 'src/interface/foo.sv', peut-il y avoir aussi un' src/engine/foo.sv'? 2) Est-ce que 'src /' peut avoir plus de deux niveaux de profondeur? Autrement dit, pourrait-il y avoir un 'src/foo/bar/baz.sv'? – Beta

+0

J'ai l'exigence que le paquet/interface/module a le même nom que le fichier. Donc, toute collision entraînerait des erreurs de compilation de toute façon. Pour le moment, les répertoires ne sont profonds qu'à deux niveaux, mais je pourrais envisager d'ajouter plus de niveaux plus tard. –

+0

Avez-vous déjà regardé l'utilitaire 'vmake' fourni avec Questa? –

Répondre

0

J'ai trouvé une solution qui fonctionne. Je ne suis pas sûr que ce soit le plus soigné, mais je le posterai ici pour aider toute personne qui a ce problème.

Fondamentalement, je crée une macro qui prend deux arguments: le chemin et le nom du fichier source .sv, et une liste de dépendances. Cela convertit le chemin du fichier source dans le chemin d'accès au fichier objet et le crée en tant que cible. Avec une dépendance sur le fichier source et tout passé dans les dépendances. Je crée ensuite une variable contenant une liste de toutes mes sources. Enfin je fais: $ (foreach src, $ (SRCS), $ (eval $ (appelez create_target_for, $ (src)))) qui crée toutes mes cibles.

En outre, j'ai chaque sous-répertoire comme une cible bidon, avec les dépendances pertinentes, ce qui me permet d'obtenir l'ordre de compilation correct sur les répertoires.

La seule chose manquante est si j'ai besoin de m'assurer que les fichiers dans un seul répertoire ont l'ordre de compilation correct.

Mon Makefile:

# 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 -> @[email protected] 
# 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 [email protected]$(COLOUR_NONE)\n" 

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

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

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

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

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

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

scoreboards: $(call src2obj, $(SCOREBOARD_SRCS)) 
    @echo -e "$(COLOUR_GREEN)Compiled all [email protected]$(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)