Changing operand matching for class operand style

This commit is contained in:
stefandesouza
2023-09-25 21:35:17 +02:00
parent 42f96753c1
commit db899a2709
4 changed files with 60 additions and 58 deletions

View File

@@ -320,13 +320,15 @@ class MachineModel(object):
@staticmethod @staticmethod
def get_full_instruction_name(instruction_form): def get_full_instruction_name(instruction_form):
"""Get one instruction name string including the mnemonic and all operands.""" """Get one instruction name string including the mnemonic and all operands."""
if instruction_form==None:
return ""
operands = [] operands = []
for op in instruction_form.operands: for op in instruction_form["operands"]:
op_attrs = [ op_attrs = [
y + ":" + str(op[y]) "name:" + op.name
for y in list(filter(lambda x: True if x != "class" else False, op)) #for y in list(filter(lambda x: True if x != "class" else False, op))
] ]
operands.append("{}({})".format(op["class"], ",".join(op_attrs))) operands.append("{}({})".format("register", ",".join(op_attrs)))
return "{} {}".format(instruction_form["name"].lower(), ",".join(operands)) return "{} {}".format(instruction_form["name"].lower(), ",".join(operands))
@staticmethod @staticmethod
@@ -595,53 +597,53 @@ class MachineModel(object):
def _check_AArch64_operands(self, i_operand, operand): def _check_AArch64_operands(self, i_operand, operand):
"""Check if the types of operand ``i_operand`` and ``operand`` match.""" """Check if the types of operand ``i_operand`` and ``operand`` match."""
if "class" in operand: #if "class" in operand:
# compare two DB entries # compare two DB entries
return self._compare_db_entries(i_operand, operand) # return self._compare_db_entries(i_operand, operand)
# TODO support class wildcards # TODO support class wildcards
# register # register
if "register" in operand: if isinstance(operand, RegisterOperand):
if i_operand["class"] != "register": if not isinstance(i_operand, RegisterOperand):
return False return False
return self._is_AArch64_reg_type(i_operand, operand["register"]) return self._is_AArch64_reg_type(i_operand, operand)
# memory # memory
if "memory" in operand: if isinstance(operand, MemoryOperand):
if i_operand["class"] != "memory": if not isinstance(i_operand, MemoryOperand):
return False return False
return self._is_AArch64_mem_type(i_operand, operand["memory"]) return self._is_AArch64_mem_type(i_operand, operand)
# immediate # immediate
if i_operand["class"] == "immediate" and i_operand["imd"] == self.WILDCARD: if isinstance(i_operand, ImmediateOperand) and i_operand.type == self.WILDCARD:
return "value" in operand or ( return "value" in operand.value or (
"immediate" in operand and "value" in operand["immediate"] "immediate" in operand and "value" in operand["immediate"]
) )
if i_operand["class"] == "immediate" and i_operand["imd"] == "int": if isinstance(i_operand, ImmediateOperand) and i_operand.type == "int":
return ("value" in operand and operand.get("type", None) == "int") or ( return ("value" in operand and operand.get("type", None) == "int") or (
"immediate" in operand "immediate" in operand
and "value" in operand["immediate"] and "value" in operand["immediate"]
and operand["immediate"].get("type", None) == "int" and operand["immediate"].get("type", None) == "int"
) )
if i_operand["class"] == "immediate" and i_operand["imd"] == "float": if isinstance(i_operand, ImmediateOperand) and i_operand.type == "float":
return ("float" in operand and operand.get("type", None) == "float") or ( return ("float" in operand and operand.get("type", None) == "float") or (
"immediate" in operand "immediate" in operand
and "float" in operand["immediate"] and "float" in operand["immediate"]
and operand["immediate"].get("type", None) == "float" and operand["immediate"].get("type", None) == "float"
) )
if i_operand["class"] == "immediate" and i_operand["imd"] == "double": if isinstance(i_operand, ImmediateOperand) and i_operand.type == "double":
return ("double" in operand and operand.get("type", None) == "double") or ( return ("double" in operand and operand.get("type", None) == "double") or (
"immediate" in operand "immediate" in operand
and "double" in operand["immediate"] and "double" in operand["immediate"]
and operand["immediate"].get("type", None) == "double" and operand["immediate"].get("type", None) == "double"
) )
# identifier # identifier
if "identifier" in operand or ( if isinstance(operand, IdentifierOperand) or (
"immediate" in operand and "identifier" in operand["immediate"] isinstance(operand, ImmediateOperand) and isinstance(operand, IdentifierOperand)
): ):
return i_operand["class"] == "identifier" return i_operand["class"] == "identifier"
# prefetch option # prefetch option
if "prfop" in operand: if not isinstance(operand, Operand) and "prfop" in operand:
return i_operand["class"] == "prfop" return i_operand["class"] == "prfop"
# condition # condition
if "condition" in operand: if not isinstance(operand, Operand) and "condition" in operand:
if i_operand["ccode"] == self.WILDCARD: if i_operand["ccode"] == self.WILDCARD:
return True return True
return i_operand["class"] == "condition" and ( return i_operand["class"] == "condition" and (
@@ -698,27 +700,27 @@ class MachineModel(object):
def _is_AArch64_reg_type(self, i_reg, reg): def _is_AArch64_reg_type(self, i_reg, reg):
"""Check if register type match.""" """Check if register type match."""
# check for wildcards # check for wildcards
if reg["prefix"] == self.WILDCARD or i_reg["prefix"] == self.WILDCARD: if reg.prefix == self.WILDCARD or i_reg.prefix == self.WILDCARD:
if "shape" in reg: if reg.shape!=None:
if "shape" in i_reg and ( if i_reg.shape!=None and (
reg["shape"] == i_reg["shape"] reg.shape == i_reg.shape
or self.WILDCARD in (reg["shape"] + i_reg["shape"]) or self.WILDCARD in (reg.shape + i_reg.shape)
): ):
return True return True
return False return False
return True return True
# check for prefix and shape # check for prefix and shape
if reg["prefix"] != i_reg["prefix"]: if reg.prefix != i_reg.prefix:
return False return False
if "shape" in reg: if reg.shape!=None:
if "shape" in i_reg and ( if i_reg.shape!=None and (
reg["shape"] == i_reg["shape"] or self.WILDCARD in (reg["shape"] + i_reg["shape"]) reg.shape == i_reg.shape or self.WILDCARD in (reg.shape + i_reg.shape)
): ):
return True return True
return False return False
if "lanes" in reg: if reg.lanes!=None:
if "lanes" in i_reg and ( if i_reg.lanes!=None and (
reg["lanes"] == i_reg["lanes"] or self.WILDCARD in (reg["lanes"] + i_reg["lanes"]) reg.lanes == i_reg.lanes or self.WILDCARD in (reg.lanes + i_reg.lanes)
): ):
return True return True
return False return False
@@ -735,6 +737,8 @@ class MachineModel(object):
else: else:
i_reg_name = i_reg i_reg_name = i_reg
# check for wildcards # check for wildcards
if isinstance(reg,str):
return False
if i_reg_name == self.WILDCARD or reg.name == self.WILDCARD: if i_reg_name == self.WILDCARD or reg.name == self.WILDCARD:
return True return True
# differentiate between vector registers (mm, xmm, ymm, zmm) and others (gpr) # differentiate between vector registers (mm, xmm, ymm, zmm) and others (gpr)
@@ -780,7 +784,7 @@ class MachineModel(object):
( (
(mem.base is None and i_mem.base is None) (mem.base is None and i_mem.base is None)
or i_mem.base == self.WILDCARD or i_mem.base == self.WILDCARD
or mem.base["prefix"] == i_mem.base or mem.base.prefix == i_mem.base
) )
# check offset # check offset
and ( and (
@@ -799,8 +803,8 @@ class MachineModel(object):
or i_mem.index == self.WILDCARD or i_mem.index == self.WILDCARD
or ( or (
mem.index is not None mem.index is not None
and mem["index"].prefix != None and mem.index.prefix != None
and mem.index["prefix"] == i_mem.index and mem.index.prefix == i_mem.index
) )
) )
# check scale # check scale
@@ -811,12 +815,12 @@ class MachineModel(object):
) )
# check pre-indexing # check pre-indexing
and ( and (
i_mem.pre - indexed == self.WILDCARD or (mempre - indexed) == (i_mem.pre - indexed) i_mem.pre_indexed == self.WILDCARD or (mem.pre_indexed) == (i_mem.pre_indexed)
) )
# check post-indexing # check post-indexing
and ( and (
i_mem.post - indexed == self.WILDCARD i_mem.post_indexed == self.WILDCARD
or (mem.post - indexed) == (i_mem.post - indexed) or (mem.post_indexed) == (i_mem.post_indexed)
) )
): ):
return True return True
@@ -856,7 +860,7 @@ class MachineModel(object):
or i_mem.index == self.WILDCARD or i_mem.index == self.WILDCARD
or ( or (
mem.index is not None mem.index is not None
and mem.index.name != None #and mem.index.name != None
and self._is_x86_reg_type(i_mem.index, mem.index) and self._is_x86_reg_type(i_mem.index, mem.index)
) )
) )

