1414
1515def 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
5749def 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 ("\n endpackage\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
178177if __name__ == "__main__" :
179- main ()
178+ main ()
0 commit comments