Source code for microprobe.passes.float

# Copyright 2011-2021 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""":mod:`microprobe.passes.float` module

"""

# Futures
from __future__ import absolute_import

# Own modules
import microprobe.code.var
import microprobe.passes
from microprobe.code.address import Address, MemoryValue
from microprobe.exceptions import MicroprobeCodeGenerationError
from microprobe.utils.ieee import ieee_float_to_int64
from microprobe.utils.logger import get_logger

# Constants
LOG = get_logger(__name__)
__all__ = ["InitializeMemoryFloatPass"]

# Functions


# Classes
[docs] class InitializeMemoryFloatPass(microprobe.passes.Pass): """ """
[docs] def __init__(self, value=0): """ :param value: (Default value = 0) """ super().__init__() self._var = microprobe.code.var.VariableSingle( "FP_INITVAL", "double", value=f"{value:.20f}" ) self._varaddress = Address(base_address=self._var) self._value = value self._memvalue = MemoryValue(self._varaddress, value, 8) self._description = ( "Initialize all the memory location accessed by" f" binary floating point operations to value: '{value}'." )
def __call__(self, building_block, target): """ :param building_block: :param target: """ variable_to_declare = False addresses_set = [] # context = building_block.context context = target.wrapper.context() if building_block.context.register_has_value(0): reg = building_block.context.registers_get_value(0)[0] context.set_register_value(reg, 0) for bbl in building_block.cfg.bbls: for instr in bbl.instrs: # if not instr.hfp_exponent_overflow_exception: # continue is_float = False for operand in instr.operands(): if operand.type.float and operand.is_input: is_float = True if not is_float: continue for memoperand in instr.memory_operands(): if memoperand.address is None: continue if memoperand.address in addresses_set: continue if not memoperand.is_load: continue addresses_set.append(memoperand.address) addresses_set = sorted(addresses_set) for address in addresses_set: if variable_to_declare is False: variable_to_declare = True reg2 = target.scratch_registers[0] instrs = target.set_register( reg2, ieee_float_to_int64(self._value), context ) for instr in instrs: instr.add_comment("Initialize reg to float value") building_block.add_init(instrs) context.set_register_value( reg2, ieee_float_to_int64(self._value) ) reg1 = target.scratch_registers[1] instrs = target.set_register_to_address(reg1, address, context) context.set_register_value(reg1, address) building_block.add_init(instrs) try: instrs = target.store_integer(reg2, address, 64, context) except MicroprobeCodeGenerationError: instrs = target.set_register_to_address(reg1, address, context) context.set_register_value(reg1, address) building_block.add_init(instrs) instrs = target.store_integer(reg2, address, 64, context) context.set_memory_value(MemoryValue(address, self._value, 8)) for instr in instrs: instr.add_comment(f"Initialize memory float: {address}") building_block.add_init(instrs) LOG.debug("Instruction: %s: %s", instr.address, instr) LOG.debug("Address: %s", address)
[docs] def check(self, building_block, dummy_target): """ :param building_block: :param dummy_target: """ pass_ok = True for bbl in building_block.cfg.bbls: for instr in bbl.instrs: is_float = False for operand in instr.operands(): if operand.type.float: is_float = True if not is_float: continue for memoperand in instr.memory_operands(): if memoperand.address is None: continue if not memoperand.is_load: continue LOG.debug("Checking memory value: %s", memoperand.address) memory_value = building_block.context.get_memory_value( memoperand.address ) if memory_value is None: LOG.debug("Instruction: %s: %s", instr.address, instr) LOG.debug( "Memory value not present: %s", memoperand.address ) return False if memory_value.address != memoperand.address: LOG.debug( "%s != %s", memory_value.address, memoperand.address, ) return False if memory_value.length != 8: LOG.debug("Invalid length: %s", memory_value.length) return False if memory_value.value != self._value: LOG.debug( "Invalid value: %d != %d", memory_value.value, self._value, ) return False return pass_ok