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,58 @@ 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
+ return depset (transitive = [
77
+ dep [PyInfo ].imports
78
+ for dep in ctx .attr .deps
79
+ if PyInfo in dep
80
+ ])
81
+
82
+ def _collect_python_direct_imports (ctx ):
83
+ return depset (direct = [module .dirname for module in ctx .files .test_module ])
84
+
85
+ def _collect_transitive_files (ctx ):
86
+ py_toolchain = ctx .toolchains ["@bazel_tools//tools/python:toolchain_type" ].py3_runtime
87
+ return depset (
88
+ direct = [py_toolchain .interpreter ],
89
+ transitive = [dep [PyInfo ].transitive_sources for dep in ctx .attr .deps ] +
90
+ [ctx .attr .cocotb_wrapper [PyInfo ].transitive_sources ] +
91
+ [py_toolchain .files ],
92
+ )
93
+
94
+ def _collect_transitive_runfiles (ctx ):
95
+ return ctx .runfiles ().merge_all (
96
+ [dep .default_runfiles for dep in ctx .attr .deps ] +
97
+ [dep .default_runfiles for dep in ctx .attr .sim ],
98
+ )
99
+
100
+ # Helpers for preparing test script and its environment
101
+
102
+ def _get_pythonpath_to_set (ctx ):
103
+ direct_imports = _collect_python_direct_imports (ctx ).to_list ()
104
+ transitive_imports = [
105
+ "../" + path
106
+ for path in _collect_python_transitive_imports (ctx ).to_list ()
107
+ ]
108
+ imports = _remove_duplicates_from_list (transitive_imports + direct_imports )
109
+ return ":" .join (imports )
110
+
111
+ def _get_path_to_set (ctx ):
112
+ sim_paths = _remove_duplicates_from_list ([dep .label .workspace_root for dep in ctx .attr .sim ])
113
+ path = ":" .join (["$PWD/" + str (p ) for p in sim_paths ])
114
+ return path
75
115
76
- verilog_files = _collect_verilog_files (ctx )
116
+ def _get_test_command (ctx , verilog_files , vhdl_files ):
117
+ vhdl_sources_args = _files_to_argstring (vhdl_files , "vhdl_sources" )
77
118
verilog_sources_args = _files_to_argstring (verilog_files , "verilog_sources" )
78
119
79
120
includes_args = _list_to_argstring (ctx .attr .includes , "includes" )
@@ -86,21 +127,14 @@ def _cocotb_test_impl(ctx):
86
127
87
128
defines_args = _dict_to_argstring (ctx .attr .defines , "defines" )
88
129
parameters_args = _dict_to_argstring (ctx .attr .parameters , "parameters" )
89
-
90
130
verbose_args = " --verbose" if ctx .attr .verbose else ""
91
131
waves_args = " --waves" if ctx .attr .waves else ""
92
132
seed_args = " --seed {}" .format (ctx .attr .seed ) if ctx .attr .seed != "" else ""
93
133
94
134
test_module_args = _pymodules_to_argstring (ctx .files .test_module , "test_module" )
95
135
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
136
command = (
103
- "PATH={}:$PATH " .format (path ) +
137
+ "PATH={}:$PATH " .format (_get_path_to_set ( ctx ) ) +
104
138
"python {}" .format (ctx .executable .cocotb_wrapper .short_path ) +
105
139
" --sim {}" .format (ctx .attr .sim_name ) +
106
140
" --hdl_library {}" .format (ctx .attr .hdl_library ) +
@@ -123,33 +157,32 @@ def _cocotb_test_impl(ctx):
123
157
test_module_args
124
158
)
125
159
126
- ctx . actions . write ( output = runner_script , content = command )
160
+ return command
127
161
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 ],
162
+ def _cocotb_test_impl (ctx ):
163
+ verilog_files = _collect_verilog_files (ctx ).to_list ()
164
+ vhdl_files = _collect_vhdl_files (ctx ).to_list ()
165
+
166
+ # create test script
167
+ runner_script = ctx .actions .declare_file ("cocotb_runner.sh" )
168
+ ctx .actions .write (
169
+ output = runner_script ,
170
+ content = _get_test_command (ctx , verilog_files , vhdl_files ),
135
171
)
136
172
173
+ # specify dependencies for the script
137
174
runfiles = ctx .runfiles (
138
175
files = ctx .files .cocotb_wrapper +
139
176
verilog_files +
140
177
vhdl_files +
141
178
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 ],
179
+ transitive_files = _collect_transitive_files (ctx ),
180
+ ).merge (
181
+ _collect_transitive_runfiles (ctx ),
147
182
)
148
183
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 }
184
+ # specify PYTHONPATH for the script
185
+ env = {"PYTHONPATH" : _get_pythonpath_to_set (ctx )}
153
186
154
187
# return the information about testing script and its dependencies
155
188
return [
0 commit comments