-
Notifications
You must be signed in to change notification settings - Fork 247
Add initial Golang generation support. #526
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
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4a3025a
Add initial Golang generation support.
1fc7590
Enhance go generator to allow filtering by extensions
5b3a379
Enhance Go CSR generation by filtering out unused extensions and defi…
60bdf6c
update checked out version of inst.go changed by latest commits.
a0e4abc
Refactor to ensure reusable code, given the extensibility of outputs …
a2fe524
Fix Go awkward struct spacing.
f92f410
Add rake task to generate Golang input - inst.go
362b01e
Add CSR ordering to match riscv-opcodes.
89873fa
Remove checked out inst.go
7d3c6f7
Merge branch 'main' into AFOliveira/GoSupport
11461ed
Update all spacing to exactly match riscv-opcodes.
0505d06
Change check_requirement due to being out of scope for go_generator c…
11ec002
Add gen:go to CI regression.
096df87
Add gen:go to local regression test.
45b59c4
Merge branch 'main' into AFOliveira/GoSupport
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
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,170 @@ | ||
| #!/usr/bin/env python3 | ||
| import os | ||
| import sys | ||
| import argparse | ||
| import logging | ||
|
|
||
| # Add parent directory to path to find generator.py | ||
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||
| from generator import load_instructions, load_csrs, parse_match, signed | ||
|
|
||
| logging.basicConfig(level=logging.INFO, format="%(levelname)s:: %(message)s") | ||
|
|
||
|
|
||
| def make_go(instr_dict, csrs, output_file="inst.go"): | ||
| """ | ||
| Generate a Go source file with the instruction encodings followed by | ||
| a map of CSR names and addresses. | ||
| """ | ||
| args = " ".join(sys.argv) | ||
| prelude = f"// Code generated by {args}; DO NOT EDIT.\n" | ||
| prelude += """package riscv | ||
|
|
||
| import "cmd/internal/obj" | ||
|
|
||
| type inst struct { | ||
| opcode uint32 | ||
| funct3 uint32 | ||
| rs1 uint32 | ||
| rs2 uint32 | ||
| csr int64 | ||
| funct7 uint32 | ||
| } | ||
|
|
||
| func encode(a obj.As) *inst { | ||
| switch a { | ||
| """ | ||
|
|
||
| instr_str = "" | ||
| # Process instructions in sorted order (by name) | ||
| for name, info in sorted(instr_dict.items(), key=lambda x: x[0].upper()): | ||
| match_str = info["match"] | ||
| enc_match = parse_match(match_str) | ||
| opcode = (enc_match >> 0) & ((1 << 7) - 1) | ||
| funct3 = (enc_match >> 12) & ((1 << 3) - 1) | ||
| rs1 = (enc_match >> 15) & ((1 << 5) - 1) | ||
| rs2 = (enc_match >> 20) & ((1 << 5) - 1) | ||
| csr_val = (enc_match >> 20) & ((1 << 12) - 1) | ||
| funct7 = (enc_match >> 25) & ((1 << 7) - 1) | ||
| # Create the instruction case name. For example, "bclri" becomes "ABCLRI" | ||
| instr_case = f"A{name.upper().replace('.','')}" | ||
| instr_str += f""" case {instr_case}: | ||
| return &inst{{ {hex(opcode)}, {hex(funct3)}, {hex(rs1)}, {hex(rs2)}, {signed(csr_val,12)}, {hex(funct7)} }} | ||
| """ | ||
| instructions_end = """ } | ||
| return nil | ||
| } | ||
| """ | ||
|
|
||
| # Build the CSR map block - now matching the second script's format | ||
| csrs_map_str = "var csrs = map[uint16]string {\n" | ||
| # Convert the dictionary to a list of tuples and sort by address | ||
| csr_items = [(int(addr), name.upper()) for addr, name in csrs.items()] | ||
| for addr, name in sorted(csr_items, key=lambda x: x[0]): | ||
| csrs_map_str += f'{hex(addr)} : "{name}",\n' | ||
| csrs_map_str += "}\n" | ||
|
|
||
| go_code = prelude + instr_str + instructions_end + "\n" + csrs_map_str | ||
|
|
||
| with open(output_file, "w", encoding="utf-8") as f: | ||
| f.write(go_code) | ||
| logging.info( | ||
| f"Generated {output_file} with {len(instr_dict)} instructions and {len(csrs)} CSRs" | ||
| ) | ||
|
|
||
|
|
||
| def parse_args(): | ||
| parser = argparse.ArgumentParser( | ||
| description="Generate Go code for RISC-V instructions and CSRs filtered by extensions" | ||
| ) | ||
| parser.add_argument( | ||
| "--inst-dir", | ||
| default="../../../arch/inst/", | ||
| help="Directory containing instruction YAML files", | ||
| ) | ||
| parser.add_argument( | ||
| "--csr-dir", | ||
| default="../../../arch/csr/", | ||
| help="Directory containing CSR YAML files", | ||
| ) | ||
| parser.add_argument("--output", default="inst.go", help="Output Go file name") | ||
| parser.add_argument( | ||
| "--extensions", | ||
| default="A,D,F,I,M,Q,Zba,Zbb,Zbs,S,System,V,Zicsr,Smpmp,Sm,H,U,Zicntr,Zihpm,Smhpm", | ||
| help="Comma-separated list of enabled extensions. Default includes standard extensions.", | ||
| ) | ||
| parser.add_argument( | ||
| "--arch", | ||
| default="RV64", | ||
| choices=["RV32", "RV64", "BOTH"], | ||
| help="Target architecture (RV32, RV64, or BOTH). Default is RV64.", | ||
| ) | ||
| parser.add_argument( | ||
| "--verbose", "-v", action="store_true", help="Enable verbose logging" | ||
| ) | ||
| parser.add_argument( | ||
| "--include-all", | ||
| "-a", | ||
| action="store_true", | ||
| help="Include all instructions, ignoring extension filtering", | ||
| ) | ||
| return parser.parse_args() | ||
|
|
||
|
|
||
| def main(): | ||
| args = parse_args() | ||
|
|
||
| if args.verbose: | ||
| logging.getLogger().setLevel(logging.DEBUG) | ||
|
|
||
| # Check if we should include all instructions | ||
| include_all = args.include_all or not args.extensions | ||
|
|
||
| # Parse enabled extensions | ||
| if include_all: | ||
| enabled_extensions = [] | ||
| logging.info( | ||
| "Including all instructions and CSRs (extension filtering disabled)" | ||
| ) | ||
| else: | ||
| # Get extensions from the command line | ||
| enabled_extensions = [ | ||
| ext.strip() for ext in args.extensions.split(",") if ext.strip() | ||
| ] | ||
| logging.info(f"Enabled extensions: {', '.join(enabled_extensions)}") | ||
|
|
||
| # Log target architecture | ||
| logging.info(f"Target architecture: {args.arch}") | ||
|
|
||
| # Check if the directories exist | ||
| if not os.path.isdir(args.inst_dir): | ||
| logging.error(f"Instruction directory not found: {args.inst_dir}") | ||
| sys.exit(1) | ||
| if not os.path.isdir(args.csr_dir): | ||
| logging.warning(f"CSR directory not found: {args.csr_dir}") | ||
|
|
||
| # Load instructions filtered by extensions or all instructions | ||
| instr_dict = load_instructions( | ||
| args.inst_dir, enabled_extensions, include_all, args.arch | ||
| ) | ||
| if not instr_dict: | ||
| logging.error("No instructions found or all were filtered out.") | ||
| logging.error( | ||
| "Try using --verbose to see more details about the filtering process." | ||
| ) | ||
| sys.exit(1) | ||
| logging.info(f"Loaded {len(instr_dict)} instructions") | ||
|
|
||
| # Load CSRs filtered by extensions or all CSRs | ||
| csrs = load_csrs(args.csr_dir, enabled_extensions, include_all, args.arch) | ||
| if not csrs: | ||
| logging.warning("No CSRs found or all were filtered out.") | ||
| else: | ||
| logging.info(f"Loaded {len(csrs)} CSRs") | ||
|
|
||
| # Generate the Go code | ||
| make_go(instr_dict, csrs, args.output) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
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.
Check warning
Code scanning / CodeQL
Workflow does not contain permissions