Pigeon Computer 0.1 documentation

pigeon.assembler.util

Contents

Source code for pigeon.assembler.util

import logging
log = logging.getLogger(__name__)
from struct import pack
from functools import wraps
from myhdl import intbv, concat


ADDRESS_MAX = 0x3fff


def update(a, b):
  '''
  In-place update of an intbv with the value of another one.
  '''
  for n in range(len(a)):
    a[n] = b[n]


def int2addr(i):
  return intbv(i, min=0, max=ADDRESS_MAX+1)


def low(i):
  i = ibv(i)
  return i[8:]


def high(i):
  i = ibv(i)
  return i[16:8]


def ibv(i):
  if isinstance(i, (int, long)):
    return intbv(i)
  if not isinstance(i, intbv):
    raise ValueError
  return i


def compute_dw(values):
  accumulator = []
  for value in values:
    accumulator.append(pack('H', value))
  return ''.join(accumulator)


def compute_db(values):
  accumulator = []
  for value in values:
    if isinstance(value, str):
      accumulator.append(value)
    elif isinstance(value, int):
      accumulator.append(pack('B', value))
  data = ''.join(accumulator)
  if len(data) % 2:
    data = data + '\0'
  return data


def instr(method):
  op = method.__name__

  @wraps(method)
  def inner(self, arg0=None, arg1=None):
    addr = self._get_here()

    if arg0 is None:
      assert arg1 is None
      log.debug('assembling %s instruction at %s', op, addr)
      instruction = (op,)
      method(self)

    elif arg1 is not None:
      arg0, arg1 = method(self, arg0, arg1)
      tname, taddress = self._name_or_addr(arg0)
      name, address = self._name_or_addr(arg1)
      log.debug('assembling %s instruction at %s %s <- %s', op, addr, tname, name)
      instruction = (op, taddress, address)

    else:
      arg0 = method(self, arg0)
      name, address = self._name_or_addr(arg0)
      log.debug('assembling %s instruction at %s to %s', op, addr, name)
      instruction = (op, address)

    self.data[addr] = instruction
    self.here += 2

  return inner


def spec(method):
  @wraps(method)
  def inner(self, ptr, register):
    op = method.__name__
    if ptr == 26:
      op = op + '_X'
    elif ptr == 28:
      op = op + '_Y'
    elif ptr == 30:
      op = op + '_Z'
    else:
      raise Exception("Invalid target for %s: %#x" % (op, ptr,))
    self._one(op, register)
  return inner


def spec_reversed(method):
  method = spec(method)
  @wraps(method)
  def inner(self, ptr, register):
    return method(self, register, ptr)
  return inner


def A(func):
  @wraps(func)
  def inner(address):
    return K(func.__doc__, k=address >> 1)
  return inner


def B(func):
  @wraps(func)
  def inner(register, address):
    return K(func.__doc__, d=register, k=address >> 1)
  return inner


def B_reversed(func):
  @wraps(func)
  def inner(address, register):
    return K(func.__doc__, d=register, k=address >> 1)
  return inner


def C(func):
  @wraps(func)
  def inner(io_port, register):
    return K(func.__doc__, a=io_port, r=register)
  return inner


def D(func):
  @wraps(func)
  def inner(Rd, Rr):
    return K(func.__doc__, d=Rd, r=Rr)
  return inner


def E(func):
  @wraps(func)
  def inner(Rr, bit):
    return K(func.__doc__, r=Rr, b=bit)
  return inner


def F(func):
  @wraps(func)
  def inner(Rr):
    return K(func.__doc__, r=Rr)
  return inner


def G(func):
  @wraps(func)
  def inner(Rd):
    return K(func.__doc__, d=Rd)
  return inner


def H(func):
  @wraps(func)
  def inner(register, bit):
    return K(func.__doc__, A=register, b=bit)
  return inner


[docs]def K(pattern, **values): counts = dict((variable_letter, 0) for variable_letter in values) p = ''.join(pattern.lower().split())[::-1] n = len(p) assert n in (16, 32), repr(pattern) accumulator = [] for i, bit in enumerate(p): if bit in '10': accumulator.append(bool(int(bit))) continue assert bit in values, repr((i, bit, values)) index, value = counts[bit], values[bit] counts[bit] += 1 bit = value[index] accumulator.append(bit) data = concat(*reversed(accumulator)) return n, data

Contents