Changed style to conform to PEP-8 conventions; Added source and destination attributes to parent Operand class

This commit is contained in:
stefandesouza
2023-10-29 13:52:49 +01:00
parent 4186edbc03
commit 14a2aa0b52
26 changed files with 876 additions and 916 deletions

View File

@@ -87,7 +87,7 @@ The usage of OSACA can be listed as:
.. code:: bash .. code:: bash
osaca [-h] [-V] [--arch ARCH] [--fixed] [--lines LINES] osaca [-h] [-V] [--arch ARCH] [--fixed] [--lines lineS]
[--ignore-unknown] [--lcd-timeout SECONDS] [--ignore-unknown] [--lcd-timeout SECONDS]
[--db-check] [--import MICROBENCH] [--insert-marker] [--db-check] [--import MICROBENCH] [--insert-marker]
[--export-graph GRAPHNAME] [--consider-flag-deps] [--export-graph GRAPHNAME] [--consider-flag-deps]

View File

@@ -3363,7 +3363,7 @@ instruction_forms:
name: "rsp" name: "rsp"
source: true source: true
destination: true destination: true
# All of EFLAGS and RFLAGS, without VM and RF # All of Eflags and Rflags, without VM and RF
- class: "flag" - class: "flag"
name: "CF" name: "CF"
source: true source: true

View File

@@ -10,10 +10,10 @@ from collections import OrderedDict
import ruamel.yaml import ruamel.yaml
from osaca.semantics import MachineModel from osaca.semantics import MachineModel
from osaca.parser import InstructionForm from osaca.parser import instructionForm
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
def sanity_check(arch: str, verbose=False, internet_check=False, output_file=sys.stdout): def sanity_check(arch: str, verbose=False, internet_check=False, output_file=sys.stdout):
@@ -190,14 +190,14 @@ def _get_ibench_output(input_data, isa):
entry["throughput"] = _validate_measurement(float(line.split()[1]), "tp") entry["throughput"] = _validate_measurement(float(line.split()[1]), "tp")
if not entry["throughput"]: if not entry["throughput"]:
warnings.warn( warnings.warn(
"Your THROUGHPUT measurement for {} looks suspicious".format(key) "Your throughput measurement for {} looks suspicious".format(key)
+ " and was not added. Please inspect your benchmark." + " and was not added. Please inspect your benchmark."
) )
elif "LT" in instruction: elif "LT" in instruction:
entry["latency"] = _validate_measurement(float(line.split()[1]), "lt") entry["latency"] = _validate_measurement(float(line.split()[1]), "lt")
if not entry["latency"]: if not entry["latency"]:
warnings.warn( warnings.warn(
"Your LATENCY measurement for {} looks suspicious".format(key) "Your latency measurement for {} looks suspicious".format(key)
+ " and was not added. Please inspect your benchmark." + " and was not added. Please inspect your benchmark."
) )
db_entries[key] = entry db_entries[key] = entry
@@ -436,12 +436,12 @@ def _check_sanity_arch_db(arch_mm, isa_mm, internet_check=True):
# Check operands # Check operands
for operand in instr_form["operands"]: for operand in instr_form["operands"]:
if isinstance(operand, RegisterOperand) and not ( if isinstance(operand, registerOperand) and not (
operand.name != None or operand.prefix != None operand.name != None or operand.prefix != None
): ):
# Missing 'name' key # Missing 'name' key
bad_operand.append(instr_form) bad_operand.append(instr_form)
elif isinstance(operand, MemoryOperand) and ( elif isinstance(operand, memoryOperand) and (
operand.base is None operand.base is None
or operand.offset is None or operand.offset is None
or operand.index is None or operand.index is None
@@ -449,7 +449,7 @@ def _check_sanity_arch_db(arch_mm, isa_mm, internet_check=True):
): ):
# Missing at least one key necessary for memory operands # Missing at least one key necessary for memory operands
bad_operand.append(instr_form) bad_operand.append(instr_form)
elif isinstance(operand, ImmediateOperand) and operand.type == None: elif isinstance(operand, immediateOperand) and operand.type == None:
# Missing 'imd' key # Missing 'imd' key
bad_operand.append(instr_form) bad_operand.append(instr_form)
# every entry exists twice --> uniquify # every entry exists twice --> uniquify
@@ -611,7 +611,7 @@ 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"]:
if isinstance(op, RegisterOperand): if isinstance(op, registerOperand):
op_attrs = [] op_attrs = []
if op.name != None: if op.name != None:
op_attrs.append("name:" + op.name) op_attrs.append("name:" + op.name)

View File

@@ -7,7 +7,7 @@ import os
import re import re
from datetime import datetime as dt from datetime import datetime as dt
from osaca.semantics import INSTR_FLAGS, ArchSemantics, KernelDG, MachineModel from osaca.semantics import INSTR_flags, ArchSemantics, KernelDG, MachineModel
def _get_version(*file_paths): def _get_version(*file_paths):
@@ -116,7 +116,7 @@ class Frontend(object):
separator, separator,
instruction_form.latency_cp, instruction_form.latency_cp,
separator, separator,
"X" if INSTR_FLAGS.LT_UNKWN in instruction_form.flags else " ", "X" if INSTR_flags.LT_UNKWN in instruction_form.flags else " ",
separator, separator,
instruction_form.line, instruction_form.line,
) )
@@ -237,7 +237,7 @@ class Frontend(object):
if lcd_warning: if lcd_warning:
warnings.append("LCDWarning") warnings.append("LCDWarning")
# if INSTR_FLAGS.TP_UNKWN in [flag for instr in kernel for flag in instr.flags]: # if INSTR_flags.TP_UNKWN in [flag for instr in kernel for flag in instr.flags]:
# warnings.append("UnknownInstrWarning") # warnings.append("UnknownInstrWarning")
tp_sum = ArchSemantics.get_throughput_sum(kernel) or kernel[0].port_pressure tp_sum = ArchSemantics.get_throughput_sum(kernel) or kernel[0].port_pressure
@@ -373,11 +373,11 @@ class Frontend(object):
) )
s += "\n" s += "\n"
# check for unknown instructions and throw warning if called without --ignore-unknown # check for unknown instructions and throw warning if called without --ignore-unknown
if not ignore_unknown and INSTR_FLAGS.TP_UNKWN in [ if not ignore_unknown and INSTR_flags.TP_UNKWN in [
flag for instr in kernel for flag in instr.flags flag for instr in kernel for flag in instr.flags
]: ]:
num_missing = len( num_missing = len(
[instr.flags for instr in kernel if INSTR_FLAGS.TP_UNKWN in instr.flags] [instr.flags for instr in kernel if INSTR_flags.TP_UNKWN in instr.flags]
) )
s += self._missing_instruction_error(num_missing) s += self._missing_instruction_error(num_missing)
else: else:
@@ -471,9 +471,9 @@ class Frontend(object):
def _get_flag_symbols(self, flag_obj): def _get_flag_symbols(self, flag_obj):
"""Returns flags for a flag object of an instruction""" """Returns flags for a flag object of an instruction"""
string_result = "" string_result = ""
string_result += "*" if INSTR_FLAGS.NOT_BOUND in flag_obj else "" string_result += "*" if INSTR_flags.NOT_BOUND in flag_obj else ""
string_result += "X" if INSTR_FLAGS.TP_UNKWN in flag_obj else "" string_result += "X" if INSTR_flags.TP_UNKWN in flag_obj else ""
string_result += "P" if INSTR_FLAGS.HIDDEN_LD in flag_obj else "" string_result += "P" if INSTR_flags.HIDDEN_LD in flag_obj else ""
# TODO add other flags # TODO add other flags
string_result += " " if len(string_result) == 0 else "" string_result += " " if len(string_result) == 0 else ""
return string_result return string_result
@@ -554,10 +554,10 @@ class Frontend(object):
def _symbol_map(self): def _symbol_map(self):
"""Prints instruction flag map.""" """Prints instruction flag map."""
symbol_dict = { symbol_dict = {
INSTR_FLAGS.NOT_BOUND: "Instruction micro-ops not bound to a port", INSTR_flags.NOT_BOUND: "Instruction micro-ops not bound to a port",
INSTR_FLAGS.TP_UNKWN: "No throughput/latency information for this instruction in " INSTR_flags.TP_UNKWN: "No throughput/latency information for this instruction in "
+ "data file", + "data file",
INSTR_FLAGS.HIDDEN_LD: "Throughput of LOAD operation can be hidden behind a past " INSTR_flags.HIDDEN_LD: "Throughput of LOAD operation can be hidden behind a past "
+ "or future STORE instruction", + "or future STORE instruction",
} }
symbol_map = "" symbol_map = ""

View File

@@ -13,7 +13,7 @@ from osaca.db_interface import import_benchmark_output, sanity_check
from osaca.frontend import Frontend from osaca.frontend import Frontend
from osaca.parser import BaseParser, ParserAArch64, ParserX86ATT from osaca.parser import BaseParser, ParserAArch64, ParserX86ATT
from osaca.semantics import ( from osaca.semantics import (
INSTR_FLAGS, INSTR_flags,
ArchSemantics, ArchSemantics,
KernelDG, KernelDG,
MachineModel, MachineModel,
@@ -430,7 +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 INSTR_FLAGS.TP_UNKWN in instruction.flags and INSTR_FLAGS.LT_UNKWN in instruction.flags: if 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)

View File

@@ -7,12 +7,12 @@ from .attr_dict import AttrDict
from .base_parser import BaseParser from .base_parser import BaseParser
from .parser_x86att import ParserX86ATT from .parser_x86att import ParserX86ATT
from .parser_AArch64 import ParserAArch64 from .parser_AArch64 import ParserAArch64
from .instruction_form import InstructionForm from .instruction_form import instructionForm
from .operand import Operand from .operand import Operand
__all__ = [ __all__ = [
"Operand", "Operand",
"InstructionForm", "instructionForm",
"AttrDict", "AttrDict",
"BaseParser", "BaseParser",
"ParserX86ATT", "ParserX86ATT",

View File

@@ -6,16 +6,16 @@ import re
class BaseParser(object): class BaseParser(object):
# Identifiers for operand types # Identifiers for operand types
COMMENT_ID = "comment" comment_id = "comment"
DIRECTIVE_ID = "directive" directive_id = "directive"
IMMEDIATE_ID = "immediate" IMMEDIATE_ID = "immediate"
LABEL_ID = "label" label_id = "label"
IDENTIFIER_ID = "identifier" IDENTIFIER_ID = "identifier"
MEMORY_ID = "memory" MEMORY_ID = "memory"
REGISTER_ID = "register" REGISTER_ID = "register"
SEGMENT_EXT_ID = "segment_extension" segment_ext_id = "segment_extension"
INSTRUCTION_ID = "instruction" instruction_id = "instruction"
OPERANDS_ID = "operands" operands_id = "operands"
_parser_constructed = False _parser_constructed = False
def __init__(self): def __init__(self):

View File

@@ -3,49 +3,49 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class DirectiveOperand(Operand): class directiveOperand(Operand):
def __init__(self, NAME_ID=None, PARAMETER_ID=None, COMMENT_ID=None): def __init__(self, name_id=None, parameter_id=None, comment_id=None):
super().__init__(NAME_ID) super().__init__(name_id)
self._PARAMETER_ID = PARAMETER_ID self._parameter_id = parameter_id
self._COMMENT_ID = COMMENT_ID self._comment_id = comment_id
@property @property
def parameters(self): def parameters(self):
return self._PARAMETER_ID return self._parameter_id
@property @property
def comment(self): def comment(self):
return self._COMMENT_ID return self._comment_id
def __iter__(self): def __iter__(self):
return self return self
def __next__(self): def __next__(self):
if not self._COMMENT_ID: if not self._comment_id:
raise StopIteration raise StopIteration
return self._COMMENT_ID.pop(0) return self._comment_id.pop(0)
@parameters.setter @parameters.setter
def parameters(self, parameters): def parameters(self, parameters):
self._PARAMETER_ID = parameters self._parameter_id = parameters
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID = comment self._comment_id = comment
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, DirectiveOperand): if isinstance(other, directiveOperand):
return ( return (
self._NAME_ID == other._NAME_ID self._name_id == other._name_id
and self._PARAMETER_ID == other._PARAMETER_ID and self._parameter_id == other._parameter_id
and self._COMMENT_ID == other._COMMENT_ID and self._comment_id == other._comment_id
) )
elif isinstance(other, dict): elif isinstance(other, dict):
return self._NAME_ID == other["name"] and self._PARAMETER_ID == other["parameters"] return self._name_id == other["name"] and self._parameter_id == other["parameters"]
return False return False
def __str__(self): def __str__(self):
return f"Directive(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})" return f"Directive(name_id={self._name_id}, parameters={self._parameter_id}, comment={self._comment_id})"
def __repr__(self): def __repr__(self):
return f"DirectiveOperand(NAME_ID={self._NAME_ID}, PARAMETERS={self._PARAMETER_ID}, COMMENT={self._COMMENT_ID})" return f"directiveOperand(name_id={self._name_id}, parameters={self._parameter_id}, comment={self._comment_id})"

View File

@@ -3,32 +3,32 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class IdentifierOperand(Operand): class identifierOperand(Operand):
def __init__(self, name=None, OFFSET=None, RELOCATION=None): def __init__(self, name=None, offset=None, relocation=None):
super().__init__(name) super().__init__(name)
self._OFFSET = OFFSET self._offset = offset
self._RELOCATION = RELOCATION self._relocation = relocation
@property @property
def offset(self): def offset(self):
return self._OFFSET return self._offset
@offset.setter @offset.setter
def offset(self, offset): def offset(self, offset):
self._OFFSET = offset self._offset = offset
@property @property
def relocation(self): def relocation(self):
return self._RELOCATION return self._relocation
@relocation.setter @relocation.setter
def relocation(self, relocation): def relocation(self, relocation):
self._RELOCATION = relocation self._relocation = relocation
def __str__(self): def __str__(self):
return ( return (
f"IdentifierOperand({self.name}, offset={self.offset}, relocation={self.relocation})" f"identifierOperand({self.name}, offset={self.offset}, relocation={self.relocation})"
) )
def __repr__(self): def __repr__(self):
return f"IdentifierOperand(name={self.name}, offset={self.offset}, relocation={self.relocation})" return f"identifierOperand(name={self.name}, offset={self.offset}, relocation={self.relocation})"

View File

@@ -3,90 +3,72 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class ImmediateOperand(Operand): class immediateOperand(Operand):
def __init__( def __init__(
self, self,
IDENTIFIER_ID=None, identifier_id=None,
TYPE_ID=None, type_id=None,
VALUE_ID=None, value_id=None,
SHIFT_ID=None, shift_id=None,
SOURCE=False, source=False,
DESTINATION=False destination=False,
): ):
super().__init__(str(VALUE_ID)) super().__init__(str(value_id), source, destination)
self._IDENTIFIER_ID = IDENTIFIER_ID self._identifier_id = identifier_id
self._TYPE_ID = TYPE_ID self._type_id = type_id
self._VALUE_ID = VALUE_ID self._value_id = value_id
self._SHIFT_ID = SHIFT_ID self._shift_id = shift_id
self._SOURCE = SOURCE
self._DESTINATION = DESTINATION
@property @property
def identifier(self): def identifier(self):
return self._IDENTIFIER_ID return self._identifier_id
@property @property
def type(self): def type(self):
return self._TYPE_ID return self._type_id
@property @property
def value(self): def value(self):
return self._VALUE_ID return self._value_id
@property @property
def shift(self): def shift(self):
return self._TYPE_ID return self._type_id
@property
def source(self):
return self._SOURCE
@source.setter
def source(self, source):
self._SOURCE = source
@property
def destination(self):
return self._DESTINATION
@destination.setter
def destination(self, destination):
self._DESTINATION = destination
@identifier.setter @identifier.setter
def identifier(self, identifier): def identifier(self, identifier):
self._IDENTIFIER_ID = identifier self._identifier_id = identifier
@type.setter @type.setter
def type(self, type): def type(self, type):
self._TYPE_ID = type self._type_id = type
@value.setter @value.setter
def value(self, value): def value(self, value):
self._VALUE_ID = value self._value_id = value
@shift.setter @shift.setter
def index(self, shift): def index(self, shift):
self._SHIFT_ID = shift self._shift_id = shift
def __str__(self): def __str__(self):
return ( return (
f"ImmediateOperand(IDENTIFIER_ID={self._IDENTIFIER_ID}, TYPE_ID={self._TYPE_ID}, " f"immediateOperand(identifier_id={self._identifier_id}, type_id={self._type_id}, "
f"VALUE_ID={self._VALUE_ID}, SHIFT_ID={self._SHIFT_ID})" f"value_id={self._value_id}, shift_id={self._shift_id})"
) )
def __repr__(self): def __repr__(self):
return ( return (
f"ImmediateOperand(IDENTIFIER_ID={self._IDENTIFIER_ID}, TYPE_ID={self._TYPE_ID}, " f"immediateOperand(identifier_id={self._identifier_id}, type_id={self._type_id}, "
f"VALUE_ID={self._VALUE_ID}, SHIFT_ID={self._SHIFT_ID})" f"value_id={self._value_id}, shift_id={self._shift_id})"
) )
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, ImmediateOperand): if isinstance(other, immediateOperand):
return ( return (
self._IDENTIFIER_ID == other._IDENTIFIER_ID self._identifier_id == other._identifier_id
and self._TYPE_ID == other._TYPE_ID and self._type_id == other._type_id
and self._VALUE_ID == other._VALUE_ID and self._value_id == other._value_id
and self._SHIFT_ID == other._SHIFT_ID and self._shift_id == other._shift_id
) )
return False return False

View File

@@ -1,200 +1,200 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from osaca.parser.directive import DirectiveOperand from osaca.parser.directive import directiveOperand
class InstructionForm: class instructionForm:
def __init__( def __init__(
self, self,
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
HIDDEN_OPERANDS=[], hidden_operands=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE=None, line=None,
LINE_NUMBER=None, line_number=None,
SEMANTIC_OPERANDS={"source": [], "destination": [], "src_dst": []}, semantic_operands={"source": [], "destination": [], "src_dst": []},
THROUGHPUT = None, throughput=None,
LATENCY = None, latency=None,
UOPS = None, uops=None,
PORT_PRESSURE = None, port_pressure=None,
BREAKS_DEP = False breaks_dep=False,
): ):
self._INSTRUCTION_ID = INSTRUCTION_ID self._instruction_id = instruction_id
self._OPERANDS_ID = OPERANDS_ID self._operands_id = operands_id
self._HIDDEN_OPERANDS = HIDDEN_OPERANDS self._hidden_operands = hidden_operands
self._DIRECTIVE_ID = DIRECTIVE_ID self._directive_id = directive_id
self._COMMENT_ID = COMMENT_ID self._comment_id = comment_id
self._LABEL_ID = LABEL_ID self._label_id = label_id
self._LINE = LINE self._line = line
self._LINE_NUMBER = LINE_NUMBER self._line_number = line_number
self._SEMANTIC_OPERANDS = SEMANTIC_OPERANDS self._semantic_operands = semantic_operands
self._UOPS = UOPS self._uops = uops
self._BREAKS_DEP = BREAKS_DEP self._breaks_dep = breaks_dep
# self.semantic_operands = {"source": [], "destination": [], "src_dst": []} # self.semantic_operands = {"source": [], "destination": [], "src_dst": []}
self._LATENCY = LATENCY self._latency = latency
self._THROUGHPUT = THROUGHPUT self._throughput = throughput
self._LATENCY_CP = [] self._latency_cp = []
self._LATENCY_LCD = [] self._latency_lcd = []
self._LATENCY_WO_LOAD = None self._latency_wo_load = None
self._PORT_PRESSURE = PORT_PRESSURE self._port_pressure = port_pressure
self._PORT_UOPS = [] self._port_uops = []
self._FLAGS = [] self._flags = []
@property @property
def semantic_operands(self): def semantic_operands(self):
return self._SEMANTIC_OPERANDS return self._semantic_operands
@property @property
def instruction(self): def instruction(self):
return self._INSTRUCTION_ID return self._instruction_id
@property @property
def label(self): def label(self):
return self._LABEL_ID return self._label_id
@property @property
def comment(self): def comment(self):
return self._COMMENT_ID return self._comment_id
@property @property
def directive(self): def directive(self):
return self._DIRECTIVE_ID return self._directive_id
@property @property
def line_number(self): def line_number(self):
return self._LINE_NUMBER return self._line_number
@property @property
def line(self): def line(self):
return self._LINE return self._line
@property @property
def operands(self): def operands(self):
return self._OPERANDS_ID return self._operands_id
@property @property
def hidden_operands(self): def hidden_operands(self):
return self._HIDDEN_OPERANDS return self._hidden_operands
@property @property
def port_pressure(self): def port_pressure(self):
return self._PORT_PRESSURE return self._port_pressure
@property @property
def port_uops(self): def port_uops(self):
return self._PORT_UOPS return self._port_uops
@property @property
def flags(self): def flags(self):
return self._FLAGS return self._flags
@property @property
def uops(self): def uops(self):
return self._UOPS return self._uops
@property @property
def throughput(self): def throughput(self):
return self._THROUGHPUT return self._throughput
@property @property
def latency(self): def latency(self):
return self._LATENCY return self._latency
@property @property
def latency_wo_load(self): def latency_wo_load(self):
return self._LATENCY_WO_LOAD return self._latency_wo_load
@property @property
def breaks_dep(self): def breaks_dep(self):
return self._BREAKS_DEP return self._breaks_dep
@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
@directive.setter @directive.setter
def directive(self, directive): def directive(self, directive):
self._DIRECTIVE_ID = directive self._directive_id = directive
@line_number.setter @line_number.setter
def line_number(self, line_number): def line_number(self, line_number):
self._LINE_NUMBER = line_number self._line_number = line_number
@line.setter @line.setter
def line(self, line): def line(self, line):
self._LINE = line self._line = line
@operands.setter @operands.setter
def operands(self, operands): def operands(self, operands):
self._OPERANDS_ID = operands self._operands_id = operands
@hidden_operands.setter @hidden_operands.setter
def hidden_operands(self, hidden_operands): def hidden_operands(self, hidden_operands):
self._HIDDEN_OPERANDS = hidden_operands self._hidden_operands = hidden_operands
@breaks_dep.setter @breaks_dep.setter
def breaks_dep(self, boolean): def breaks_dep(self, boolean):
self._BREAKS_DEP = boolean self._breaks_dep = boolean
@instruction.setter @instruction.setter
def instruction(self, instruction): def instruction(self, instruction):
self._INSTRUCTION_ID = instruction self._instruction_id = instruction
@label.setter @label.setter
def label(self, label): def label(self, label):
self._LABEL_ID = label self._label_id = label
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID = comment self._comment_id = comment
@port_pressure.setter @port_pressure.setter
def port_pressure(self, port_pressure): def port_pressure(self, port_pressure):
self._PORT_PRESSURE = port_pressure self._port_pressure = port_pressure
@port_uops.setter @port_uops.setter
def port_uops(self, port_uops): def port_uops(self, port_uops):
self._PORT_UOPS = port_uops self._port_uops = port_uops
@flags.setter @flags.setter
def flags(self, flags): def flags(self, flags):
self._FLAGS = flags self._flags = flags
@uops.setter @uops.setter
def uops(self, uops): def uops(self, uops):
self._UOPS = uops self._uops = uops
@throughput.setter @throughput.setter
def throughput(self, throughput): def throughput(self, throughput):
self._THROUGHPUT = throughput self._throughput = throughput
@latency.setter @latency.setter
def latency(self, latency): def latency(self, latency):
self._LATENCY = latency self._latency = latency
@latency_wo_load.setter @latency_wo_load.setter
def latency_wo_load(self, latency_wo_load): def latency_wo_load(self, latency_wo_load):
self._LATENCY_WO_LOAD = 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})"
def __str__(self): def __str__(self):
return f"Instruction: {self._INSTRUCTION_ID}\nOperands: {self._OPERANDS_ID}\nDirective: {self._DIRECTIVE_ID}\nComment: {self._COMMENT_ID}\nLabel: {self._LABEL_ID}\nLine: {self._LINE}\nLine Number: {self._LINE_NUMBER}\nSemantic Operands: {self._SEMANTIC_OPERANDS}\nFlags: {self._FLAGS}" return f"Instruction: {self._instruction_id}\nOperands: {self._operands_id}\nDirective: {self._directive_id}\nComment: {self._comment_id}\nLabel: {self._label_id}\nLine: {self._line}\nLine Number: {self._line_number}\nSemantic Operands: {self._semantic_operands}\nFlags: {self._flags}"
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, InstructionForm): if isinstance(other, instructionForm):
return ( return (
self._INSTRUCTION_ID == other._INSTRUCTION_ID self._instruction_id == other._instruction_id
and self._OPERANDS_ID == other._OPERANDS_ID and self._operands_id == other._operands_id
and self._DIRECTIVE_ID == other._DIRECTIVE_ID and self._directive_id == other._directive_id
and self._COMMENT_ID == other._COMMENT_ID and self._comment_id == other._comment_id
and self._LABEL_ID == other._LABEL_ID and self._label_id == other._label_id
and self._LINE == other._LINE and self._line == other._line
and self._LINE_NUMBER == other._LINE_NUMBER and self._line_number == other._line_number
and self._SEMANTIC_OPERANDS == other._SEMANTIC_OPERANDS and self._semantic_operands == other._semantic_operands
) )
return False return False

