Skip to content

Commit 2c7c616

Browse files
committed
Enhance error handling and support for non-default extensions, such as qc_iu
Signed-off-by: Afonso Oliveira <[email protected]>
1 parent 62e0711 commit 2c7c616

File tree

1 file changed

+110
-80
lines changed

1 file changed

+110
-80
lines changed

ext/opcodes_maker/yaml_to_json.py

Lines changed: 110 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
from typing import List, Dict
1+
#!/usr/bin/env python3
2+
3+
from typing import List, Dict, Union, Any
24
import os
35
import yaml
46
import json
57
import argparse
8+
import sys
69

710

811
def range_size(range_str: str) -> int:
@@ -16,7 +19,7 @@ def range_size(range_str: str) -> int:
1619
reg_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

177207
if __name__ == "__main__":

0 commit comments

Comments
 (0)