17
17
load ("//verilog:providers.bzl" , "VerilogInfo" )
18
18
load ("@rules_python//python:defs.bzl" , "PyInfo" )
19
19
20
+ ## Helpers for parsing arguments
21
+
20
22
def _list_to_argstring (data , argname , attr = None , operation = None ):
21
23
result = " --{}" .format (argname ) if data else ""
22
24
for value in data :
@@ -45,6 +47,8 @@ def _remove_duplicates_from_list(data):
45
47
result .append (e )
46
48
return result
47
49
50
+ # Helpers for collecting information from context
51
+
48
52
def _collect_verilog_files (ctx ):
49
53
transitive_srcs_list = [
50
54
dep
@@ -59,21 +63,67 @@ def _collect_verilog_files(ctx):
59
63
verilog_info_struct .srcs
60
64
for verilog_info_struct in transitive_srcs_depset .to_list ()
61
65
]
62
- verilog_files = depset (
66
+
67
+ return depset (
63
68
[src for sub_tuple in verilog_srcs for src in sub_tuple ] +
64
69
ctx .files .verilog_sources ,
65
70
)
66
- return verilog_files .to_list ()
67
71
68
72
def _collect_vhdl_files (ctx ):
69
- return ctx .files .vhdl_sources
73
+ return depset ( direct = ctx .files .vhdl_sources )
70
74
71
- def _cocotb_test_impl (ctx ):
72
- # prepare arguments for the test command
73
- vhdl_files = _collect_vhdl_files (ctx )
74
- vhdl_sources_args = _files_to_argstring (vhdl_files , "vhdl_sources" )
75
+ def _collect_python_transitive_imports (ctx ):
76
+ all_imports = []
77
+ for attr in [ctx .attr .deps , ctx .attr .test_module ]:
78
+ imports = depset (transitive = [
79
+ dep [PyInfo ].imports
80
+ for dep in attr
81
+ if PyInfo in dep
82
+ ])
83
+ all_imports .append (imports )
84
+ return depset (transitive = all_imports )
85
+
86
+ def _collect_python_direct_imports (ctx ):
87
+ return depset (direct = [module .dirname for module in ctx .files .test_module ])
88
+
89
+ def _collect_transitive_files (ctx ):
90
+ py_toolchain = ctx .toolchains ["@bazel_tools//tools/python:toolchain_type" ].py3_runtime
91
+ return depset (
92
+ direct = [py_toolchain .interpreter ],
93
+ transitive = [dep [PyInfo ].transitive_sources for dep in ctx .attr .deps ] +
94
+ [dep [PyInfo ].transitive_sources for dep in ctx .attr .test_module if PyInfo in dep ] +
95
+ [ctx .attr .cocotb_wrapper [PyInfo ].transitive_sources ] +
96
+ [py_toolchain .files ],
97
+ )
98
+
99
+ def _collect_transitive_runfiles (ctx ):
100
+ return ctx .runfiles ().merge_all (
101
+ [dep .default_runfiles for dep in ctx .attr .deps ] +
102
+ [dep .default_runfiles for dep in ctx .attr .test_module ] +
103
+ [dep .default_runfiles for dep in ctx .attr .sim ],
104
+ )
105
+
106
+ # Helpers for preparing tests script
107
+
108
+ def _get_pythonpath_to_set (ctx ):
109
+ direct_imports_list = _collect_python_direct_imports (ctx ).to_list ()
110
+
111
+ transitive_imports = _collect_python_transitive_imports (ctx )
112
+ prefixed_transitive_imports_list = [
113
+ "external/" + path
114
+ for path in transitive_imports .to_list ()
115
+ ]
116
+
117
+ pypath = ":" .join (prefixed_transitive_imports_list + direct_imports_list )
118
+ return pypath
75
119
76
- verilog_files = _collect_verilog_files (ctx )
120
+ def _get_path_to_set (ctx ):
121
+ sim_paths = _remove_duplicates_from_list ([dep .label .workspace_root for dep in ctx .attr .sim ])
122
+ path = ":" .join (["$PWD/" + str (p ) for p in sim_paths ])
123
+ return path
124
+
125
+ def _get_test_command (ctx , verilog_files , vhdl_files ):
126
+ vhdl_sources_args = _files_to_argstring (vhdl_files , "vhdl_sources" )
77
127
verilog_sources_args = _files_to_argstring (verilog_files , "verilog_sources" )
78
128
79
129
includes_args = _list_to_argstring (ctx .attr .includes , "includes" )
@@ -86,21 +136,14 @@ def _cocotb_test_impl(ctx):
86
136
87
137
defines_args = _dict_to_argstring (ctx .attr .defines , "defines" )
88
138
parameters_args = _dict_to_argstring (ctx .attr .parameters , "parameters" )
89
-
90
139
verbose_args = " --verbose" if ctx .attr .verbose else ""
91
140
waves_args = " --waves" if ctx .attr .waves else ""
92
141
seed_args = " --seed {}" .format (ctx .attr .seed ) if ctx .attr .seed != "" else ""
93
142
94
143
test_module_args = _pymodules_to_argstring (ctx .files .test_module , "test_module" )
95
144
96
- # define a script and a command
97
- runner_script = ctx .actions .declare_file ("cocotb_runner.sh" )
98
-
99
- sim_paths = _remove_duplicates_from_list ([dep .label .workspace_root for dep in ctx .attr .sim ])
100
- path = ":" .join (["$PWD/" + str (p ) for p in sim_paths ])
101
-
102
145
command = (
103
- "PATH={}:$PATH " .format (path ) +
146
+ "PATH={}:$PATH " .format (_get_path_to_set ( ctx ) ) +
104
147
"python {}" .format (ctx .executable .cocotb_wrapper .short_path ) +
105
148
" --sim {}" .format (ctx .attr .sim_name ) +
106
149
" --hdl_library {}" .format (ctx .attr .hdl_library ) +
@@ -123,33 +166,30 @@ def _cocotb_test_impl(ctx):
123
166
test_module_args
124
167
)
125
168
126
- ctx .actions .write (output = runner_script , content = command )
169
+ def _cocotb_test_impl (ctx ):
170
+ verilog_files = _collect_verilog_files (ctx ).to_list ()
171
+ vhdl_files = _collect_vhdl_files (ctx ).to_list ()
127
172
128
- # specify dependencies for the script
129
- py_toolchain = ctx .toolchains ["@bazel_tools//tools/python:toolchain_type" ].py3_runtime
130
- transitive_files = depset (
131
- direct = [py_toolchain .interpreter ],
132
- transitive = [dep [PyInfo ].transitive_sources for dep in ctx .attr .deps ] +
133
- [ctx .attr .cocotb_wrapper [PyInfo ].transitive_sources ] +
134
- [py_toolchain .files ],
173
+ # create test script
174
+ runner_script = ctx .actions .declare_file ("cocotb_runner.sh" )
175
+ ctx .actions .write (
176
+ output = runner_script ,
177
+ content = _get_test_command (ctx , verilog_files , vhdl_files ),
135
178
)
136
179
180
+ # specify dependencies for the script
137
181
runfiles = ctx .runfiles (
138
182
files = ctx .files .cocotb_wrapper +
139
183
verilog_files +
140
184
vhdl_files +
141
185
ctx .files .test_module ,
142
- transitive_files = transitive_files ,
143
- ).merge_all (
144
- [dep .default_runfiles for dep in ctx .attr .deps ] +
145
- [dep .default_runfiles for dep in ctx .attr .test_module ] +
146
- [dep .default_runfiles for dep in ctx .attr .sim ],
186
+ transitive_files = _collect_transitive_files (ctx ),
187
+ ).merge (
188
+ _collect_transitive_runfiles (ctx ),
147
189
)
148
190
149
- # specify pythonpath for the script
150
- test_module_paths = _remove_duplicates_from_list ([module .dirname for module in ctx .files .test_module ])
151
- pypath = ":" .join ([str (p ) for p in test_module_paths ])
152
- env = {"PYTHONPATH" : pypath }
191
+ # specify PYTHONPATH for the script
192
+ env = {"PYTHONPATH" : _get_pythonpath_to_set (ctx )}
153
193
154
194
# return the information about testing script and its dependencies
155
195
return [
0 commit comments