summaryrefslogtreecommitdiff
path: root/mk/verilator.mk
blob: 26928630b769dadca309ecf2c6e6683dfef0fc17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
targets += sim

vtop_dir = $(call per_target,vtop_dir)
vtop_exe = $(call per_target,vtop_exe)

vl_main = $(call per_target,vl_main)
vl_flags = $(call per_target,vl_flags)
vl_cflags = $(call per_target,vl_cflags)
vl_ldflags = $(call per_target,vl_ldflags)

define target/sim/prepare
  enable_opt := 1

  $(prepare_verilator_target)
endef

define target/sim/setup
  $(setup_verilator_target)

  $$(call target_var,vl_main) := $$(strip $$(call require_core_paths,$$(rule_top),vl_main))
endef

define target/sim/rules
  $(verilator_target_rules)

  .PHONY: $$(rule_top_path)/sim

  $$(rule_top_path)/sim: $$(vtop_exe)
	$$<
endef

define prepare_verilator_target
  flow/type := sim
endef

define setup_verilator_target
  $(call build_vars,$(addprefix enable_,rand threads trace cov opt lto prof))

  $(call target_var,vl_flags) = $(common_vl_flags)
  $(call target_var,vl_cflags) = $(common_vl_cflags)
  $(call target_var,vl_ldflags) = $(common_vl_ldflags)
endef

$(eval $(call defer,common_vl_flags,$$(set_verilator_common)))
$(eval $(call defer,common_vl_cflags,$$(set_verilator_common)))
$(eval $(call defer,common_vl_ldflags,$$(set_verilator_common)))

define set_verilator_common
  ifneq (,$$(enable_lto))
    enable_opt := 1
  endif

  x_mode := $$(if $$(enable_rand),unique,fast)

  static_flags := \
    --x-assign $$(x_mode) --x-initial $$(x_mode) \
    $$(if $$(enable_threads),--threads $$(call shell_checked,nproc)) \
    $$(if $$(enable_trace),--trace --trace-fst --trace-structs) \
    $$(if $$(enable_cov),--coverage) \
    $$(if $$(enable_opt),-O3) \
    $$(if $$(enable_prof),--prof-cfuncs) \
    --cc --exe --prefix Vtop --MMD --MP

  common_vl_flags := $$(static_flags) $$(core_info/$$(rule_top)/vl_flags)

  common_vl_cflags := \
    $$(if $$(enable_opt),-O3) \
    $$(if $$(enable_lto),-flto)

  common_vl_ldflags := \
    $$(if $$(enable_lto),-flto)
endef

define verilator_target_rules
  $(call target_var,vtop_dir) := $$(obj)/vl
  $(call target_var,vtop_exe) := $$(vtop_dir)/Vtop

  vtop_mk_file := $$(vtop_dir)/Vtop.mk
  vtop_mk_stamp := $$(vtop_dir)/stamp
  vtop_dep_file := $$(vtop_dir)/Vtop__ver.d

  -include $$(vtop_dep_file)
  $$(vtop_dep_file):

  $$(vtop_exe): export VPATH := $$(src)
  $$(vtop_exe): $$(vtop_mk_stamp)
	$$(call run_submake,BUILD) $$(if $$(V),,-s) -C $$(vtop_dir) -f Vtop.mk
	@touch -c $$@

  $$(vtop_mk_file):
	@rm -f $$@

  $$(vtop_mk_stamp): $$(top_stamp) $$(vtop_mk_file)
	$$(eval $$(final_vflags))
	$$(call run,VERILATE) $$(VERILATOR) $$(vl_flags) $$(verilator_src_args)
	@touch $$@

  $(call target_entrypoint,$$(vtop_exe))
endef

define final_vflags
  $(call find_with_pkgconfig, \
    $(call map_core_deps,vl_pkgconfig,$(rule_top)), \
    $(call target_var,vl_cflags), \
    $(call target_var,vl_ldflags))

  $$(call target_var,vl_flags) += --Mdir $$(vtop_dir)
  $$(call target_var,vl_cflags) := $$(strip $$(vl_cflags))
  $$(call target_var,vl_ldflags) := $$(strip $$(vl_ldflags))

  # Verilator's wrapper script can't handle `-CFLAGS ''` correctly
  ifneq (,$$(vl_cflags))
    $$(call target_var,vl_flags) += -CFLAGS '$$(vl_cflags)'
  endif

  ifneq (,$$(vl_ldflags))
    $$(call target_var,vl_flags) += -LDFLAGS '$$(vl_ldflags)'
  endif
endef

verilator_src_args = \
  $(strip \
    $(let rtl_top,$(call require_core_var,$(rule_top),rtl_top), \
      --top $(rtl_top) \
      $(foreach dep,$(dep_tree/$(rule_top)), \
        $(let prefix,$(core_info/$(dep)/workdir)/, \
          $(foreach rtl_dir,$(call core_paths,$(dep),rtl_dirs), \
            -y $(rtl_dir)) \
          $(foreach include_dir,$(call core_paths,$(dep),rtl_include_dirs), \
            -I$(include_dir)) \
          $(foreach src_file,$(call core_paths,$(dep),rtl_files) $(call core_paths,$(dep),vl_files), \
            $(src_file))))) \
    $(if $(vl_main),$(vl_main),$(error $$(vl_main) not defined by target '$(rule_target)')))