Skip to content

Commit e378ea3

Browse files
committed
Add generator for capstone
1 parent 3d9129d commit e378ea3

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate a C function mapping RISC-V CSR numbers to names using a switch statement.
4+
"""
5+
6+
import sys
7+
import os
8+
9+
# Add parent directory to path to import generator.py
10+
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
11+
sys.path.append(parent_dir)
12+
13+
# Import functions from generator.py
14+
from generator import load_csrs
15+
16+
17+
def generate_csr_switch(csrs, output_file):
18+
with open(output_file, "w", encoding="utf-8") as f:
19+
fn_str = """// This file is auto-generated by riscv-unified-db
20+
static const char *getCSRSystemRegisterName(unsigned CsrNo)
21+
{
22+
switch (CsrNo) {
23+
"""
24+
for addr, name in sorted(csrs.items()):
25+
fn_str += f'\tcase 0x{addr:04x}:\n\t\treturn "{name.lower()}";\n'
26+
27+
fn_str += """ }
28+
return NULL;
29+
}
30+
"""
31+
f.write(fn_str)
32+
33+
34+
def main():
35+
import argparse
36+
37+
parser = argparse.ArgumentParser(description="Generate C switch for RISC-V CSRs")
38+
parser.add_argument(
39+
"--csr-dir",
40+
default=os.path.abspath(
41+
os.path.join(os.path.dirname(__file__), "../../../arch/csr/")
42+
),
43+
help="Directory containing CSR YAML files",
44+
)
45+
parser.add_argument(
46+
"--extensions",
47+
default="",
48+
help="Comma-separated list of enabled extensions (default: all)",
49+
)
50+
parser.add_argument(
51+
"--arch",
52+
default="BOTH",
53+
choices=["RV32", "RV64", "BOTH"],
54+
help="Target architecture (RV32, RV64, BOTH)",
55+
)
56+
parser.add_argument(
57+
"--output",
58+
default=os.path.join(os.path.dirname(__file__), "csr_switch.c"),
59+
help="Output C file name",
60+
)
61+
args = parser.parse_args()
62+
63+
enabled_extensions = (
64+
[ext.strip() for ext in args.extensions.split(",") if ext.strip()]
65+
if args.extensions
66+
else []
67+
)
68+
include_all = not enabled_extensions
69+
csrs = load_csrs(args.csr_dir, enabled_extensions, include_all, args.arch)
70+
71+
generate_csr_switch(csrs, args.output)
72+
print(f"Generated: {args.output}")
73+
74+
75+
if __name__ == "__main__":
76+
main()

backends/generators/tasks.rake

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require 'tempfile'
66

77
directory "#{$root}/gen/go"
88
directory "#{$root}/gen/c_header"
9+
directory "#{$root}/gen/capstone"
910

1011
namespace :gen do
1112
desc <<~DESC
@@ -87,4 +88,28 @@ namespace :gen do
8788
resolved_codes_file.unlink
8889
end
8990
end
91+
92+
desc <<~DESC
93+
Generate Capstone CSR switch from RISC-V CSR definitions
94+
95+
Options:
96+
* CONFIG - Configuration name (defaults to "_")
97+
* OUTPUT_DIR - Output directory for generated Capstone code (defaults to "#{$root}/gen/capstone")
98+
DESC
99+
task capstone: "#{$root}/gen/capstone" do
100+
config_name = ENV["CONFIG"] || "_"
101+
output_dir = ENV["OUTPUT_DIR"] || "#{$root}/gen/capstone/"
102+
103+
# Ensure the output directory exists
104+
FileUtils.mkdir_p output_dir
105+
106+
# Get the arch paths based on the config
107+
resolver = Udb::Resolver.new
108+
cfg_arch = resolver.cfg_arch_for(config_name)
109+
inst_dir = cfg_arch.path / "inst"
110+
csr_dir = cfg_arch.path / "csr"
111+
112+
# Run the Capstone CSR switch generator Python script
113+
sh "#{$root}/.home/.venv/bin/python3 #{$root}/backends/generators/capstone/generate_csr_switch.py --csr-dir=#{csr_dir} --arch=BOTH --output=#{output_dir}csr_switch.c"
114+
end
90115
end

0 commit comments

Comments
 (0)