View File

@@ -3,29 +3,29 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class LabelOperand(Operand): class labelOperand(Operand):
def __init__(self, NAME_ID=None, COMMENT_ID=None): def __init__(self, name_id=None, comment_id=None):
super().__init__(NAME_ID) super().__init__(name_id)
self._COMMENT_ID = COMMENT_ID self._comment_id = comment_id
@property @property
def comment(self): def comment(self):
return self._COMMENT_ID return self._comment_id
@comment.setter @comment.setter
def comment(self, comment): def comment(self, comment):
self._COMMENT_ID = comment self._comment_id = comment
def __iter__(self): def __iter__(self):
return self return self
def __next__(self): def __next__(self):
if not self._COMMENT_ID: if not self._comment_id:
raise StopIteration raise StopIteration
return self._COMMENT_ID.pop(0) return self._comment_id.pop(0)
def __str__(self): def __str__(self):
return f"LabelOperand(NAME_ID={self._NAME_ID}, COMMENT={self._COMMENT_ID})" return f"labelOperand(name_id={self._name_id}, comment={self._comment_id})"
def __repr__(self): def __repr__(self):
return f"LabelOperand(NAME_ID={self._NAME_ID}, COMMENT={self._COMMENT_ID})" return f"labelOperand(name_id={self._name_id}, comment={self._comment_id})"

View File

@@ -3,41 +3,39 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class MemoryOperand(Operand): class memoryOperand(Operand):
def __init__( def __init__(
self, self,
OFFSET_ID=None, offset_ID=None,
BASE_ID=None, base_id=None,
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
SEGMENT_EXT_ID=None, segment_ext_id=None,
MASK=None, mask=None,
PRE_INDEXED=False, pre_indexed=False,
POST_INDEXED=False, post_indexed=False,
INDEXED_VAL=None, indexed_val=None,
PORT_PRESSURE=[], port_pressure=[],
DST=None, dst=None,
SOURCE=False, source=False,
DESTINATION=False, destination=False,
): ):
super().__init__("memory") super().__init__("memory", source, destination)
self._OFFSET_ID = OFFSET_ID self._offset_ID = offset_ID
self._BASE_ID = BASE_ID self._base_id = base_id
self._INDEX_ID = INDEX_ID self._index_id = index_id
self._SCALE_ID = SCALE_ID self._scale_id = scale_id
self._SEGMENT_EXT_ID = SEGMENT_EXT_ID self._segment_ext_id = segment_ext_id
self._MASK = MASK self._mask = mask
self._PRE_INDEXED = PRE_INDEXED self._pre_indexed = pre_indexed
self._POST_INDEXED = POST_INDEXED self._post_indexed = post_indexed
self._INDEXED_VAL = INDEXED_VAL self._indexed_val = indexed_val
self._PORT_PRESSURE = PORT_PRESSURE self._port_pressure = port_pressure
self._DST = DST self._dst = dst
self._SOURCE = SOURCE
self._DESTINATION = DESTINATION
@property @property
def offset(self): def offset(self):
return self._OFFSET_ID return self._offset_ID
@property @property
def immediate(self): def immediate(self):
@@ -45,135 +43,119 @@ class MemoryOperand(Operand):
@property @property
def base(self): def base(self):
return self._BASE_ID return self._base_id
@property @property
def index(self): def index(self):
return self._INDEX_ID return self._index_id
@property @property
def scale(self): def scale(self):
return self._SCALE_ID return self._scale_id
@property @property
def segment_ext_id(self): def segment_ext_id(self):
return self._SEGMENT_EXT_ID return self._segment_ext_id
@property @property
def mask(self): def mask(self):
return self._MASK return self._mask
@property @property
def pre_indexed(self): def pre_indexed(self):
return self._PRE_INDEXED return self._pre_indexed
@property @property
def post_indexed(self): def post_indexed(self):
return self._POST_INDEXED return self._post_indexed
@property @property
def indexed_val(self): def indexed_val(self):
return self._INDEXED_VAL return self._indexed_val
@property @property
def port_pressure(self): def port_pressure(self):
return self._PORT_PRESSURE return self._port_pressure
@property @property
def dst(self): def dst(self):
return self._DST return self._dst
@dst.setter @dst.setter
def dst(self, dst): def dst(self, dst):
self._DST = dst self._dst = dst
@port_pressure.setter @port_pressure.setter
def port_pressure(self, port_pressure): def port_pressure(self, port_pressure):
self._PORT_PRESSURE = port_pressure self._port_pressure = port_pressure
@segment_ext_id.setter @segment_ext_id.setter
def segment_ext_id(self, segment): def segment_ext_id(self, segment):
self._SEGMENT_EXT_ID = segment self._segment_ext_id = segment
@offset.setter @offset.setter
def offset(self, offset): def offset(self, offset):
self._OFFSET_ID = offset self._offset_ID = offset
@base.setter @base.setter
def base(self, base): def base(self, base):
self._BASE_ID = base self._base_id = base
@index.setter @index.setter
def index(self, index): def index(self, index):
self._INDEX_ID = index self._index_id = index
@scale.setter @scale.setter
def scale(self, scale): def scale(self, scale):
self._SCALE_ID = scale self._scale_id = scale
@mask.setter @mask.setter
def mask(self, mask): def mask(self, mask):
self._MASK = mask self._mask = mask
@pre_indexed.setter @pre_indexed.setter
def pre_indexed(self, pre_indexed): def pre_indexed(self, pre_indexed):
self._PRE_INDEXED = pre_indexed self._pre_indexed = pre_indexed
@post_indexed.setter @post_indexed.setter
def post_indexed(self, post_indexed): def post_indexed(self, post_indexed):
self._POST_INDEXED = post_indexed self._post_indexed = post_indexed
@indexed_val.setter @indexed_val.setter
def indexed_val(self, value): def indexed_val(self, value):
self._INDEXED_VAL = value self._indexed_val = value
@property
def source(self):
return self._SOURCE
@source.setter
def source(self, source):
self._SOURCE = source
@property
def destination(self):
return self._DESTINATION
@destination.setter
def destination(self, destination):
self._DESTINATION = destination
def __str__(self): def __str__(self):
return ( return (
f"MemoryOperand(NAME_ID={self._NAME_ID}, OFFSET_ID={self._OFFSET_ID}, " f"memoryOperand(name_id={self._name_id}, offset_ID={self._offset_ID}, "
f"BASE_ID={self._BASE_ID}, INDEX_ID={self._INDEX_ID}, SCALE_ID={self._SCALE_ID}, " f"base_id={self._base_id}, index_id={self._index_id}, scale_id={self._scale_id}, "
f"SEGMENT_EXT_ID={self._SEGMENT_EXT_ID}, MASK={self._MASK}, " f"segment_ext_id={self._segment_ext_id}, mask={self._mask}, "
f"PRE_INDEXED={self._PRE_INDEXED}, POST_INDEXED={self._POST_INDEXED}, " f"pre_indexed={self._pre_indexed}, post_indexed={self._post_indexed}, "
f"INDEXED_VAL={self._INDEXED_VAL}, PORT_PRESSURE={self._PORT_PRESSURE})," f"indexed_val={self._indexed_val}, port_pressure={self._port_pressure}),"
f"SOURCE={self._SOURCE}, DESTINATION={self._DESTINATION})" f"source={self._source}, destination={self._destination})"
) )
def __repr__(self): def __repr__(self):
return ( return (
f"MemoryOperand(NAME_ID={self._NAME_ID}, OFFSET_ID={self._OFFSET_ID}, " f"memoryOperand(name_id={self._name_id}, offset_ID={self._offset_ID}, "
f"BASE_ID={self._BASE_ID}, INDEX_ID={self._INDEX_ID}, SCALE_ID={self._SCALE_ID}, " f"base_id={self._base_id}, index_id={self._index_id}, scale_id={self._scale_id}, "
f"SEGMENT_EXT_ID={self._SEGMENT_EXT_ID}, MASK={self._MASK}, " f"segment_ext_id={self._segment_ext_id}, mask={self._mask}, "
f"PRE_INDEXED={self._PRE_INDEXED}, POST_INDEXED={self._POST_INDEXED}, " f"pre_indexed={self._pre_indexed}, post_indexed={self._post_indexed}, "
f"INDEXED_VAL={self._INDEXED_VAL}, PORT_PRESSURE={self._PORT_PRESSURE})," f"indexed_val={self._indexed_val}, port_pressure={self._port_pressure}),"
f"SOURCE={self._SOURCE}, DESTINATION={self._DESTINATION})" f"source={self._source}, destination={self._destination})"
) )
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, MemoryOperand): if isinstance(other, memoryOperand):
return ( return (
self._OFFSET_ID == other._OFFSET_ID self._offset_ID == other._offset_ID
and self._BASE_ID == other._BASE_ID and self._base_id == other._base_id
and self._INDEX_ID == other._INDEX_ID and self._index_id == other._index_id
and self._SCALE_ID == other._SCALE_ID and self._scale_id == other._scale_id
and self._SEGMENT_EXT_ID == other._SEGMENT_EXT_ID and self._segment_ext_id == other._segment_ext_id
and self._MASK == other._MASK and self._mask == other._mask
and self._PRE_INDEXED == other._PRE_INDEXED and self._pre_indexed == other._pre_indexed
and self._POST_INDEXED == other._POST_INDEXED and self._post_indexed == other._post_indexed
and self._INDEXED_VAL == other._INDEXED_VAL and self._indexed_val == other._indexed_val
) )
return False return False

