From db899a27091754a779c6679e0b8c298829e12b46 Mon Sep 17 00:00:00 2001 From: stefandesouza Date: Mon, 25 Sep 2023 21:35:17 +0200 Subject: [PATCH] Changing operand matching for class operand style --- osaca/semantics/hw_model.py | 84 +++++++++++++++++--------------- osaca/semantics/isa_semantics.py | 13 ++--- osaca/semantics/kernel_dg.py | 4 +- tests/test_semantics.py | 17 +++---- 4 files changed, 60 insertions(+), 58 deletions(-) diff --git a/osaca/semantics/hw_model.py b/osaca/semantics/hw_model.py index da859f9..3d94dad 100644 --- a/osaca/semantics/hw_model.py +++ b/osaca/semantics/hw_model.py @@ -320,13 +320,15 @@ class MachineModel(object): @staticmethod def get_full_instruction_name(instruction_form): """Get one instruction name string including the mnemonic and all operands.""" + if instruction_form==None: + return "" operands = [] - for op in instruction_form.operands: + for op in instruction_form["operands"]: op_attrs = [ - y + ":" + str(op[y]) - for y in list(filter(lambda x: True if x != "class" else False, op)) + "name:" + op.name + #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)) @staticmethod @@ -595,53 +597,53 @@ class MachineModel(object): def _check_AArch64_operands(self, i_operand, operand): """Check if the types of operand ``i_operand`` and ``operand`` match.""" - if "class" in operand: + #if "class" in operand: # compare two DB entries - return self._compare_db_entries(i_operand, operand) + # return self._compare_db_entries(i_operand, operand) # TODO support class wildcards # register - if "register" in operand: - if i_operand["class"] != "register": + if isinstance(operand, RegisterOperand): + if not isinstance(i_operand, RegisterOperand): return False - return self._is_AArch64_reg_type(i_operand, operand["register"]) + return self._is_AArch64_reg_type(i_operand, operand) # memory - if "memory" in operand: - if i_operand["class"] != "memory": + if isinstance(operand, MemoryOperand): + if not isinstance(i_operand, MemoryOperand): return False - return self._is_AArch64_mem_type(i_operand, operand["memory"]) + return self._is_AArch64_mem_type(i_operand, operand) # immediate - if i_operand["class"] == "immediate" and i_operand["imd"] == self.WILDCARD: - return "value" in operand or ( + if isinstance(i_operand, ImmediateOperand) and i_operand.type == self.WILDCARD: + return "value" in operand.value or ( "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 ( "immediate" in operand and "value" in operand["immediate"] 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 ( "immediate" in operand and "float" in operand["immediate"] 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 ( "immediate" in operand and "double" in operand["immediate"] and operand["immediate"].get("type", None) == "double" ) # identifier - if "identifier" in operand or ( - "immediate" in operand and "identifier" in operand["immediate"] + if isinstance(operand, IdentifierOperand) or ( + isinstance(operand, ImmediateOperand) and isinstance(operand, IdentifierOperand) ): return i_operand["class"] == "identifier" # prefetch option - if "prfop" in operand: + if not isinstance(operand, Operand) and "prfop" in operand: return i_operand["class"] == "prfop" # condition - if "condition" in operand: + if not isinstance(operand, Operand) and "condition" in operand: if i_operand["ccode"] == self.WILDCARD: return True return i_operand["class"] == "condition" and ( @@ -698,27 +700,27 @@ class MachineModel(object): def _is_AArch64_reg_type(self, i_reg, reg): """Check if register type match.""" # check for wildcards - if reg["prefix"] == self.WILDCARD or i_reg["prefix"] == self.WILDCARD: - if "shape" in reg: - if "shape" in i_reg and ( - reg["shape"] == i_reg["shape"] - or self.WILDCARD in (reg["shape"] + i_reg["shape"]) + if reg.prefix == self.WILDCARD or i_reg.prefix == self.WILDCARD: + if reg.shape!=None: + if i_reg.shape!=None and ( + reg.shape == i_reg.shape + or self.WILDCARD in (reg.shape + i_reg.shape) ): return True return False return True # check for prefix and shape - if reg["prefix"] != i_reg["prefix"]: + if reg.prefix != i_reg.prefix: return False - if "shape" in reg: - if "shape" in i_reg and ( - reg["shape"] == i_reg["shape"] or self.WILDCARD in (reg["shape"] + i_reg["shape"]) + if reg.shape!=None: + if i_reg.shape!=None and ( + reg.shape == i_reg.shape or self.WILDCARD in (reg.shape + i_reg.shape) ): return True return False - if "lanes" in reg: - if "lanes" in i_reg and ( - reg["lanes"] == i_reg["lanes"] or self.WILDCARD in (reg["lanes"] + i_reg["lanes"]) + if reg.lanes!=None: + if i_reg.lanes!=None and ( + reg.lanes == i_reg.lanes or self.WILDCARD in (reg.lanes + i_reg.lanes) ): return True return False @@ -735,6 +737,8 @@ class MachineModel(object): else: i_reg_name = i_reg # check for wildcards + if isinstance(reg,str): + return False if i_reg_name == self.WILDCARD or reg.name == self.WILDCARD: return True # 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) or i_mem.base == self.WILDCARD - or mem.base["prefix"] == i_mem.base + or mem.base.prefix == i_mem.base ) # check offset and ( @@ -799,8 +803,8 @@ class MachineModel(object): or i_mem.index == self.WILDCARD or ( mem.index is not None - and mem["index"].prefix != None - and mem.index["prefix"] == i_mem.index + and mem.index.prefix != None + and mem.index.prefix == i_mem.index ) ) # check scale @@ -811,12 +815,12 @@ class MachineModel(object): ) # check pre-indexing 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 and ( - i_mem.post - indexed == self.WILDCARD - or (mem.post - indexed) == (i_mem.post - indexed) + i_mem.post_indexed == self.WILDCARD + or (mem.post_indexed) == (i_mem.post_indexed) ) ): return True @@ -856,7 +860,7 @@ class MachineModel(object): or i_mem.index == self.WILDCARD or ( 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) ) ) diff --git a/osaca/semantics/isa_semantics.py b/osaca/semantics/isa_semantics.py index a32a745..76e0bbb 100644 --- a/osaca/semantics/isa_semantics.py +++ b/osaca/semantics/isa_semantics.py @@ -182,19 +182,19 @@ class ISASemantics(object): isa_data = self._isa_model.get_instruction( instruction_form.instruction[:suffix_start], instruction_form.operands ) - """ + if only_postindexed: 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 return { 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 {} - """ + reg_operand_names = {} # e.g., {'rax': 'op1'} operand_state = {} # e.g., {'op1': {'name': 'rax', 'value': 0}} 0 means unchanged @@ -253,13 +253,12 @@ class ISASemantics(object): op_dict["destination"] += operands if "hidden_operands" in isa_data: op_dict["destination"] += [ - AttrDict.convert_dict( { hop["class"]: { k: hop[k] for k in ["name", "class", "source", "destination"] } } - ) + for hop in isa_data["hidden_operands"] ] return op_dict @@ -267,6 +266,7 @@ class ISASemantics(object): for i, op in enumerate(isa_data["operands"]): if isinstance(op, RegisterOperand): continue + ''' if op["source"] and op["destination"]: op_dict["src_dst"].append(operands[i]) continue @@ -276,6 +276,7 @@ class ISASemantics(object): if op["destination"]: op_dict["destination"].append(operands[i]) continue + ''' # check for hidden operands like flags or registers if "hidden_operands" in isa_data: # add operand(s) to semantic_operands of instruction form diff --git a/osaca/semantics/kernel_dg.py b/osaca/semantics/kernel_dg.py index f7794db..54502a0 100644 --- a/osaca/semantics/kernel_dg.py +++ b/osaca/semantics/kernel_dg.py @@ -443,8 +443,8 @@ class KernelDG(nx.DiGraph): continue if mem.index and src.index: index_change = register_changes.get( - src.index.get("prefix", "") + src.index.name, - {"name": src.index.get("prefix", "") + src.index.name, "value": 0}, + src.index.prefix if src.index.prefix!=None else "" + src.index.name, + {"name": src.index.prefix if src.index.prefix!=None else "" + src.index.name, "value": 0}, ) if index_change is None: # Unknown change occurred diff --git a/tests/test_semantics.py b/tests/test_semantics.py index 6c84794..09fb578 100755 --- a/tests/test_semantics.py +++ b/tests/test_semantics.py @@ -125,7 +125,7 @@ class TestSemanticTools(unittest.TestCase): ArchSemantics(tmp_mm) except ValueError: self.fail() - """ + def test_machine_model_various_functions(self): # check dummy MachineModel creation try: @@ -173,7 +173,7 @@ class TestSemanticTools(unittest.TestCase): test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [{"class": "identifier"}]), test_mm_arm.get_instruction("b.someOtherName", [{"class": "identifier"}]), ) - + # test full instruction name self.assertEqual( 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)," + "register(prefix:v,shape:s)", ) - """ - """ # test get_store_tp self.assertEqual( test_mm_x86.get_store_throughput( 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"]], ) @@ -248,7 +246,7 @@ class TestSemanticTools(unittest.TestCase): with open("/dev/null", "w") as dev_null: test_mm_x86.dump(stream=dev_null) test_mm_arm.dump(stream=dev_null) - """ + def test_src_dst_assignment_x86(self): for instruction_form in self.kernel_x86: @@ -286,7 +284,6 @@ class TestSemanticTools(unittest.TestCase): self.assertIsInstance(instruction_form.port_pressure, list) self.assertEqual(len(instruction_form.port_pressure), port_num) - """ def test_optimal_throughput_assignment(self): # x86 kernel_fixed = deepcopy(self.kernel_x86) @@ -396,7 +393,7 @@ class TestSemanticTools(unittest.TestCase): dg.get_dependent_instruction_forms() # test dot creation dg.export_graph(filepath="/dev/null") - """ + def test_kernelDG_SVE(self): KernelDG( @@ -438,7 +435,7 @@ class TestSemanticTools(unittest.TestCase): with self.assertRaises(NotImplementedError): dg.get_loopcarried_dependencies() - """ + def test_loop_carried_dependency_aarch64(self): dg = KernelDG( self.kernel_aarch64_memdep, @@ -540,7 +537,7 @@ class TestSemanticTools(unittest.TestCase): self.assertTrue(time_10 > 10) self.assertTrue(2 < time_2) self.assertTrue(time_2 < (time_10 - 7)) - """ + def test_is_read_is_written_x86(self): # independent form HW model