1- from typing import List , Dict
1+ #!/usr/bin/env python3
2+
3+ from typing import List , Dict , Union , Any
24import os
35import yaml
46import json
57import argparse
8+ import sys
69
710
811def range_size (range_str : str ) -> int :
@@ -16,7 +19,7 @@ def range_size(range_str: str) -> int:
1619reg_names = {"qs1" , "qs2" , "qd" , "fs1" , "fs2" , "fd" }
1720
1821
19- def GetVariables (vars : List [Dict [str , str ]]):
22+ def GetVariables (vars : List [Dict [str , str ]]) -> List [ str ] :
2023 var_names = []
2124 for var in vars :
2225 var_name = var ["name" ]
@@ -33,7 +36,6 @@ def GetVariables(vars: List[Dict[str, str]]):
3336 var_name = "shamtd"
3437 var_names .append (var_name )
3538 var_names .reverse ()
36-
3739 return var_names
3840
3941
@@ -57,86 +59,105 @@ def GetMask(bit_str: str) -> str:
5759 return hex (int (mask_str , 2 ))
5860
5961
60- def GetExtension (ext , base ):
62+ def process_extension (ext : Union [str , dict ]) -> List [str ]:
63+ """Process an extension definition into a list of strings."""
64+ if isinstance (ext , str ):
65+ return [ext .lower ()]
66+ elif isinstance (ext , dict ):
67+ result = []
68+ for item in ext .values ():
69+ if isinstance (item , list ):
70+ result .extend (
71+ [
72+ x .lower () if isinstance (x , str ) else x ["name" ].lower ()
73+ for x in item
74+ ]
75+ )
76+ elif isinstance (item , (str , dict )):
77+ if isinstance (item , str ):
78+ result .append (item .lower ())
79+ else :
80+ result .append (item ["name" ].lower ())
81+ return result
82+ return []
83+
84+
85+ def GetExtension (ext : Union [str , dict , list ], base : str ) -> List [str ]:
86+ """Get a list of extensions with proper prefix."""
6187 prefix = f"rv{ base } _"
6288 final_extensions = []
6389
64- if isinstance (ext , str ):
65- final_extensions .append (prefix + ext .lower ())
66- elif isinstance (ext , dict ):
67- for _ , extensions in ext .items ():
68- for extension in extensions :
69- final_extensions .append (prefix + extension .lower ())
70- final_extensions .reverse ()
71-
72- return final_extensions
73-
74-
75- def find_first_match (data ):
76- if isinstance (data , dict ):
77- for key , value in data .items ():
78- if key == "match" :
79- return value
80- elif isinstance (value , (dict , list )):
81- result = find_first_match (value )
82- if result is not None :
83- return result
84- elif isinstance (data , list ):
85- for item in data :
86- result = find_first_match (item )
87- if result is not None :
88- return result
89- return ""
90-
91-
92- def GetEncodings (enc : str ):
90+ if isinstance (ext , (str , dict )):
91+ extensions = process_extension (ext )
92+ final_extensions .extend (prefix + x for x in extensions )
93+ elif isinstance (ext , list ):
94+ for item in ext :
95+ extensions = process_extension (item )
96+ final_extensions .extend (prefix + x for x in extensions )
97+
98+ # Remove duplicates while preserving order
99+ seen = set ()
100+ return [x for x in final_extensions if not (x in seen or seen .add (x ))]
101+
102+
103+ def GetEncodings (enc : str ) -> str :
93104 n = len (enc )
94105 if n < 32 :
95106 return "-" * (32 - n ) + enc
96107 return enc
97108
98109
99- def convert (file_dir : str , json_out ):
100- with open (file_dir ) as file :
101- data = yaml .safe_load (file )
102- instr_name = data ["name" ].replace ("." , "_" )
103-
104- print (instr_name )
105- encodings = data ["encoding" ]
106-
107- # USE RV_64
108- rv64_flag = False
109- if "RV64" in encodings :
110- encodings = encodings ["RV64" ]
111- rv64_flag = True
112- enc_match = GetEncodings (encodings ["match" ])
113-
114- var_names = []
115- if "variables" in encodings :
116- var_names = GetVariables (encodings ["variables" ])
117-
118- extension = []
119- prefix = ""
120- if rv64_flag :
121- prefix = "64"
122- if "base" in data :
123- extension = GetExtension (data ["definedBy" ], data ["base" ])
124- else :
125- extension = GetExtension (data ["definedBy" ], prefix )
126-
127- match_hex = BitStringToHex (enc_match )
128- match_mask = GetMask (enc_match )
129-
130- json_out [instr_name ] = {
131- "encoding" : enc_match ,
132- "variable_fields" : var_names ,
133- "extension" : extension ,
134- "match" : match_hex ,
135- "mask" : match_mask ,
136- }
137-
138-
139- def read_yaml_insts (path : str ):
110+ def convert (file_dir : str , json_out : Dict [str , Any ]) -> None :
111+ try :
112+ with open (file_dir ) as file :
113+ data = yaml .safe_load (file )
114+ instr_name = data ["name" ].replace ("." , "_" )
115+
116+ print (instr_name )
117+ encodings = data ["encoding" ]
118+
119+ # USE RV_64
120+ rv64_flag = False
121+ if "RV64" in encodings :
122+ encodings = encodings ["RV64" ]
123+ rv64_flag = True
124+ enc_match = GetEncodings (encodings ["match" ])
125+
126+ var_names = []
127+ if "variables" in encodings :
128+ var_names = GetVariables (encodings ["variables" ])
129+
130+ extension = []
131+ prefix = ""
132+ if rv64_flag :
133+ prefix = "64"
134+ try :
135+ if "base" in data :
136+ extension = GetExtension (data ["definedBy" ], data ["base" ])
137+ else :
138+ extension = GetExtension (data ["definedBy" ], prefix )
139+ except Exception as e :
140+ print (
141+ f"Warning: Error processing extensions for { instr_name } : { str (e )} "
142+ )
143+ extension = []
144+
145+ match_hex = BitStringToHex (enc_match )
146+ match_mask = GetMask (enc_match )
147+
148+ json_out [instr_name ] = {
149+ "encoding" : enc_match ,
150+ "variable_fields" : var_names ,
151+ "extension" : extension ,
152+ "match" : match_hex ,
153+ "mask" : match_mask ,
154+ }
155+ except Exception as e :
156+ print (f"Error processing file { file_dir } : { str (e )} " )
157+ raise
158+
159+
160+ def read_yaml_insts (path : str ) -> List [str ]:
140161 yaml_files = []
141162 for root , _ , files in os .walk (path ):
142163 for file in files :
@@ -165,13 +186,22 @@ def main():
165186 inst_dict = {}
166187 output_file = os .path .join (args .output_dir , "instr_dict.json" )
167188
168- with open ( output_file , "w" ) as outfile :
189+ try :
169190 for inst_dir in insts :
170- convert (inst_dir , inst_dict )
171- json .dump (inst_dict , outfile , indent = 4 )
172-
173- print (f"Successfully processed { len (insts )} YAML files" )
174- print (f"Output written to: { output_file } " )
191+ try :
192+ convert (inst_dir , inst_dict )
193+ except Exception as e :
194+ print (f"Warning: Failed to process { inst_dir } : { str (e )} " )
195+ continue
196+
197+ with open (output_file , "w" ) as outfile :
198+ json .dump (inst_dict , outfile , indent = 4 )
199+
200+ print (f"Successfully processed { len (insts )} YAML files" )
201+ print (f"Output written to: { output_file } " )
202+ except Exception as e :
203+ print (f"Error: Failed to process YAML files: { str (e )} " )
204+ sys .exit (1 )
175205
176206
177207if __name__ == "__main__" :
0 commit comments