View File

@@ -2,19 +2,37 @@
class Operand: class Operand:
def __init__(self, NAME_ID): def __init__(self, name_id, source=False, destination=False):
self._NAME_ID = NAME_ID self._name_id = name_id
self._source = source
self._destination = destination
@property @property
def name(self): def name(self):
return self._NAME_ID return self._name_id
@property
def source(self):
return self._source
@property
def destination(self):
return self._destination
@name.setter @name.setter
def name(self, name): def name(self, name):
self._NAME_ID = name self._name_id = name
@name.setter
def source(self, source):
self._source = source
@destination.setter
def destination(self, destination):
self._destination = destination
def __repr__(self): def __repr__(self):
return f"Operand(NAME_ID={self._NAME_ID}" return f"Operand(name_id={self._name_id},source={self._source},destination={self._destination})"
def __str__(self): def __str__(self):
return f"Name: {self._NAME_ID}" return f"Name: {self._name_id}, Source: {self._source}, Destination: {self._destination}"

View File

@@ -3,14 +3,14 @@ from copy import deepcopy
import pyparsing as pp import pyparsing as pp
from osaca.parser import BaseParser from osaca.parser import BaseParser
from osaca.parser.instruction_form import InstructionForm from osaca.parser.instruction_form import instructionForm
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
from osaca.parser.directive import DirectiveOperand from osaca.parser.directive import directiveOperand
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.label import LabelOperand from osaca.parser.label import labelOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import identifierOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
class ParserAArch64(BaseParser): class ParserAArch64(BaseParser):
@@ -32,7 +32,7 @@ class ParserAArch64(BaseParser):
symbol_comment = "//" symbol_comment = "//"
self.comment = pp.Literal(symbol_comment) + pp.Group( self.comment = pp.Literal(symbol_comment) + pp.Group(
pp.ZeroOrMore(pp.Word(pp.printables)) pp.ZeroOrMore(pp.Word(pp.printables))
).setResultsName(self.COMMENT_ID) ).setResultsName(self.comment_id)
# Define ARM assembly identifier # Define ARM assembly identifier
decimal_number = pp.Combine( decimal_number = pp.Combine(
pp.Optional(pp.Literal("-")) + pp.Word(pp.nums) pp.Optional(pp.Literal("-")) + pp.Word(pp.nums)
@@ -54,7 +54,7 @@ class ParserAArch64(BaseParser):
# Label # Label
self.label = pp.Group( self.label = pp.Group(
identifier.setResultsName("name") + pp.Literal(":") + pp.Optional(self.comment) identifier.setResultsName("name") + pp.Literal(":") + pp.Optional(self.comment)
).setResultsName(self.LABEL_ID) ).setResultsName(self.label_id)
# Directive # Directive
directive_option = pp.Combine( directive_option = pp.Combine(
pp.Word(pp.alphas + "#@.%", exact=1) pp.Word(pp.alphas + "#@.%", exact=1)
@@ -69,7 +69,7 @@ class ParserAArch64(BaseParser):
+ pp.Word(pp.alphanums + "_").setResultsName("name") + pp.Word(pp.alphanums + "_").setResultsName("name")
+ (pp.OneOrMore(directive_parameter) ^ commaSeparatedList).setResultsName("parameters") + (pp.OneOrMore(directive_parameter) ^ commaSeparatedList).setResultsName("parameters")
+ pp.Optional(self.comment) + pp.Optional(self.comment)
).setResultsName(self.DIRECTIVE_ID) ).setResultsName(self.directive_id)
# LLVM-MCA markers # LLVM-MCA markers
self.llvm_markers = pp.Group( self.llvm_markers = pp.Group(
pp.Literal("#") pp.Literal("#")
@@ -78,7 +78,7 @@ class ParserAArch64(BaseParser):
+ (pp.CaselessLiteral("BEGIN") | pp.CaselessLiteral("END")) + (pp.CaselessLiteral("BEGIN") | pp.CaselessLiteral("END"))
) )
+ pp.Optional(self.comment) + pp.Optional(self.comment)
).setResultsName(self.COMMENT_ID) ).setResultsName(self.comment_id)
############################## ##############################
# Instructions # Instructions
@@ -260,21 +260,21 @@ class ParserAArch64(BaseParser):
:type line_number: int, optional :type line_number: int, optional
:return: `dict` -- parsed asm line (comment, label, directive or instruction form) :return: `dict` -- parsed asm line (comment, label, directive or instruction form)
""" """
instruction_form = InstructionForm( instruction_form = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE=line, line=line,
LINE_NUMBER=line_number, line_number=line_number,
) )
result = None result = None
# 1. Parse comment # 1. Parse comment
try: try:
result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict()) result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict())
instruction_form.comment = " ".join(result[self.COMMENT_ID]) instruction_form.comment = " ".join(result[self.comment_id])
except pp.ParseException: except pp.ParseException:
pass pass
# 1.2 check for llvm-mca marker # 1.2 check for llvm-mca marker
@@ -282,7 +282,7 @@ class ParserAArch64(BaseParser):
result = self.process_operand( result = self.process_operand(
self.llvm_markers.parseString(line, parseAll=True).asDict() self.llvm_markers.parseString(line, parseAll=True).asDict()
) )
instruction_form.comment = " ".join(result[self.COMMENT_ID]) instruction_form.comment = " ".join(result[self.comment_id])
except pp.ParseException: except pp.ParseException:
pass pass
# 2. Parse label # 2. Parse label
@@ -301,8 +301,8 @@ class ParserAArch64(BaseParser):
result = self.process_operand( result = self.process_operand(
self.directive.parseString(line, parseAll=True).asDict() self.directive.parseString(line, parseAll=True).asDict()
) )
instruction_form.directive = DirectiveOperand( instruction_form.directive = directiveOperand(
NAME_ID=result.name, PARAMETER_ID=result.parameters name_id=result.name, parameter_id=result.parameters
) )
if result.comment is not None: if result.comment is not None:
instruction_form.comment = " ".join(result.comment) instruction_form.comment = " ".join(result.comment)
@@ -353,10 +353,10 @@ class ParserAArch64(BaseParser):
if "operand5" in result: if "operand5" in result:
operand = self.process_operand(result["operand5"]) operand = self.process_operand(result["operand5"])
operands.extend(operand) if isinstance(operand, list) else operands.append(operand) operands.extend(operand) if isinstance(operand, list) else operands.append(operand)
return_dict = InstructionForm( return_dict = instructionForm(
INSTRUCTION_ID=result["mnemonic"], instruction_id=result["mnemonic"],
OPERANDS_ID=operands, operands_id=operands,
COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None, comment_id=" ".join(result[self.comment_id]) if self.comment_id in result else None,
) )
return return_dict return return_dict
@@ -376,30 +376,30 @@ class ParserAArch64(BaseParser):
# add value attribute to floating point immediates without exponent # add value attribute to floating point immediates without exponent
if self.IMMEDIATE_ID in operand: if self.IMMEDIATE_ID in operand:
return self.process_immediate(operand[self.IMMEDIATE_ID]) return self.process_immediate(operand[self.IMMEDIATE_ID])
if self.LABEL_ID in operand: if self.label_id in operand:
return self.process_label(operand[self.LABEL_ID]) return self.process_label(operand[self.label_id])
if self.IDENTIFIER_ID in operand: if self.IDENTIFIER_ID in operand:
return self.process_identifier(operand[self.IDENTIFIER_ID]) return self.process_identifier(operand[self.IDENTIFIER_ID])
if self.REGISTER_ID in operand: if self.REGISTER_ID in operand:
return self.process_register_operand(operand[self.REGISTER_ID]) return self.process_register_operand(operand[self.REGISTER_ID])
if self.DIRECTIVE_ID in operand: if self.directive_id in operand:
return DirectiveOperand( return directiveOperand(
NAME_ID=operand["directive"]["name"], name_id=operand["directive"]["name"],
PARAMETER_ID=operand["directive"]["parameters"], parameter_id=operand["directive"]["parameters"],
COMMENT_ID=operand["directive"]["comment"] comment_id=operand["directive"]["comment"]
if "comment" in operand["directive"] if "comment" in operand["directive"]
else None, else None,
) )
return operand return operand
def process_register_operand(self, operand): def process_register_operand(self, operand):
return RegisterOperand( return registerOperand(
PREFIX_ID=operand["prefix"], prefix_id=operand["prefix"],
NAME_ID=operand["name"], name_id=operand["name"],
SHAPE=operand["shape"] if "shape" in operand else None, shape=operand["shape"] if "shape" in operand else None,
LANES=operand["lanes"] if "lanes" in operand else None, lanes=operand["lanes"] if "lanes" in operand else None,
INDEX=operand["index"] if "index" in operand else None, index=operand["index"] if "index" in operand else None,
PREDICATION=operand["predication"] if "predication" in operand else None, predication=operand["predication"] if "predication" in operand else None,
) )
def process_memory_address(self, memory_address): def process_memory_address(self, memory_address):
@@ -422,11 +422,11 @@ class ParserAArch64(BaseParser):
if "shift" in memory_address["index"]: if "shift" in memory_address["index"]:
if memory_address["index"]["shift_op"].lower() in valid_shift_ops: if memory_address["index"]["shift_op"].lower() in valid_shift_ops:
scale = 2 ** int(memory_address["index"]["shift"][0]["value"]) scale = 2 ** int(memory_address["index"]["shift"][0]["value"])
new_dict = MemoryOperand( new_dict = memoryOperand(
OFFSET_ID=offset, offset_ID=offset,
BASE_ID=RegisterOperand(NAME_ID=base["name"], PREFIX_ID=base["prefix"]), base_id=registerOperand(name_id=base["name"], prefix_id=base["prefix"]),
INDEX_ID=index, index_id=index,
SCALE_ID=scale, scale_id=scale,
) )
if "pre_indexed" in memory_address: if "pre_indexed" in memory_address:
new_dict.pre_indexed = True new_dict.pre_indexed = True
@@ -440,7 +440,7 @@ class ParserAArch64(BaseParser):
def process_sp_register(self, register): def process_sp_register(self, register):
"""Post-process stack pointer register""" """Post-process stack pointer register"""
# reg = register # reg = register
new_reg = RegisterOperand(PREFIX_ID="x", NAME_ID="sp") new_reg = registerOperand(prefix_id="x", name_id="sp")
# reg["prefix"] = "x" # reg["prefix"] = "x"
return new_reg return new_reg
@@ -509,7 +509,7 @@ class ParserAArch64(BaseParser):
immediate["type"] = "int" immediate["type"] = "int"
# convert hex/bin immediates to dec # convert hex/bin immediates to dec
immediate["value"] = self.normalize_imd(immediate) immediate["value"] = self.normalize_imd(immediate)
return ImmediateOperand(TYPE_ID=immediate["type"], VALUE_ID=immediate["value"]) return immediateOperand(type_id=immediate["type"], value_id=immediate["value"])
if "base_immediate" in immediate: if "base_immediate" in immediate:
# arithmetic immediate, add calculated value as value # arithmetic immediate, add calculated value as value
immediate["shift"] = immediate["shift"][0] immediate["shift"] = immediate["shift"][0]
@@ -517,8 +517,8 @@ class ParserAArch64(BaseParser):
immediate["shift"]["value"] immediate["shift"]["value"]
) )
immediate["type"] = "int" immediate["type"] = "int"
return ImmediateOperand( return immediateOperand(
TYPE_ID=immediate["type"], VALUE_ID=immediate["value"], SHIFT_ID=immediate["shift"] type_id=immediate["type"], value_id=immediate["value"], shift_id=immediate["shift"]
) )
if "float" in immediate: if "float" in immediate:
dict_name = "float" dict_name = "float"
@@ -526,18 +526,18 @@ class ParserAArch64(BaseParser):
dict_name = "double" dict_name = "double"
if "exponent" in immediate[dict_name]: if "exponent" in immediate[dict_name]:
immediate["type"] = dict_name immediate["type"] = dict_name
return ImmediateOperand(TYPE_ID=immediate["type"]) return immediateOperand(type_id=immediate["type"])
else: else:
# change 'mantissa' key to 'value' # change 'mantissa' key to 'value'
return ImmediateOperand(VALUE_ID=immediate[dict_name]["mantissa"], TYPE_ID=dict_name) return immediateOperand(value_id=immediate[dict_name]["mantissa"], type_id=dict_name)
def process_label(self, label): def process_label(self, label):
"""Post-process label asm line""" """Post-process label asm line"""
# remove duplicated 'name' level due to identifier # remove duplicated 'name' level due to identifier
# label["name"] = label["name"]["name"] # label["name"] = label["name"]["name"]
new_label = LabelOperand( new_label = labelOperand(
NAME_ID=label["name"]["name"], name_id=label["name"]["name"],
COMMENT_ID=label["comment"] if self.COMMENT_ID in label else None, comment_id=label["comment"] if self.comment_id in label else None,
) )
return new_label return new_label
@@ -546,7 +546,7 @@ class ParserAArch64(BaseParser):
# remove value if it consists of symbol+offset # remove value if it consists of symbol+offset
if "value" in identifier: if "value" in identifier:
del identifier["value"] del identifier["value"]
return IdentifierOperand(OFFSET=identifier["offset"], RELOCATION=identifier["relocation"]) return identifierOperand(offset=identifier["offset"], RELOCATION=identifier["relocation"])
def get_full_reg_name(self, register): def get_full_reg_name(self, register):
"""Return one register name string including all attributes""" """Return one register name string including all attributes"""

View File