View File

@@ -182,19 +182,19 @@ class ISASemantics(object):
isa_data = self._isa_model.get_instruction( isa_data = self._isa_model.get_instruction(
instruction_form.instruction[:suffix_start], instruction_form.operands instruction_form.instruction[:suffix_start], instruction_form.operands
) )
"""
if only_postindexed: if only_postindexed:
for o in instruction_form.operands: for o in instruction_form.operands:
if isinstance(o, MemoryOperand) and o.base!=None: if isinstance(o, MemoryOperand) and o.base!=None and o.post_indexed!=False:
base_name = o.base.prefix if o.base.prefix!=None else "" + o.base.name base_name = o.base.prefix if o.base.prefix!=None else "" + o.base.name
return { return {
base_name: { base_name: {
"name": o.base.prefix if o.base.prefix!=None else "" + o.base.name, "name": o.base.prefix if o.base.prefix!=None else "" + o.base.name,
"value": o.post_indexed["value"], "value": o.post_indexed['value'],
} }
} }
return {} return {}
"""
reg_operand_names = {} # e.g., {'rax': 'op1'} reg_operand_names = {} # e.g., {'rax': 'op1'}
operand_state = {} # e.g., {'op1': {'name': 'rax', 'value': 0}} 0 means unchanged operand_state = {} # e.g., {'op1': {'name': 'rax', 'value': 0}} 0 means unchanged
@@ -253,13 +253,12 @@ class ISASemantics(object):
op_dict["destination"] += operands op_dict["destination"] += operands
if "hidden_operands" in isa_data: if "hidden_operands" in isa_data:
op_dict["destination"] += [ op_dict["destination"] += [
AttrDict.convert_dict(
{ {
hop["class"]: { hop["class"]: {
k: hop[k] for k in ["name", "class", "source", "destination"] k: hop[k] for k in ["name", "class", "source", "destination"]
} }
} }
)
for hop in isa_data["hidden_operands"] for hop in isa_data["hidden_operands"]
] ]
return op_dict return op_dict
@@ -267,6 +266,7 @@ class ISASemantics(object):
for i, op in enumerate(isa_data["operands"]): for i, op in enumerate(isa_data["operands"]):
if isinstance(op, RegisterOperand): if isinstance(op, RegisterOperand):
continue continue
'''
if op["source"] and op["destination"]: if op["source"] and op["destination"]:
op_dict["src_dst"].append(operands[i]) op_dict["src_dst"].append(operands[i])
continue continue
@@ -276,6 +276,7 @@ class ISASemantics(object):
if op["destination"]: if op["destination"]:
op_dict["destination"].append(operands[i]) op_dict["destination"].append(operands[i])
continue continue
'''
# check for hidden operands like flags or registers # check for hidden operands like flags or registers
if "hidden_operands" in isa_data: if "hidden_operands" in isa_data:
# add operand(s) to semantic_operands of instruction form # add operand(s) to semantic_operands of instruction form

