Skip to content

Commit 13ae618

Browse files
fix: add backward compatibility for new instruction schema format (#1092)
This pull request enhances support for a new instruction schema in the code generator by adding logic to interpret and convert the newer `format` field into the legacy `encoding` format when loading instructions. This ensures backward compatibility and smoother migration to the new schema without breaking existing functionality. **Support for new instruction schema:** * Added a new function `build_match_from_format` in `generator.py` to construct a match string from the `format` field, supporting 16-, 32-, and 48-bit instructions. This function interprets opcode and variable bit locations and values to generate the appropriate match string. * Updated the instruction loading logic in `load_instructions` to detect when only a `format` field (and not an `encoding` field) is present. If found, it uses `build_match_from_format` to synthesize an `encoding` entry, allowing the rest of the pipeline to function unchanged. If conversion fails, the instruction is filtered out with an error log. --------- Signed-off-by: Afonso Oliveira <[email protected]> Co-authored-by: Afonso Oliveira <[email protected]>
1 parent 7ae166e commit 13ae618

File tree

1 file changed

+120
-5
lines changed

1 file changed

+120
-5
lines changed

backends/generators/generator.py

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,105 @@ def check_requirement(req, exts):
1717
return False
1818

1919

20+
def build_match_from_format(format_field):
21+
"""
22+
Build a match string from the format field in the new schema.
23+
"""
24+
if not format_field or "opcodes" not in format_field:
25+
return None
26+
27+
# Determine instruction width by finding maximum bit position
28+
valid_locations = []
29+
30+
opcodes = format_field["opcodes"]
31+
# Check opcodes
32+
for field_data in opcodes.values():
33+
if isinstance(field_data, dict) and "location" in field_data:
34+
if isinstance(field_data["location"], str):
35+
try:
36+
location = field_data["location"]
37+
split_location = location.split("|")
38+
high = max(
39+
(
40+
int(location.split("-")[0])
41+
if "-" in location
42+
else int(location)
43+
)
44+
for location in split_location
45+
)
46+
valid_locations.append(high)
47+
except (ValueError, IndexError):
48+
raise ValueError(
49+
f"Invalid location format: {field_data['location']}"
50+
)
51+
elif isinstance(field_data["location"], int):
52+
try:
53+
valid_locations.append(field_data["location"])
54+
except (ValueError, IndexError):
55+
raise ValueError(
56+
f"Invalid location format: {field_data['location']}"
57+
)
58+
else:
59+
raise ValueError(f"Unknown location format: {field_data['location']}")
60+
61+
if "variables" in format_field:
62+
variables = format_field["variables"]
63+
# Check variables
64+
for var_data in variables.values():
65+
if isinstance(var_data, dict) and "location" in var_data:
66+
if isinstance(var_data["location"], str):
67+
try:
68+
location = var_data["location"]
69+
if "-" in location:
70+
high = int(location.split("-")[0])
71+
else:
72+
high = int(location)
73+
valid_locations.append(high)
74+
except (ValueError, IndexError):
75+
raise ValueError(
76+
f"Invalid location format: {var_data['location']}"
77+
)
78+
elif isinstance(var_data["location"], int):
79+
try:
80+
valid_locations.append(var_data["location"])
81+
except (ValueError, IndexError):
82+
raise ValueError(
83+
f"Invalid location format: {var_data['location']}"
84+
)
85+
else:
86+
raise ValueError(f"Invalid location format: {var_data['location']}")
87+
88+
if not valid_locations:
89+
raise ValueError("No valid bit locations found in format field")
90+
91+
max_bit = max(valid_locations)
92+
93+
# Set instruction width based on maximum bit position
94+
width = max_bit + 1
95+
match_bits = ["-"] * width
96+
97+
# Populate match string with opcode bits
98+
for field_data in opcodes.values():
99+
if isinstance(field_data, dict):
100+
try:
101+
location = field_data["location"]
102+
if isinstance(location, str) and "-" in location:
103+
high, low = map(int, location.split("-"))
104+
else:
105+
high = low = int(location)
106+
107+
if high < low or high >= width:
108+
logging.warning(f"Invalid bit range: {location}")
109+
continue # Skip invalid bit ranges
110+
111+
binary_value = format(field_data["value"], f"0{high - low + 1}b")
112+
match_bits[width - high - 1 : width - low] = binary_value
113+
except (ValueError, IndexError):
114+
raise ValueError(f"Error processing opcode field: {field_data}")
115+
116+
return "".join(match_bits)
117+
118+
20119
def parse_extension_requirements(extensions_spec):
21120
"""
22121
Parse the extension requirements from the definedBy field.
@@ -177,11 +276,27 @@ def load_instructions(
177276

178277
encoding = data.get("encoding", {})
179278
if not encoding:
180-
logging.error(
181-
f"Missing 'encoding' field in instruction {name} in {path}"
182-
)
183-
encoding_filtered += 1
184-
continue
279+
# Check if this instruction uses the new schema with a 'format' field
280+
format_field = data.get("format")
281+
if not format_field:
282+
logging.error(
283+
f"Missing 'encoding' field in instruction {name} in {path}"
284+
)
285+
encoding_filtered += 1
286+
continue
287+
288+
# Try to build a match string from the format field
289+
match_string = build_match_from_format(format_field)
290+
if not match_string:
291+
logging.error(
292+
f"Could not build encoding from format field in instruction {name} in {path}"
293+
)
294+
encoding_filtered += 1
295+
continue
296+
297+
# Create a synthetic encoding compatible with existing logic
298+
encoding = {"match": match_string, "variables": []}
299+
logging.debug(f"Built encoding from format field for {name}")
185300

186301
# Check if the instruction specifies a base architecture constraint
187302
base = data.get("base")

0 commit comments

Comments
 (0)