Skip to content

Commit

Permalink
Merge 353099d into f0b5ff4
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardt committed Mar 20, 2019
2 parents f0b5ff4 + 353099d commit bb2798a
Show file tree
Hide file tree
Showing 73 changed files with 1,403 additions and 427 deletions.
19 changes: 17 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: python
python:
- '3.6'
# python managed by conda until 3.7 available
# python:
# - '3.6'
addons:
apt:
sources:
Expand All @@ -11,9 +12,23 @@ addons:
before_install:
- source .travis/install_coreir.sh
install:
# install conda for py 3.7
- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
- chmod +x miniconda.sh
- ./miniconda.sh -b -p $TRAVIS_BUILD_DIR/miniconda
- export PATH=$TRAVIS_BUILD_DIR/miniconda/bin:$PATH
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda create -q -n test-env python=3.7
- source activate test-env
- conda install pip
# End install conda

- pip install python-coveralls
- pip install pytest-cov pytest-codestyle
- pip install -r requirements.txt
- pip install fault
- pip install -e .
after_success:
- coveralls
Expand Down
13 changes: 13 additions & 0 deletions magma/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,16 @@ def set_mantle_target(t):

from .is_primitive import isprimitive
from .is_definition import isdefinition

from .product import Product


from hwtypes.bit_vector_abc import TypeFamily


BitVector = Bits
UIntVector = UInt
SIntVector = SInt
_Family_ = TypeFamily(Bit, BitVector, UIntVector, SIntVector)
def get_family():
return _Family_
148 changes: 96 additions & 52 deletions magma/array.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,115 @@
from collections import Sequence
from .bitutils import int2seq
from .ref import AnonRef, ArrayRef
from .t import Type, Kind
from .compatibility import IntegerTypes
from .bit import VCC, GND
from .bitutils import seq2int
from .debug import debug_wire, get_callee_frame_info
from .port import report_wiring_error
import weakref

__all__ = ['ArrayType', 'ArrayKind', 'Array']


class ArrayType(Type):
class ArrayKind(Kind):
_class_cache = weakref.WeakValueDictionary()
def __init__(cls, name, bases, dct):
Kind.__init__(cls, name, bases, dct)

def __str__(cls):
return "Array[%d, %s]" % (cls.N, cls.T)

def __getitem__(cls, index):
width, sub_type = index
try:
return ArrayKind._class_cache[width, sub_type]
except KeyError:
pass
bases = [cls]
bases = tuple(bases)
class_name = '{}[{}, {}]'.format(cls.__name__, width, sub_type.__name__)
t = type(cls)(class_name, bases, dict(N=width, T=sub_type))
t.__module__ = cls.__module__
ArrayKind._class_cache[width, sub_type] = t
return t

def __eq__(cls, rhs):
if not issubclass(type(rhs), ArrayKind):
return False

if cls.N != rhs.N:
return False
if cls.T != rhs.T:
return False

return True

__ne__ = Kind.__ne__
__hash__ = Kind.__hash__

def __len__(cls):
return cls.N

# def __getitem__(cls, key):
# if isinstance(key, slice):
# return array([cls[i] for i in range(*key.indices(len(cls)))])
# else:
# if not (0 <= key and key < cls.N):
# raise IndexError

# return cls.ts[key]

def size(cls):
return cls.N * cls.T.size()

def qualify(cls, direction):
if cls.T.isoriented(direction):
return cls
return Array[cls.N, cls.T.qualify(direction)]

def flip(cls):
return Array[cls.N, cls.T.flip()]

def __call__(cls, *args, **kwargs):
result = super().__call__(*args, **kwargs)
if len(args) == 1 and isinstance(args[0], Array):
arg = args[0]
if len(arg) < len(result):
from .conversions import zext
arg = zext(arg, len(result) - len(arg))
result(arg)
return result


class Array(Type, metaclass=ArrayKind):
def __init__(self, *largs, **kwargs):

Type.__init__(self, **kwargs)

if isinstance(largs, Sequence) and len(largs) > 0:
assert len(largs) == self.N
if isinstance(largs, Sequence) and len(largs) == self.N:
self.ts = []
for t in largs:
if isinstance(t, IntegerTypes):
t = VCC if t else GND
assert type(t) == self.T, (type(t), self.T)
self.ts.append(t)
elif len(largs) == 1 and isinstance(largs[0], int):
self.ts = []
for bit in int2seq(largs[0], self.N):
self.ts.append(VCC if bit else GND)
elif len(largs) == 1 and isinstance(largs[0], Array):
assert len(largs[0]) <= self.N
T = self.T
self.ts = list(type(t)() for t in largs[0])
if len(largs[0]) < self.N:
self.ts += [self.T() for _ in range(self.N - len(largs[0]))]
elif len(largs) == 1 and isinstance(largs[0], list):
assert len(largs[0]) <= self.N
T = self.T
self.ts = largs[0][:]
if len(largs[0]) < self.N:
self.ts += [self.T() for _ in range(self.N - len(largs[0]))]
else:
self.ts = []
for i in range(self.N):
Expand Down Expand Up @@ -170,56 +257,13 @@ def flatten(self):
return sum([t.flatten() for t in self.ts], [])