View File

@@ -443,8 +443,8 @@ class KernelDG(nx.DiGraph):
continue continue
if mem.index and src.index: if mem.index and src.index:
index_change = register_changes.get( index_change = register_changes.get(
src.index.get("prefix", "") + src.index.name, src.index.prefix if src.index.prefix!=None else "" + src.index.name,
{"name": src.index.get("prefix", "") + src.index.name, "value": 0}, {"name": src.index.prefix if src.index.prefix!=None else "" + src.index.name, "value": 0},
) )
if index_change is None: if index_change is None:
# Unknown change occurred # Unknown change occurred

View File

@@ -125,7 +125,7 @@ class TestSemanticTools(unittest.TestCase):
ArchSemantics(tmp_mm) ArchSemantics(tmp_mm)
except ValueError: except ValueError:
self.fail() self.fail()
"""
def test_machine_model_various_functions(self): def test_machine_model_various_functions(self):
# check dummy MachineModel creation # check dummy MachineModel creation
try: try:
@@ -173,7 +173,7 @@ class TestSemanticTools(unittest.TestCase):
test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [{"class": "identifier"}]), test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [{"class": "identifier"}]),
test_mm_arm.get_instruction("b.someOtherName", [{"class": "identifier"}]), test_mm_arm.get_instruction("b.someOtherName", [{"class": "identifier"}]),
) )
# test full instruction name # test full instruction name
self.assertEqual( self.assertEqual(
MachineModel.get_full_instruction_name(instr_form_x86_1), MachineModel.get_full_instruction_name(instr_form_x86_1),
@@ -185,14 +185,12 @@ class TestSemanticTools(unittest.TestCase):
"fadd register(prefix:v,shape:s),register(prefix:v,shape:s)," "fadd register(prefix:v,shape:s),register(prefix:v,shape:s),"
+ "register(prefix:v,shape:s)", + "register(prefix:v,shape:s)",
) )
"""
"""
# test get_store_tp # test get_store_tp
self.assertEqual( self.assertEqual(
test_mm_x86.get_store_throughput( test_mm_x86.get_store_throughput(
MemoryOperand(BASE_ID=RegisterOperand(NAME_ID="x"), OFFSET_ID=None,INDEX_ID=None,SCALE_ID="1") MemoryOperand(BASE_ID=RegisterOperand(NAME_ID="x"), OFFSET_ID=None,INDEX_ID=None,SCALE_ID="1")
)[0]["port_pressure"], )[0].port_pressure,
[[2, "237"], [2, "4"]], [[2, "237"], [2, "4"]],
) )
@@ -248,7 +246,7 @@ class TestSemanticTools(unittest.TestCase):
with open("/dev/null", "w") as dev_null: with open("/dev/null", "w") as dev_null:
test_mm_x86.dump(stream=dev_null) test_mm_x86.dump(stream=dev_null)
test_mm_arm.dump(stream=dev_null) test_mm_arm.dump(stream=dev_null)
"""
def test_src_dst_assignment_x86(self): def test_src_dst_assignment_x86(self):
for instruction_form in self.kernel_x86: for instruction_form in self.kernel_x86:
@@ -286,7 +284,6 @@ class TestSemanticTools(unittest.TestCase):
self.assertIsInstance(instruction_form.port_pressure, list) self.assertIsInstance(instruction_form.port_pressure, list)
self.assertEqual(len(instruction_form.port_pressure), port_num) self.assertEqual(len(instruction_form.port_pressure), port_num)
"""
def test_optimal_throughput_assignment(self): def test_optimal_throughput_assignment(self):
# x86 # x86
kernel_fixed = deepcopy(self.kernel_x86) kernel_fixed = deepcopy(self.kernel_x86)
@@ -396,7 +393,7 @@ class TestSemanticTools(unittest.TestCase):
dg.get_dependent_instruction_forms() dg.get_dependent_instruction_forms()
# test dot creation # test dot creation
dg.export_graph(filepath="/dev/null") dg.export_graph(filepath="/dev/null")
"""
def test_kernelDG_SVE(self): def test_kernelDG_SVE(self):
KernelDG( KernelDG(
@@ -438,7 +435,7 @@ class TestSemanticTools(unittest.TestCase):
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
dg.get_loopcarried_dependencies() dg.get_loopcarried_dependencies()
"""
def test_loop_carried_dependency_aarch64(self): def test_loop_carried_dependency_aarch64(self):
dg = KernelDG( dg = KernelDG(
self.kernel_aarch64_memdep, self.kernel_aarch64_memdep,
@@ -540,7 +537,7 @@ class TestSemanticTools(unittest.TestCase):
self.assertTrue(time_10 > 10) self.assertTrue(time_10 > 10)
self.assertTrue(2 < time_2) self.assertTrue(2 < time_2)
self.assertTrue(time_2 < (time_10 - 7)) self.assertTrue(time_2 < (time_10 - 7))
"""
def test_is_read_is_written_x86(self): def test_is_read_is_written_x86(self):
# independent form HW model # independent form HW model