1717load ("//verilog:providers.bzl" , "VerilogInfo" )
1818load ("@rules_python//python:defs.bzl" , "PyInfo" )
1919
20+ ## Helpers for parsing arguments
21+
2022def _list_to_argstring (data , argname , attr = None , operation = None ):
2123 result = " --{}" .format (argname ) if data else ""
2224 for value in data :
@@ -45,6 +47,8 @@ def _remove_duplicates_from_list(data):
4547 result .append (e )
4648 return result
4749
50+ # Helpers for collecting information from context
51+
4852def _collect_verilog_files (ctx ):
4953 transitive_srcs_list = [
5054 dep
@@ -59,21 +63,58 @@ def _collect_verilog_files(ctx):
5963 verilog_info_struct .srcs
6064 for verilog_info_struct in transitive_srcs_depset .to_list ()
6165 ]
62- verilog_files = depset (
66+
67+ return depset (
6368 [src for sub_tuple in verilog_srcs for src in sub_tuple ] +
6469 ctx .files .verilog_sources ,
6570 )
66- return verilog_files .to_list ()
6771
6872def _collect_vhdl_files (ctx ):
69- return ctx .files .vhdl_sources
73+ return depset ( direct = ctx .files .vhdl_sources )
7074
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
75115
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" )
77118 verilog_sources_args = _files_to_argstring (verilog_files , "verilog_sources" )
78119
79120 includes_args = _list_to_argstring (ctx .attr .includes , "includes" )
@@ -86,21 +127,14 @@ def _cocotb_test_impl(ctx):
86127
87128 defines_args = _dict_to_argstring (ctx .attr .defines , "defines" )
88129 parameters_args = _dict_to_argstring (ctx .attr .parameters , "parameters" )
89-
90130 verbose_args = " --verbose" if ctx .attr .verbose else ""
91131 waves_args = " --waves" if ctx .attr .waves else ""
92132 seed_args = " --seed {}" .format (ctx .attr .seed ) if ctx .attr .seed != "" else ""
93133
94134 test_module_args = _pymodules_to_argstring (ctx .files .test_module , "test_module" )
95135
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-
102136 command = (
103- "PATH={}:$PATH " .format (path ) +
137+ "PATH={}:$PATH " .format (_get_path_to_set ( ctx ) ) +
104138 "python {}" .format (ctx .executable .cocotb_wrapper .short_path ) +
105139 " --sim {}" .format (ctx .attr .sim_name ) +
106140 " --hdl_library {}" .format (ctx .attr .hdl_library ) +
@@ -123,33 +157,32 @@ def _cocotb_test_impl(ctx):
123157 test_module_args
124158 )
125159
126- ctx . actions . write ( output = runner_script , content = command )
160+ return command
127161
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 ),
135171 )
136172
173+ # specify dependencies for the script
137174 runfiles = ctx .runfiles (
138175 files = ctx .files .cocotb_wrapper +
139176 verilog_files +
140177 vhdl_files +
141178 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 ),
147182 )
148183
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 )}
153186
154187 # return the information about testing script and its dependencies
155188 return [
0 commit comments