files.new_contents: #!/usr/bin/env python
  
  # Copyright (c) 2013 Potential Ventures Ltd
  # Copyright (c) 2013 SolarFlare Communications Inc
  # All rights reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions are met:
  #     * Redistributions of source code must retain the above copyright
  #       notice, this list of conditions and the following disclaimer.
  #     * Redistributions in binary form must reproduce the above copyright
  #       notice, this list of conditions and the following disclaimer in the
  #       documentation and/or other materials provided with the distribution.
  #     * Neither the name of Potential Ventures Ltd,
  #       SolarFlare Communications Inc nor the
  #       names of its contributors may be used to endorse or promote products
  #       derived from this software without specific prior written permission.
  #
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
  # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  import os
  import random
  import re
  import warnings
  
  
  _RESOLVE_TO_0      = "-lL"
  _RESOLVE_TO_1      = "hH"
  _RESOLVE_TO_CHOICE = "xXzZuUwW"
  resolve_x_to = os.getenv('COCOTB_RESOLVE_X', "VALUE_ERROR")
  
  
  class _ResolveTable(dict):
      """Translation table class for resolving binary strings.
  
      For use with :func:`str.translate()`, which indexes into table with Unicode ordinals.
      """
      def __init__(self):
          self.update({ord("0"): ord("0"), ord("1"): ord("1")})
          self.update({ord(k): ord("0") for k in _RESOLVE_TO_0})
          self.update({ord(k): ord("1") for k in _RESOLVE_TO_1})
  
          # Do not resolve if resolve_x_to is not set to one of the supported values
          def no_resolve(key):
              return key
          self.resolve_x = no_resolve
  
          if resolve_x_to == "VALUE_ERROR":
              def resolve_error(key):
                  raise ValueError("Unresolvable bit in binary string: '{}'".format(chr(key)))
              self.resolve_x = resolve_error
          elif resolve_x_to == "ZEROS":
              self.update({ord(k): ord("0") for k in _RESOLVE_TO_CHOICE})
          elif resolve_x_to == "ONES":
              self.update({ord(k): ord("1") for k in _RESOLVE_TO_CHOICE})
          elif resolve_x_to == "RANDOM":
              def resolve_random(key):
                  # convert to correct Unicode ordinal:
                  # ord('0') = 48
                  # ord('1') = 49
                  return random.getrandbits(1) + 48
              self.resolve_x = resolve_random
  
          self._resolve_to_choice = {ord(c) for c in _RESOLVE_TO_CHOICE}
  
      def __missing__(self, key):
          if key in self._resolve_to_choice:
              return self.resolve_x(key)
          else:
              return key
  
  
  _resolve_table = _ResolveTable()
  
  
  def resolve(string):
      return string.translate(_resolve_table)
  
  
  def _clog2(val):
      if val < 0:
          raise ValueError("_clog2 can't take a negative")
      exp = 0
      while True:
          if (1 << exp) >= val:
              return exp
          exp += 1
  
  
  class BinaryRepresentation:  # noqa
      UNSIGNED         = 0  #: Unsigned format
      SIGNED_MAGNITUDE = 1  #: Sign and magnitude format
      TWOS_COMPLEMENT  = 2  #: Two's complement format
  
  
  class BinaryValue:
      """Representation of values in binary format.
  
      The underlying value can be set or accessed using these aliasing attributes:
  
          - :attr:`BinaryValue.integer` is an integer
          - :attr:`BinaryValue.signed_integer` is a signed integer
          - :attr:`BinaryValue.binstr` is a string of ``01xXzZ``
          - :attr:`BinaryValue.buff` is a binary buffer of bytes
          - :attr:`BinaryValue.value` is an integer **deprecated**
  
      For example:
  
      >>> vec = BinaryValue()
      >>> vec.integer = 42
      >>> print(vec.binstr)
      101010
      >>> print(vec.buff)
      b'*'
  
      """
      _permitted_chars  = _RESOLVE_TO_0 +_RESOLVE_TO_1 + _RESOLVE_TO_CHOICE + "01"  # noqa
  
      def __init__(self, value=None, n_bits=None, bigEndian=True,
                   binaryRepresentation=BinaryRepresentation.UNSIGNED,
                   bits=None):
          """
          Args:
              value (str or int or long, optional): Value to assign to the bus.
              n_bits (int, optional): Number of bits to use for the underlying
                  binary representation.
              bigEndian (bool, optional): Interpret the binary as big-endian
                  when converting to/from a string buffer.
              binaryRepresentation (BinaryRepresentation): The representation
                  of the binary value
                  (one of :any:`UNSIGNED`, :any:`SIGNED_MAGNITUDE`, :any:`TWOS_COMPLEMENT`).
                  Defaults to unsigned representation.
              bits (int, optional): Deprecated: Compatibility wrapper for :attr:`n_bits`.
          """
          self._str = ""
          self.big_endian = bigEndian
          self.binaryRepresentation = binaryRepresentation
  
          # bits is the deprecated name for n_bits, allow its use for
          # backward-compat reasons.
          if (bits is not None and n_bits is not None):
              raise TypeError("You cannot use n_bits and bits at the same time.")
          if bits is not None:
              warnings.warn(
                  "The bits argument to BinaryValue has been renamed to n_bits",
                  DeprecationWarning, stacklevel=2)
              n_bits = bits
  
          self._n_bits = n_bits
  
          self._convert_to = {
              BinaryRepresentation.UNSIGNED         : self._convert_to_unsigned   ,
              BinaryRepresentation.SIGNED_MAGNITUDE : self._convert_to_signed_mag ,
              BinaryRepresentation.TWOS_COMPLEMENT  : self._convert_to_twos_comp  ,
          }
  
          self._convert_from = {
              BinaryRepresentation.UNSIGNED         : self._convert_from_unsigned   ,
              BinaryRepresentation.SIGNED_MAGNITUDE : self._convert_from_signed_mag ,
              BinaryRepresentation.TWOS_COMPLEMENT  : self._convert_from_twos_comp  ,
          }
  
          if value is not None:
              self.assign(value)
  
      def assign(self, value):
          """Decides how best to assign the value to the vector.
  
          Picks from the type of its argument whether to set :attr:`integer`,
          :attr:`binstr`, or :attr:`buff`.
  
          Args:
              value (str or int or bytes): The value to assign.
  
          .. versionchanged:: 1.4
  
              This no longer falls back to setting :attr:`buff` if a :class:`str`
              containining any characters that aren't ``0``, ``1``, ``X`` or ``Z``
              is used, since :attr:`buff` now accepts only :class:`bytes`. Instead,
              an error is raised.
          """
          if isinstance(value, int):
              self.integer = value
          elif isinstance(value, str):
              self.binstr = value
          elif isinstance(value, bytes):
              self.buff = value
          else:
              raise TypeError(
                  "value must be int, str, or bytes, not {!r}"
                  .format(type(value).__qualname__)
              )
  
      def _convert_to_unsigned(self, x):
          x = bin(x)
          if x[0] == '-':
              raise ValueError('Attempt to assigned negative number to unsigned '
                               'BinaryValue')
          return self._adjust_unsigned(x[2:
  
  [... the rest is omitted ...]
files.new_path: cocotb/binary.py
files.old_contents: #!/usr/bin/env python
  
  # Copyright (c) 2013 Potential Ventures Ltd
  # Copyright (c) 2013 SolarFlare Communications Inc
  # All rights reserved.
  #
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions are met:
  #     * Redistributions of source code must retain the above copyright
  #       notice, this list of conditions and the following disclaimer.
  #     * Redistributions in binary form must reproduce the above copyright
  #       notice, this list of conditions and the following disclaimer in the
  #       documentation and/or other materials provided with the distribution.
  #     * Neither the name of Potential Ventures Ltd,
  #       SolarFlare Communications Inc nor the
  #       names of its contributors may be used to endorse or promote products
  #       derived from this software without specific prior written permission.
  #
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  # DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
  # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  import os
  import random
  import warnings
  
  resolve_x_to = os.getenv('COCOTB_RESOLVE_X', "VALUE_ERROR")
  
  
  def resolve(string):
      for char in BinaryValue._resolve_to_0:
          string = string.replace(char, "0")
      for char in BinaryValue._resolve_to_1:
          string = string.replace(char, "1")
      for char in BinaryValue._resolve_to_error:
          if resolve_x_to == "VALUE_ERROR" and char in string:
              raise ValueError("Unable to resolve to binary >%s<" % string)
          elif resolve_x_to == "ZEROS":
              string = string.replace(char, "0")
          elif resolve_x_to == "ONES":
              string = string.replace(char, "1")
          elif resolve_x_to == "RANDOM":
              bits = "{0:b}".format(random.getrandbits(1))
              string = string.replace(char, bits)
      return string
  
  
  def _clog2(val):
      if val < 0:
          raise ValueError("_clog2 can't take a negative")
      exp = 0
      while True:
          if (1 << exp) >= val:
              return exp
          exp += 1
  
  
  class BinaryRepresentation:  # noqa
      UNSIGNED         = 0  #: Unsigned format
      SIGNED_MAGNITUDE = 1  #: Sign and magnitude format
      TWOS_COMPLEMENT  = 2  #: Two's complement format
  
  
  class BinaryValue:
      """Representation of values in binary format.
  
      The underlying value can be set or accessed using these aliasing attributes:
  
          - :attr:`BinaryValue.integer` is an integer
          - :attr:`BinaryValue.signed_integer` is a signed integer
          - :attr:`BinaryValue.binstr` is a string of ``01xXzZ``
          - :attr:`BinaryValue.buff` is a binary buffer of bytes
          - :attr:`BinaryValue.value` is an integer **deprecated**
  
      For example:
  
      >>> vec = BinaryValue()
      >>> vec.integer = 42
      >>> print(vec.binstr)
      101010
      >>> print(vec.buff)
      b'*'
  
      """
      _resolve_to_0     = "-lL"  # noqa
      _resolve_to_1     = "hH"  # noqa
      _resolve_to_error = "xXzZuUwW"  # Resolve to a ValueError() since these usually mean something is wrong
      _permitted_chars  = _resolve_to_0 +_resolve_to_1 + _resolve_to_error + "01"  # noqa
  
      def __init__(self, value=None, n_bits=None, bigEndian=True,
                   binaryRepresentation=BinaryRepresentation.UNSIGNED,
                   bits=None):
          """
          Args:
              value (str or int or long, optional): Value to assign to the bus.
              n_bits (int, optional): Number of bits to use for the underlying
                  binary representation.
              bigEndian (bool, optional): Interpret the binary as big-endian
                  when converting to/from a string buffer.
              binaryRepresentation (BinaryRepresentation): The representation
                  of the binary value
                  (one of :any:`UNSIGNED`, :any:`SIGNED_MAGNITUDE`, :any:`TWOS_COMPLEMENT`).
                  Defaults to unsigned representation.
              bits (int, optional): Deprecated: Compatibility wrapper for :attr:`n_bits`.
          """
          self._str = ""
          self.big_endian = bigEndian
          self.binaryRepresentation = binaryRepresentation
  
          # bits is the deprecated name for n_bits, allow its use for
          # backward-compat reasons.
          if (bits is not None and n_bits is not None):
              raise TypeError("You cannot use n_bits and bits at the same time.")
          if bits is not None:
              warnings.warn(
                  "The bits argument to BinaryValue has been renamed to n_bits",
                  DeprecationWarning, stacklevel=2)
              n_bits = bits
  
          self._n_bits = n_bits
  
          self._convert_to = {
              BinaryRepresentation.UNSIGNED         : self._convert_to_unsigned   ,
              BinaryRepresentation.SIGNED_MAGNITUDE : self._convert_to_signed_mag ,
              BinaryRepresentation.TWOS_COMPLEMENT  : self._convert_to_twos_comp  ,
          }
  
          self._convert_from = {
              BinaryRepresentation.UNSIGNED         : self._convert_from_unsigned   ,
              BinaryRepresentation.SIGNED_MAGNITUDE : self._convert_from_signed_mag ,
              BinaryRepresentation.TWOS_COMPLEMENT  : self._convert_from_twos_comp  ,
          }
  
          if value is not None:
              self.assign(value)
  
      def assign(self, value):
          """Decides how best to assign the value to the vector.
  
          Picks from the type of its argument whether to set :attr:`integer`,
          :attr:`binstr`, or :attr:`buff`.
  
          Args:
              value (str or int or bytes): The value to assign.
  
          .. versionchanged:: 1.4
  
              This no longer falls back to setting :attr:`buff` if a :class:`str`
              containining any characters that aren't ``0``, ``1``, ``X`` or ``Z``
              is used, since :attr:`buff` now accepts only :class:`bytes`. Instead,
              an error is raised.
          """
          if isinstance(value, int):
              self.integer = value
          elif isinstance(value, str):
              self.binstr = value
          elif isinstance(value, bytes):
              self.buff = value
          else:
              raise TypeError(
                  "value must be int, str, or bytes, not {!r}"
                  .format(type(value).__qualname__)
              )
  
      def _convert_to_unsigned(self, x):
          x = bin(x)
          if x[0] == '-':
              raise ValueError('Attempt to assigned negative number to unsigned '
                               'BinaryValue')
          return self._adjust_unsigned(x[2:])
  
      def _convert_to_signed_mag(self, x):
          x = bin(x)
          if x[0] == '-':
              binstr = self._adjust_signed_mag('1' + x[3:])
          else:
              binstr = self._adjust_signed_mag('0' + x[2:])
          if self.big_endian:
              binstr = binstr[::-1]
          return binstr
  
      def _convert_to_twos_comp(self, x):
          if x < 0:
              binstr = bin(2 ** (_clog2(abs(x)) + 1) + x)[2:]
              binstr = self._adjust_twos_comp(binstr)
          else:
              binstr = self._adjust_twos_comp('0' + bin(x)[2:])
          if self.big_endian:
              binstr = binstr[::-1]
          return binstr
  
      def _convert_from_unsigned(self, x):
          return int(resolve(x), 2)
  
      def _convert_from
  
  [... the rest is omitted ...]
files.old_path: cocotb/binary.py