Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions backends/generators/capstone/generate_csr_switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""
Generate a C function mapping RISC-V CSR numbers to names using a switch statement.
"""

import sys
import os

# Add parent directory to path to import generator.py
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)

# Import functions from generator.py
from generator import load_csrs


def generate_csr_switch(csrs, output_file):
with open(output_file, "w", encoding="utf-8") as f:
fn_str = """// This file is auto-generated by riscv-unified-db
static const char *getCSRSystemRegisterName(unsigned CsrNo)
{
switch (CsrNo) {
"""
for addr, name in sorted(csrs.items()):
fn_str += f'\tcase 0x{addr:04x}:\n\t\treturn "{name.lower()}";\n'

fn_str += """ }
return NULL;
}
"""
f.write(fn_str)


def main():
import argparse

parser = argparse.ArgumentParser(description="Generate C switch for RISC-V CSRs")
parser.add_argument(
"--csr-dir",
default=os.path.abspath(
os.path.join(os.path.dirname(__file__), "../../../arch/csr/")
),
help="Directory containing CSR YAML files",
)
parser.add_argument(
"--extensions",
default="",
help="Comma-separated list of enabled extensions (default: all)",
)
parser.add_argument(
"--arch",
default="BOTH",
choices=["RV32", "RV64", "BOTH"],
help="Target architecture (RV32, RV64, BOTH)",
)
parser.add_argument(
"--output",
default=os.path.join(os.path.dirname(__file__), "csr_switch.c"),
help="Output C file name",
)
args = parser.parse_args()

enabled_extensions = (
[ext.strip() for ext in args.extensions.split(",") if ext.strip()]
if args.extensions
else []
)
include_all = not enabled_extensions
csrs = load_csrs(args.csr_dir, enabled_extensions, include_all, args.arch)

generate_csr_switch(csrs, args.output)
print(f"Generated: {args.output}")


if __name__ == "__main__":
main()
30 changes: 28 additions & 2 deletions backends/generators/tasks.rake
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# typed: false
# frozen_string_literal: true

require "udb/resolver"
require 'json'
require 'tempfile'
require "json"
require "tempfile"

directory "#{$root}/gen/go"
directory "#{$root}/gen/c_header"
directory "#{$root}/gen/sverilog"
directory "#{$root}/gen/capstone"

def with_resolved_exception_codes(cfg_arch)
# Process ERB templates in exception codes using Ruby ERB processing
Expand Down Expand Up @@ -127,4 +129,28 @@ namespace :gen do
"--output=#{output_dir}riscv_decode_package.svh --include-all"
end
end

desc <<~DESC
Generate Capstone CSR switch from RISC-V CSR definitions
Options:
* CONFIG - Configuration name (defaults to "_")
* OUTPUT_DIR - Output directory for generated Capstone code (defaults to "#{$root}/gen/capstone")
DESC
task capstone: "#{$root}/gen/capstone" do
config_name = ENV["CONFIG"] || "_"
output_dir = ENV["OUTPUT_DIR"] || "#{$root}/gen/capstone/"

# Ensure the output directory exists
FileUtils.mkdir_p output_dir

# Get the arch paths based on the config
resolver = Udb::Resolver.new
cfg_arch = resolver.cfg_arch_for(config_name)
inst_dir = cfg_arch.path / "inst"
csr_dir = cfg_arch.path / "csr"

# Run the Capstone CSR switch generator Python script
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"
end
end
Loading