-
Notifications
You must be signed in to change notification settings - Fork 14
Add --verilator-hier-blocks option to emit hier_block annotations #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
John Demme (teqdruid)
merged 9 commits into
main
from
copilot/emit-hierarchical-annotations
Sep 10, 2026
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
ac6ddfc
Initial plan
Copilot 9fdc7af
Add --verilator-hier-blocks option to emit hier_block annotations
Copilot 3d88f3e
Make module-declaration check in CLI test more precise
Copilot f20f8af
Assert non-exported modules omit verilator hier_block metacomment
Copilot d74f8b5
Parse modules on declaration boundaries for robustness
Copilot 0c833dd
Fix review feedback on hier_block placement and docs
Copilot 54133d1
Merge remote-tracking branch 'origin/main' into copilot/emit-hierarch…
Copilot 796b4f2
Remove hier_block CLI flag and emit annotation by default
Copilot c42242a
Generalize SV module pattern checks for CLI tests
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -145,4 +145,3 @@ data Options | |
| , log_file :: Maybe String | ||
| } | ||
| deriving (Show, Data, Typeable) | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| #!/usr/bin/env python3 | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| """ | ||
| Generic checks for generated SystemVerilog modules. | ||
|
|
||
| This script parses all `module` declarations in `*.sv` files under an output | ||
| directory and applies generic pattern-based assertions. | ||
| """ | ||
| import argparse | ||
| import re | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| MODULE_DECL = re.compile(r'(?:^|\s)module\s+(\w+)', re.MULTILINE) | ||
|
|
||
|
|
||
| def collect_modules(sv_files): | ||
| modules = [] | ||
| for sv in sv_files: | ||
| text = sv.read_text() | ||
| decls = list(MODULE_DECL.finditer(text)) | ||
| for i, decl in enumerate(decls): | ||
| end = decls[i + 1].start() if i + 1 < len(decls) else len(text) | ||
| modules.append((sv.name, decl.group(1), text[decl.start():end])) | ||
| return modules | ||
|
|
||
|
|
||
| def check_modules( | ||
| output_dir, | ||
| expect_any_regex=(), | ||
| expect_any_regex_after_port_list=(), | ||
| expect_any_without_regex=(), | ||
| ): | ||
| sv_files = sorted(output_dir.glob('*.sv')) | ||
| if not sv_files: | ||
| print("Expected at least one generated .sv file, but none was found.") | ||
| return 1 | ||
|
|
||
| modules = collect_modules(sv_files) | ||
| if not modules: | ||
| names = ', '.join(s.name for s in sv_files) | ||
| print(f"No SystemVerilog modules found in {names}.") | ||
| return 1 | ||
|
|
||
| module_names = ', '.join(m[1] for m in modules) | ||
|
|
||
| for pattern in expect_any_regex: | ||
| regex = re.compile(pattern, re.MULTILINE) | ||
| if not any(regex.search(m[2]) for m in modules): | ||
| print(f"Expected at least one module to match regex {pattern!r}: {module_names}.") | ||
| return 1 | ||
|
|
||
| for pattern in expect_any_regex_after_port_list: | ||
| regex = re.compile(pattern, re.MULTILINE) | ||
| matched = False | ||
| for _, _, body in modules: | ||
| port_list_end = body.find(');') | ||
| if port_list_end != -1 and regex.search(body[port_list_end + 2:]): | ||
| matched = True | ||
| break | ||
| if not matched: | ||
| print( | ||
| f"Expected at least one module to match regex {pattern!r} after " | ||
| f"the port list (`);`): {module_names}." | ||
| ) | ||
| return 1 | ||
|
|
||
| for pattern in expect_any_without_regex: | ||
| regex = re.compile(pattern, re.MULTILINE) | ||
| if not any(not regex.search(m[2]) for m in modules): | ||
| print(f"Expected at least one module not to match regex {pattern!r}: {module_names}.") | ||
| return 1 | ||
|
|
||
| return 0 | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument('output_dir', help='Directory containing compiler outputs') | ||
| parser.add_argument('--expect-any-regex', action='append', default=[]) | ||
| parser.add_argument('--expect-any-regex-after-port-list', action='append', default=[]) | ||
| parser.add_argument('--expect-any-without-regex', action='append', default=[]) | ||
| args = parser.parse_args() | ||
|
|
||
| output_dir = Path(args.output_dir) | ||
| if not output_dir.is_dir(): | ||
| print(f"Output directory does not exist: {output_dir}") | ||
| return 1 | ||
|
|
||
| return check_modules( | ||
| output_dir, | ||
| expect_any_regex=args.expect_any_regex, | ||
| expect_any_regex_after_port_list=args.expect_any_regex_after_port_list, | ||
| expect_any_without_regex=args.expect_any_without_regex, | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| sys.exit(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #!/usr/bin/env python3 | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| """Verify hier_block annotations in generated SystemVerilog output.""" | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| from check_generated_sv_modules import check_modules | ||
|
|
||
| HIER_BLOCK_REGEX = r'/\*verilator hier_block\*/' | ||
|
|
||
|
|
||
| def main(): | ||
| if len(sys.argv) != 2: | ||
| print("Usage: check_verilator_hier_blocks.py <output_dir>") | ||
| return 1 | ||
|
|
||
| output_dir = Path(sys.argv[1]) | ||
| if not output_dir.is_dir(): | ||
| print(f"Output directory does not exist: {output_dir}") | ||
| return 1 | ||
|
|
||
| return check_modules( | ||
| output_dir, | ||
| expect_any_regex=[HIER_BLOCK_REGEX], | ||
| expect_any_regex_after_port_list=[HIER_BLOCK_REGEX], | ||
| expect_any_without_regex=[HIER_BLOCK_REGEX], | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| sys.exit(main()) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| // Minimal program used by the Verilator hier_block CLI test. | ||
| class VerilatorHierBlock | ||
| { | ||
| public: | ||
| uint32 TimesTwo(uint32 x) | ||
| { | ||
| return x + x; | ||
| } | ||
| } | ||
|
|
||
| export VerilatorHierBlock; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.