|  | #!/usr/bin/env python3 | 
|  |  | 
|  | import subprocess | 
|  | import os | 
|  | import xml.etree.ElementTree as ET | 
|  | from collections import defaultdict | 
|  |  | 
|  |  | 
|  | def get_workspace_root(): | 
|  | return subprocess.check_output(['bazel', 'info', | 
|  | 'workspace']).decode('utf-8').strip() | 
|  |  | 
|  |  | 
|  | def get_all_cocotb_test_suites(): | 
|  | xml_output = subprocess.check_output([ | 
|  | 'bazel', 'query', | 
|  | 'kind("cocotb_test", //...) intersect attr("tags", "verilator_cocotb_test_suite", //...)', | 
|  | '--output=xml' | 
|  | ]).decode('utf-8').strip() | 
|  | if not xml_output: | 
|  | return [] | 
|  | return ET.fromstring(xml_output) | 
|  |  | 
|  |  | 
|  | def get_test_suite_info(suite_rule): | 
|  | test_module = None | 
|  | variable_name = None | 
|  |  | 
|  | for child in suite_rule: | 
|  | if child.tag == 'list' and child.attrib.get('name') == 'test_module': | 
|  | for label in child: | 
|  | if label.tag == 'label': | 
|  | test_module = label.attrib.get('value') | 
|  | break | 
|  | if child.tag == 'list' and child.attrib.get('name') == 'tags': | 
|  | for string_attr in child: | 
|  | if string_attr.tag == 'string': | 
|  | value = string_attr.attrib.get('value', '') | 
|  | if value.startswith("testcases_vname="): | 
|  | variable_name = value.split("=")[1] | 
|  | break | 
|  | if test_module and variable_name: | 
|  | break | 
|  |  | 
|  | return test_module, variable_name | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | workspace_root = get_workspace_root() | 
|  | os.chdir(workspace_root) | 
|  |  | 
|  | all_suites_xml = get_all_cocotb_test_suites() | 
|  |  | 
|  | if all_suites_xml is None: | 
|  | print("No cocotb test suites found.") | 
|  | return | 
|  |  | 
|  | for suite_rule in all_suites_xml.findall('rule'): | 
|  | suite_name = suite_rule.get('name').split(':')[1] | 
|  | print(f"Processing suite: {suite_name}") | 
|  |  | 
|  | build_file = suite_rule.get('location').split(':')[0] | 
|  | test_module_label, variable_name = get_test_suite_info(suite_rule) | 
|  |  | 
|  | if not test_module_label or not variable_name: | 
|  | print( | 
|  | f"Warning: Could not extract 'test_module' or 'testcases_vname' from {suite_name}" | 
|  | ) | 
|  | continue | 
|  |  | 
|  | # The test_module_label is a bazel label, e.g. //tests/cocotb:core_mini_axi_sim.py | 
|  | # We need to convert it to a file path. | 
|  | test_module_path = test_module_label.replace('//', | 
|  | '').replace(':', '/') | 
|  |  | 
|  | test_file_path = os.path.join(workspace_root, test_module_path) | 
|  |  | 
|  | print(f"Updating testcases for {suite_name}...") | 
|  |  | 
|  | update_script_path = os.path.join(workspace_root, "utils", | 
|  | "update_cocotb_tests.py") | 
|  | update_command = [ | 
|  | 'python3', | 
|  | update_script_path, | 
|  | f'--build_file={build_file}', | 
|  | f'--test_file={test_file_path}', | 
|  | f'--variable_name={variable_name}', | 
|  | f'--name={suite_name}', | 
|  | ] | 
|  |  | 
|  | subprocess.run(update_command, check=True) | 
|  | print(f"Successfully updated {suite_name}.") | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | main() |