@@ -6,14 +6,14 @@ import re
import pyparsing as pp import pyparsing as pp
from osaca.parser import BaseParser from osaca.parser import BaseParser
from osaca.parser.instruction_form import InstructionForm from osaca.parser.instruction_form import instructionForm
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
from osaca.parser.directive import DirectiveOperand from osaca.parser.directive import directiveOperand
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.label import LabelOperand from osaca.parser.label import labelOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import identifierOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
class ParserX86ATT(BaseParser): class ParserX86ATT(BaseParser):
@@ -40,7 +40,7 @@ class ParserX86ATT(BaseParser):
# Comment - either '#' or '//' (icc) # Comment - either '#' or '//' (icc)
self.comment = (pp.Literal("#") | pp.Literal("//")) + pp.Group( self.comment = (pp.Literal("#") | pp.Literal("//")) + pp.Group(
pp.ZeroOrMore(pp.Word(pp.printables)) pp.ZeroOrMore(pp.Word(pp.printables))
).setResultsName(self.COMMENT_ID) ).setResultsName(self.comment_id)
# Define x86 assembly identifier # Define x86 assembly identifier
relocation = pp.Combine(pp.Literal("@") + pp.Word(pp.alphas)) relocation = pp.Combine(pp.Literal("@") + pp.Word(pp.alphas))
id_offset = pp.Word(pp.nums) + pp.Suppress(pp.Literal("+")) id_offset = pp.Word(pp.nums) + pp.Suppress(pp.Literal("+"))
@@ -72,7 +72,7 @@ class ParserX86ATT(BaseParser):
(label_identifier | numeric_identifier).setResultsName("name") (label_identifier | numeric_identifier).setResultsName("name")
+ pp.Literal(":") + pp.Literal(":")
+ pp.Optional(self.comment) + pp.Optional(self.comment)
).setResultsName(self.LABEL_ID) ).setResultsName(self.label_id)
# Register: pp.Regex('^%[0-9a-zA-Z]+{}{z},?') # Register: pp.Regex('^%[0-9a-zA-Z]+{}{z},?')
self.register = pp.Group( self.register = pp.Group(
pp.Literal("%") pp.Literal("%")
@@ -120,7 +120,7 @@ class ParserX86ATT(BaseParser):
pp.Optional(pp.Suppress(pp.Literal("*"))) pp.Optional(pp.Suppress(pp.Literal("*")))
+ self.register.setResultsName("base") + self.register.setResultsName("base")
+ pp.Literal(":") + pp.Literal(":")
+ segment_extension.setResultsName(self.SEGMENT_EXT_ID) + segment_extension.setResultsName(self.segment_ext_id)
) )
# Memory: offset | seg:seg_ext | offset(base, index, scale){mask} # Memory: offset | seg:seg_ext | offset(base, index, scale){mask}
memory_abs = pp.Suppress(pp.Literal("*")) + (offset | self.register).setResultsName( memory_abs = pp.Suppress(pp.Literal("*")) + (offset | self.register).setResultsName(
@@ -165,7 +165,7 @@ class ParserX86ATT(BaseParser):
+ pp.Word(pp.alphanums + "_").setResultsName("name") + pp.Word(pp.alphanums + "_").setResultsName("name")
+ pp.ZeroOrMore(directive_parameter).setResultsName("parameters") + pp.ZeroOrMore(directive_parameter).setResultsName("parameters")
+ pp.Optional(self.comment) + pp.Optional(self.comment)
).setResultsName(self.DIRECTIVE_ID) ).setResultsName(self.directive_id)
# Instructions # Instructions
# Mnemonic # Mnemonic
@@ -207,13 +207,13 @@ class ParserX86ATT(BaseParser):
:type line_number: int, optional :type line_number: int, optional
:return: ``dict`` -- parsed asm line (comment, label, directive or instruction form) :return: ``dict`` -- parsed asm line (comment, label, directive or instruction form)
""" """
instruction_form = InstructionForm(LINE=line, LINE_NUMBER=line_number) instruction_form = instructionForm(line=line, line_number=line_number)
result = None result = None
# 1. Parse comment # 1. Parse comment
try: try:
result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict()) result = self.process_operand(self.comment.parseString(line, parseAll=True).asDict())
instruction_form.comment = " ".join(result[self.COMMENT_ID]) instruction_form.comment = " ".join(result[self.comment_id])
except pp.ParseException: except pp.ParseException:
pass pass
@@ -233,9 +233,9 @@ class ParserX86ATT(BaseParser):
result = self.process_operand( result = self.process_operand(
self.directive.parseString(line, parseAll=True).asDict() self.directive.parseString(line, parseAll=True).asDict()
) )
instruction_form.directive = DirectiveOperand( instruction_form.directive = directiveOperand(
NAME_ID=result.name, name_id=result.name,
PARAMETER_ID=result.parameters, parameter_id=result.parameters,
) )
if result.comment != None: if result.comment != None:
@@ -279,10 +279,10 @@ class ParserX86ATT(BaseParser):
# Check fourth operand # Check fourth operand
if "operand4" in result: if "operand4" in result:
operands.append(self.process_operand(result["operand4"])) operands.append(self.process_operand(result["operand4"]))
return_dict = InstructionForm( return_dict = instructionForm(
INSTRUCTION_ID=result["mnemonic"].split(",")[0], instruction_id=result["mnemonic"].split(",")[0],
OPERANDS_ID=operands, operands_id=operands,
COMMENT_ID=" ".join(result[self.COMMENT_ID]) if self.COMMENT_ID in result else None, comment_id=" ".join(result[self.comment_id]) if self.comment_id in result else None,
) )
return return_dict return return_dict
@@ -294,27 +294,27 @@ class ParserX86ATT(BaseParser):
return self.process_memory_address(operand[self.MEMORY_ID]) return self.process_memory_address(operand[self.MEMORY_ID])
if self.IMMEDIATE_ID in operand: if self.IMMEDIATE_ID in operand:
return self.process_immediate(operand[self.IMMEDIATE_ID]) return self.process_immediate(operand[self.IMMEDIATE_ID])
if self.LABEL_ID in operand: if self.label_id in operand:
return self.process_label(operand[self.LABEL_ID]) return self.process_label(operand[self.label_id])
if self.DIRECTIVE_ID in operand: if self.directive_id in operand:
return self.process_directive(operand[self.DIRECTIVE_ID]) return self.process_directive(operand[self.directive_id])
if self.REGISTER_ID in operand: if self.REGISTER_ID in operand:
return RegisterOperand( return registerOperand(
PREFIX_ID=operand["register"]["prefix"] prefix_id=operand["register"]["prefix"]
if "prefix" in operand["register"] if "prefix" in operand["register"]
else None, else None,
NAME_ID=operand["register"]["name"], name_id=operand["register"]["name"],
SHAPE=operand["register"]["shape"] if "shape" in operand["register"] else None, shape=operand["register"]["shape"] if "shape" in operand["register"] else None,
LANES=operand["register"]["lanes"] if "lanes" in operand["register"] else None, lanes=operand["register"]["lanes"] if "lanes" in operand["register"] else None,
INDEX=operand["register"]["index"] if "index" in operand["register"] else None, index=operand["register"]["index"] if "index" in operand["register"] else None,
PREDICATION=operand["register"]["predication"] predication=operand["register"]["predication"]
if "predication" in operand["register"] if "predication" in operand["register"]
else None, else None,
) )
return operand return operand
def process_directive(self, directive): def process_directive(self, directive):
directive_new = DirectiveOperand(NAME_ID=directive["name"], PARAMETER_ID=[]) directive_new = directiveOperand(name_id=directive["name"], parameter_id=[])
if "parameters" in directive: if "parameters" in directive:
directive_new.parameters = directive["parameters"] directive_new.parameters = directive["parameters"]
if "comment" in directive: if "comment" in directive:
@@ -338,27 +338,27 @@ class ParserX86ATT(BaseParser):
elif offset is not None and "value" in offset: elif offset is not None and "value" in offset:
offset["value"] = int(offset["value"], 0) offset["value"] = int(offset["value"], 0)
if base != None: if base != None:
baseOp = RegisterOperand( baseOp = registerOperand(
NAME_ID=base["name"], PREFIX_ID=base["prefix"] if "prefix" in base else None name_id=base["name"], prefix_id=base["prefix"] if "prefix" in base else None
) )
if index != None: if index != None:
indexOp = RegisterOperand( indexOp = registerOperand(
NAME_ID=index["name"], PREFIX_ID=index["prefix"] if "prefix" in index else None name_id=index["name"], prefix_id=index["prefix"] if "prefix" in index else None
) )
new_dict = MemoryOperand( new_dict = memoryOperand(
OFFSET_ID=offset, BASE_ID=baseOp, INDEX_ID=indexOp, SCALE_ID=scale offset_ID=offset, base_id=baseOp, index_id=indexOp, scale_id=scale
) )
# Add segmentation extension if existing # Add segmentation extension if existing
if self.SEGMENT_EXT_ID in memory_address: if self.segment_ext_id in memory_address:
new_dict.segment_ext_id = memory_address[self.SEGMENT_EXT_ID] new_dict.segment_ext_id = memory_address[self.segment_ext_id]
return new_dict return new_dict
def process_label(self, label): def process_label(self, label):
"""Post-process label asm line""" """Post-process label asm line"""
# remove duplicated 'name' level due to identifier # remove duplicated 'name' level due to identifier
label["name"] = label["name"][0]["name"] label["name"] = label["name"][0]["name"]
new_label = LabelOperand( new_label = labelOperand(
NAME_ID=label["name"], COMMENT_ID=label["comment"] if "comment" in label else None name_id=label["name"], comment_id=label["comment"] if "comment" in label else None
) )
return new_label return new_label

View File

@@ -3,163 +3,143 @@
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
class RegisterOperand(Operand): class registerOperand(Operand):
def __init__( def __init__(
self, self,
NAME_ID=None, name_id=None,
WIDTH_ID=None, width_id=None,
PREFIX_ID=None, prefix_id=None,
REG_ID=None, reg_id=None,
REGTYPE_ID=None, regtype_id=None,
LANES=None, lanes=None,
SHAPE=None, shape=None,
INDEX=None, index=None,
MASK=False, mask=False,
ZEROING=False, zeroing=False,
PREDICATION=None, predication=None,
SOURCE=False, source=False,
DESTINATION=False, destination=False,
): ):
super().__init__(NAME_ID) super().__init__(name_id, source, destination)
self._WIDTH_ID = WIDTH_ID self._width_id = width_id
self._PREFIX_ID = PREFIX_ID self._prefix_id = prefix_id
self._REG_ID = REG_ID self._reg_id = reg_id
self._REGTYPE_ID = REGTYPE_ID self._regtype_id = regtype_id
self._LANES = LANES self._lanes = lanes
self._SHAPE = SHAPE self._shape = shape
self._INDEX = INDEX self._index = index
self._MASK = MASK self._mask = mask
self._ZEROING = ZEROING self._zeroing = zeroing
self._PREDICATION = PREDICATION self._predication = predication
self._SOURCE = SOURCE
self._DESTINATION = DESTINATION
@property @property
def width(self): def width(self):
return self._WIDTH_ID return self._width_id
@width.setter @width.setter
def width(self, width): def width(self, width):
self._WIDTH_ID = width self._width_id = width
@property @property
def predication(self): def predication(self):
return self._PREDICATION return self._predication
@predication.setter @predication.setter
def predication(self, predication): def predication(self, predication):
self._PREDICATION = predication self._predication = predication
@property @property
def regtype(self): def regtype(self):
return self._REGTYPE_ID return self._regtype_id
@regtype.setter @regtype.setter
def regtype(self, regtype): def regtype(self, regtype):
self._REGTYPE_ID = regtype self._regtype_id = regtype
@property @property
def prefix(self): def prefix(self):
return self._PREFIX_ID return self._prefix_id
@prefix.setter @prefix.setter
def prefix(self, prefix): def prefix(self, prefix):
self._PREFIX = prefix self._prefix = prefix
@property @property
def reg_id(self): def reg_id(self):
return self._REG_ID return self._reg_id
@reg_id.setter @reg_id.setter
def reg_id(self, reg_id): def reg_id(self, reg_id):
self._REG_ID = reg_id self._reg_id = reg_id
@property @property
def lanes(self): def lanes(self):
return self._LANES return self._lanes
@lanes.setter @lanes.setter
def lanes(self, lanes): def lanes(self, lanes):
self._LANES = lanes self._lanes = lanes
@property @property
def shape(self): def shape(self):
return self._SHAPE return self._shape
@shape.setter @shape.setter
def shape(self, shape): def shape(self, shape):
self._SHAPE = shape self._shape = shape
@property @property
def index(self): def index(self):
return self._INDEX return self._index
@index.setter @index.setter
def index(self, index): def index(self, index):
self._INDEX = index self._index = index
@property @property
def mask(self): def mask(self):
return self._MASK return self._mask
@mask.setter @mask.setter
def mask(self, mask): def mask(self, mask):
self._MASK = mask self._mask = mask
@property @property
def zeroing(self): def zeroing(self):
return self._ZEROING return self._zeroing
@zeroing.setter @zeroing.setter
def zeroing(self, zeroing): def zeroing(self, zeroing):
self._ZEROING = zeroing self._zeroing = zeroing
@property
def source(self):
return self._SOURCE
@source.setter
def source(self, source):
self._SOURCE = source
@property
def destination(self):
return self._DESTINATION
@destination.setter
def destination(self, destination):
self._DESTINATION = destination
def __str__(self): def __str__(self):
return ( return (
f"RegisterOperand(NAME_ID={self._NAME_ID}, WIDTH_ID={self._WIDTH_ID}, " f"registerOperand(name_id={self._name_id}, width_id={self._width_id}, "
f"PREFIX_ID={self._PREFIX_ID}, REG_ID={self._REG_ID}, REGTYPE_ID={self._REGTYPE_ID}, " f"prefix_id={self._prefix_id}, reg_id={self._reg_id}, REGtype_id={self._regtype_id}, "
f"LANES={self._LANES}, SHAPE={self._SHAPE}, INDEX={self._INDEX}, " f"lanes={self._lanes}, shape={self._shape}, index={self._index}, "
f"MASK={self._MASK}, ZEROING={self._ZEROING})," f"mask={self._mask}, zeroing={self._zeroing})"
f"SOURCE={self._SOURCE}, DESTINATION={self._DESTINATION})"
) )
def __repr__(self): def __repr__(self):
return ( return (
f"RegisterOperand(NAME_ID={self._NAME_ID}, WIDTH_ID={self._WIDTH_ID}, " f"registerOperand(name_id={self._name_id}, width_id={self._width_id}, "
f"PREFIX_ID={self._PREFIX_ID}, REG_ID={self._REG_ID}, REGTYPE_ID={self._REGTYPE_ID}, " f"prefix_id={self._prefix_id}, reg_id={self._reg_id}, REGtype_id={self._regtype_id}, "
f"LANES={self._LANES}, SHAPE={self._SHAPE}, INDEX={self._INDEX}, " f"lanes={self._lanes}, shape={self._shape}, index={self._index}, "
f"MASK={self._MASK}, ZEROING={self._ZEROING})," f"mask={self._mask}, zeroing={self._zeroing})"
f"SOURCE={self._SOURCE}, DESTINATION={self._DESTINATION})"
) )
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, RegisterOperand): if isinstance(other, registerOperand):
return ( return (
self._NAME_ID == other._NAME_ID self._name_id == other._name_id
and self._WIDTH_ID == other._WIDTH_ID and self._width_id == other._width_id
and self._PREFIX_ID == other._PREFIX_ID and self._prefix_id == other._prefix_id
and self._REG_ID == other._REG_ID and self._reg_id == other._reg_id
and self._REGTYPE_ID == other._REGTYPE_ID and self._regtype_id == other._regtype_id
and self._LANES == other._LANES and self._lanes == other._lanes
and self._SHAPE == other._SHAPE and self._shape == other._shape
and self._INDEX == other._INDEX and self._index == other._index
and self._MASK == other._MASK and self._mask == other._mask
and self._ZEROING == other._ZEROING and self._zeroing == other._zeroing
) )
return False return False

View File

