mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2026-01-06 11:10:06 +01:00
Changes to accomodate the new OO style
This commit is contained in:
0
osaca/db_interface.py
Executable file → Normal file
0
osaca/db_interface.py
Executable file → Normal file
0
osaca/frontend.py
Executable file → Normal file
0
osaca/frontend.py
Executable file → Normal file
5
osaca/osaca.py
Executable file → Normal file
5
osaca/osaca.py
Executable file → Normal file
@@ -430,10 +430,7 @@ def get_unmatched_instruction_ratio(kernel):
|
|||||||
"""Return ratio of unmatched from total instructions in kernel."""
|
"""Return ratio of unmatched from total instructions in kernel."""
|
||||||
unmatched_counter = 0
|
unmatched_counter = 0
|
||||||
for instruction in kernel:
|
for instruction in kernel:
|
||||||
if (
|
if INSTR_FLAGS.TP_UNKWN in instruction.flags and INSTR_FLAGS.LT_UNKWN in instruction.flags:
|
||||||
INSTR_FLAGS.TP_UNKWN in instruction["flags"]
|
|
||||||
and INSTR_FLAGS.LT_UNKWN in instruction["flags"]
|
|
||||||
):
|
|
||||||
unmatched_counter += 1
|
unmatched_counter += 1
|
||||||
return unmatched_counter / len(kernel)
|
return unmatched_counter / len(kernel)
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,6 @@ from osaca.parser.directive import DirectiveOperand
|
|||||||
|
|
||||||
|
|
||||||
class InstructionForm:
|
class InstructionForm:
|
||||||
# Identifiers for operand types
|
|
||||||
COMMENT_ID = "comment"
|
|
||||||
DIRECTIVE_ID = "directive"
|
|
||||||
IMMEDIATE_ID = "immediate"
|
|
||||||
LABEL_ID = "label"
|
|
||||||
IDENTIFIER_ID = "identifier"
|
|
||||||
MEMORY_ID = "memory"
|
|
||||||
REGISTER_ID = "register"
|
|
||||||
SEGMENT_EXT_ID = "segment_extension"
|
|
||||||
INSTRUCTION_ID = "instruction"
|
|
||||||
OPERANDS_ID = "operands"
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
INSTRUCTION_ID=None,
|
INSTRUCTION_ID=None,
|
||||||
@@ -91,6 +79,18 @@ class InstructionForm:
|
|||||||
def flags(self):
|
def flags(self):
|
||||||
return self._FLAGS
|
return self._FLAGS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def throughput(self):
|
||||||
|
return self._THROUGHPUT
|
||||||
|
|
||||||
|
@property
|
||||||
|
def latency(self):
|
||||||
|
return self._LATENCY
|
||||||
|
|
||||||
|
@property
|
||||||
|
def latency_wo_load(self):
|
||||||
|
return self._LATENCY_WO_LOAD
|
||||||
|
|
||||||
@semantic_operands.setter
|
@semantic_operands.setter
|
||||||
def semantic_operands(self, semantic_operands):
|
def semantic_operands(self, semantic_operands):
|
||||||
self._SEMANTIC_OPERANDS = semantic_operands
|
self._SEMANTIC_OPERANDS = semantic_operands
|
||||||
@@ -135,6 +135,18 @@ class InstructionForm:
|
|||||||
def flags(self, flags):
|
def flags(self, flags):
|
||||||
self._FLAGS = flags
|
self._FLAGS = flags
|
||||||
|
|
||||||
|
@throughput.setter
|
||||||
|
def throughput(self, throughput):
|
||||||
|
self._THROUGHPUT = throughput
|
||||||
|
|
||||||
|
@latency.setter
|
||||||
|
def latency(self, latency):
|
||||||
|
self._LATENCY = latency
|
||||||
|
|
||||||
|
@latency_wo_load.setter
|
||||||
|
def latency_wo_load(self, latency_wo_load):
|
||||||
|
self._LATENCY_WO_LOAD = latency_wo_load
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"InstructionForm(INSTRUCTION_ID={self._INSTRUCTION_ID}, OPERANDS_ID={self._OPERANDS_ID}, DIRECTIVE_ID={self._DIRECTIVE_ID}, COMMENT_ID={self._COMMENT_ID}, LABEL_ID={self._LABEL_ID}, LINE={self._LINE}, LINE_NUMBER={self._LINE_NUMBER}, SEMANTIC_OPERANDS={self._SEMANTIC_OPERANDS})"
|
return f"InstructionForm(INSTRUCTION_ID={self._INSTRUCTION_ID}, OPERANDS_ID={self._OPERANDS_ID}, DIRECTIVE_ID={self._DIRECTIVE_ID}, COMMENT_ID={self._COMMENT_ID}, LABEL_ID={self._LABEL_ID}, LINE={self._LINE}, LINE_NUMBER={self._LINE_NUMBER}, SEMANTIC_OPERANDS={self._SEMANTIC_OPERANDS})"
|
||||||
|
|
||||||
|
|||||||
@@ -386,8 +386,8 @@ class ParserX86ATT(BaseParser):
|
|||||||
def is_reg_dependend_of(self, reg_a, reg_b):
|
def is_reg_dependend_of(self, reg_a, reg_b):
|
||||||
"""Check if ``reg_a`` is dependent on ``reg_b``"""
|
"""Check if ``reg_a`` is dependent on ``reg_b``"""
|
||||||
# Normalize name
|
# Normalize name
|
||||||
reg_a_name = reg_a["name"].upper()
|
reg_a_name = reg_a.name.upper()
|
||||||
reg_b_name = reg_b["name"].upper()
|
reg_b_name = reg_b.name.upper()
|
||||||
|
|
||||||
# Check if they are the same registers
|
# Check if they are the same registers
|
||||||
if reg_a_name == reg_b_name:
|
if reg_a_name == reg_b_name:
|
||||||
@@ -428,8 +428,8 @@ class ParserX86ATT(BaseParser):
|
|||||||
|
|
||||||
def is_basic_gpr(self, register):
|
def is_basic_gpr(self, register):
|
||||||
"""Check if register is a basic general purpose register (ebi, rax, ...)"""
|
"""Check if register is a basic general purpose register (ebi, rax, ...)"""
|
||||||
if any(char.isdigit() for char in register["name"]) or any(
|
if any(char.isdigit() for char in register.name) or any(
|
||||||
register["name"].lower().startswith(x) for x in ["mm", "xmm", "ymm", "zmm"]
|
register.name.lower().startswith(x) for x in ["mm", "xmm", "ymm", "zmm"]
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -446,7 +446,7 @@ class ParserX86ATT(BaseParser):
|
|||||||
"""Check if register is a vector register"""
|
"""Check if register is a vector register"""
|
||||||
if register is None:
|
if register is None:
|
||||||
return False
|
return False
|
||||||
if register["name"].rstrip(string.digits).lower() in [
|
if register.name.rstrip(string.digits).lower() in [
|
||||||
"mm",
|
"mm",
|
||||||
"xmm",
|
"xmm",
|
||||||
"ymm",
|
"ymm",
|
||||||
|
|||||||
@@ -69,9 +69,7 @@ class ArchSemantics(ISASemantics):
|
|||||||
indices = [port_list.index(p) for p in ports]
|
indices = [port_list.index(p) for p in ports]
|
||||||
# check if port sum of used ports for uop are unbalanced
|
# check if port sum of used ports for uop are unbalanced
|
||||||
port_sums = self._to_list(itemgetter(*indices)(self.get_throughput_sum(kernel)))
|
port_sums = self._to_list(itemgetter(*indices)(self.get_throughput_sum(kernel)))
|
||||||
instr_ports = self._to_list(
|
instr_ports = self._to_list(itemgetter(*indices)(instruction_form.port_pressure))
|
||||||
itemgetter(*indices)(instruction_form.port_pressure)
|
|
||||||
)
|
|
||||||
if len(set(port_sums)) > 1:
|
if len(set(port_sums)) > 1:
|
||||||
# balance ports
|
# balance ports
|
||||||
# init list for keeping track of the current change
|
# init list for keeping track of the current change
|
||||||
@@ -110,9 +108,7 @@ class ArchSemantics(ISASemantics):
|
|||||||
][0]
|
][0]
|
||||||
instruction_form.port_pressure[zero_index] = 0.0
|
instruction_form.port_pressure[zero_index] = 0.0
|
||||||
# Remove from further balancing
|
# Remove from further balancing
|
||||||
indices = [
|
indices = [p for p in indices if instruction_form.port_pressure[p] > 0]
|
||||||
p for p in indices if instruction_form.port_pressure[p] > 0
|
|
||||||
]
|
|
||||||
instr_ports = self._to_list(
|
instr_ports = self._to_list(
|
||||||
itemgetter(*indices)(instruction_form.port_pressure)
|
itemgetter(*indices)(instruction_form.port_pressure)
|
||||||
)
|
)
|
||||||
@@ -193,6 +189,7 @@ class ArchSemantics(ISASemantics):
|
|||||||
instruction_data = self._machine_model.get_instruction(
|
instruction_data = self._machine_model.get_instruction(
|
||||||
instruction_form.instruction, instruction_form.operands
|
instruction_form.instruction, instruction_form.operands
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not instruction_data
|
not instruction_data
|
||||||
and self._isa == "x86"
|
and self._isa == "x86"
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ import ruamel.yaml
|
|||||||
from osaca import __version__, utils
|
from osaca import __version__, utils
|
||||||
from osaca.parser import ParserX86ATT
|
from osaca.parser import ParserX86ATT
|
||||||
from ruamel.yaml.compat import StringIO
|
from ruamel.yaml.compat import StringIO
|
||||||
|
from osaca.parser.operand import Operand
|
||||||
|
from osaca.parser.memory import MemoryOperand
|
||||||
|
from osaca.parser.register import RegisterOperand
|
||||||
|
from osaca.parser.immediate import ImmediateOperand
|
||||||
|
from osaca.parser.identifier import IdentifierOperand
|
||||||
|
|
||||||
|
|
||||||
class MachineModel(object):
|
class MachineModel(object):
|
||||||
@@ -21,7 +26,7 @@ class MachineModel(object):
|
|||||||
INTERNAL_VERSION = 1 # increase whenever self._data format changes to invalidate cache!
|
INTERNAL_VERSION = 1 # increase whenever self._data format changes to invalidate cache!
|
||||||
_runtime_cache = {}
|
_runtime_cache = {}
|
||||||
|
|
||||||
def __init__(self, arch=None, path_to_yaml=None, isa=None, lazy=False):
|
def __init__(self, arch=None, path_to_yaml=None, isa=None, lazy=True):
|
||||||
if not arch and not path_to_yaml:
|
if not arch and not path_to_yaml:
|
||||||
if not isa:
|
if not isa:
|
||||||
raise ValueError("One of arch, path_to_yaml and isa must be specified")
|
raise ValueError("One of arch, path_to_yaml and isa must be specified")
|
||||||
@@ -97,6 +102,7 @@ class MachineModel(object):
|
|||||||
# Normalize instruction_form names (to UPPERCASE) and build dict for faster access:
|
# Normalize instruction_form names (to UPPERCASE) and build dict for faster access:
|
||||||
self._data["instruction_forms_dict"] = defaultdict(list)
|
self._data["instruction_forms_dict"] = defaultdict(list)
|
||||||
for iform in self._data["instruction_forms"]:
|
for iform in self._data["instruction_forms"]:
|
||||||
|
print(iform)
|
||||||
iform["name"] = iform["name"].upper()
|
iform["name"] = iform["name"].upper()
|
||||||
self._data["instruction_forms_dict"][iform["name"]].append(iform)
|
self._data["instruction_forms_dict"][iform["name"]].append(iform)
|
||||||
self._data["internal_version"] = self.INTERNAL_VERSION
|
self._data["internal_version"] = self.INTERNAL_VERSION
|
||||||
@@ -128,6 +134,7 @@ class MachineModel(object):
|
|||||||
if name is None:
|
if name is None:
|
||||||
return None
|
return None
|
||||||
name_matched_iforms = self._data["instruction_forms_dict"].get(name.upper(), [])
|
name_matched_iforms = self._data["instruction_forms_dict"].get(name.upper(), [])
|
||||||
|
# print(name_matched_iforms)
|
||||||
try:
|
try:
|
||||||
return next(
|
return next(
|
||||||
instruction_form
|
instruction_form
|
||||||
@@ -264,7 +271,7 @@ class MachineModel(object):
|
|||||||
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."""
|
||||||
operands = []
|
operands = []
|
||||||
for op in instruction_form["operands"]:
|
for op in instruction_form.operands:
|
||||||
op_attrs = [
|
op_attrs = [
|
||||||
y + ":" + str(op[y])
|
y + ":" + str(op[y])
|
||||||
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))
|
||||||
@@ -526,7 +533,9 @@ class MachineModel(object):
|
|||||||
def _check_operands(self, i_operand, operand):
|
def _check_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."""
|
||||||
# check for wildcard
|
# check for wildcard
|
||||||
if self.WILDCARD in operand.name:
|
if (isinstance(operand, Operand) and operand.name == self.WILDCARD) or (
|
||||||
|
not isinstance(operand, Operand) and self.WILDCARD in operand
|
||||||
|
):
|
||||||
if (
|
if (
|
||||||
"class" in i_operand
|
"class" in i_operand
|
||||||
and i_operand["class"] == "register"
|
and i_operand["class"] == "register"
|
||||||
@@ -601,25 +610,27 @@ class MachineModel(object):
|
|||||||
|
|
||||||
def _check_x86_operands(self, i_operand, operand):
|
def _check_x86_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.name:
|
# if "class" in operand.name:
|
||||||
# compare two DB entries
|
# compare two DB entries
|
||||||
return self._compare_db_entries(i_operand, operand)
|
# return self._compare_db_entries(i_operand, operand)
|
||||||
# register
|
# register
|
||||||
if "register" in operand.name:
|
if isinstance(operand, RegisterOperand):
|
||||||
if i_operand["class"] != "register":
|
if i_operand["class"] != "register":
|
||||||
return False
|
return False
|
||||||
return self._is_x86_reg_type(i_operand, operand, consider_masking=False)
|
return self._is_x86_reg_type(i_operand, operand, consider_masking=False)
|
||||||
# memory
|
# memory
|
||||||
if "memory" in operand.name:
|
if isinstance(operand, MemoryOperand):
|
||||||
if i_operand["class"] != "memory":
|
if i_operand["class"] != "memory":
|
||||||
return False
|
return False
|
||||||
return self._is_x86_mem_type(i_operand, operand)
|
return self._is_x86_mem_type(i_operand, operand)
|
||||||
# immediate
|
# immediate
|
||||||
if "immediate" in operand.name or operand.value != None:
|
if isinstance(operand, ImmediateOperand):
|
||||||
|
# if "immediate" in operand.name or operand.value != None:
|
||||||
return i_operand["class"] == "immediate" and i_operand["imd"] == "int"
|
return i_operand["class"] == "immediate" and i_operand["imd"] == "int"
|
||||||
# identifier (e.g., labels)
|
# identifier (e.g., labels)
|
||||||
if "identifier" in operand.name:
|
if isinstance(operand, IdentifierOperand):
|
||||||
return i_operand["class"] == "identifier"
|
return i_operand["class"] == "identifier"
|
||||||
|
return self._compare_db_entries(i_operand, operand)
|
||||||
|
|
||||||
def _compare_db_entries(self, operand_1, operand_2):
|
def _compare_db_entries(self, operand_1, operand_2):
|
||||||
"""Check if operand types in DB format (i.e., not parsed) match."""
|
"""Check if operand types in DB format (i.e., not parsed) match."""
|
||||||
@@ -676,29 +687,29 @@ class MachineModel(object):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
# check for wildcards
|
# check for wildcards
|
||||||
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)
|
||||||
parser_x86 = ParserX86ATT()
|
parser_x86 = ParserX86ATT()
|
||||||
if parser_x86.is_vector_register(reg):
|
if parser_x86.is_vector_register(reg):
|
||||||
if reg["name"].rstrip(string.digits).lower() == i_reg_name:
|
if reg.name.rstrip(string.digits).lower() == i_reg_name:
|
||||||
# Consider masking and zeroing for AVX512
|
# Consider masking and zeroing for AVX512
|
||||||
if consider_masking:
|
if consider_masking:
|
||||||
mask_ok = zero_ok = True
|
mask_ok = zero_ok = True
|
||||||
if "mask" in reg or "mask" in i_reg:
|
if reg.mask != None or "mask" in i_reg:
|
||||||
# one instruction is missing the masking while the other has it
|
# one instruction is missing the masking while the other has it
|
||||||
mask_ok = False
|
mask_ok = False
|
||||||
# check for wildcard
|
# check for wildcard
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
"mask" in reg
|
reg.mask != None
|
||||||
and reg["mask"].rstrip(string.digits).lower() == i_reg.get("mask")
|
and reg.mask.rstrip(string.digits).lower() == i_reg.get("mask")
|
||||||
)
|
)
|
||||||
or reg.get("mask") == self.WILDCARD
|
or reg.mask == self.WILDCARD
|
||||||
or i_reg.get("mask") == self.WILDCARD
|
or i_reg.get("mask") == self.WILDCARD
|
||||||
):
|
):
|
||||||
mask_ok = True
|
mask_ok = True
|
||||||
if bool("zeroing" in reg) ^ bool("zeroing" in i_reg):
|
if bool(reg.zeroing) ^ bool("zeroing" in i_reg):
|
||||||
# one instruction is missing zeroing while the other has it
|
# one instruction is missing zeroing while the other has it
|
||||||
zero_ok = False
|
zero_ok = False
|
||||||
# check for wildcard
|
# check for wildcard
|
||||||
@@ -776,48 +787,48 @@ class MachineModel(object):
|
|||||||
if (
|
if (
|
||||||
# check base
|
# check base
|
||||||
(
|
(
|
||||||
(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 self._is_x86_reg_type(i_mem["base"], mem["base"])
|
or self._is_x86_reg_type(i_mem["base"], mem.base)
|
||||||
)
|
)
|
||||||
# check offset
|
# check offset
|
||||||
and (
|
and (
|
||||||
mem["offset"] == i_mem["offset"]
|
mem.offset == i_mem["offset"]
|
||||||
or i_mem["offset"] == self.WILDCARD
|
or i_mem["offset"] == self.WILDCARD
|
||||||
or (
|
or (
|
||||||
mem["offset"] is not None
|
mem.offset is not None
|
||||||
and "identifier" in mem["offset"]
|
and "identifier" in mem.offset
|
||||||
and i_mem["offset"] == "identifier"
|
and i_mem["offset"] == "identifier"
|
||||||
)
|
)
|
||||||
or (
|
or (
|
||||||
mem["offset"] is not None
|
mem.offset is not None
|
||||||
and "value" in mem["offset"]
|
and "value" in mem.offset
|
||||||
and (
|
and (
|
||||||
i_mem["offset"] == "imd"
|
i_mem.offset == "imd"
|
||||||
or (i_mem["offset"] is None and mem["offset"]["value"] == "0")
|
or (i_mem["offset"] is None and mem.offset["value"] == "0")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or (
|
or (
|
||||||
mem["offset"] is not None
|
mem.offset is not None
|
||||||
and "identifier" in mem["offset"]
|
and "identifier" in mem.offset
|
||||||
and i_mem["offset"] == "id"
|
and i_mem["offset"] == "id"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# check index
|
# check index
|
||||||
and (
|
and (
|
||||||
mem["index"] == i_mem["index"]
|
mem.index == i_mem["index"]
|
||||||
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 "name" in mem["index"]
|
and "name" in mem.index
|
||||||
and self._is_x86_reg_type(i_mem["index"], mem["index"])
|
and self._is_x86_reg_type(i_mem["index"], mem.index)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# check scale
|
# check scale
|
||||||
and (
|
and (
|
||||||
mem["scale"] == i_mem["scale"]
|
mem.scale == i_mem["scale"]
|
||||||
or i_mem["scale"] == self.WILDCARD
|
or i_mem["scale"] == self.WILDCARD
|
||||||
or (mem["scale"] != 1 and i_mem["scale"] != 1)
|
or (mem.scale != 1 and i_mem["scale"] != 1)
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -4,39 +4,10 @@ from itertools import chain
|
|||||||
from osaca import utils
|
from osaca import utils
|
||||||
from osaca.parser import AttrDict, ParserAArch64, ParserX86ATT
|
from osaca.parser import AttrDict, ParserAArch64, ParserX86ATT
|
||||||
from osaca.parser.memory import MemoryOperand
|
from osaca.parser.memory import MemoryOperand
|
||||||
|
from osaca.parser.register import RegisterOperand
|
||||||
|
|
||||||
from .hw_model import MachineModel
|
from .hw_model import MachineModel
|
||||||
|
|
||||||
class SemanticForm:
|
|
||||||
def __init__(self, SOURCE_ID = [], DESTINATION_ID = [], SRC_DST = []):
|
|
||||||
self._SOURCE_ID = SOURCE_ID
|
|
||||||
self._DESTINATION_ID = DESTINATION_ID
|
|
||||||
self._SRC_DST = SRC_DST
|
|
||||||
|
|
||||||
@property
|
|
||||||
def source(self):
|
|
||||||
return self._SOURCE_ID
|
|
||||||
|
|
||||||
@source.setter
|
|
||||||
def source(self, source):
|
|
||||||
self._SOURCE_ID = source
|
|
||||||
|
|
||||||
@property
|
|
||||||
def destination(self):
|
|
||||||
return self._DESTINATION_ID
|
|
||||||
|
|
||||||
@destination.setter
|
|
||||||
def destination(self, destination):
|
|
||||||
self._DESTINATION_ID = destination
|
|
||||||
|
|
||||||
@property
|
|
||||||
def src_dst(self):
|
|
||||||
return self._SRC_DST
|
|
||||||
|
|
||||||
@src_dst.setter
|
|
||||||
def src_dst(self, src_dst):
|
|
||||||
self._SRC_DST = src_dst
|
|
||||||
|
|
||||||
|
|
||||||
class INSTR_FLAGS:
|
class INSTR_FLAGS:
|
||||||
"""
|
"""
|
||||||
@@ -77,9 +48,7 @@ class ISASemantics(object):
|
|||||||
"""Update instruction form dictionary with source, destination and flag information."""
|
"""Update instruction form dictionary with source, destination and flag information."""
|
||||||
# if the instruction form doesn't have operands or is None, there's nothing to do
|
# if the instruction form doesn't have operands or is None, there's nothing to do
|
||||||
if instruction_form.operands is None or instruction_form.instruction is None:
|
if instruction_form.operands is None or instruction_form.instruction is None:
|
||||||
instruction_form.semantic_operands = SemanticForm(
|
instruction_form.semantic_operands = {"source": [], "destination": [], "src_dst": []}
|
||||||
SOURCE_ID = [], DESTINATION_ID = [], SRC_DST = []
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
# check if instruction form is in ISA yaml, otherwise apply standard operand assignment
|
# check if instruction form is in ISA yaml, otherwise apply standard operand assignment
|
||||||
# (one dest, others source)
|
# (one dest, others source)
|
||||||
@@ -111,8 +80,7 @@ class ISASemantics(object):
|
|||||||
# Couldn't found instruction form in ISA DB
|
# Couldn't found instruction form in ISA DB
|
||||||
assign_default = True
|
assign_default = True
|
||||||
# check for equivalent register-operands DB entry if LD/ST
|
# check for equivalent register-operands DB entry if LD/ST
|
||||||
|
if any([isinstance(op, MemoryOperand) for op in operands]):
|
||||||
if isinstance(operands, MemoryOperand) and operands.name == "memory":
|
|
||||||
operands_reg = self.substitute_mem_address(instruction_form.operands)
|
operands_reg = self.substitute_mem_address(instruction_form.operands)
|
||||||
isa_data_reg = self._isa_model.get_instruction(
|
isa_data_reg = self._isa_model.get_instruction(
|
||||||
instruction_form.instruction, operands_reg
|
instruction_form.instruction, operands_reg
|
||||||
@@ -146,46 +114,34 @@ class ISASemantics(object):
|
|||||||
op_dict["src_dst"] = []
|
op_dict["src_dst"] = []
|
||||||
# post-process pre- and post-indexing for aarch64 memory operands
|
# post-process pre- and post-indexing for aarch64 memory operands
|
||||||
if self._isa == "aarch64":
|
if self._isa == "aarch64":
|
||||||
for operand in [op for op in op_dict["source"] if "memory" in op]:
|
for operand in [op for op in op_dict["source"] if isinstance(op, MemoryOperand)]:
|
||||||
post_indexed = (
|
post_indexed = operand.post_indexed
|
||||||
"post_indexed" in operand["memory"] and operand["memory"]["post_indexed"]
|
pre_indexed = operand.pre_indexed
|
||||||
)
|
|
||||||
pre_indexed = (
|
|
||||||
"pre_indexed" in operand["memory"] and operand["memory"]["pre_indexed"]
|
|
||||||
)
|
|
||||||
if post_indexed or pre_indexed:
|
if post_indexed or pre_indexed:
|
||||||
op_dict["src_dst"].append(
|
op_dict["src_dst"].append(
|
||||||
AttrDict.convert_dict(
|
|
||||||
{
|
{
|
||||||
"register": operand["memory"]["base"],
|
"register": operand.base,
|
||||||
"pre_indexed": pre_indexed,
|
"pre_indexed": pre_indexed,
|
||||||
"post_indexed": post_indexed,
|
"post_indexed": post_indexed,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
for operand in [op for op in op_dict["destination"] if isinstance(op, MemoryOperand)]:
|
||||||
for operand in [op for op in op_dict["destination"] if "memory" in op]:
|
post_indexed = operand.post_indexed
|
||||||
post_indexed = (
|
pre_indexed = operand.pre_indexed
|
||||||
"post_indexed" in operand["memory"] and operand["memory"]["post_indexed"]
|
|
||||||
)
|
|
||||||
pre_indexed = (
|
|
||||||
"pre_indexed" in operand["memory"] and operand["memory"]["pre_indexed"]
|
|
||||||
)
|
|
||||||
if post_indexed or pre_indexed:
|
if post_indexed or pre_indexed:
|
||||||
op_dict["src_dst"].append(
|
op_dict["src_dst"].append(
|
||||||
AttrDict.convert_dict(
|
|
||||||
{
|
{
|
||||||
"register": operand["memory"]["base"],
|
"register": operand.base,
|
||||||
"pre_indexed": pre_indexed,
|
"pre_indexed": pre_indexed,
|
||||||
"post_indexed": post_indexed,
|
"post_indexed": post_indexed,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
|
||||||
# store operand list in dict and reassign operand key/value pair
|
# store operand list in dict and reassign operand key/value pair
|
||||||
instruction_form.semantic_operands = AttrDict.convert_dict(op_dict)
|
instruction_form.semantic_operands = op_dict
|
||||||
# assign LD/ST flags
|
# assign LD/ST flags
|
||||||
instruction_form.flags = (
|
# instruction_form.flags = (
|
||||||
instruction_form.flags if instruction_form.flags != [] else []
|
# instruction_form.flags if "flags" in instruction_form else []
|
||||||
)
|
# )
|
||||||
if self._has_load(instruction_form):
|
if self._has_load(instruction_form):
|
||||||
instruction_form.flags += [INSTR_FLAGS.HAS_LD]
|
instruction_form.flags += [INSTR_FLAGS.HAS_LD]
|
||||||
if self._has_store(instruction_form):
|
if self._has_store(instruction_form):
|
||||||
@@ -198,15 +154,15 @@ class ISASemantics(object):
|
|||||||
Empty dict if no changes of registers occured. None for registers with unknown changes.
|
Empty dict if no changes of registers occured. None for registers with unknown changes.
|
||||||
If only_postindexed is True, only considers changes due to post_indexed memory references.
|
If only_postindexed is True, only considers changes due to post_indexed memory references.
|
||||||
"""
|
"""
|
||||||
if instruction_form.get("instruction") is None:
|
if instruction_form.instruction is None:
|
||||||
return {}
|
return {}
|
||||||
dest_reg_names = [
|
dest_reg_names = [
|
||||||
op.register.get("prefix", "") + op.register.name
|
op.prefix if op.prefix != None else "" + op.name
|
||||||
for op in chain(
|
for op in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
)
|
)
|
||||||
if "register" in op
|
if isinstance(op, RegisterOperand)
|
||||||
]
|
]
|
||||||
isa_data = self._isa_model.get_instruction(
|
isa_data = self._isa_model.get_instruction(
|
||||||
instruction_form.instruction, instruction_form.operands
|
instruction_form.instruction, instruction_form.operands
|
||||||
@@ -243,7 +199,7 @@ class ISASemantics(object):
|
|||||||
operand_state = {} # e.g., {'op1': {'name': 'rax', 'value': 0}} 0 means unchanged
|
operand_state = {} # e.g., {'op1': {'name': 'rax', 'value': 0}} 0 means unchanged
|
||||||
|
|
||||||
for o in instruction_form.operands:
|
for o in instruction_form.operands:
|
||||||
if "pre_indexed" in o.get("memory", {}):
|
if isinstance(o, MemoryOperand) and o.pre_indexed:
|
||||||
# Assuming no isa_data.operation
|
# Assuming no isa_data.operation
|
||||||
if isa_data is not None and isa_data.get("operation", None) is not None:
|
if isa_data is not None and isa_data.get("operation", None) is not None:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@@ -340,20 +296,20 @@ class ISASemantics(object):
|
|||||||
def _has_load(self, instruction_form):
|
def _has_load(self, instruction_form):
|
||||||
"""Check if instruction form performs a LOAD"""
|
"""Check if instruction form performs a LOAD"""
|
||||||
for operand in chain(
|
for operand in chain(
|
||||||
instruction_form.semantic_operands.source,
|
instruction_form.semantic_operands["source"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
if operand.name == "memory":
|
if isinstance(operand, MemoryOperand):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _has_store(self, instruction_form):
|
def _has_store(self, instruction_form):
|
||||||
"""Check if instruction form perfroms a STORE"""
|
"""Check if instruction form perfroms a STORE"""
|
||||||
for operand in chain(
|
for operand in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
if "memory" in operand:
|
if isinstance(operand, MemoryOperand):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -386,7 +342,9 @@ class ISASemantics(object):
|
|||||||
|
|
||||||
def substitute_mem_address(self, operands):
|
def substitute_mem_address(self, operands):
|
||||||
"""Create memory wildcard for all memory operands"""
|
"""Create memory wildcard for all memory operands"""
|
||||||
return [self._create_reg_wildcard() if "memory" in op else op for op in operands]
|
return [
|
||||||
|
self._create_reg_wildcard() if isinstance(op, MemoryOperand) else op for op in operands
|
||||||
|
]
|
||||||
|
|
||||||
def _create_reg_wildcard(self):
|
def _create_reg_wildcard(self):
|
||||||
"""Wildcard constructor"""
|
"""Wildcard constructor"""
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from multiprocessing import Manager, Process, cpu_count
|
|||||||
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
from osaca.semantics import INSTR_FLAGS, ArchSemantics, MachineModel
|
from osaca.semantics import INSTR_FLAGS, ArchSemantics, MachineModel
|
||||||
|
from osaca.parser.memory import MemoryOperand
|
||||||
|
from osaca.parser.register import RegisterOperand
|
||||||
|
|
||||||
|
|
||||||
class KernelDG(nx.DiGraph):
|
class KernelDG(nx.DiGraph):
|
||||||
@@ -60,8 +62,7 @@ class KernelDG(nx.DiGraph):
|
|||||||
dg = nx.DiGraph()
|
dg = nx.DiGraph()
|
||||||
for i, instruction_form in enumerate(kernel):
|
for i, instruction_form in enumerate(kernel):
|
||||||
dg.add_node(instruction_form.line_number)
|
dg.add_node(instruction_form.line_number)
|
||||||
print(dg.nodes[instruction_form.line_number])
|
dg.nodes[instruction_form.line_number]["instruction_form"] = instruction_form
|
||||||
dg.nodes[instruction_form.line_number].instruction_form = instruction_form
|
|
||||||
# add load as separate node if existent
|
# add load as separate node if existent
|
||||||
if (
|
if (
|
||||||
INSTR_FLAGS.HAS_LD in instruction_form.flags
|
INSTR_FLAGS.HAS_LD in instruction_form.flags
|
||||||
@@ -271,8 +272,8 @@ class KernelDG(nx.DiGraph):
|
|||||||
if instruction_form.semantic_operands is None:
|
if instruction_form.semantic_operands is None:
|
||||||
return
|
return
|
||||||
for dst in chain(
|
for dst in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
# TODO instructions before must be considered as well, if they update registers
|
# TODO instructions before must be considered as well, if they update registers
|
||||||
# not used by insruction_form. E.g., validation/build/A64FX/gcc/O1/gs-2d-5pt.marked.s
|
# not used by insruction_form. E.g., validation/build/A64FX/gcc/O1/gs-2d-5pt.marked.s
|
||||||
@@ -281,27 +282,32 @@ class KernelDG(nx.DiGraph):
|
|||||||
for i, instr_form in enumerate(instructions):
|
for i, instr_form in enumerate(instructions):
|
||||||
self._update_reg_changes(instr_form, register_changes)
|
self._update_reg_changes(instr_form, register_changes)
|
||||||
# print(" TO", instr_form.line, register_changes)
|
# print(" TO", instr_form.line, register_changes)
|
||||||
if "register" in dst:
|
if isinstance(dst, RegisterOperand):
|
||||||
# read of register
|
# read of register
|
||||||
if self.is_read(dst.register, instr_form):
|
if self.is_read(dst, instr_form):
|
||||||
if dst.get("pre_indexed", False) or dst.get("post_indexed", False):
|
if dst.get("pre_indexed", False) or dst.get("post_indexed", False):
|
||||||
yield instr_form, ["p_indexed"]
|
yield instr_form, ["p_indexed"]
|
||||||
else:
|
else:
|
||||||
yield instr_form, []
|
yield instr_form, []
|
||||||
# write to register -> abort
|
# write to register -> abort
|
||||||
if self.is_written(dst.register, instr_form):
|
if self.is_written(dst, instr_form):
|
||||||
break
|
break
|
||||||
if "flag" in dst and flag_dependencies:
|
if (
|
||||||
|
not isinstance(dst, RegisterOperand)
|
||||||
|
and not isinstance(dst, MemoryOperandOperand)
|
||||||
|
and "flag" in dst
|
||||||
|
and flag_dependencies
|
||||||
|
):
|
||||||
# read of flag
|
# read of flag
|
||||||
if self.is_read(dst.flag, instr_form):
|
if self.is_read(dst.flag, instr_form):
|
||||||
yield instr_form, []
|
yield instr_form, []
|
||||||
# write to flag -> abort
|
# write to flag -> abort
|
||||||
if self.is_written(dst.flag, instr_form):
|
if self.is_written(dst.flag, instr_form):
|
||||||
break
|
break
|
||||||
if "memory" in dst:
|
if isinstance(dst, MemoryOperand):
|
||||||
# base register is altered during memory access
|
# base register is altered during memory access
|
||||||
if "pre_indexed" in dst.memory:
|
if dist.pre_indexed != None:
|
||||||
if self.is_written(dst.memory.base, instr_form):
|
if self.is_written(dst.base, instr_form):
|
||||||
break
|
break
|
||||||
# if dst.memory.base:
|
# if dst.memory.base:
|
||||||
# if self.is_read(dst.memory.base, instr_form):
|
# if self.is_read(dst.memory.base, instr_form):
|
||||||
@@ -309,18 +315,18 @@ class KernelDG(nx.DiGraph):
|
|||||||
# if dst.memory.index:
|
# if dst.memory.index:
|
||||||
# if self.is_read(dst.memory.index, instr_form):
|
# if self.is_read(dst.memory.index, instr_form):
|
||||||
# yield instr_form, []
|
# yield instr_form, []
|
||||||
if "post_indexed" in dst.memory:
|
if dst.post_indexed:
|
||||||
# Check for read of base register until overwrite
|
# Check for read of base register until overwrite
|
||||||
if self.is_written(dst.memory.base, instr_form):
|
if self.is_written(dst.base, instr_form):
|
||||||
break
|
break
|
||||||
# TODO record register changes
|
# TODO record register changes
|
||||||
# (e.g., mov, leaadd, sub, inc, dec) in instructions[:i]
|
# (e.g., mov, leaadd, sub, inc, dec) in instructions[:i]
|
||||||
# and pass to is_memload and is_memstore to consider relevance.
|
# and pass to is_memload and is_memstore to consider relevance.
|
||||||
# load from same location (presumed)
|
# load from same location (presumed)
|
||||||
if self.is_memload(dst.memory, instr_form, register_changes):
|
if self.is_memload(dst, instr_form, register_changes):
|
||||||
yield instr_form, ["storeload_dep"]
|
yield instr_form, ["storeload_dep"]
|
||||||
# store to same location (presumed)
|
# store to same location (presumed)
|
||||||
if self.is_memstore(dst.memory, instr_form, register_changes):
|
if self.is_memstore(dst, instr_form, register_changes):
|
||||||
break
|
break
|
||||||
self._update_reg_changes(instr_form, register_changes, only_postindexed=True)
|
self._update_reg_changes(instr_form, register_changes, only_postindexed=True)
|
||||||
|
|
||||||
@@ -364,32 +370,32 @@ class KernelDG(nx.DiGraph):
|
|||||||
if instruction_form.semantic_operands is None:
|
if instruction_form.semantic_operands is None:
|
||||||
return is_read
|
return is_read
|
||||||
for src in chain(
|
for src in chain(
|
||||||
instruction_form.semantic_operands.source,
|
instruction_form.semantic_operands["source"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
|
):
|
||||||
|
if isinstance(src, RegisterOperand):
|
||||||
|
is_read = self.parser.is_reg_dependend_of(register, src) or is_read
|
||||||
|
if (
|
||||||
|
not isinstance(src, RegisterOperand)
|
||||||
|
and not isinstance(src, MemoryOperand)
|
||||||
|
and "flag" in src
|
||||||
):
|
):
|
||||||
if "register" in src:
|
|
||||||
is_read = self.parser.is_reg_dependend_of(register, src.register) or is_read
|
|
||||||
if "flag" in src:
|
|
||||||
is_read = self.parser.is_flag_dependend_of(register, src.flag) or is_read
|
is_read = self.parser.is_flag_dependend_of(register, src.flag) or is_read
|
||||||
if "memory" in src:
|
if isinstance(src, MemoryOperand):
|
||||||
if src.memory.base is not None:
|
if src.base is not None:
|
||||||
is_read = self.parser.is_reg_dependend_of(register, src.memory.base) or is_read
|
is_read = self.parser.is_reg_dependend_of(register, src.base) or is_read
|
||||||
if src.memory.index is not None:
|
if src.index is not None:
|
||||||
is_read = (
|
is_read = self.parser.is_reg_dependend_of(register, src.index) or is_read
|
||||||
self.parser.is_reg_dependend_of(register, src.memory.index) or is_read
|
|
||||||
)
|
|
||||||
# Check also if read in destination memory address
|
# Check also if read in destination memory address
|
||||||
for dst in chain(
|
for dst in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
if "memory" in dst:
|
if isinstance(dst, MemoryOperand):
|
||||||
if dst.memory.base is not None:
|
if dst.base is not None:
|
||||||
is_read = self.parser.is_reg_dependend_of(register, dst.memory.base) or is_read
|
is_read = self.parser.is_reg_dependend_of(register, dst.base) or is_read
|
||||||
if dst.memory.index is not None:
|
if dst.index is not None:
|
||||||
is_read = (
|
is_read = self.parser.is_reg_dependend_of(register, dst.index) or is_read
|
||||||
self.parser.is_reg_dependend_of(register, dst.memory.index) or is_read
|
|
||||||
)
|
|
||||||
return is_read
|
return is_read
|
||||||
|
|
||||||
def is_memload(self, mem, instruction_form, register_changes={}):
|
def is_memload(self, mem, instruction_form, register_changes={}):
|
||||||
@@ -455,28 +461,28 @@ class KernelDG(nx.DiGraph):
|
|||||||
if instruction_form.semantic_operands is None:
|
if instruction_form.semantic_operands is None:
|
||||||
return is_written
|
return is_written
|
||||||
for dst in chain(
|
for dst in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
|
):
|
||||||
|
if isinstance(dst, RegisterOperand):
|
||||||
|
is_written = self.parser.is_reg_dependend_of(register, dst) or is_written
|
||||||
|
if (
|
||||||
|
not isinstance(dst, RegisterOperand)
|
||||||
|
and not isinstance(dst, MemoryOperand)
|
||||||
|
and "flag" in dst
|
||||||
):
|
):
|
||||||
if "register" in dst:
|
|
||||||
is_written = self.parser.is_reg_dependend_of(register, dst.register) or is_written
|
|
||||||
if "flag" in dst:
|
|
||||||
is_written = self.parser.is_flag_dependend_of(register, dst.flag) or is_written
|
is_written = self.parser.is_flag_dependend_of(register, dst.flag) or is_written
|
||||||
if "memory" in dst:
|
if isinstance(dst, MemoryOperand):
|
||||||
if "pre_indexed" in dst.memory or "post_indexed" in dst.memory:
|
if dst.pre_indexed or dst.post_indexed:
|
||||||
is_written = (
|
is_written = self.parser.is_reg_dependend_of(register, dst.base) or is_written
|
||||||
self.parser.is_reg_dependend_of(register, dst.memory.base) or is_written
|
|
||||||
)
|
|
||||||
# Check also for possible pre- or post-indexing in memory addresses
|
# Check also for possible pre- or post-indexing in memory addresses
|
||||||
for src in chain(
|
for src in chain(
|
||||||
instruction_form.semantic_operands.source,
|
instruction_form.semantic_operands["source"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
if "memory" in src:
|
if isinstance(src, MemoryOperand):
|
||||||
if "pre_indexed" in src.memory or "post_indexed" in src.memory:
|
if src.pre_indexed or src.post_indexed:
|
||||||
is_written = (
|
is_written = self.parser.is_reg_dependend_of(register, src.base) or is_written
|
||||||
self.parser.is_reg_dependend_of(register, src.memory.base) or is_written
|
|
||||||
)
|
|
||||||
return is_written
|
return is_written
|
||||||
|
|
||||||
def is_memstore(self, mem, instruction_form, register_changes={}):
|
def is_memstore(self, mem, instruction_form, register_changes={}):
|
||||||
@@ -485,10 +491,10 @@ class KernelDG(nx.DiGraph):
|
|||||||
if instruction_form.semantic_operands is None:
|
if instruction_form.semantic_operands is None:
|
||||||
return is_store
|
return is_store
|
||||||
for dst in chain(
|
for dst in chain(
|
||||||
instruction_form.semantic_operands.destination,
|
instruction_form.semantic_operands["destination"],
|
||||||
instruction_form.semantic_operands.src_dst,
|
instruction_form.semantic_operands["src_dst"],
|
||||||
):
|
):
|
||||||
if "memory" in dst:
|
if isinstance(dst, MemoryOperand):
|
||||||
is_store = mem == dst["memory"] or is_store
|
is_store = mem == dst["memory"] or is_store
|
||||||
return is_store
|
return is_store
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ def find_marked_section(
|
|||||||
"immediate" in source
|
"immediate" in source
|
||||||
and parser.normalize_imd(source.immediate) == mov_vals[0]
|
and parser.normalize_imd(source.immediate) == mov_vals[0]
|
||||||
and "register" in destination
|
and "register" in destination
|
||||||
and parser.get_full_reg_name(destination['register']) == mov_reg
|
and parser.get_full_reg_name(destination["register"]) == mov_reg
|
||||||
):
|
):
|
||||||
# operands of first instruction match start, check for second one
|
# operands of first instruction match start, check for second one
|
||||||
match, line_count = match_bytes(lines, i + 1, nop_bytes)
|
match, line_count = match_bytes(lines, i + 1, nop_bytes)
|
||||||
@@ -161,7 +161,7 @@ def find_marked_section(
|
|||||||
"immediate" in source
|
"immediate" in source
|
||||||
and parser.normalize_imd(source.immediate) == mov_vals[1]
|
and parser.normalize_imd(source.immediate) == mov_vals[1]
|
||||||
and "register" in destination
|
and "register" in destination
|
||||||
and parser.get_full_reg_name(destination['register']) == mov_reg
|
and parser.get_full_reg_name(destination["register"]) == mov_reg
|
||||||
):
|
):
|
||||||
# operand of first instruction match end, check for second one
|
# operand of first instruction match end, check for second one
|
||||||
match, line_count = match_bytes(lines, i + 1, nop_bytes)
|
match, line_count = match_bytes(lines, i + 1, nop_bytes)
|
||||||
@@ -169,7 +169,8 @@ def find_marked_section(
|
|||||||
# return line of the marker
|
# return line of the marker
|
||||||
index_end = i
|
index_end = i
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print(i, line)
|
pass
|
||||||
|
# print("TESTER",i, line)
|
||||||
if index_start != -1 and index_end != -1:
|
if index_start != -1 and index_end != -1:
|
||||||
break
|
break
|
||||||
return index_start, index_end
|
return index_start, index_end
|
||||||
|
|||||||
@@ -256,38 +256,38 @@ class TestSemanticTools(unittest.TestCase):
|
|||||||
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:
|
||||||
with self.subTest(instruction_form=instruction_form):
|
with self.subTest(instruction_form=instruction_form):
|
||||||
if instruction_form["semantic_operands"] is not None:
|
if instruction_form.semantic_operands is not None:
|
||||||
self.assertTrue("source" in instruction_form["semantic_operands"])
|
self.assertTrue("source" in instruction_form.semantic_operands)
|
||||||
self.assertTrue("destination" in instruction_form["semantic_operands"])
|
self.assertTrue("destination" in instruction_form.semantic_operands)
|
||||||
self.assertTrue("src_dst" in instruction_form["semantic_operands"])
|
self.assertTrue("src_dst" in instruction_form.semantic_operands)
|
||||||
|
|
||||||
def test_src_dst_assignment_AArch64(self):
|
def test_src_dst_assignment_AArch64(self):
|
||||||
for instruction_form in self.kernel_AArch64:
|
for instruction_form in self.kernel_AArch64:
|
||||||
with self.subTest(instruction_form=instruction_form):
|
with self.subTest(instruction_form=instruction_form):
|
||||||
if instruction_form["semantic_operands"] is not None:
|
if instruction_form.semantic_operands is not None:
|
||||||
self.assertTrue("source" in instruction_form["semantic_operands"])
|
self.assertTrue("source" in instruction_form.semantic_operands)
|
||||||
self.assertTrue("destination" in instruction_form["semantic_operands"])
|
self.assertTrue("destination" in instruction_form.semantic_operands)
|
||||||
self.assertTrue("src_dst" in instruction_form["semantic_operands"])
|
self.assertTrue("src_dst" in instruction_form.semantic_operands)
|
||||||
|
|
||||||
def test_tp_lt_assignment_x86(self):
|
def test_tp_lt_assignment_x86(self):
|
||||||
self.assertTrue("ports" in self.machine_model_csx)
|
self.assertTrue("ports" in self.machine_model_csx)
|
||||||
port_num = len(self.machine_model_csx["ports"])
|
port_num = len(self.machine_model_csx["ports"])
|
||||||
for instruction_form in self.kernel_x86:
|
for instruction_form in self.kernel_x86:
|
||||||
with self.subTest(instruction_form=instruction_form):
|
with self.subTest(instruction_form=instruction_form):
|
||||||
self.assertTrue("throughput" in instruction_form)
|
self.assertTrue(instruction_form.throughput != None)
|
||||||
self.assertTrue("latency" in instruction_form)
|
self.assertTrue(instruction_form.latency != None)
|
||||||
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_tp_lt_assignment_AArch64(self):
|
def test_tp_lt_assignment_AArch64(self):
|
||||||
self.assertTrue("ports" in self.machine_model_tx2)
|
self.assertTrue("ports" in self.machine_model_tx2)
|
||||||
port_num = len(self.machine_model_tx2["ports"])
|
port_num = len(self.machine_model_tx2["ports"])
|
||||||
for instruction_form in self.kernel_AArch64:
|
for instruction_form in self.kernel_AArch64:
|
||||||
with self.subTest(instruction_form=instruction_form):
|
with self.subTest(instruction_form=instruction_form):
|
||||||
self.assertTrue("throughput" in instruction_form)
|
self.assertTrue(instruction_form.throughput != None)
|
||||||
self.assertTrue("latency" in instruction_form)
|
self.assertTrue(instruction_form.latency != None)
|
||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user