Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ba3e3308eab6
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 18224141f496
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on Mar 8, 2019

  1. Copy the full SHA
    7c4be81 View commit details
  2. Copy the full SHA
    1822414 View commit details
3 changes: 2 additions & 1 deletion software/glasgow/arch/arc/core.py
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@
AUX_AUX_USER_SP_addr = 0x0d
AUX_INT_VECTOR_BASE_addr = 0x25

AUX_STATUS32 = Bitfield("AUX_STATUS32", 4, [
AUX_STATUS32 = Bitfield("AUX_STATUS32", 32, [
("H", 1),
("E1", 1),
("E2", 1),
@@ -38,6 +38,7 @@
("U", 1),
(None, 4),
("L", 1),
(None, 19),
])

# Build Configuration Registers
6 changes: 3 additions & 3 deletions software/glasgow/arch/arc/jtag.py
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@

# DR values

DR_STATUS = Bitfield("DR_STATUS", 1, [
DR_STATUS = Bitfield("DR_STATUS", 4, [
("ST", 1),
("FL", 1),
("RD", 1),
@@ -45,10 +45,10 @@
DR_TXN_COMMAND_READ_CORE = bitarray("1010", endian="little")
DR_TXN_COMMAND_READ_AUX = bitarray("0110", endian="little")

DR_ADDRESS = Bitfield("DR_ADDRESS", 4, [
DR_ADDRESS = Bitfield("DR_ADDRESS", 32, [
("Address", 32),
])

DR_DATA = Bitfield("DR_DATA", 4, [
DR_DATA = Bitfield("DR_DATA", 32, [
("Data", 32),
])
11 changes: 7 additions & 4 deletions software/glasgow/arch/arc/mec16xx.py
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
"Flash_Config",
]

DR_RESET_TEST = Bitfield("DR_RESET_TEST", 4, [
DR_RESET_TEST = Bitfield("DR_RESET_TEST", 32, [
# Probably ME. It seems to work for me, but none of SMSC documents ever coherently point
# to a single DR with the ME bit *or* specify the location of the ME bit. Cursed.
("ME", 1),
@@ -41,20 +41,21 @@
Flash_Config_addr = Flash_base_addr + 0x110
Flash_Init_addr = Flash_base_addr + 0x114

Flash_Command = Bitfield("Flash_Command", 4, [
Flash_Command = Bitfield("Flash_Command", 32, [
("Flash_Mode", 2),
("Burst", 1),
("EC_Int", 1),
(None, 4),
("Reg_Ctl", 1),
(None, 23),
])

Flash_Mode_Standby = 0
Flash_Mode_Read = 1
Flash_Mode_Program = 2
Flash_Mode_Erase = 3

Flash_Status = Bitfield("Flash_Status", 4, [
Flash_Status = Bitfield("Flash_Status", 32, [
("Busy", 1),
("Data_Full", 1),
("Address_Full", 1),
@@ -66,9 +67,10 @@
("Busy_Err", 1),
("CMD_Err", 1),
("Protect_Err", 1),
(None, 21),
])

Flash_Config = Bitfield("Flash_Config", 4, [
Flash_Config = Bitfield("Flash_Config", 32, [
("Reg_Ctl_En", 1),
("Host_Ctl", 1),
("Boot_Lock", 1),
@@ -79,4 +81,5 @@
("EEPROM_Access", 1),
("EEPROM_Protect", 1),
("EEPROM_Force_Block", 1),
(None, 21),
])
2 changes: 1 addition & 1 deletion software/glasgow/arch/jtag.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
]


DR_IDCODE = Bitfield("DR_IDCODE", 4, [
DR_IDCODE = Bitfield("DR_IDCODE", 32, [
("present", 1),
("mfg_id", 11),
("part_id", 16),
9 changes: 5 additions & 4 deletions software/glasgow/arch/mips/core.py
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@

# CP0 Config layout

CP0_Config = Bitfield("CP0_Config", 4, [
CP0_Config = Bitfield("CP0_Config", 32, [
("K0", 3),
(None, 4),
("MT", 3),
@@ -93,7 +93,7 @@

# CP0 Config1 layout

CP0_Config1 = Bitfield("CP0_Config1", 4, [
CP0_Config1 = Bitfield("CP0_Config1", 32, [
("FP", 1),
("EP", 1),
("CA", 1),
@@ -113,7 +113,7 @@

# CP0 Debug layout

CP0_Debug = Bitfield("CP0_Debug", 4, [
CP0_Debug = Bitfield("CP0_Debug", 32, [
("DSS", 1),
("DBp", 1),
("DDBL", 1),
@@ -144,9 +144,10 @@

# CP0 Debug2 layout

CP0_Debug2 = Bitfield("CP0_Debug2", 4, [
CP0_Debug2 = Bitfield("CP0_Debug2", 32, [
("PaCo", 1),
("Tup", 1),
("DQ", 1),
("Prm", 1),
(None, 28),
])
14 changes: 7 additions & 7 deletions software/glasgow/arch/mips/ejtag.py
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@

# IMPCODE DR layout

DR_IMPCODE = Bitfield("DR_IMPCODE", 4, [
DR_IMPCODE = Bitfield("DR_IMPCODE", 32, [
("MIPS32_64", 1),
("TypeInfo", 10),
("Type", 3),
@@ -71,7 +71,7 @@

# CONTROL DR layout

DR_CONTROL = Bitfield("DR_CONTROL", 4, [
DR_CONTROL = Bitfield("DR_CONTROL", 32, [
(None, 3),
("DM", 1),
(None, 1),
@@ -142,7 +142,7 @@ def DRSEG_DBVn_addr_v1(n): return DRSEG_addr + 0x020c + 0x10 * n

# DRSEG DCR layout

DRSEG_DCR = Bitfield("DRSEG_DCR", 4, [
DRSEG_DCR = Bitfield("DRSEG_DCR", 32, [
("ProbEn", 1),
("SRstE", 1),
("NMIpend", 1),
@@ -174,7 +174,7 @@ def DRSEG_DBVn_addr_v1(n): return DRSEG_addr + 0x020c + 0x10 * n

# DRSEG IBS layout

DRSEG_IBS = Bitfield("DRSEG_IBS", 4, [
DRSEG_IBS = Bitfield("DRSEG_IBS", 32, [
("BS", 15),
("IBPshare", 1),
(None, 8),
@@ -186,7 +186,7 @@ def DRSEG_DBVn_addr_v1(n): return DRSEG_addr + 0x020c + 0x10 * n

# DRSEG IBC layout

DRSEG_IBC = Bitfield("DRSEG_IBC", 4, [
DRSEG_IBC = Bitfield("DRSEG_IBC", 32, [
("BE", 1),
(None, 1),
("TE", 1),
@@ -202,7 +202,7 @@ def DRSEG_DBVn_addr_v1(n): return DRSEG_addr + 0x020c + 0x10 * n

# DRSEG DBS layout

DRSEG_DBS = Bitfield("DRSEG_DBS", 4, [
DRSEG_DBS = Bitfield("DRSEG_DBS", 32, [
("BS", 15),
("DBPshare", 1),
(None, 8),
@@ -215,7 +215,7 @@ def DRSEG_DBVn_addr_v1(n): return DRSEG_addr + 0x020c + 0x10 * n

# DRSEG DBC layout

DRSEG_DBC = Bitfield("DRSEG_DBC", 4, [
DRSEG_DBC = Bitfield("DRSEG_DBC", 32, [
("BE", 1),
("IVM", 1),
("TE", 1),
6 changes: 3 additions & 3 deletions software/glasgow/arch/xilinx/xc9500xl.py
Original file line number Diff line number Diff line change
@@ -37,19 +37,19 @@
IR_BYPASS = bitarray("11111111", endian="little") # BYPASS[1]


DR_ISDATA = Bitfield("DR_ISDATA", 5, [
DR_ISDATA = Bitfield("DR_ISDATA", 34, [
("valid", 1),
("strobe", 1),
("data", 32),
])

DR_ISADDRESS = Bitfield("DR_ISADDRESS", 3, [
DR_ISADDRESS = Bitfield("DR_ISADDRESS", 18, [
("valid", 1),
("strobe", 1),
("address", 16),
])

DR_ISCONFIGURATION = Bitfield("DR_ISCONFIGURATION", 7, [
DR_ISCONFIGURATION = Bitfield("DR_ISCONFIGURATION", 50, [
("valid", 1),
("strobe", 1),
("data", 32),
18 changes: 9 additions & 9 deletions software/glasgow/protocol/sfdp.py
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ def jedec_revision(self):
return "unknown JESD216 revision"


_JEDEC_Flash_Param_0 = Bitfield("JEDEC_Flash_Param_0", 4, [
_JEDEC_Flash_Param_0 = Bitfield("JEDEC_Flash_Param_0", 32, [
("block_sector_erase_size", 2),
("write_granularity", 1),
("volatile_wren_required", 1),
@@ -46,12 +46,12 @@ def jedec_revision(self):
(None, 9),
])

_JEDEC_Flash_Param_1 = Bitfield("JEDEC_Flash_Param_1", 4, [
_JEDEC_Flash_Param_1 = Bitfield("JEDEC_Flash_Param_1", 32, [
("density_value", 31),
("density_over_2gbit", 1),
])

_JEDEC_Flash_Param_2 = Bitfield("JEDEC_Flash_Param_2", 4, [
_JEDEC_Flash_Param_2 = Bitfield("JEDEC_Flash_Param_2", 32, [
("_fast_read_1_4_4_wait_states", 5),
("_fast_read_1_4_4_mode_bits", 3),
("_fast_read_1_4_4_opcode", 8),
@@ -60,7 +60,7 @@ def jedec_revision(self):
("_fast_read_1_1_4_opcode", 8),
])

_JEDEC_Flash_Param_3 = Bitfield("JEDEC_Flash_Param_3", 4, [
_JEDEC_Flash_Param_3 = Bitfield("JEDEC_Flash_Param_3", 32, [
("_fast_read_1_1_2_wait_states", 5),
("_fast_read_1_1_2_mode_bits", 3),
("_fast_read_1_1_2_opcode", 8),
@@ -69,35 +69,35 @@ def jedec_revision(self):
("_fast_read_1_2_2_opcode", 8),
])

_JEDEC_Flash_Param_4 = Bitfield("JEDEC_Flash_Param_4", 4, [
_JEDEC_Flash_Param_4 = Bitfield("JEDEC_Flash_Param_4", 32, [
("has_2_2_2_fast_read", 1),
(None, 3),
("has_4_4_4_fast_read", 1),
(None, 27),
])

_JEDEC_Flash_Param_5 = Bitfield("JEDEC_Flash_Param_5", 4, [
_JEDEC_Flash_Param_5 = Bitfield("JEDEC_Flash_Param_5", 32, [
(None, 16),
("_fast_read_2_2_2_wait_states", 5),
("_fast_read_2_2_2_mode_bits", 3),
("_fast_read_2_2_2_opcode", 8),
])

_JEDEC_Flash_Param_6 = Bitfield("JEDEC_Flash_Param_6", 4, [
_JEDEC_Flash_Param_6 = Bitfield("JEDEC_Flash_Param_6", 32, [
(None, 16),
("_fast_read_4_4_4_wait_states", 5),
("_fast_read_4_4_4_mode_bits", 3),
("_fast_read_4_4_4_opcode", 8),
])

_JEDEC_Flash_Param_7 = Bitfield("JEDEC_Flash_Param_7", 4, [
_JEDEC_Flash_Param_7 = Bitfield("JEDEC_Flash_Param_7", 32, [
("sector_type_1_size", 8),
("sector_type_1_opcode", 8),
("sector_type_2_size", 8),
("sector_type_2_opcode", 8),
])

_JEDEC_Flash_Param_8 = Bitfield("JEDEC_Flash_Param_8", 4, [
_JEDEC_Flash_Param_8 = Bitfield("JEDEC_Flash_Param_8", 32, [
("sector_type_3_size", 8),
("sector_type_3_opcode", 8),
("sector_type_4_size", 8),
291 changes: 206 additions & 85 deletions software/glasgow/support/bits.py
Original file line number Diff line number Diff line change
@@ -1,173 +1,294 @@
import sys
import types
import unittest
from collections import OrderedDict
from bitarray import bitarray
from ctypes import c_ubyte, c_uint64, LittleEndianStructure, Union


__all__ = ["Bitfield"]


class _PackedUnion(Union):
class _Bitfield:
@staticmethod
def _check_bytes(action, expected_length, value):
if len(value) != expected_length:
raise ValueError("%s requires %d-byte array, got %d-byte (%s)"
% (action, expected_length, len(value), value.hex()))

@staticmethod
def _check_bitarray(action, expected_width, value):
assert isinstance(value, bitarray)
if value.length() != expected_width:
raise ValueError("%s requires %d-bit bitarray, got %d-bit (%s)"
% (action, expected_width, len(value), value.to01()))

@staticmethod
def _check_integer(action, expected_width, value):
assert isinstance(value, int)
if value < 0:
raise ValueError("%s requires a non-negative integer, got %d"
% (action, value))
if value.bit_length() > expected_width:
raise ValueError("%s requires a %d-bit integer, got %d-bit (%d)"
% (action, expected_width, value.bit_length(), value))

@classmethod
def from_int(cls, data):
pack = cls()
pack._int_ = data
return pack
def _define_fields(cls, size_bits, fields):
total_width = sum(width for name, width in fields)
if total_width != size_bits:
raise TypeError("declared total width is %d bits, but sum of field widths is %d bits"
% (total_width, size_bits))

cls._size_bits = size_bits
cls._size_bytes = (size_bits + 7) // 8
cls._named_fields = []
cls._widths = OrderedDict()

bit = 0
for name, width in fields:
if name is None:
name = "_padding_%d" % bit
else:
cls._named_fields.append(name)

cls._define_field(name, bit, width)
bit += width

@classmethod
def from_bytes(cls, data):
data = bytes(data)
pack = cls()
pack._bytes_[:] = data
return pack
def _define_field(cls, name, start, width):
cls._widths[name] = width
end = start + width
num_bytes = (width + 7) // 8

@property
def getter(self):
return int.from_bytes(self._bits[start:end].tobytes(), "little")

@getter.setter
def setter(self, value):
if isinstance(value, bitarray):
cls._check_bitarray("field assignment", width, value)
self._bits[start:end] = b
else:
cls._check_integer("field assignment", width, value)
b = bitarray(endian="little")
b.frombytes(value.to_bytes(num_bytes, "little"))
self._bits[start:end] = b[:width]

setattr(cls, name, setter)

@classmethod
def from_bytearray(cls, data):
data = bytearray(data)
def from_bitarray(cls, value):
cls._check_bitarray("initialization", cls._size_bits, value)
# Bitarray copy is byte-wise, so endianness of input matters for fractional byte bitarrays.
assert value.endian() == "little"
pack = cls()
pack._bytes_[:] = data
pack._bits = bitarray(value, endian="little")
return pack

@classmethod
def from_bitarray(cls, data):
data = bitarray(data, endian="little")
return cls.from_bytes(data.tobytes())

def __init__(self, *args, **kwargs):
_, bits_cls = self._fields_[0]

arg_index = 0
fields = {}
for f_name, f_type, f_width in bits_cls._fields_:
if arg_index == len(args):
break
def from_bytes(cls, value):
cls._check_bytes("initialization", cls._size_bytes, value)
b = bitarray(endian="little")
b.frombytes(value)
return cls.from_bitarray(b[:cls._size_bits])

if not f_name.startswith("_reserved_"):
assert f_name not in fields
fields[f_name] = args[arg_index]
arg_index += 1
@classmethod
def from_bytearray(cls, value):
return cls.from_bytes(bytes(value))

fields.update(kwargs)
@classmethod
def from_int(cls, value):
cls._check_integer("initialization", cls._size_bits, value)
return cls.from_bytes(value.to_bytes(cls._size_bytes, "little"))

super().__init__(bits_cls(**fields))
@classmethod
def bit_length(cls):
return cls._size_bits

def copy(self):
pack = self.__class__()
pack._bytes_[:] = self._bytes_[:]
return pack
def __init__(self, *args, **kwargs):
self._bits = bitarray(self._size_bits, endian="little")
self._bits.setall(0)

if len(args) + len(kwargs) > len(self._named_fields):
raise TypeError("constructor got %d arguments, but bitfield only has %d fields"
% (len(args) + len(kwargs), len(self._named_fields)))

already_set = set()
for index, value in enumerate(args):
name = self._named_fields[index]
setattr(self, name, value)
already_set.add(name)

for name, value in kwargs.items():
if name not in self._widths:
raise TypeError("keyword argument %s refers to a nonexistent field" % name)
if name in already_set:
raise TypeError("field %s already set by a positional argument" % name)
setattr(self, name, value)

def to_int(self):
return self._int_
def to_bitarray(self):
return bitarray(self._bits, endian="little")

def to_bytes(self):
return bytes(self._bytes_)
return self._bits.tobytes()

def to_bytearray(self):
return bytearray(self._bytes_)
return bytearray(self.to_bytes())

def to_bitarray(self):
data = bitarray(endian="little")
data.frombytes(self.to_bytes())
return data
def to_int(self):
return int.from_bytes(self.to_bytes(), "little")

def bits_repr(self, omit_zero=False):
fields = []
for f_name, f_type, f_width in self._bits_._fields_:
if f_name.startswith("_reserved_"):
continue
def copy(self):
return self.__class__.from_bitarray(self._bits)

f_value = getattr(self._bits_, f_name)
def bits_repr(self, omit_zero=False, omit_padding=True):
fields = []
if omit_padding:
names = self._named_fields
else:
names = self._widths.keys()

for name in names:
width = self._widths[name]
value = getattr(self, name)
if omit_zero and not f_value:
continue

fields.append("{}={:0{}b}".format(f_name, f_value, f_width))
fields.append("{}={:0{}b}".format(name, value, width))

return " ".join(fields)

def __repr__(self):
return "<{}.{} {}>".format(self.__module__, self.__class__.__name__, self.bits_repr())

def __eq__(self, other):
return self._bytes_[:] == other._bytes_[:]
return self._bits[:] == other._bits[:]

def __ne__(self, other):
return self._bytes_[:] != other._bytes_[:]
return self._bits[:] != other._bits[:]


def Bitfield(name, size_bytes, fields):
def Bitfield(name, size_bits, fields):
mod = sys._getframe(1).f_globals["__name__"] # see namedtuple()

reserved = 0
def make_reserved():
nonlocal reserved
reserved += 1
return "_reserved_{}".format(reserved)
cls = types.new_class(name, (_Bitfield,))
cls.__module__ = mod
cls._define_fields(size_bits, fields)

bits_cls = types.new_class(name + "_bits_", (LittleEndianStructure,))
bits_cls.__module__ = mod
bits_cls._packed_ = True
bits_cls._fields_ = [(make_reserved() if f_name is None else f_name, c_uint64, f_width)
for f_name, f_width in fields]

pack_cls = types.new_class(name, (_PackedUnion,))
pack_cls.__module__ = mod
pack_cls._packed_ = True
pack_cls._anonymous_ = ("_bits_",)
pack_cls._fields_ = [("_bits_", bits_cls),
("_bytes_", c_ubyte * size_bytes),
("_int_", c_uint64)]

return pack_cls
return cls

# -------------------------------------------------------------------------------------------------

class BitfieldTestCase(unittest.TestCase):
def test_definition(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 10, [("a", 3), ("b", 5), (None, 2)])
self.assertEqual(bf.__name__, "bf")
self.assertEqual(bf.__module__, __name__)
x = bf(1, 2)
self.assertEqual(x.a, 1)
self.assertEqual(x.b, 2)
self.assertEqual(bf.bit_length(), 10)
self.assertEqual(x.bit_length(), 10)

def test_misuse(self):
with self.assertRaises(TypeError):
Bitfield("bf", 10, [("a", 3), ("b", 5)])

bf = Bitfield("bf", 10, [("a", 3), ("b", 5), (None, 2)])

with self.assertRaises(TypeError):
bf(1, 2, b=3)

with self.assertRaises(TypeError):
bf(c=3)

x = bf()
with self.assertRaises(ValueError):
x.a = -1
with self.assertRaises(ValueError):
x.a = 8
with self.assertRaises(ValueError):
x.a = bitarray("1")
with self.assertRaises(ValueError):
x.a = bitarray("1111")

with self.assertRaises(ValueError):
bf.from_bytes(bytes(3))
with self.assertRaises(ValueError):
bf.from_bytes(bytes(1))
with self.assertRaises(ValueError):
bf.from_bytearray(bytes(3))
with self.assertRaises(ValueError):
bf.from_bytearray(bytes(1))
with self.assertRaises(ValueError):
bf.from_bitarray(bitarray(9))
with self.assertRaises(ValueError):
bf.from_bitarray(bitarray(11))
with self.assertRaises(ValueError):
bf.from_int(-1)
with self.assertRaises(ValueError):
bf.from_int(1<<10)

def test_kwargs(self):
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x = bf(a=1, b=2)
self.assertEqual(x.a, 1)
self.assertEqual(x.b, 2)

def test_large(self):
bf = Bitfield("bf", 8, [("a", 64)])
bf = Bitfield("bf", 72, [(None, 8), ("a", 64)])
val = (3 << 62) + 1
x = bf(val)
self.assertEqual(x.to_int(), val << 8)

def test_huge(self):
bf = Bitfield("bf", 2080, [("e", 32), ("m", 2048)])
x = bf(65537, (30<<2048) // 31)
self.assertEqual(x.e, 65537)
self.assertEqual(x.m, (30<<2048) // 31)

def test_reserved(self):
bf = Bitfield("bf", 8, [(None, 1), ("a", 1)])
bf = Bitfield("bf", 64, [(None, 1), ("a", 1), (None, 62)])
x = bf(1)
self.assertEqual(repr(x), "<%s.bf a=1>" % __name__)

def test_bytes(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x = bf(1, 2)
self.assertIsInstance(x.to_bytes(), bytes)
self.assertEqual(x.to_bytes(), b"\x11\x00")
self.assertEqual(x.to_bytes(), b"\x11")
self.assertEqual(bf.from_bytes(x.to_bytes()), x)

def test_bytearray(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x = bf(1, 2)
self.assertIsInstance(x.to_bytearray(), bytearray)
self.assertEqual(x.to_bytearray(), bytearray(b"\x11\x00"))
self.assertEqual(x.to_bytearray(), bytearray(b"\x11"))
self.assertEqual(bf.from_bytearray(x.to_bytearray()), x)

def test_int(self):
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x = bf(1, 2)
self.assertIsInstance(x.to_int(), int)
self.assertEqual(x.to_int(), 17)
self.assertEqual(bf.from_int(x.to_int()), x)

def test_bitaray(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 10, [("a", 3), ("b", 7)])
x = bf(1, 2)
self.assertIsInstance(x.to_bitarray(), bitarray)
self.assertEqual(x.to_bitarray().endian(), "little")
self.assertEqual(x.to_bitarray(), bitarray(b"1000100000000000", endian="little"))
self.assertEqual(x.to_bitarray(), bitarray(b"1000100000", endian="little"))
self.assertEqual(bf.from_bitarray(x.to_bitarray()), x)

def test_repr(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x = bf(1, 2)
self.assertEqual(repr(x), "<%s.bf a=001 b=00010>" % __name__)

def test_copy(self):
bf = Bitfield("bf", 2, [("a", 3), ("b", 5)])
bf = Bitfield("bf", 8, [("a", 3), ("b", 5)])
x1 = bf(1, 2)
x2 = x1.copy()
self.assertFalse(x1 is x2)