@@ -3,7 +3,7 @@ Tools for semantic analysis of parser result.
Only the classes below will be exported, so please add new semantic tools to __all__. Only the classes below will be exported, so please add new semantic tools to __all__.
""" """
from .isa_semantics import ISASemantics, INSTR_FLAGS from .isa_semantics import ISASemantics, INSTR_flags
from .arch_semantics import ArchSemantics from .arch_semantics import ArchSemantics
from .hw_model import MachineModel from .hw_model import MachineModel
from .kernel_dg import KernelDG from .kernel_dg import KernelDG
@@ -16,7 +16,7 @@ __all__ = [
"reduce_to_section", "reduce_to_section",
"ArchSemantics", "ArchSemantics",
"ISASemantics", "ISASemantics",
"INSTR_FLAGS", "INSTR_flags",
"find_basic_blocks", "find_basic_blocks",
"find_basic_loop_bodies", "find_basic_loop_bodies",
"find_jump_labels", "find_jump_labels",

View File

@@ -8,11 +8,11 @@ from operator import itemgetter
from copy import deepcopy from copy import deepcopy
from .hw_model import MachineModel from .hw_model import MachineModel
from .isa_semantics import INSTR_FLAGS, ISASemantics from .isa_semantics import INSTR_flags, ISASemantics
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import identifierOperand
class ArchSemantics(ISASemantics): class ArchSemantics(ISASemantics):
@@ -139,8 +139,8 @@ class ArchSemantics(ISASemantics):
def set_hidden_loads(self, kernel): def set_hidden_loads(self, kernel):
"""Hide loads behind stores if architecture supports hidden loads (depricated)""" """Hide loads behind stores if architecture supports hidden loads (depricated)"""
loads = [instr for instr in kernel if INSTR_FLAGS.HAS_LD in instr.flags] loads = [instr for instr in kernel if INSTR_flags.HAS_LD in instr.flags]
stores = [instr for instr in kernel if INSTR_FLAGS.HAS_ST in instr.flags] stores = [instr for instr in kernel if INSTR_flags.HAS_ST in instr.flags]
# Filter instructions including load and store # Filter instructions including load and store
load_ids = [instr.line_number for instr in loads] load_ids = [instr.line_number for instr in loads]
store_ids = [instr.line_number for instr in stores] store_ids = [instr.line_number for instr in stores]
@@ -154,7 +154,7 @@ class ArchSemantics(ISASemantics):
if len(loads) <= len(stores): if len(loads) <= len(stores):
# Hide all loads # Hide all loads
for load in loads: for load in loads:
load.flags += [INSTR_FLAGS.HIDDEN_LD] load.flags += [INSTR_flags.HIDDEN_LD]
load.port_pressure = self._nullify_data_ports(load.port_pressure) load.port_pressure = self._nullify_data_ports(load.port_pressure)
else: else:
for store in stores: for store in stores:
@@ -166,12 +166,12 @@ class ArchSemantics(ISASemantics):
load_instr.line_number, load_instr.line_number,
) )
for load_instr in loads for load_instr in loads
if INSTR_FLAGS.HIDDEN_LD not in load_instr.flags if INSTR_flags.HIDDEN_LD not in load_instr.flags
] ]
) )
load = [instr for instr in kernel if instr.line_number == min_distance_load[1]][0] load = [instr for instr in kernel if instr.line_number == min_distance_load[1]][0]
# Hide load # Hide load
load.flags += [INSTR_FLAGS.HIDDEN_LD] load.flags += [INSTR_flags.HIDDEN_LD]
load.port_pressure = self._nullify_data_ports(load.port_pressure) load.port_pressure = self._nullify_data_ports(load.port_pressure)
# get parser result and assign throughput and latency value to instruction form # get parser result and assign throughput and latency value to instruction form
@@ -226,8 +226,8 @@ class ArchSemantics(ISASemantics):
assign_unknown = True assign_unknown = True
# check for equivalent register-operands DB entry if LD # check for equivalent register-operands DB entry if LD
if ( if (
INSTR_FLAGS.HAS_LD in instruction_form.flags INSTR_flags.HAS_LD in instruction_form.flags
or INSTR_FLAGS.HAS_ST in instruction_form.flags or INSTR_flags.HAS_ST in instruction_form.flags
): ):
# dynamically combine LD/ST and reg form of instruction form # dynamically combine LD/ST and reg form of instruction form
# substitute mem and look for reg-only variant # substitute mem and look for reg-only variant
@@ -262,17 +262,17 @@ class ArchSemantics(ISASemantics):
] ]
) )
# dummy_reg = {"class": "register", "name": reg_type} # dummy_reg = {"class": "register", "name": reg_type}
dummy_reg = RegisterOperand(NAME_ID=reg_type) dummy_reg = registerOperand(name_id=reg_type)
data_port_pressure = [0.0 for _ in range(port_number)] data_port_pressure = [0.0 for _ in range(port_number)]
data_port_uops = [] data_port_uops = []
if INSTR_FLAGS.HAS_LD in instruction_form.flags: if INSTR_flags.HAS_LD in instruction_form.flags:
# LOAD performance data # LOAD performance data
load_perf_data = self._machine_model.get_load_throughput( load_perf_data = self._machine_model.get_load_throughput(
[ [
x x
for x in instruction_form.semantic_operands["source"] for x in instruction_form.semantic_operands["source"]
+ instruction_form.semantic_operands["src_dst"] + instruction_form.semantic_operands["src_dst"]
if isinstance(x, MemoryOperand) if isinstance(x, memoryOperand)
][0] ][0]
) )
# if multiple options, choose based on reg type # if multiple options, choose based on reg type
@@ -281,7 +281,7 @@ class ArchSemantics(ISASemantics):
for ldp in load_perf_data for ldp in load_perf_data
if ldp.dst != None if ldp.dst != None
and self._machine_model._check_operands( and self._machine_model._check_operands(
dummy_reg, RegisterOperand(NAME_ID=ldp.dst) dummy_reg, registerOperand(name_id=ldp.dst)
) )
] ]
if len(data_port_uops) < 1: if len(data_port_uops) < 1:
@@ -296,14 +296,14 @@ class ArchSemantics(ISASemantics):
reg_type reg_type
] ]
data_port_pressure = [pp * multiplier for pp in data_port_pressure] data_port_pressure = [pp * multiplier for pp in data_port_pressure]
if INSTR_FLAGS.HAS_ST in instruction_form.flags: if INSTR_flags.HAS_ST in instruction_form.flags:
# STORE performance data # STORE performance data
destinations = ( destinations = (
instruction_form.semantic_operands["destination"] instruction_form.semantic_operands["destination"]
+ instruction_form.semantic_operands["src_dst"] + instruction_form.semantic_operands["src_dst"]
) )
store_perf_data = self._machine_model.get_store_throughput( store_perf_data = self._machine_model.get_store_throughput(
[x for x in destinations if isinstance(x, MemoryOperand)][0], [x for x in destinations if isinstance(x, memoryOperand)][0],
dummy_reg, dummy_reg,
) )
st_data_port_uops = store_perf_data[0].port_pressure st_data_port_uops = store_perf_data[0].port_pressure
@@ -320,12 +320,12 @@ class ArchSemantics(ISASemantics):
[ [
op.post_indexed or op.pre_indexed op.post_indexed or op.pre_indexed
for op in instruction_form.semantic_operands["src_dst"] for op in instruction_form.semantic_operands["src_dst"]
if isinstance(op, MemoryOperand) if isinstance(op, memoryOperand)
] ]
) )
): ):
st_data_port_uops = [] st_data_port_uops = []
instruction_form.flags.remove(INSTR_FLAGS.HAS_ST) instruction_form.flags.remove(INSTR_flags.HAS_ST)
# sum up all data ports in case for LOAD and STORE # sum up all data ports in case for LOAD and STORE
st_data_port_pressure = self._machine_model.average_port_pressure( st_data_port_pressure = self._machine_model.average_port_pressure(
@@ -347,12 +347,12 @@ class ArchSemantics(ISASemantics):
# Add LD and ST latency # Add LD and ST latency
latency += ( latency += (
self._machine_model.get_load_latency(reg_type) self._machine_model.get_load_latency(reg_type)
if INSTR_FLAGS.HAS_LD in instruction_form.flags if INSTR_flags.HAS_LD in instruction_form.flags
else 0 else 0
) )
latency += ( latency += (
self._machine_model.get_store_latency(reg_type) self._machine_model.get_store_latency(reg_type)
if INSTR_FLAGS.HAS_ST in instruction_form.flags if INSTR_flags.HAS_ST in instruction_form.flags
else 0 else 0
) )
latency_wo_load = instruction_data_reg.latency latency_wo_load = instruction_data_reg.latency
@@ -391,7 +391,7 @@ class ArchSemantics(ISASemantics):
latency_wo_load = latency latency_wo_load = latency
instruction_form.port_pressure = [0.0 for i in range(port_number)] instruction_form.port_pressure = [0.0 for i in range(port_number)]
instruction_formport_uops = [] instruction_formport_uops = []
flags += [INSTR_FLAGS.TP_UNKWN, INSTR_FLAGS.LT_UNKWN] flags += [INSTR_flags.TP_UNKWN, INSTR_flags.LT_UNKWN]
# flatten flag list # flatten flag list
flags = list(set(flags)) flags = list(set(flags))
if instruction_form.flags == []: if instruction_form.flags == []:
@@ -416,7 +416,7 @@ class ArchSemantics(ISASemantics):
instruction_form.port_pressure = port_pressure instruction_form.port_pressure = port_pressure
if sum(port_pressure) == 0 and throughput is not None: if sum(port_pressure) == 0 and throughput is not None:
# port pressure on all ports 0 --> not bound to a port # port pressure on all ports 0 --> not bound to a port
flags.append(INSTR_FLAGS.NOT_BOUND) flags.append(INSTR_flags.NOT_BOUND)
except AssertionError: except AssertionError:
warnings.warn( warnings.warn(
"Port pressure could not be imported correctly from database. " "Port pressure could not be imported correctly from database. "
@@ -424,31 +424,31 @@ class ArchSemantics(ISASemantics):
) )
instruction_form.port_pressure = [0.0 for i in range(port_number)] instruction_form.port_pressure = [0.0 for i in range(port_number)]
instruction_form.port_uops = [] instruction_form.port_uops = []
flags.append(INSTR_FLAGS.TP_UNKWN) flags.append(INSTR_flags.TP_UNKWN)
if throughput is None: if throughput is None:
# assume 0 cy and mark as unknown # assume 0 cy and mark as unknown
throughput = 0.0 throughput = 0.0
flags.append(INSTR_FLAGS.TP_UNKWN) flags.append(INSTR_flags.TP_UNKWN)
latency = instruction_data.latency latency = instruction_data.latency
latency_wo_load = latency latency_wo_load = latency
if latency is None: if latency is None:
# assume 0 cy and mark as unknown # assume 0 cy and mark as unknown
latency = 0.0 latency = 0.0
latency_wo_load = latency latency_wo_load = latency
flags.append(INSTR_FLAGS.LT_UNKWN) flags.append(INSTR_flags.LT_UNKWN)
if INSTR_FLAGS.HAS_LD in instruction_form.flags: if INSTR_flags.HAS_LD in instruction_form.flags:
flags.append(INSTR_FLAGS.LD) flags.append(INSTR_flags.LD)
return throughput, port_pressure, latency, latency_wo_load return throughput, port_pressure, latency, latency_wo_load
def convert_op_to_reg(self, reg_type, reg_id="0"): def convert_op_to_reg(self, reg_type, reg_id="0"):
"""Create register operand for a memory addressing operand""" """Create register operand for a memory addressing operand"""
if self._isa == "x86": if self._isa == "x86":
if reg_type == "gpr": if reg_type == "gpr":
register = RegisterOperand(NAME_ID="r" + str(int(reg_id) + 9)) register = registerOperand(name_id="r" + str(int(reg_id) + 9))
else: else:
register = RegisterOperand(NAME_ID=reg_type + reg_id) register = registerOperand(name_id=reg_type + reg_id)
elif self._isa == "aarch64": elif self._isa == "aarch64":
register = RegisterOperand(NAME_ID=reg_id, PREFIX_ID=reg_type) register = registerOperand(name_id=reg_id, prefix_id=reg_type)
return register return register
def _nullify_data_ports(self, port_pressure): def _nullify_data_ports(self, port_pressure):

View File

@@ -14,12 +14,12 @@ 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.instruction_form import InstructionForm from osaca.parser.instruction_form import instructionForm
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import identifierOperand
class MachineModel(object): class MachineModel(object):
@@ -73,7 +73,7 @@ class MachineModel(object):
self._data = MachineModel._runtime_cache[self._path] self._data = MachineModel._runtime_cache[self._path]
# check if file is cached # check if file is cached
cached = self._get_cached(self._path) if not lazy else False cached = self._get_cached(self._path) if not lazy else False
if False: if cached:
self._data = cached self._data = cached
else: else:
yaml = self._create_yaml_object() yaml = self._create_yaml_object()
@@ -104,8 +104,6 @@ class MachineModel(object):
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"]:
if "breaks_dependency_on_equal_operands" in iform:
print(iform["breaks_dependency_on_equal_operands"],"\n")
iform["name"] = iform["name"].upper() iform["name"] = iform["name"].upper()
if iform["operands"] != []: if iform["operands"] != []:
new_operands = [] new_operands = []
@@ -114,34 +112,37 @@ class MachineModel(object):
self.operand_to_class(o, new_operands) self.operand_to_class(o, new_operands)
iform["operands"] = new_operands iform["operands"] = new_operands
# Do the same for hidden operands # Do the same for hidden operands
if iform["hidden_operands"] != []: if "hidden_operands" in iform:
new_operands = [] new_operands = []
# Change operand types from dicts to classes # Change operand types from dicts to classes
for o in iform["hidden_operands"]: for o in iform["hidden_operands"]:
self.operand_to_class(o, new_operands) self.operand_to_class(o, new_operands)
iform["hidden_operands"] = new_operands iform["hidden_operands"] = new_operands
# Change dict iform style to class style # Change dict iform style to class style
new_iform = InstructionForm( new_iform = instructionForm(
INSTRUCTION_ID=iform["name"].upper() if "name" in iform else None, instruction_id=iform["name"].upper() if "name" in iform else None,
OPERANDS_ID=iform["operands"] if "operands" in iform else [], operands_id=iform["operands"] if "operands" in iform else [],
HIDDEN_OPERANDS=iform["hidden_operands"] if "hidden_operansd" in iform else [], hidden_operands=iform["hidden_operands"]
DIRECTIVE_ID=iform["directive"] if "directive" in iform else None, if "hidden_operansd" in iform
COMMENT_ID=iform["comment"] if "comment" in iform else None, else [],
LINE=iform["line"] if "line" in iform else None, directive_id=iform["directive"] if "directive" in iform else None,
LINE_NUMBER=iform["line_number"] if "line_number" in iform else None, comment_id=iform["comment"] if "comment" in iform else None,
LATENCY=iform["latency"] if "latency" in iform else None, line=iform["line"] if "line" in iform else None,
THROUGHPUT=iform["throughput"] if "throughput" in iform else None, line_number=iform["line_number"] if "line_number" in iform else None,
UOPS=iform["uops"] if "uops" in iform else None, latency=iform["latency"] if "latency" in iform else None,
PORT_PRESSURE=iform["port_pressure"] if "port_pressure" in iform else None, throughput=iform["throughput"] if "throughput" in iform else None,
BREAKS_DEP=iform["breaks_dependency_on_equal_operands"] if "breaks_dependency_on_equal_operands" in iform else False, uops=iform["uops"] if "uops" in iform else None,
SEMANTIC_OPERANDS=iform["semantic_operands"] port_pressure=iform["port_pressure"] if "port_pressure" in iform else None,
breaks_dep=iform["breaks_dependency_on_equal_operands"]
if "breaks_dependency_on_equal_operands" in iform
else False,
semantic_operands=iform["semantic_operands"]
if "semantic_operands" in iform if "semantic_operands" in iform
else {"source": [], "destination": [], "src_dst": []}, else {"source": [], "destination": [], "src_dst": []},
) )
# List containing classes with same name/instruction # List containing classes with same name/instruction
self._data["instruction_forms_dict"][iform["name"]].append(new_iform) self._data["instruction_forms_dict"][iform["name"]].append(new_iform)
self._data["internal_version"] = self.INTERNAL_VERSION self._data["internal_version"] = self.INTERNAL_VERSION
if not lazy: if not lazy:
@@ -156,13 +157,13 @@ class MachineModel(object):
if "load_throughput" in self._data: if "load_throughput" in self._data:
for m in self._data["load_throughput"]: for m in self._data["load_throughput"]:
new_throughputs.append( new_throughputs.append(
MemoryOperand( memoryOperand(
BASE_ID=m["base"], base_id=m["base"],
OFFSET_ID=m["offset"], offset_ID=m["offset"],
SCALE_ID=m["scale"], scale_id=m["scale"],
INDEX_ID=m["index"], index_id=m["index"],
PORT_PRESSURE=m["port_pressure"], port_pressure=m["port_pressure"],
DST=m["dst"] if "dst" in m else None, ds=m["dst"] if "dst" in m else None,
) )
) )
self._data["load_throughput"] = new_throughputs self._data["load_throughput"] = new_throughputs
@@ -171,12 +172,12 @@ class MachineModel(object):
if "store_throughput" in self._data: if "store_throughput" in self._data:
for m in self._data["store_throughput"]: for m in self._data["store_throughput"]:
new_throughputs.append( new_throughputs.append(
MemoryOperand( memoryOperand(
BASE_ID=m["base"], base_id=m["base"],
OFFSET_ID=m["offset"], offset_ID=m["offset"],
SCALE_ID=m["scale"], scale_id=m["scale"],
INDEX_ID=m["index"], index_id=m["index"],
PORT_PRESSURE=m["port_pressure"], port_pressure=m["port_pressure"],
) )
) )
self._data["store_throughput"] = new_throughputs self._data["store_throughput"] = new_throughputs
@@ -185,36 +186,36 @@ class MachineModel(object):
"""Convert an operand from dict type to class""" """Convert an operand from dict type to class"""
if o["class"] == "register": if o["class"] == "register":
new_operands.append( new_operands.append(
RegisterOperand( registerOperand(
NAME_ID=o["name"] if "name" in o else None, name_id=o["name"] if "name" in o else None,
PREFIX_ID=o["prefix"] if "prefix" in o else None, prefix_id=o["prefix"] if "prefix" in o else None,
SHAPE=o["shape"] if "shape" in o else None, shape=o["shape"] if "shape" in o else None,
MASK=o["mask"] if "mask" in o else False, mask=o["mask"] if "mask" in o else False,
SOURCE=o["source"] if "source" in o else False, source=o["source"] if "source" in o else False,
DESTINATION=o["destination"] if "destination" in o else False, destination=o["destination"] if "destination" in o else False,
) )
) )
elif o["class"] == "memory": elif o["class"] == "memory":
new_operands.append( new_operands.append(
MemoryOperand( memoryOperand(
BASE_ID=o["base"], base_id=o["base"],
OFFSET_ID=o["offset"], offset_ID=o["offset"],
INDEX_ID=o["index"], index_id=o["index"],
SCALE_ID=o["scale"], scale_id=o["scale"],
SOURCE=o["source"] if "source" in o else False, source=o["source"] if "source" in o else False,
DESTINATION=o["destination"] if "destination" in o else False, destination=o["destination"] if "destination" in o else False,
) )
) )
elif o["class"] == "immediate": elif o["class"] == "immediate":
new_operands.append( new_operands.append(
ImmediateOperand( immediateOperand(
TYPE_ID=o["imd"], type_id=o["imd"],
SOURCE=o["source"] if "source" in o else False, source=o["source"] if "source" in o else False,
DESTINATION=o["destination"] if "destination" in o else False, destination=o["destination"] if "destination" in o else False,
) )
) )
elif o["class"] == "identifier": elif o["class"] == "identifier":
new_operands.append(IdentifierOperand()) new_operands.append(identifierOperand())
else: else:
new_operands.append(o) new_operands.append(o)
@@ -283,7 +284,7 @@ class MachineModel(object):
# If it already exists. Overwrite information. # If it already exists. Overwrite information.
instr_data = self.get_instruction(instruction, operands) instr_data = self.get_instruction(instruction, operands)
if instr_data is None: if instr_data is None:
instr_data = InstructionForm() instr_data = instructionForm()
self._data["instruction_forms"].append(instr_data) self._data["instruction_forms"].append(instr_data)
self._data["instruction_forms_dict"][instruction].append(instr_data) self._data["instruction_forms_dict"][instruction].append(instr_data)
@@ -339,7 +340,7 @@ class MachineModel(object):
ld_tp = [m for m in self._data["load_throughput"] if self._match_mem_entries(memory, m)] ld_tp = [m for m in self._data["load_throughput"] if self._match_mem_entries(memory, m)]
if len(ld_tp) > 0: if len(ld_tp) > 0:
return ld_tp.copy() return ld_tp.copy()
return [MemoryOperand(PORT_PRESSURE=self._data["load_throughput_default"].copy())] return [memoryOperand(port_pressure=self._data["load_throughput_default"].copy())]
def get_store_latency(self, reg_type): def get_store_latency(self, reg_type):
"""Return store latency for given register type.""" """Return store latency for given register type."""
@@ -354,11 +355,11 @@ class MachineModel(object):
tp tp
for tp in st_tp for tp in st_tp
if "src" in tp if "src" in tp
and self._check_operands(src_reg, RegisterOperand(NAME_ID=tp["src"])) and self._check_operands(src_reg, registerOperand(name_id=tp["src"]))
] ]
if len(st_tp) > 0: if len(st_tp) > 0:
return st_tp.copy() return st_tp.copy()
return [MemoryOperand(PORT_PRESSURE=self._data["store_throughput_default"].copy())] return [memoryOperand(port_pressure=self._data["store_throughput_default"].copy())]
def _match_mem_entries(self, mem, i_mem): def _match_mem_entries(self, mem, i_mem):
"""Check if memory addressing ``mem`` and ``i_mem`` are of the same type.""" """Check if memory addressing ``mem`` and ``i_mem`` are of the same type."""
@@ -570,19 +571,19 @@ class MachineModel(object):
def _create_db_operand_aarch64(self, operand): def _create_db_operand_aarch64(self, operand):
"""Create instruction form operand for DB out of operand string.""" """Create instruction form operand for DB out of operand string."""
if operand == "i": if operand == "i":
return ImmediateOperand(TYPE_ID="int") return immediateOperand(type_id="int")
elif operand in "wxbhsdq": elif operand in "wxbhsdq":
return RegisterOperand(PREFIX_ID=operand) return registerOperand(prefix_id=operand)
elif operand.startswith("v"): elif operand.startswith("v"):
return RegisterOperand(PREFIX_ID="v", SHAPE=operand[1:2]) return registerOperand(prefix_id="v", shape=operand[1:2])
elif operand.startswith("m"): elif operand.startswith("m"):
return MemoryOperand( return memoryOperand(
BASE_ID="x" if "b" in operand else None, base_id="x" if "b" in operand else None,
OFFSET_ID="imd" if "o" in operand else None, offset_ID="imd" if "o" in operand else None,
INDEX_ID="gpr" if "i" in operand else None, index_id="gpr" if "i" in operand else None,
SCALE_ID=8 if "s" in operand else 1, scale_id=8 if "s" in operand else 1,
PRE_INDEXED=True if "r" in operand else False, pre_indexed=True if "r" in operand else False,
POST_INDEXED=True if "p" in operand else False, post_indexed=True if "p" in operand else False,
) )
else: else:
raise ValueError("Parameter {} is not a valid operand code".format(operand)) raise ValueError("Parameter {} is not a valid operand code".format(operand))
@@ -590,17 +591,17 @@ class MachineModel(object):
def _create_db_operand_x86(self, operand): def _create_db_operand_x86(self, operand):
"""Create instruction form operand for DB out of operand string.""" """Create instruction form operand for DB out of operand string."""
if operand == "r": if operand == "r":
return RegisterOperand(NAME_ID="gpr") return registerOperand(name_id="gpr")
elif operand in "xyz": elif operand in "xyz":
return RegisterOperand(NAME_ID=operand + "mm") return registerOperand(name_id=operand + "mm")
elif operand == "i": elif operand == "i":
return ImmediateOperand(TYPE_ID="int") return immediateOperand(type_id="int")
elif operand.startswith("m"): elif operand.startswith("m"):
return MemoryOperand( return memoryOperand(
BASE_ID="gpr" if "b" in operand else None, base_id="gpr" if "b" in operand else None,
OFFSET_ID="imd" if "o" in operand else None, offset_ID="imd" if "o" in operand else None,
INDEX_ID="gpr" if "i" in operand else None, index_id="gpr" if "i" in operand else None,
SCALE_ID=8 if "s" in operand else 1, scale_id=8 if "s" in operand else 1,
) )
else: else:
raise ValueError("Parameter {} is not a valid operand code".format(operand)) raise ValueError("Parameter {} is not a valid operand code".format(operand))
@@ -643,7 +644,7 @@ class MachineModel(object):
if (isinstance(operand, Operand) and operand.name == self.WILDCARD) or ( if (isinstance(operand, Operand) and operand.name == self.WILDCARD) or (
not isinstance(operand, Operand) and self.WILDCARD in operand not isinstance(operand, Operand) and self.WILDCARD in operand
): ):
if isinstance(i_operand, RegisterOperand): if isinstance(i_operand, registerOperand):
return True return True
else: else:
return False return False
@@ -659,45 +660,45 @@ class MachineModel(object):
# 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 isinstance(operand, RegisterOperand): if isinstance(operand, registerOperand):
if not isinstance(i_operand, RegisterOperand): if not isinstance(i_operand, registerOperand):
return False return False
return self._is_AArch64_reg_type(i_operand, operand) return self._is_AArch64_reg_type(i_operand, operand)
# memory # memory
if isinstance(operand, MemoryOperand): if isinstance(operand, memoryOperand):
if not isinstance(i_operand, MemoryOperand): if not isinstance(i_operand, memoryOperand):
return False return False
return self._is_AArch64_mem_type(i_operand, operand) return self._is_AArch64_mem_type(i_operand, operand)
# immediate # immediate
if isinstance(i_operand, ImmediateOperand) and i_operand.type == self.WILDCARD: if isinstance(i_operand, immediateOperand) and i_operand.type == self.WILDCARD:
return isinstance(operand, ImmediateOperand) and (operand.value != None) return isinstance(operand, immediateOperand) and (operand.value != None)
if isinstance(i_operand, ImmediateOperand) and i_operand.type == "int": if isinstance(i_operand, immediateOperand) and i_operand.type == "int":
return ( return (
isinstance(operand, ImmediateOperand) isinstance(operand, immediateOperand)
and operand.type == "int" and operand.type == "int"
and operand.value != None and operand.value != None
) )
if isinstance(i_operand, ImmediateOperand) and i_operand.type == "float": if isinstance(i_operand, immediateOperand) and i_operand.type == "float":
return ( return (
isinstance(operand, ImmediateOperand) isinstance(operand, immediateOperand)
and operand.type == "float" and operand.type == "float"
and operand.value != None and operand.value != None
) )
if isinstance(i_operand, ImmediateOperand) and i_operand.type == "double": if isinstance(i_operand, immediateOperand) and i_operand.type == "double":
return ( return (
isinstance(operand, ImmediateOperand) isinstance(operand, immediateOperand)
and operand.type == "double" and operand.type == "double"
and operand.value != None and operand.value != None
) )
# identifier # identifier
if isinstance(operand, IdentifierOperand) or ( if isinstance(operand, identifierOperand) or (
isinstance(operand, ImmediateOperand) and operand.identifier != None isinstance(operand, immediateOperand) and operand.identifier != None
): ):
return isinstance(i_operand, IdentifierOperand) return isinstance(i_operand, identifierOperand)
# prefetch option # prefetch option
if not isinstance(operand, Operand) and "prfop" in operand: if not isinstance(operand, Operand) and "prfop" in operand:
return i_operand["class"] == "prfop" return i_operand["class"] == "prfop"
@@ -719,22 +720,22 @@ class MachineModel(object):
# 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 isinstance(operand, RegisterOperand): if isinstance(operand, registerOperand):
if not isinstance(i_operand, RegisterOperand): if not isinstance(i_operand, registerOperand):
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 isinstance(operand, MemoryOperand): if isinstance(operand, memoryOperand):
if not isinstance(i_operand, MemoryOperand): if not isinstance(i_operand, memoryOperand):
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 isinstance(operand, ImmediateOperand): if isinstance(operand, immediateOperand):
# if "immediate" in operand.name or operand.value != None: # if "immediate" in operand.name or operand.value != None:
return isinstance(i_operand, ImmediateOperand) and i_operand.type == "int" return isinstance(i_operand, immediateOperand) and i_operand.type == "int"
# identifier (e.g., labels) # identifier (e.g., labels)
if isinstance(operand, IdentifierOperand): if isinstance(operand, identifierOperand):
return isinstance(i_operand, IdentifierOperand) return isinstance(i_operand, identifierOperand)
return self._compare_db_entries(i_operand, operand) 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):
@@ -790,7 +791,7 @@ class MachineModel(object):
if i_reg is None: if i_reg is None:
return True return True
return False return False
if isinstance(i_reg, RegisterOperand): if isinstance(i_reg, registerOperand):
i_reg_name = i_reg.name i_reg_name = i_reg.name
else: else:
i_reg_name = i_reg i_reg_name = i_reg
@@ -842,7 +843,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 (isinstance(mem.base, RegisterOperand) and (mem.base.prefix == i_mem.base)) or (isinstance(mem.base, registerOperand) and (mem.base.prefix == i_mem.base))
) )
# check offset # check offset
and ( and (

View File

@@ -3,14 +3,14 @@ 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 osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
from .hw_model import MachineModel from .hw_model import MachineModel
class INSTR_FLAGS: class INSTR_flags:
""" """
Flags used for unknown or special instructions Flags used for unknown or special instructions
""" """
@@ -81,7 +81,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 any([isinstance(op, memoryOperand) for op in operands]):
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
@@ -116,7 +116,7 @@ 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 isinstance(op, MemoryOperand)]: for operand in [op for op in op_dict["source"] if isinstance(op, memoryOperand)]:
post_indexed = operand.post_indexed post_indexed = operand.post_indexed
pre_indexed = operand.pre_indexed pre_indexed = operand.pre_indexed
if post_indexed or pre_indexed: if post_indexed or pre_indexed:
@@ -127,7 +127,7 @@ class ISASemantics(object):
"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 isinstance(op, memoryOperand)]:
post_indexed = operand.post_indexed post_indexed = operand.post_indexed
pre_indexed = operand.pre_indexed pre_indexed = operand.pre_indexed
if post_indexed or pre_indexed: if post_indexed or pre_indexed:
@@ -146,9 +146,9 @@ class ISASemantics(object):
# ) # )
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):
instruction_form.flags += [INSTR_FLAGS.HAS_ST] instruction_form.flags += [INSTR_flags.HAS_ST]
def get_reg_changes(self, instruction_form, only_postindexed=False): def get_reg_changes(self, instruction_form, only_postindexed=False):
""" """
@@ -165,7 +165,7 @@ class ISASemantics(object):
instruction_form.semantic_operands["destination"], instruction_form.semantic_operands["destination"],
instruction_form.semantic_operands["src_dst"], instruction_form.semantic_operands["src_dst"],
) )
if isinstance(op, RegisterOperand) 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
@@ -188,7 +188,7 @@ class ISASemantics(object):
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 and o.post_indexed != False: 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: {
@@ -202,7 +202,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 isinstance(o, MemoryOperand) and o.pre_indexed: 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(
@@ -216,13 +216,13 @@ class ISASemantics(object):
if isa_data is not None: if isa_data is not None:
for i, o in enumerate(instruction_form.operands): for i, o in enumerate(instruction_form.operands):
operand_name = "op{}".format(i + 1) operand_name = "op{}".format(i + 1)
if isinstance(o, RegisterOperand): if isinstance(o, registerOperand):
o_reg_name = o.prefix if o.prefix != None else "" + o.name o_reg_name = o.prefix if o.prefix != None else "" + o.name
reg_operand_names[o_reg_name] = operand_name reg_operand_names[o_reg_name] = operand_name
operand_state[operand_name] = {"name": o_reg_name, "value": 0} operand_state[operand_name] = {"name": o_reg_name, "value": 0}
elif isinstance(o, ImmediateOperand): elif isinstance(o, immediateOperand):
operand_state[operand_name] = {"value": o.value} operand_state[operand_name] = {"value": o.value}
elif isinstance(o, MemoryOperand): elif isinstance(o, memoryOperand):
# TODO lea needs some thinking about # TODO lea needs some thinking about
pass pass
@@ -301,7 +301,7 @@ class ISASemantics(object):
instruction_form.semantic_operands["source"], instruction_form.semantic_operands["source"],
instruction_form.semantic_operands["src_dst"], instruction_form.semantic_operands["src_dst"],
): ):
if isinstance(operand, MemoryOperand): if isinstance(operand, memoryOperand):
return True return True
return False return False
@@ -311,7 +311,7 @@ class ISASemantics(object):
instruction_form.semantic_operands["destination"], instruction_form.semantic_operands["destination"],
instruction_form.semantic_operands["src_dst"], instruction_form.semantic_operands["src_dst"],
): ):
if isinstance(operand, MemoryOperand): if isinstance(operand, memoryOperand):
return True return True
return False return False
@@ -345,7 +345,7 @@ 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 [ return [
self._create_reg_wildcard() if isinstance(op, MemoryOperand) else op for op in operands self._create_reg_wildcard() if isinstance(op, memoryOperand) else op for op in operands
] ]
def _create_reg_wildcard(self): def _create_reg_wildcard(self):

