Skip to content

Commit 5a69acc

Browse files
committed
refactor: update SystemVerilog generator for improved match handling and output file naming
1 parent cfbf86c commit 5a69acc

File tree

2 files changed

+39
-40
lines changed

2 files changed

+39
-40
lines changed

backends/generators/sverilog/sverilog_generator.py

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414

1515
def format_instruction_name(name):
1616
"""Format instruction name for SystemVerilog (uppercase with underscores)."""
17-
# Handle compressed instructions
18-
if name.startswith("c."):
19-
name = "C_" + name[2:]
2017
# Replace dots with underscores and convert to uppercase
2118
return name.replace(".", "_").upper()
2219

@@ -26,76 +23,78 @@ def format_csr_name(name):
2623
return "CSR_" + name.replace(".", "_").upper()
2724

2825

29-
def match_to_sverilog_bits(match_str, is_compressed=False):
26+
def match_to_sverilog_bits(match_str):
3027
"""Convert a match string to SystemVerilog bit pattern."""
3128
if not match_str:
32-
return "32'b" + "?" * 32
33-
34-
# For compressed instructions (16-bit), we need to handle them differently
35-
# The riscv-opcodes format puts the 16-bit pattern in the lower 16 bits
29+
logging.error(f"Empty match string encountered.")
30+
# return "32'b" + "?" * 32
31+
32+
# For compressed instructions (16-bit), we need to handle them differently.
33+
# The 16-bit pattern is in the lower 16 bits,
3634
# with the upper 16 bits as wildcards
37-
if is_compressed or len(match_str) == 16:
35+
if len(match_str) == 16:
3836
# Pad with wildcards on the left for 16-bit instructions
3937
match_str = "?" * 16 + match_str
4038
elif len(match_str) < 32:
4139
# For other cases, pad on the right
42-
match_str = match_str + "-" * (32 - len(match_str))
43-
40+
logging.error(f"Match string length is {len(match_str)}, expected 32 or 16.")
41+
# match_str = match_str + "-" * (32 - len(match_str))
42+
4443
# Convert to SystemVerilog format (0, 1, or ?)
45-
result = []
46-
for bit in match_str:
47-
if bit == "0":
48-
result.append("0")
49-
elif bit == "1":
50-
result.append("1")
51-
else: # '-' or any other character
52-
result.append("?")
53-
44+
result = match_str.replace("-", "?")
45+
5446
return "32'b" + "".join(result)
5547

5648

5749
def generate_sverilog(instructions, csrs, output_file):
5850
"""Generate SystemVerilog package file."""
5951
with open(output_file, "w") as f:
6052
# Write header
61-
f.write("\n/* Automatically generated by parse_opcodes */\n")
53+
f.write("\n/* Automatically generated by UDB */\n")
6254
f.write("package riscv_instr;\n")
63-
55+
6456
# Find the maximum name length for alignment
65-
max_instr_len = max((len(format_instruction_name(name)) for name in instructions.keys()), default=0)
66-
max_csr_len = max((len(format_csr_name(csrs[addr])) for addr in csrs.keys()), default=0)
57+
max_instr_len = max(
58+
(len(format_instruction_name(name)) for name in instructions.keys()),
59+
default=0,
60+
)
61+
max_csr_len = max(
62+
(len(format_csr_name(csrs[addr])) for addr in csrs.keys()), default=0
63+
)
6764
max_len = max(max_instr_len, max_csr_len)
68-
65+
6966
# Write instruction parameters
7067
for name in sorted(instructions.keys()):
7168
encoding = instructions[name]
7269
sv_name = format_instruction_name(name)
7370
# Pad the name for alignment
7471
padded_name = sv_name.ljust(max_len)
75-
72+
# if not name.startswith("v"):
73+
# logging.info(f"Processing instruction: {name}")
74+
# logging.info(f"Formatted instruction: {sv_name}")
75+
# logging.info(f"Padded instruction: {padded_name}")
76+
7677
# Get the match pattern
7778
if isinstance(encoding, dict) and "match" in encoding:
7879
match = encoding["match"]
7980
else:
8081
# If no match field, use all wildcards
81-
match = "-" * 32
82-
83-
# Check if this is a compressed instruction
84-
is_compressed = name.startswith("c.")
85-
sv_bits = match_to_sverilog_bits(match, is_compressed)
86-
f.write(f" localparam [31:0] {padded_name} = {sv_bits};\n")
87-
82+
logging.warning(f"No match field for instruction {name}.")
83+
84+
sv_bits = match_to_sverilog_bits(match)
85+
f.write(f" localparam logic [31:0] {padded_name} = {sv_bits};\n")
86+
8887
# Write CSR parameters
8988
# CSRs are returned as {address: name} by load_csrs
9089
for addr in sorted(csrs.keys()):
9190
csr_name = csrs[addr]
9291
sv_name = format_csr_name(csr_name)
9392
# Pad the name for alignment
9493
padded_name = sv_name.ljust(max_len)
95-
94+
9695
# Format CSR address as 12-bit hex
9796
f.write(f" localparam logic [11:0] {padded_name} = 12'h{addr:03x};\n")
98-
97+
9998
# Write footer
10099
f.write("\nendpackage\n")
101100

@@ -115,9 +114,9 @@ def parse_args():
115114
help="Directory containing CSR YAML files",
116115
)
117116
parser.add_argument(
118-
"--output",
119-
default="inst.sverilog",
120-
help="Output SystemVerilog file name"
117+
"--output",
118+
default="riscv_decode_package.svh",
119+
help="Output SystemVerilog file name",
121120
)
122121
parser.add_argument(
123122
"--extensions",
@@ -176,4 +175,4 @@ def main():
176175

177176

178177
if __name__ == "__main__":
179-
main()
178+
main()

backends/generators/tasks.rake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,6 @@ namespace :gen do
110110
csr_dir = cfg_arch.path / "csr"
111111

112112
# Run the SystemVerilog generator script using the same Python environment
113-
sh "#{$root}/.home/.venv/bin/python3 #{$root}/backends/generators/sverilog/sverilog_generator.py --inst-dir=#{inst_dir} --csr-dir=#{csr_dir} --output=#{output_dir}inst.sverilog"
113+
sh "#{$root}/.home/.venv/bin/python3 #{$root}/backends/generators/sverilog/sverilog_generator.py --inst-dir=#{inst_dir} --csr-dir=#{csr_dir} --output=#{output_dir}riscv_decode_package.svh"
114114
end
115115
end

0 commit comments

Comments
 (0)