class ArrayKind(Kind):
def __init__(cls, name, bases, dct):
Kind.__init__(cls, name, bases, dct)

def __str__(cls):
return "Array(%d,%s)" % (cls.N, cls.T)

def __eq__(cls, rhs):
if not isinstance(rhs, ArrayKind):
return False

if cls.N != rhs.N:
return False
if cls.T != rhs.T:
return False

return True

__ne__ = Kind.__ne__
__hash__ = Kind.__hash__

def __len__(cls):
return cls.N

def __getitem__(cls, key):
if isinstance(key, slice):
return array([cls[i] for i in range(*key.indices(len(cls)))])
else:
if not (0 <= key and key < cls.N):
raise IndexError

return cls.ts[key]

def size(cls):
return cls.N * cls.T.size()

def qualify(cls, direction):
if cls.T.isoriented(direction):
return cls
return Array(cls.N, cls.T.qualify(direction))

def flip(cls):
return Array(cls.N, cls.T.flip())

# def Array(N, T):
# assert isinstance(N, IntegerTypes)
# assert isinstance(T, Kind)
# name = 'Array(%d,%s)' % (N, str(T))
# return ArrayKind(name, (ArrayType,), dict(N=N, T=T))

def Array(N, T):
assert isinstance(N, IntegerTypes)
assert isinstance(T, Kind)
name = 'Array(%d,%s)' % (N, str(T))
return ArrayKind(name, (ArrayType,), dict(N=N, T=T))
ArrayType = Array


# Workaround for circular dependency
Expand Down
13 changes: 10 additions & 3 deletions magma/ast_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import typing
import astor
import traceback
import functools


def get_ast(obj):
Expand Down Expand Up @@ -59,12 +60,18 @@ def inspect_enclosing_env(fn):
* Maintain the stack hierarchy. Again, not currently used, but could be
useful.
"""
@functools.wraps(fn)
def wrapped(*args, **kwargs):
stack = inspect.stack()
enclosing_env = {}
for i in range(1, len(stack)):
enclosing_env.update(stack[i].frame.f_locals)
enclosing_env.update(stack[i].frame.f_globals)
for i in range(0, len(stack)):
for key, value in stack[i].frame.f_locals.items():
if key not in enclosing_env:
enclosing_env[key] = value
for i in range(0, len(stack)):
for key, value in stack[i].frame.f_globals.items():
if key not in enclosing_env:
enclosing_env[key] = value
return fn(enclosing_env, *args, **kwargs)
return wrapped

Expand Down
6 changes: 4 additions & 2 deletions magma/backend/coreir_.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ def magma_port_to_coreir(port):
name = get_top_name(name)
if isinstance(name, DefnRef):
if name.defn.name != "":
select = select.replace(name.defn.name, "self")
select_list = select.split(".")
select_list[0] = "self"
select = ".".join(select_list)

return select.replace("[", ".").replace("]", "")

Expand Down Expand Up @@ -152,7 +154,7 @@ def get_ports(self, coreir_type):
elif (coreir_type.kind == "BitIn"):
return BitIn
elif (coreir_type.kind == "Array"):
return Array(len(coreir_type), self.get_ports(coreir_type.element_type))
return Array[len(coreir_type), self.get_ports(coreir_type.element_type)]
elif (coreir_type.kind == "Record"):
elements = {}
for item in coreir_type.items():
Expand Down
14 changes: 14 additions & 0 deletions magma/bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ def __init__(cls, name, bases, dct):
if not hasattr(cls, 'direction'):
cls.direction = None

def __call__(cls, value=None, *args, **kwargs):
if value is not None:
if isinstance(value, (bool, IntegerTypes)):
return VCC if value else GND
result = super().__call__(*args, **kwargs)
if value is not None:
assert isinstance(value, BitType), type(value)
result(value)
return result

def __eq__(cls, rhs):
if not isinstance(rhs, _BitKind):
return False
Expand Down Expand Up @@ -131,6 +141,10 @@ def qualify(cls, direction):
def flip(cls):
pass

def get_family(cls):
import magma as m
return m.get_family()


class BitType(_BitType):
__hash__ = Type.__hash__
Expand Down

0 comments on commit bb2798a

Please sign in to comment.