View File

@@ -8,10 +8,10 @@ from itertools import chain
from multiprocessing import Manager, Process, cpu_count 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.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
class KernelDG(nx.DiGraph): class KernelDG(nx.DiGraph):
@@ -66,8 +66,8 @@ class KernelDG(nx.DiGraph):
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
and INSTR_FLAGS.LD not in instruction_form.flags and INSTR_flags.LD not in instruction_form.flags
): ):
# add new node # add new node
dg.add_node(instruction_form.line_number + 0.1) dg.add_node(instruction_form.line_number + 0.1)
@@ -283,7 +283,7 @@ 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 isinstance(dst, RegisterOperand): if isinstance(dst, registerOperand):
# read of register # read of register
if self.is_read(dst, instr_form): if self.is_read(dst, instr_form):
# if dst.pre_indexed or dst.post_indexed: # if dst.pre_indexed or dst.post_indexed:
@@ -294,8 +294,8 @@ class KernelDG(nx.DiGraph):
if self.is_written(dst, instr_form): if self.is_written(dst, instr_form):
break break
if ( if (
not isinstance(dst, RegisterOperand) not isinstance(dst, registerOperand)
and not isinstance(dst, MemoryOperand) and not isinstance(dst, memoryOperand)
and "flag" in dst and "flag" in dst
and flag_dependencies and flag_dependencies
): ):
@@ -305,7 +305,7 @@ class KernelDG(nx.DiGraph):
# 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 isinstance(dst, MemoryOperand): if isinstance(dst, memoryOperand):
# base register is altered during memory access # base register is altered during memory access
if dst.pre_indexed != None: if dst.pre_indexed != None:
if self.is_written(dst.base, instr_form): if self.is_written(dst.base, instr_form):
@@ -374,16 +374,16 @@ class KernelDG(nx.DiGraph):
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): if isinstance(src, registerOperand):
is_read = self.parser.is_reg_dependend_of(register, src) or is_read is_read = self.parser.is_reg_dependend_of(register, src) or is_read
if ( if (
not isinstance(src, RegisterOperand) not isinstance(src, registerOperand)
and not isinstance(src, MemoryOperand) and not isinstance(src, memoryOperand)
and not isinstance(src, ImmediateOperand) and not isinstance(src, immediateOperand)
and "flag" in src and "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 isinstance(src, MemoryOperand): if isinstance(src, memoryOperand):
if src.base is not None: if src.base is not None:
is_read = self.parser.is_reg_dependend_of(register, src.base) or is_read is_read = self.parser.is_reg_dependend_of(register, src.base) or is_read
if src.index is not None: if src.index is not None:
@@ -393,7 +393,7 @@ class KernelDG(nx.DiGraph):
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, MemoryOperand): if isinstance(dst, memoryOperand):
if dst.base is not None: if dst.base is not None:
is_read = self.parser.is_reg_dependend_of(register, dst.base) or is_read is_read = self.parser.is_reg_dependend_of(register, dst.base) or is_read
if dst.index is not None: if dst.index is not None:
@@ -409,7 +409,7 @@ class KernelDG(nx.DiGraph):
instruction_form.semantic_operands["src_dst"], instruction_form.semantic_operands["src_dst"],
): ):
# Here we check for mem dependecies only # Here we check for mem dependecies only
if not isinstance(src, MemoryOperand): if not isinstance(src, memoryOperand):
continue continue
# src = src.memory # src = src.memory
@@ -482,15 +482,15 @@ class KernelDG(nx.DiGraph):
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): if isinstance(dst, registerOperand):
is_written = self.parser.is_reg_dependend_of(register, dst) or is_written is_written = self.parser.is_reg_dependend_of(register, dst) or is_written
if ( if (
not isinstance(dst, RegisterOperand) not isinstance(dst, registerOperand)
and not isinstance(dst, MemoryOperand) and not isinstance(dst, memoryOperand)
and "flag" in dst and "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 isinstance(dst, MemoryOperand): if isinstance(dst, memoryOperand):
if dst.pre_indexed or dst.post_indexed: if dst.pre_indexed or dst.post_indexed:
is_written = self.parser.is_reg_dependend_of(register, dst.base) or is_written is_written = self.parser.is_reg_dependend_of(register, dst.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
@@ -498,7 +498,7 @@ class KernelDG(nx.DiGraph):
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, MemoryOperand): if isinstance(src, memoryOperand):
if src.pre_indexed or src.post_indexed: if src.pre_indexed or src.post_indexed:
is_written = self.parser.is_reg_dependend_of(register, src.base) or is_written is_written = self.parser.is_reg_dependend_of(register, src.base) or is_written
return is_written return is_written
@@ -512,7 +512,7 @@ class KernelDG(nx.DiGraph):
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, MemoryOperand): if isinstance(dst, memoryOperand):
is_store = mem == dst or is_store is_store = mem == dst or is_store
return is_store return is_store

View File

@@ -9,24 +9,24 @@ from io import StringIO
import osaca.db_interface as dbi import osaca.db_interface as dbi
from osaca.db_interface import sanity_check from osaca.db_interface import sanity_check
from osaca.semantics import MachineModel from osaca.semantics import MachineModel
from osaca.parser import InstructionForm from osaca.parser import instructionForm
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
import copy import copy
class TestDBInterface(unittest.TestCase): class TestDBInterface(unittest.TestCase):
@classmethod @classmethod
def setUpClass(self): def setUpClass(self):
sample_entry = InstructionForm( sample_entry = instructionForm(
INSTRUCTION_ID="DoItRightAndDoItFast", instruction_id="DoItRightAndDoItFast",
OPERANDS_ID=[ operands_id=[
MemoryOperand(OFFSET_ID="imd", BASE_ID="gpr", INDEX_ID="gpr", SCALE_ID=8), memoryOperand(offset_ID="imd", base_id="gpr", index_id="gpr", scale_id=8),
RegisterOperand(NAME_ID="xmm"), registerOperand(name_id="xmm"),
], ],
THROUGHPUT=1.25, throughput=1.25,
LATENCY=125, latency=125,
UOPS=6, uops=6,
) )
self.entry_csx = copy.copy(sample_entry) self.entry_csx = copy.copy(sample_entry)
@@ -61,7 +61,7 @@ class TestDBInterface(unittest.TestCase):
mm_csx.set_instruction_entry(self.entry_csx) mm_csx.set_instruction_entry(self.entry_csx)
mm_tx2.set_instruction_entry(self.entry_tx2) mm_tx2.set_instruction_entry(self.entry_tx2)
mm_zen1.set_instruction_entry(InstructionForm(INSTRUCTION_ID="empty_operation")) mm_zen1.set_instruction_entry(instructionForm(instruction_id="empty_operation"))
num_entries_csx = len(mm_csx["instruction_forms"]) - num_entries_csx num_entries_csx = len(mm_csx["instruction_forms"]) - num_entries_csx
num_entries_tx2 = len(mm_tx2["instruction_forms"]) - num_entries_tx2 num_entries_tx2 = len(mm_tx2["instruction_forms"]) - num_entries_tx2
@@ -72,7 +72,7 @@ class TestDBInterface(unittest.TestCase):
self.assertEqual(num_entries_zen1, 1) self.assertEqual(num_entries_zen1, 1)
def test_invalid_add(self): def test_invalid_add(self):
entry = InstructionForm() entry = instructionForm()
# with self.assertRaises(KeyError): # with self.assertRaises(KeyError):
# MachineModel("csx").set_instruction_entry(entry) # MachineModel("csx").set_instruction_entry(entry)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):

View File

@@ -8,12 +8,12 @@ import unittest
from pyparsing import ParseException from pyparsing import ParseException
from osaca.parser import ParserAArch64, InstructionForm from osaca.parser import ParserAArch64, instructionForm
from osaca.parser.operand import Operand from osaca.parser.operand import Operand
from osaca.parser.directive import DirectiveOperand from osaca.parser.directive import directiveOperand
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.immediate import ImmediateOperand from osaca.parser.immediate import immediateOperand
class TestParserAArch64(unittest.TestCase): class TestParserAArch64(unittest.TestCase):
@@ -181,140 +181,140 @@ class TestParserAArch64(unittest.TestCase):
line_5_operands = "fcmla z26.d, p0/m, z29.d, z21.d, #90" line_5_operands = "fcmla z26.d, p0/m, z29.d, z21.d, #90"
line_conditions = "ccmn x11, #1, #3, eq" line_conditions = "ccmn x11, #1, #3, eq"
instruction_form_1 = InstructionForm( instruction_form_1 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="-- Begin main", comment_id="-- Begin main",
LABEL_ID=None, label_id=None,
LINE="// -- Begin main", line="// -- Begin main",
LINE_NUMBER=1, line_number=1,
) )
instruction_form_2 = InstructionForm( instruction_form_2 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="=>This Inner Loop Header: Depth=1", comment_id="=>This Inner Loop Header: Depth=1",
LABEL_ID=".LBB0_1", label_id=".LBB0_1",
LINE=".LBB0_1: // =>This Inner Loop Header: Depth=1", line=".LBB0_1: // =>This Inner Loop Header: Depth=1",
LINE_NUMBER=2, line_number=2,
) )
instruction_form_3 = InstructionForm( instruction_form_3 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=DirectiveOperand(NAME_ID="cfi_def_cfa", PARAMETER_ID=["w29", "-16"]), directive_id=directiveOperand(name_id="cfi_def_cfa", parameter_id=["w29", "-16"]),
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE=".cfi_def_cfa w29, -16", line=".cfi_def_cfa w29, -16",
LINE_NUMBER=3, line_number=3,
) )
instruction_form_4 = InstructionForm( instruction_form_4 = instructionForm(
INSTRUCTION_ID="ldr", instruction_id="ldr",
OPERANDS_ID=[ operands_id=[
RegisterOperand(PREFIX_ID="s", NAME_ID="0"), registerOperand(prefix_id="s", name_id="0"),
MemoryOperand( memoryOperand(
OFFSET_ID=None, offset_ID=None,
BASE_ID=RegisterOperand(PREFIX_ID="x", NAME_ID="11"), base_id=registerOperand(prefix_id="x", name_id="11"),
INDEX_ID={ index_id={
"prefix": "w", "prefix": "w",
"name": "10", "name": "10",
"shift_op": "sxtw", "shift_op": "sxtw",
"immediate": {"value": "2"}, "immediate": {"value": "2"},
"shift": [{"value": "2"}], "shift": [{"value": "2"}],
}, },
SCALE_ID=4, scale_id=4,
), ),
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="= <<2", comment_id="= <<2",
LABEL_ID=None, label_id=None,
LINE="ldr s0, [x11, w10, sxtw #2] // = <<2", line="ldr s0, [x11, w10, sxtw #2] // = <<2",
LINE_NUMBER=4, line_number=4,
) )
instruction_form_5 = InstructionForm( instruction_form_5 = instructionForm(
INSTRUCTION_ID="prfm", instruction_id="prfm",
OPERANDS_ID=[ operands_id=[
{"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}}, {"prfop": {"type": ["PLD"], "target": ["L1"], "policy": ["KEEP"]}},
MemoryOperand( memoryOperand(
OFFSET_ID={"value": 2048}, offset_ID={"value": 2048},
BASE_ID=RegisterOperand(PREFIX_ID="x", NAME_ID="26"), base_id=registerOperand(prefix_id="x", name_id="26"),
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
), ),
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="HPL", comment_id="HPL",
LABEL_ID=None, label_id=None,
LINE="prfm pldl1keep, [x26, #2048] //HPL", line="prfm pldl1keep, [x26, #2048] //HPL",
LINE_NUMBER=5, line_number=5,
) )
instruction_form_6 = InstructionForm( instruction_form_6 = instructionForm(
INSTRUCTION_ID="stp", instruction_id="stp",
OPERANDS_ID=[ operands_id=[
RegisterOperand(PREFIX_ID="x", NAME_ID="29"), registerOperand(prefix_id="x", name_id="29"),
RegisterOperand(PREFIX_ID="x", NAME_ID="30"), registerOperand(prefix_id="x", name_id="30"),
MemoryOperand( memoryOperand(
OFFSET_ID={"value": -16}, offset_ID={"value": -16},
BASE_ID=RegisterOperand(NAME_ID="sp", PREFIX_ID="x"), base_id=registerOperand(name_id="sp", prefix_id="x"),
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
PRE_INDEXED=True, pre_indexed=True,
), ),
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE="stp x29, x30, [sp, #-16]!", line="stp x29, x30, [sp, #-16]!",
LINE_NUMBER=6, line_number=6,
) )
instruction_form_7 = InstructionForm( instruction_form_7 = instructionForm(
INSTRUCTION_ID="ldp", instruction_id="ldp",
OPERANDS_ID=[ operands_id=[
RegisterOperand(PREFIX_ID="q", NAME_ID="2"), registerOperand(prefix_id="q", name_id="2"),
RegisterOperand(PREFIX_ID="q", NAME_ID="3"), registerOperand(prefix_id="q", name_id="3"),
MemoryOperand( memoryOperand(
OFFSET_ID=None, offset_ID=None,
BASE_ID=RegisterOperand(NAME_ID="11", PREFIX_ID="x"), base_id=registerOperand(name_id="11", prefix_id="x"),
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
POST_INDEXED={"value": 64}, post_indexed={"value": 64},
), ),
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE="ldp q2, q3, [x11], #64", line="ldp q2, q3, [x11], #64",
LINE_NUMBER=7, line_number=7,
) )
instruction_form_8 = InstructionForm( instruction_form_8 = instructionForm(
INSTRUCTION_ID="fcmla", instruction_id="fcmla",
OPERANDS_ID=[ operands_id=[
RegisterOperand(PREFIX_ID="z", NAME_ID="26", SHAPE="d"), registerOperand(prefix_id="z", name_id="26", shape="d"),
RegisterOperand(PREFIX_ID="p", NAME_ID="0", PREDICATION="m"), registerOperand(prefix_id="p", name_id="0", predication="m"),
RegisterOperand(PREFIX_ID="z", NAME_ID="29", SHAPE="d"), registerOperand(prefix_id="z", name_id="29", shape="d"),
RegisterOperand(PREFIX_ID="z", NAME_ID="21", SHAPE="d"), registerOperand(prefix_id="z", name_id="21", shape="d"),
ImmediateOperand(VALUE_ID=90, TYPE_ID="int"), immediateOperand(value_id=90, type_id="int"),
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE="fcmla z26.d, p0/m, z29.d, z21.d, #90", line="fcmla z26.d, p0/m, z29.d, z21.d, #90",
LINE_NUMBER=8, line_number=8,
) )
instruction_form_9 = InstructionForm( instruction_form_9 = instructionForm(
INSTRUCTION_ID="ccmn", instruction_id="ccmn",
OPERANDS_ID=[ operands_id=[
RegisterOperand(PREFIX_ID="x", NAME_ID="11"), registerOperand(prefix_id="x", name_id="11"),
ImmediateOperand(VALUE_ID=1, TYPE_ID="int"), immediateOperand(value_id=1, type_id="int"),
ImmediateOperand(VALUE_ID=3, TYPE_ID="int"), immediateOperand(value_id=3, type_id="int"),
{"condition": "EQ"}, {"condition": "EQ"},
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID=None, comment_id=None,
LABEL_ID=None, label_id=None,
LINE="ccmn x11, #1, #3, eq", line="ccmn x11, #1, #3, eq",
LINE_NUMBER=9, line_number=9,
) )
parsed_1 = self.parser.parse_line(line_comment, 1) parsed_1 = self.parser.parse_line(line_comment, 1)
@@ -372,17 +372,17 @@ class TestParserAArch64(unittest.TestCase):
instr_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]" instr_list_with_index = "ld4 {v0.S, v1.S, v2.S, v3.S}[2]"
instr_range_single = "dummy { z1.d }" instr_range_single = "dummy { z1.d }"
reg_list = [ reg_list = [
RegisterOperand(PREFIX_ID="x", NAME_ID="5"), registerOperand(prefix_id="x", name_id="5"),
RegisterOperand(PREFIX_ID="x", NAME_ID="6"), registerOperand(prefix_id="x", name_id="6"),
RegisterOperand(PREFIX_ID="x", NAME_ID="7"), registerOperand(prefix_id="x", name_id="7"),
] ]
reg_list_idx = [ reg_list_idx = [
RegisterOperand(PREFIX_ID="v", NAME_ID="0", SHAPE="S", INDEX=2), registerOperand(prefix_id="v", name_id="0", shape="S", index=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="1", SHAPE="S", INDEX=2), registerOperand(prefix_id="v", name_id="1", shape="S", index=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="2", SHAPE="S", INDEX=2), registerOperand(prefix_id="v", name_id="2", shape="S", index=2),
RegisterOperand(PREFIX_ID="v", NAME_ID="3", SHAPE="S", INDEX=2), registerOperand(prefix_id="v", name_id="3", shape="S", index=2),
] ]
reg_list_single = [RegisterOperand(PREFIX_ID="z", NAME_ID="1", SHAPE="d")] reg_list_single = [registerOperand(prefix_id="z", name_id="1", shape="d")]
prange = self.parser.parse_line(instr_range) prange = self.parser.parse_line(instr_range)
plist = self.parser.parse_line(instr_list) plist = self.parser.parse_line(instr_list)
@@ -397,22 +397,22 @@ class TestParserAArch64(unittest.TestCase):
# self.assertEqual(p_single.operands, reg_list_single) # self.assertEqual(p_single.operands, reg_list_single)
def test_reg_dependency(self): def test_reg_dependency(self):
reg_1_1 = RegisterOperand(PREFIX_ID="b", NAME_ID="1") reg_1_1 = registerOperand(prefix_id="b", name_id="1")
reg_1_2 = RegisterOperand(PREFIX_ID="h", NAME_ID="1") reg_1_2 = registerOperand(prefix_id="h", name_id="1")
reg_1_3 = RegisterOperand(PREFIX_ID="s", NAME_ID="1") reg_1_3 = registerOperand(prefix_id="s", name_id="1")
reg_1_4 = RegisterOperand(PREFIX_ID="d", NAME_ID="1") reg_1_4 = registerOperand(prefix_id="d", name_id="1")
reg_1_4 = RegisterOperand(PREFIX_ID="q", NAME_ID="1") reg_1_4 = registerOperand(prefix_id="q", name_id="1")
reg_2_1 = RegisterOperand(PREFIX_ID="w", NAME_ID="2") reg_2_1 = registerOperand(prefix_id="w", name_id="2")
reg_2_2 = RegisterOperand(PREFIX_ID="x", NAME_ID="2") reg_2_2 = registerOperand(prefix_id="x", name_id="2")
reg_v1_1 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="16", SHAPE="b") reg_v1_1 = registerOperand(prefix_id="v", name_id="11", lanes="16", shape="b")
reg_v1_2 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="8", SHAPE="h") reg_v1_2 = registerOperand(prefix_id="v", name_id="11", lanes="8", shape="h")
reg_v1_3 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="4", SHAPE="s") reg_v1_3 = registerOperand(prefix_id="v", name_id="11", lanes="4", shape="s")
reg_v1_4 = RegisterOperand(PREFIX_ID="v", NAME_ID="11", LANES="2", SHAPE="d") reg_v1_4 = registerOperand(prefix_id="v", name_id="11", lanes="2", shape="d")
reg_b5 = RegisterOperand(PREFIX_ID="b", NAME_ID="5") reg_b5 = registerOperand(prefix_id="b", name_id="5")
reg_q15 = RegisterOperand(PREFIX_ID="q", NAME_ID="15") reg_q15 = registerOperand(prefix_id="q", name_id="15")
reg_v10 = RegisterOperand(PREFIX_ID="v", NAME_ID="10", LANES="2", SHAPE="s") reg_v10 = registerOperand(prefix_id="v", name_id="10", lanes="2", shape="s")
reg_v20 = RegisterOperand(PREFIX_ID="v", NAME_ID="20", LANES="2", SHAPE="d") reg_v20 = registerOperand(prefix_id="v", name_id="20", lanes="2", shape="d")
reg_1 = [reg_1_1, reg_1_2, reg_1_3, reg_1_4] reg_1 = [reg_1_1, reg_1_2, reg_1_3, reg_1_4]
reg_2 = [reg_2_1, reg_2_2] reg_2 = [reg_2_1, reg_2_2]

View File

@@ -8,8 +8,8 @@ import unittest
from pyparsing import ParseException from pyparsing import ParseException
from osaca.parser import ParserX86ATT, InstructionForm from osaca.parser import ParserX86ATT, instructionForm
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
class TestParserX86ATT(unittest.TestCase): class TestParserX86ATT(unittest.TestCase):
@@ -165,36 +165,36 @@ class TestParserX86ATT(unittest.TestCase):
line_directive = ".quad .2.3_2__kmpc_loc_pack.2 #qed" line_directive = ".quad .2.3_2__kmpc_loc_pack.2 #qed"
line_instruction = "lea 2(%rax,%rax), %ecx #12.9" line_instruction = "lea 2(%rax,%rax), %ecx #12.9"
instruction_form_1 = InstructionForm( instruction_form_1 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="-- Begin main", comment_id="-- Begin main",
LABEL_ID=None, label_id=None,
LINE="# -- Begin main", line="# -- Begin main",
LINE_NUMBER=1, line_number=1,
) )
instruction_form_2 = InstructionForm( instruction_form_2 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="Preds ..B1.6", comment_id="Preds ..B1.6",
LABEL_ID="..B1.7", label_id="..B1.7",
LINE="..B1.7: # Preds ..B1.6", line="..B1.7: # Preds ..B1.6",
LINE_NUMBER=2, line_number=2,
) )
instruction_form_3 = InstructionForm( instruction_form_3 = instructionForm(
INSTRUCTION_ID=None, instruction_id=None,
OPERANDS_ID=[], operands_id=[],
DIRECTIVE_ID={"name": "quad", "parameters": [".2.3_2__kmpc_loc_pack.2"]}, directive_id={"name": "quad", "parameters": [".2.3_2__kmpc_loc_pack.2"]},
COMMENT_ID="qed", comment_id="qed",
LABEL_ID=None, label_id=None,
LINE=".quad .2.3_2__kmpc_loc_pack.2 #qed", line=".quad .2.3_2__kmpc_loc_pack.2 #qed",
LINE_NUMBER=3, line_number=3,
) )
instruction_form_4 = InstructionForm( instruction_form_4 = instructionForm(
INSTRUCTION_ID="lea", instruction_id="lea",
OPERANDS_ID=[ operands_id=[
{ {
"memory": { "memory": {
"offset": {"value": 2}, "offset": {"value": 2},
@@ -205,11 +205,11 @@ class TestParserX86ATT(unittest.TestCase):
}, },
{"register": {"name": "ecx"}}, {"register": {"name": "ecx"}},
], ],
DIRECTIVE_ID=None, directive_id=None,
COMMENT_ID="12.9", comment_id="12.9",
LABEL_ID=None, label_id=None,
LINE="lea 2(%rax,%rax), %ecx #12.9", line="lea 2(%rax,%rax), %ecx #12.9",
LINE_NUMBER=4, line_number=4,
) )
parsed_1 = self.parser.parse_line(line_comment, 1) parsed_1 = self.parser.parse_line(line_comment, 1)
@@ -233,10 +233,10 @@ class TestParserX86ATT(unittest.TestCase):
register_str_3 = "%xmm1" register_str_3 = "%xmm1"
register_str_4 = "%rip" register_str_4 = "%rip"
parsed_reg_1 = RegisterOperand(NAME_ID="rax") parsed_reg_1 = registerOperand(name_id="rax")
parsed_reg_2 = RegisterOperand(NAME_ID="r9") parsed_reg_2 = registerOperand(name_id="r9")
parsed_reg_3 = RegisterOperand(NAME_ID="xmm1") parsed_reg_3 = registerOperand(name_id="xmm1")
parsed_reg_4 = RegisterOperand(NAME_ID="rip") parsed_reg_4 = registerOperand(name_id="rip")
self.assertEqual(self.parser.parse_register(register_str_1), parsed_reg_1) self.assertEqual(self.parser.parse_register(register_str_1), parsed_reg_1)
self.assertEqual(self.parser.parse_register(register_str_2), parsed_reg_2) self.assertEqual(self.parser.parse_register(register_str_2), parsed_reg_2)
@@ -259,22 +259,22 @@ class TestParserX86ATT(unittest.TestCase):
) )
def test_reg_dependency(self): def test_reg_dependency(self):
reg_a1 = RegisterOperand(NAME_ID="rax") reg_a1 = registerOperand(name_id="rax")
reg_a2 = RegisterOperand(NAME_ID="eax") reg_a2 = registerOperand(name_id="eax")
reg_a3 = RegisterOperand(NAME_ID="ax") reg_a3 = registerOperand(name_id="ax")
reg_a4 = RegisterOperand(NAME_ID="al") reg_a4 = registerOperand(name_id="al")
reg_r11 = RegisterOperand(NAME_ID="r11") reg_r11 = registerOperand(name_id="r11")
reg_r11b = RegisterOperand(NAME_ID="r11b") reg_r11b = registerOperand(name_id="r11b")
reg_r11d = RegisterOperand(NAME_ID="r11d") reg_r11d = registerOperand(name_id="r11d")
reg_r11w = RegisterOperand(NAME_ID="r11w") reg_r11w = registerOperand(name_id="r11w")
reg_xmm1 = RegisterOperand(NAME_ID="xmm1") reg_xmm1 = registerOperand(name_id="xmm1")
reg_ymm1 = RegisterOperand(NAME_ID="ymm1") reg_ymm1 = registerOperand(name_id="ymm1")
reg_zmm1 = RegisterOperand(NAME_ID="zmm1") reg_zmm1 = registerOperand(name_id="zmm1")
reg_b1 = RegisterOperand(NAME_ID="rbx") reg_b1 = registerOperand(name_id="rbx")
reg_r15 = RegisterOperand(NAME_ID="r15") reg_r15 = registerOperand(name_id="r15")
reg_xmm2 = RegisterOperand(NAME_ID="xmm2") reg_xmm2 = registerOperand(name_id="xmm2")
reg_ymm3 = RegisterOperand(NAME_ID="ymm3") reg_ymm3 = registerOperand(name_id="ymm3")
reg_a = [reg_a1, reg_a2, reg_a3, reg_a4] reg_a = [reg_a1, reg_a2, reg_a3, reg_a4]
reg_r = [reg_r11, reg_r11b, reg_r11d, reg_r11w] reg_r = [reg_r11, reg_r11b, reg_r11d, reg_r11w]

View File

@@ -12,16 +12,16 @@ import networkx as nx
from osaca.osaca import get_unmatched_instruction_ratio from osaca.osaca import get_unmatched_instruction_ratio
from osaca.parser import AttrDict, ParserAArch64, ParserX86ATT from osaca.parser import AttrDict, ParserAArch64, ParserX86ATT
from osaca.semantics import ( from osaca.semantics import (
INSTR_FLAGS, INSTR_flags,
ArchSemantics, ArchSemantics,
ISASemantics, ISASemantics,
KernelDG, KernelDG,
MachineModel, MachineModel,
reduce_to_section, reduce_to_section,
) )
from osaca.parser.register import RegisterOperand from osaca.parser.register import registerOperand
from osaca.parser.memory import MemoryOperand from osaca.parser.memory import memoryOperand
from osaca.parser.identifier import IdentifierOperand from osaca.parser.identifier import identifierOperand
class TestSemanticTools(unittest.TestCase): class TestSemanticTools(unittest.TestCase):
@@ -148,31 +148,31 @@ class TestSemanticTools(unittest.TestCase):
self.assertIsNone(test_mm_arm.get_instruction("NOT_IN_DB", [])) self.assertIsNone(test_mm_arm.get_instruction("NOT_IN_DB", []))
name_x86_1 = "vaddpd" name_x86_1 = "vaddpd"
operands_x86_1 = [ operands_x86_1 = [
RegisterOperand(NAME_ID="xmm"), registerOperand(name_id="xmm"),
RegisterOperand(NAME_ID="xmm"), registerOperand(name_id="xmm"),
RegisterOperand(NAME_ID="xmm"), registerOperand(name_id="xmm"),
] ]
instr_form_x86_1 = test_mm_x86.get_instruction(name_x86_1, operands_x86_1) instr_form_x86_1 = test_mm_x86.get_instruction(name_x86_1, operands_x86_1)
self.assertEqual(instr_form_x86_1, test_mm_x86.get_instruction(name_x86_1, operands_x86_1)) self.assertEqual(instr_form_x86_1, test_mm_x86.get_instruction(name_x86_1, operands_x86_1))
self.assertEqual( self.assertEqual(
test_mm_x86.get_instruction("jg", [IdentifierOperand()]), test_mm_x86.get_instruction("jg", [identifierOperand()]),
test_mm_x86.get_instruction("jg", [IdentifierOperand()]), test_mm_x86.get_instruction("jg", [identifierOperand()]),
) )
name_arm_1 = "fadd" name_arm_1 = "fadd"
operands_arm_1 = [ operands_arm_1 = [
RegisterOperand(PREFIX_ID="v", SHAPE="s"), registerOperand(prefix_id="v", shape="s"),
RegisterOperand(PREFIX_ID="v", SHAPE="s"), registerOperand(prefix_id="v", shape="s"),
RegisterOperand(PREFIX_ID="v", SHAPE="s"), registerOperand(prefix_id="v", shape="s"),
] ]
instr_form_arm_1 = test_mm_arm.get_instruction(name_arm_1, operands_arm_1) instr_form_arm_1 = test_mm_arm.get_instruction(name_arm_1, operands_arm_1)
self.assertEqual(instr_form_arm_1, test_mm_arm.get_instruction(name_arm_1, operands_arm_1)) self.assertEqual(instr_form_arm_1, test_mm_arm.get_instruction(name_arm_1, operands_arm_1))
self.assertEqual( self.assertEqual(
test_mm_arm.get_instruction("b.ne", [IdentifierOperand()]), test_mm_arm.get_instruction("b.ne", [identifierOperand()]),
test_mm_arm.get_instruction("b.ne", [IdentifierOperand()]), test_mm_arm.get_instruction("b.ne", [identifierOperand()]),
) )
self.assertEqual( self.assertEqual(
test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [IdentifierOperand()]), test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [identifierOperand()]),
test_mm_arm.get_instruction("b.someOtherName", [IdentifierOperand()]), test_mm_arm.get_instruction("b.someOtherName", [identifierOperand()]),
) )
# test full instruction name # test full instruction name
@@ -189,8 +189,8 @@ class TestSemanticTools(unittest.TestCase):
# 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( memoryOperand(
BASE_ID=RegisterOperand(NAME_ID="x"), OFFSET_ID=None, INDEX_ID=None, SCALE_ID=1 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"]],
@@ -198,11 +198,11 @@ class TestSemanticTools(unittest.TestCase):
self.assertEqual( self.assertEqual(
test_mm_x86.get_store_throughput( test_mm_x86.get_store_throughput(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(PREFIX_ID="NOT_IN_DB"), base_id=registerOperand(prefix_id="NOT_IN_DB"),
OFFSET_ID=None, offset_ID=None,
INDEX_ID="NOT_NONE", index_id="NOT_NONE",
SCALE_ID=1, scale_id=1,
) )
)[0].port_pressure, )[0].port_pressure,
[[1, "23"], [1, "4"]], [[1, "23"], [1, "4"]],
@@ -210,11 +210,11 @@ class TestSemanticTools(unittest.TestCase):
self.assertEqual( self.assertEqual(
test_mm_arm.get_store_throughput( test_mm_arm.get_store_throughput(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(PREFIX_ID="x"), base_id=registerOperand(prefix_id="x"),
OFFSET_ID=None, offset_ID=None,
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
) )
)[0].port_pressure, )[0].port_pressure,
[[2, "34"], [2, "5"]], [[2, "34"], [2, "5"]],
@@ -222,11 +222,11 @@ class TestSemanticTools(unittest.TestCase):
self.assertEqual( self.assertEqual(
test_mm_arm.get_store_throughput( test_mm_arm.get_store_throughput(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(PREFIX_ID="NOT_IN_DB"), base_id=registerOperand(prefix_id="NOT_IN_DB"),
OFFSET_ID=None, offset_ID=None,
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
) )
)[0].port_pressure, )[0].port_pressure,
[[1, "34"], [1, "5"]], [[1, "34"], [1, "5"]],
@@ -234,19 +234,19 @@ class TestSemanticTools(unittest.TestCase):
# test get_store_lt # test get_store_lt
self.assertEqual( self.assertEqual(
test_mm_x86.get_store_latency( test_mm_x86.get_store_latency(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(NAME_ID="x"), OFFSET_ID=None, INDEX_ID=None, SCALE_ID=1 base_id=registerOperand(name_id="x"), offset_ID=None, index_id=None, scale_id=1
) )
), ),
0, 0,
) )
self.assertEqual( self.assertEqual(
test_mm_arm.get_store_latency( test_mm_arm.get_store_latency(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(PREFIX_ID="x"), base_id=registerOperand(prefix_id="x"),
OFFSET_ID=None, offset_ID=None,
INDEX_ID=None, index_id=None,
SCALE_ID=1, scale_id=1,
) )
), ),
0, 0,
@@ -258,8 +258,8 @@ class TestSemanticTools(unittest.TestCase):
# test default load tp # test default load tp
self.assertEqual( self.assertEqual(
test_mm_x86.get_load_throughput( test_mm_x86.get_load_throughput(
MemoryOperand( memoryOperand(
BASE_ID=RegisterOperand(NAME_ID="x"), OFFSET_ID=None, INDEX_ID=None, SCALE_ID=1 base_id=registerOperand(name_id="x"), offset_ID=None, index_id=None, scale_id=1
) )
)[0].port_pressure, )[0].port_pressure,
[[1, "23"], [1, ["2D", "3D"]]], [[1, "23"], [1, ["2D", "3D"]]],
@@ -389,7 +389,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_AArch64(self): def test_kernelDG_AArch64(self):
dg = KernelDG( dg = KernelDG(
self.kernel_AArch64, self.kernel_AArch64,
@@ -421,7 +421,6 @@ class TestSemanticTools(unittest.TestCase):
# 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(
self.kernel_aarch64_SVE, self.kernel_aarch64_SVE,
@@ -446,9 +445,9 @@ class TestSemanticTools(unittest.TestCase):
semantics_hld.add_semantics(kernel_hld_2) semantics_hld.add_semantics(kernel_hld_2)
semantics_hld.add_semantics(kernel_hld_3) semantics_hld.add_semantics(kernel_hld_3)
num_hidden_loads = len([x for x in kernel_hld if INSTR_FLAGS.HIDDEN_LD in x.flags]) num_hidden_loads = len([x for x in kernel_hld if INSTR_flags.HIDDEN_LD in x.flags])
num_hidden_loads_2 = len([x for x in kernel_hld_2 if INSTR_FLAGS.HIDDEN_LD in x.flags]) num_hidden_loads_2 = len([x for x in kernel_hld_2 if INSTR_flags.HIDDEN_LD in x.flags])
num_hidden_loads_3 = len([x for x in kernel_hld_3 if INSTR_FLAGS.HIDDEN_LD in x.flags]) num_hidden_loads_3 = len([x for x in kernel_hld_3 if INSTR_flags.HIDDEN_LD in x.flags])
self.assertEqual(num_hidden_loads, 1) self.assertEqual(num_hidden_loads, 1)
self.assertEqual(num_hidden_loads_2, 0) self.assertEqual(num_hidden_loads_2, 0)
self.assertEqual(num_hidden_loads_3, 1) self.assertEqual(num_hidden_loads_3, 1)
@@ -463,7 +462,6 @@ 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,
@@ -513,7 +511,6 @@ class TestSemanticTools(unittest.TestCase):
[(4, 1.0), (5, 1.0), (10, 1.0), (11, 1.0), (12, 1.0)], [(4, 1.0), (5, 1.0), (10, 1.0), (11, 1.0), (12, 1.0)],
) )
def test_loop_carried_dependency_x86(self): def test_loop_carried_dependency_x86(self):
lcd_id = "8" lcd_id = "8"
lcd_id2 = "5" lcd_id2 = "5"
@@ -571,8 +568,8 @@ class TestSemanticTools(unittest.TestCase):
def test_is_read_is_written_x86(self): def test_is_read_is_written_x86(self):
# independent form HW model # independent form HW model
dag = KernelDG(self.kernel_x86, self.parser_x86, None, None) dag = KernelDG(self.kernel_x86, self.parser_x86, None, None)
reg_rcx = RegisterOperand(NAME_ID="rcx") reg_rcx = registerOperand(name_id="rcx")
reg_ymm1 = RegisterOperand(NAME_ID="ymm1") reg_ymm1 = registerOperand(name_id="ymm1")
instr_form_r_c = self.parser_x86.parse_line("vmovsd %xmm0, (%r15,%rcx,8)") instr_form_r_c = self.parser_x86.parse_line("vmovsd %xmm0, (%r15,%rcx,8)")
self.semantics_csx.assign_src_dst(instr_form_r_c) self.semantics_csx.assign_src_dst(instr_form_r_c)
@@ -602,11 +599,11 @@ class TestSemanticTools(unittest.TestCase):
def test_is_read_is_written_AArch64(self): def test_is_read_is_written_AArch64(self):
# independent form HW model # independent form HW model
dag = KernelDG(self.kernel_AArch64, self.parser_AArch64, None, None) dag = KernelDG(self.kernel_AArch64, self.parser_AArch64, None, None)
reg_x1 = RegisterOperand(PREFIX_ID="x", NAME_ID="1") reg_x1 = registerOperand(prefix_id="x", name_id="1")
reg_w1 = RegisterOperand(PREFIX_ID="w", NAME_ID="1") reg_w1 = registerOperand(prefix_id="w", name_id="1")
reg_d1 = RegisterOperand(PREFIX_ID="d", NAME_ID="1") reg_d1 = registerOperand(prefix_id="d", name_id="1")
reg_q1 = RegisterOperand(PREFIX_ID="q", NAME_ID="1") reg_q1 = registerOperand(prefix_id="q", name_id="1")
reg_v1 = RegisterOperand(PREFIX_ID="v", NAME_ID="1", LANES="2", SHAPE="d") reg_v1 = registerOperand(prefix_id="v", name_id="1", lanes="2", shape="d")
regs = [reg_d1, reg_q1, reg_v1] regs = [reg_d1, reg_q1, reg_v1]
regs_gp = [reg_w1, reg_x1] regs_gp = [reg_w1, reg_x1]
@@ -671,11 +668,11 @@ class TestSemanticTools(unittest.TestCase):
def test_MachineModel_getter(self): def test_MachineModel_getter(self):
sample_operands = [ sample_operands = [
MemoryOperand( memoryOperand(
OFFSET_ID=None, offset_ID=None,
BASE_ID=RegisterOperand(NAME_ID="r12"), base_id=registerOperand(name_id="r12"),
INDEX_ID=RegisterOperand(NAME_ID="rcx"), index_id=registerOperand(name_id="rcx"),
SCALE_ID=8, scale_id=8,
) )
] ]
self.assertIsNone(self.machine_model_csx.get_instruction("GETRESULT", sample_operands)) self.assertIsNone(self.machine_model_csx.get_instruction("GETRESULT", sample_operands))