diff --git a/docs/magma_2_migration_guide.md b/docs/magma_2_migration_guide.md new file mode 100644 index 0000000000..1da5714aa9 --- /dev/null +++ b/docs/magma_2_migration_guide.md @@ -0,0 +1,33 @@ +# Migrating to magma 2 + +* Operator definitions (e.g. `+`, `-`, ...) have moved from mantle to magma. + This should not cause any user facing code changes, but the names of + generated circuits may be different. It also means that coreir primitives + will always be used to implement the operators (before, it would dispatch to + the current mantle target). Support for other mantle targets will be added + later as implementations of the coreir primitives. +* Rename `<..>Type` to `<...>`. No more type constructors (e.g. `ArrayType` + becomes `Array`). Parametrized types are constructed using the bracket + syntax (e.g. `Array[5, Bit]`) +* `isinstance(..., <...>Kind)` -> `issubclass(..., <...>)`. Concrete + parameterized types are subclasses of the abstract type) (e.g. `isinstance(T, + BitsKind)` becomes `issubclass(T, Bits)` +* `_Bit` -> `Digital`. Renamed parent type of Bit, Clock, Reset, ... +* `Tuple(...)` -> `Product.from_fields("anon", dict(...))`. Tuple now refers to + a heterogenous type indexed by position (e.g. x[0], x[1], ...), while Product + is used for the key/value version (e.g. x.a, x.y, ...). Magma previously + used Tuple to represent both versions. This change is in line with the + `hwtypes` `Tuple` and `Product` types (as well as Python's `tuple` vs + `namedtuple`). `"anon"` is the name of the type (before all magma tuples + were "anonymous"). We are considering an interface for declaring + anonymous Products so the user does not have to supply a name. +* `.Ks` -> `.keys()` and `.Ts` -> `.types()` these + attributes were refactored to methods to be more clear/consistent with the + hwtypes tuple. +* `isinput`, `isinout`, `isoutput` renamed to `is_input`, `is_inout`, + `is_output` for clarity + + +See these PRs for examples of these changes +* Mantle: https://github.com/phanrahan/mantle/pull/165 +* Fault: https://github.com/leonardt/fault/pull/187 diff --git a/magma/__init__.py b/magma/__init__.py index 57d67e470c..f77e09acf2 100644 --- a/magma/__init__.py +++ b/magma/__init__.py @@ -30,12 +30,12 @@ def wrapper(*args, **kwargs): # types from .t import * + from .bit import * + from .array import * from .bits import * -# Define default operators that raise exceptions, rename so it doesn't muck -# with `from magma import *` code that also uses operator -import magma.operators +from .bfloat import BFloat from .tuple import * from .clock import * from .conversions import * @@ -74,15 +74,7 @@ def set_mantle_target(t): from .uniquification import UniquificationPass -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_ +_Family_ = TypeFamily(Bit, Bits, UInt, SInt) diff --git a/magma/array.py b/magma/array.py index bd21ec79cb..1f2f85b6e2 100644 --- a/magma/array.py +++ b/magma/array.py @@ -1,124 +1,174 @@ -from collections.abc import Sequence -from .bitutils import int2seq +import weakref +from abc import ABCMeta +import magma as m from .ref import AnonRef, ArrayRef -from .t import Type, Kind +from .t import Type, Kind, deprecated from .compatibility import IntegerTypes -from .bit import VCC, GND +from .bit import VCC, GND, Bit 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 ArrayKind(Kind): +class ArrayMeta(ABCMeta, Kind): + # BitVectorType, size : BitVectorType[size] _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 + def __new__(cls, name, bases, namespace, info=(None, None, None), **kwargs): + # TODO: A lot of this code is shared with AbstractBitVectorMeta, we + # should refactor to reuse + if '_info_' in namespace: + raise TypeError( + 'class attribute _info_ is reversed by the type machinery') + + N, T = info[1:3] + for base in bases: + if getattr(base, 'is_concrete', False): + if (N, T) is (None, None): + (N, T) = (base.N, base.T) + elif (N, T) != (base.N, base.T): + raise TypeError( + "Can't inherit from multiple arrays with different N and/or T") + + namespace['_info_'] = info[0], N, T + type_ = super().__new__(cls, name, bases, namespace, **kwargs) + if (N ,T) == (None, None): + #class is abstract so t.abstract -> t + type_._info_ = type_, N, T + elif info[0] is None: + #class inherited from concrete type so there is no abstract t + type_._info_ = None, N, T + + return type_ + + def __getitem__(cls, index: tuple) -> 'ArrayMeta': + mcs = type(cls) try: - return ArrayKind._class_cache[width, sub_type] + return mcs._class_cache[cls, index] except KeyError: pass + + if not (isinstance(index, tuple) and len(index) == 2): + raise TypeError('Parameters to array must be a tuple of length 2') + if not isinstance(index[0], int) or index[0] <= 0: + raise TypeError(f'Length of array must be an int greater than 0, got: {index[0]}') + + + if cls.is_concrete: + if index == (cls.N, cls.T): + return cls + else: + return cls.abstract_t[index] + bases = [cls] + bases.extend(b[index] for b in cls.__bases__ if isinstance(b, mcs)) 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 + orig_name = cls.__name__ + class_name = '{}[{}]'.format(cls.__name__, index) + type_ = mcs(class_name, bases, {"orig_name": orig_name}, info=(cls, ) + index) + type_.__module__ = cls.__module__ + mcs._class_cache[cls, index] = type_ + return type_ + + @property + def abstract_t(cls) -> 'ArrayMeta': + t = cls._info_[0] + if t is not None: + return t + else: + raise AttributeError('type {} has no abstract_t'.format(cls)) - def __eq__(cls, rhs): - if not issubclass(type(rhs), ArrayKind): - return False + @property + def N(cls) -> int: + return cls._info_[1] - if cls.N != rhs.N: - return False - if cls.T != rhs.T: - return False + @property + def T(cls): + return cls._info_[2] - return True - - __ne__ = Kind.__ne__ - __hash__ = Kind.__hash__ + @property + def is_concrete(cls) -> bool: + return (cls.N, cls.T) != (None, None) 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 __str__(cls): + return f"Array[{cls.N}, {cls.T}]" 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()] + return cls[cls.N, cls.T.qualify(direction)] - def __call__(cls, *args, **kwargs): - result = super().__call__(*args, **kwargs) - if len(args) == 1 and isinstance(args[0], Array) and not \ - (issubclass(cls.T, Array) and cls.N == 1): - arg = args[0] - if len(arg) < len(result): - from .conversions import zext - arg = zext(arg, len(result) - len(arg)) - result(arg) - return result + def __eq__(cls, rhs): + if not isinstance(rhs, ArrayMeta): + return NotImplemented + return (cls.N == rhs.N) and (cls.T == rhs.T) + __hash__ = type.__hash__ -class Array(Type, metaclass=ArrayKind): - def __init__(self, *largs, **kwargs): +class Array(Type, metaclass=ArrayMeta): + def __init__(self, *args, **kwargs): Type.__init__(self, **kwargs) - - 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 or isinstance(type(t), type(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]))] + self.ts = [] + if args: + if len(args) == 1 and isinstance(args[0], (list, Array, int)): + if isinstance(args[0], list): + if len(args[0]) != self.N: + raise ValueError("Array list constructor can only be used with list equal to array length") + self.ts = [] + for elem in args[0]: + if isinstance(elem, int): + self.ts.append(VCC if elem else GND) + else: + self.ts.append(elem) + elif len(self) > 1 and isinstance(args[0], Array): + if len(args[0]) != len(self): + raise TypeError(f"Will not do implicit conversion of arrays") + self.ts = args[0].ts[:] + elif isinstance(args[0], int): + if not issubclass(self.T, Bit): + raise TypeError(f"Can only instantiate Array[N, Bit] " + "with int, not Array[N, {self.T}]") + self.ts = [] + for bit in m.bitutils.int2seq(args[0], self.N): + self.ts.append(VCC if bit else GND) + elif self.N == 1: + t = args[0] + if isinstance(t, IntegerTypes): + t = m.VCC if t else m.GND + assert type(t) == self.T or type(t) == self.T.flip() or \ + issubclass(type(type(t)), type(self.T)) or \ + issubclass(type(self.T), type(type(t))), (type(t), self.T) + self.ts = [t] + elif len(args) == self.N: + self.ts = [] + for t in args: + if isinstance(t, IntegerTypes): + t = VCC if t else GND + assert type(t) == self.T or type(t) == self.T.flip() or \ + issubclass(type(type(t)), type(self.T)) or \ + issubclass(type(self.T), type(type(t))), (type(t), self.T) + self.ts.append(t) + else: + raise NotImplementedError(args) else: - self.ts = [] for i in range(self.N): T = self.T t = T(name=ArrayRef(self, i)) self.ts.append(t) + @classmethod + def is_oriented(cls, direction): + if cls.T is None: + return False + return cls.T.is_oriented(direction) + + @classmethod + @deprecated + def isoriented(cls, direction): + return cls.is_oriented(direction) + def __eq__(self, rhs): if not isinstance(rhs, ArrayType): return False @@ -132,6 +182,14 @@ def __repr__(self): ts = [repr(t) for t in self.ts] return 'array([{}])'.format(', '.join(ts)) + @property + def T(self): + return type(self).T + + @property + def N(self): + return type(self).N + def __len__(self): return self.N @@ -143,7 +201,8 @@ def __getitem__(self, key): if isinstance(key, ArrayType) and all(t in {VCC, GND} for t in key.ts): key = seq2int([0 if t is GND else 1 for t in key.ts]) if isinstance(key, slice): - return array([self[i] for i in range(*key.indices(len(self)))]) + _slice = [self[i] for i in range(*key.indices(len(self)))] + return type(self)[len(_slice), self.T](_slice) else: if not (-self.N <= key and key < self.N): raise IndexError @@ -162,8 +221,8 @@ def __call__(self, o): return self.wire(o, get_callee_frame_info()) @classmethod - def isoriented(cls, direction): - return cls.T.isoriented(direction) + def is_oriented(cls, direction): + return cls.T.is_oriented(direction) def as_list(self): return [self[i] for i in range(len(self))] @@ -242,7 +301,7 @@ def trace(self): if self.iswhole(ts): return ts[0].name.array - return array(ts) + return type(self)(*ts) def value(self): ts = [t.value() for t in self.ts] @@ -254,7 +313,7 @@ def value(self): if self.iswhole(ts): return ts[0].name.array - return array(ts) + return type(self)(*ts) def const(self): for t in self.ts: @@ -266,18 +325,8 @@ def const(self): def flatten(self): return sum([t.flatten() for t in self.ts], []) - def concat(self, *args): - return concat(self, *args) - + def concat(self, other) -> 'AbstractBitVector': + return type(self)[len(self) + len(other), self.T](self.ts + other.ts) -# 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 -from .conversions import array, concat # nopep8 diff --git a/magma/backend/blif.py b/magma/backend/blif.py index 6136d46359..a97b54231b 100644 --- a/magma/backend/blif.py +++ b/magma/backend/blif.py @@ -2,8 +2,8 @@ from collections import OrderedDict from collections.abc import Sequence from ..bitutils import seq2int, fun2seq -from ..bit import VCC, GND, BitType -from ..array import ArrayType +from ..bit import VCC, GND, Bit +from ..array import Array from ..compiler import make_compiler from ..port import INPUT, OUTPUT, INOUT from ..clock import wiredefaultclock @@ -26,7 +26,7 @@ def fullinputname(prefix, v): return fullqualifiedname(prefix, v) def compileinput(prefix, from_, to): - assert isinstance(from_, BitType) + assert isinstance(from_, Bit) to = fullqualifiedname(prefix, to) from_ = fullinputname(prefix, from_) return '.names %s %s\n1 1\n' % (from_, to) @@ -34,8 +34,8 @@ def compileinput(prefix, from_, to): def compileinputs(instance, prefix): s = '' for k, v in instance.interface.ports.items(): - if v.isinput(): - if isinstance(v, ArrayType): + if v.is_input(): + if isinstance(v, Array): for i in range(len(v)): w = v[i].value() if w: diff --git a/magma/backend/coreir_.py b/magma/backend/coreir_.py index a4b8ec4d2b..6137ede1fd 100644 --- a/magma/backend/coreir_.py +++ b/magma/backend/coreir_.py @@ -1,15 +1,14 @@ -from collections import OrderedDict -import logging import os +import logging +from coreir import Context +from ..array import Array +from ..tuple import Tuple +from ..clock import AsyncReset, AsyncResetN +from ..t import In, Out from .. import singleton -from ..array import ArrayType from ..circuit import DeclareCircuit -from ..clock import AsyncResetType, AsyncResetNType -from coreir import Context from .coreir_transformer import DefnOrDeclTransformer from ..passes import DefinitionPass -from ..t import In, Out -from ..tuple import TupleType from .util import keydefaultdict from ..wire import wire @@ -83,18 +82,17 @@ def define_wrap(self, wrap_type, in_type, out_type): simulate=self.sim) def wrap_if_arst(self, port, definition): - if isinstance(port, (ArrayType, TupleType)): + if isinstance(port, (Array, Tuple)): for t in port: self.wrap_if_arst(t, definition) - elif port.isinput(): - if isinstance(port, (AsyncResetType, AsyncResetNType)) or \ - isinstance(port.value(), (AsyncResetType, AsyncResetNType)): + elif port.is_input(): + if isinstance(port, (AsyncReset, AsyncResetN)) or \ + isinstance(port.value(), (AsyncReset, AsyncResetN)): value = port.value() - print(port, value) - if value is not None and not isinstance( - type(value), type(type(port))): + if value is not None and not issubclass( + type(value), type(port).flip()): port.unwire(value) - if isinstance(port, (AsyncResetType, AsyncResetNType)): + if isinstance(port, (AsyncReset, AsyncResetN)): inst = self.define_wrap( type(port).flip(), type(port), type(value))() else: diff --git a/magma/backend/coreir_transformer.py b/magma/backend/coreir_transformer.py index 1ecc621d25..3b6763df37 100644 --- a/magma/backend/coreir_transformer.py +++ b/magma/backend/coreir_transformer.py @@ -3,7 +3,7 @@ import json import logging import os -from ..array import ArrayType +from ..array import Array from ..bit import VCC, GND from ..clock import wiredefaultclock, wireclock from coreir import Wireable @@ -16,7 +16,7 @@ from ..interface import InterfaceKind from ..is_definition import isdefinition from ..passes import InstanceGraphPass -from ..tuple import TupleType +from ..tuple import Tuple from .util import get_codegen_debug_info @@ -168,7 +168,7 @@ def get_coreir_defn(self): self.backend.libs_used.add(self.defn.coreir_lib) non_input_ports = {} for name, port in self.defn.interface.ports.items(): - logger.debug(f"{name}, {port}, {port.isoutput()}") + logger.debug(f"{name}, {port}, {port.is_output()}") add_non_input_ports(non_input_ports, port) for inst, coreir_inst in coreir_insts.items(): if get_codegen_debug_info() and getattr(inst, "debug_info", False): @@ -184,32 +184,32 @@ def get_coreir_defn(self): def connect_non_outputs(self, module_defn, port, non_input_ports): # Recurse into non input types that may contain inout children. - if isinstance(port, TupleType) and not port.isinput() or \ - isinstance(port, ArrayType) and not port.T.isinput(): + if isinstance(port, Tuple) and not port.is_input() or \ + isinstance(port, Array) and not port.T.is_input(): for elem in port: self.connect_non_outputs(module_defn, elem, non_input_ports) - elif not port.isoutput(): + elif not port.is_output(): self.connect(module_defn, port, port.value(), non_input_ports) def connect(self, module_defn, port, value, non_input_ports): # Allow Clock or Array[Clock] to be unwired as CoreIR can wire them up. - if value is None and is_clock_or_nested_clock(port): + if value is None and is_clock_or_nested_clock(type(port)): return if value is None: - if port.isinout(): + if port.is_inout(): return # skip inouts because they might be conn. as an input. raise Exception(f"Found unconnected port: {port.debug_name}") def get_source(): if isinstance(value, Wireable): return value - if isinstance(value, ArrayType) and is_const(value): + if isinstance(value, Array) and is_const(value): return self.const_instance(value, len(value), module_defn) - if value.anon() and isinstance(value, ArrayType): + if value.anon() and isinstance(value, Array): for p, v in zip(port, value): self.connect(module_defn, p, v, non_input_ports) return None - if isinstance(value, TupleType) and value.anon(): + if isinstance(value, Tuple) and value.anon(): for p, v in zip(port, value): self.connect(module_defn, p, v, non_input_ports) return None diff --git a/magma/backend/coreir_utils.py b/magma/backend/coreir_utils.py index c361b95fc6..023c00cec6 100644 --- a/magma/backend/coreir_utils.py +++ b/magma/backend/coreir_utils.py @@ -1,14 +1,11 @@ from collections import OrderedDict import json from hwtypes import BitVector -from ..array import ArrayKind, ArrayType, Array -from ..bit import VCC, GND, BitIn, BitOut, BitKind -from ..clock import (wiredefaultclock, wireclock, ClockType, Clock, ResetType, - ClockKind, EnableKind, ResetKind, AsyncResetType, - AsyncResetKind, ResetNKind, AsyncResetNKind, - AsyncResetNType, ResetType) +from ..array import Array +from ..bit import VCC, GND, Digital +from ..clock import Clock, AsyncReset, AsyncResetN from ..ref import ArrayRef, DefnRef, TupleRef, InstRef -from ..tuple import TupleKind, TupleType, Tuple +from ..tuple import Tuple from .util import make_relative @@ -44,53 +41,49 @@ def magma_port_to_coreir_port(port): return magma_name_to_coreir_select(port.name) -_POD_KINDS = (BitKind, ClockKind, EnableKind, ResetKind, AsyncResetKind, - ResetNKind, AsyncResetNKind) - - -def check_magma_type(port, error_msg=""): - if isinstance(port, ArrayKind): - msg = error_msg.format("Array({}, {})").format(str(port.N), "{}") - check_magma_type(port.T, msg) +def check_magma_type(type_, error_msg=""): + if issubclass(type_, Array): + msg = error_msg.format("Array({}, {})").format(str(type_.N), "{}") + check_magma_type(type_.T, msg) return - if isinstance(port, TupleKind): - for (k, t) in zip(port.Ks, port.Ts): + if issubclass(type_, Tuple): + for (k, t) in zip(type_.keys(), type_.types()): msg = error_msg.format("Tuple({}:{})".format(k, "{}")) check_magma_type(t, msg) return - if isinstance(port, _POD_KINDS): + if issubclass(type_, Digital): return - raise CoreIRBackendError(error_msg.format(str(port))) + raise CoreIRBackendError(error_msg.format(str(type_))) def check_magma_interface(interface): # For now only allow Bit, Array, or Tuple. for name, port in interface.ports.items(): - check_magma_type(type(port), "Type {} not supported by CoreIR backend") + check_magma_type( + type(port), f"{name}: {type(port)} not supported by CoreIR backend" + ) -def magma_type_to_coreir_type(context, port): - if isinstance(port, (ArrayType, ArrayKind)): - return context.Array(port.N, - magma_type_to_coreir_type(context, port.T)) - if isinstance(port, (TupleType, TupleKind)): - zipped = zip(port.Ks, port.Ts) +def magma_type_to_coreir_type(context, type_): + if issubclass(type_, Array): + return context.Array(type_.N, + magma_type_to_coreir_type(context, type_.T)) + if issubclass(type_, Tuple): + zipped = zip(type_.keys(), type_.types()) return context.Record({ _tuple_key_to_string(k): magma_type_to_coreir_type(context, t) for (k, t) in zipped }) - if port.isinput(): - if isinstance(port, (ClockType, ClockKind)): + if type_.is_input(): + if issubclass(type_, Clock): return context.named_types[("coreir", "clk")] - if isinstance(port, (AsyncResetType, AsyncResetKind, AsyncResetNType, - AsyncResetNKind)): + if issubclass(type_, (AsyncReset, AsyncResetN)): return context.named_types[("coreir", "arst")] return context.Bit() - if port.isoutput(): - if isinstance(port, (ClockType, ClockKind)): + if type_.is_output(): + if issubclass(type_, Clock): return context.named_types[("coreir", "clkIn")] - if isinstance(port, (AsyncResetType, AsyncResetKind, AsyncResetNType, - AsyncResetNKind)): + if issubclass(type_, (AsyncReset, AsyncResetN)): return context.named_types[("coreir", "arstIn")] return context.BitIn() return context.BitInOut() @@ -99,14 +92,14 @@ def magma_type_to_coreir_type(context, port): def magma_interface_to_coreir_module_type(context, interface): args = OrderedDict() for name, port in interface.ports.items(): - args[name] = magma_type_to_coreir_type(context, port) + args[name] = magma_type_to_coreir_type(context, type(port)) return context.Record(args) def add_non_input_ports(non_input_ports, port): - if not port.isinput(): + if not port.is_input(): non_input_ports[port] = magma_port_to_coreir_port(port) - if isinstance(port, (TupleType, ArrayType)): + if isinstance(port, (Tuple, Array)): for element in port: add_non_input_ports(non_input_ports, element) @@ -132,11 +125,11 @@ def make_cparams(context, params): def is_clock_or_nested_clock(p): - if isinstance(p, (ClockType, ClockKind)): + if issubclass(p, Clock): return True - if isinstance(p, (ArrayType, ArrayKind)): + if issubclass(p, Array): return is_clock_or_nested_clock(p.T) - if isinstance(p, (TupleType, TupleKind)): + if issubclass(p, Tuple): for item in p.Ts: if is_clock_or_nested_clock(item): return True @@ -154,12 +147,12 @@ def fn(k, v): def map_genarg(context, value): - if isinstance(value, ClockKind): - if value.isinput(): + if isinstance(value, type) and issubclass(value, Clock): + if value.is_input(): return context.named_types[("coreir", "clkIn")] return context.named_types[("coreir", "clk")] - if isinstance(value, (AsyncResetKind, AsyncResetNKind)): - if value.isinput(): + if isinstance(value, type) and issubclass(value, (AsyncReset, AsyncResetN)): + if value.is_input(): return context.named_types[("coreir", "arstIn")] return context.named_types[("coreir", "arst")] return value @@ -193,7 +186,7 @@ def constant_to_value(constant): return 0 if constant is VCC: return 1 - if isinstance(constant, ArrayType): + if isinstance(constant, Array): values = [constant_to_value(c) for c in constant] return BitVector[len(constant)](values) raise NotImplementedError(constant) diff --git a/magma/backend/dot.py b/magma/backend/dot.py index 2234d51b14..8415678b68 100644 --- a/magma/backend/dot.py +++ b/magma/backend/dot.py @@ -1,5 +1,5 @@ -from ..array import ArrayKind, ArrayType -from ..bit import BitType, VCC, GND +from ..array import Array +from ..bit import Bit, VCC, GND from ..compiler import make_compiler from ..passes.debug_name import DebugNamePass from ..passes.clock import WireClockPass @@ -22,7 +22,7 @@ def get_name(dot, port): if port is VCC: return "1" if port is GND: return "0" - if isinstance(port, ArrayType): + if isinstance(port, Array): if not port.iswhole(port.ts): # the sequence of values is concantenated port = [get_name(dot, i) for i in port.ts] @@ -45,21 +45,21 @@ def compileinstance(dot, instance): outputs = [] for name, port in instance.interface.ports.items(): - if port.isinput(): + if port.is_input(): inputs.append('<{0}> {0}'.format(str(name))) value = port.value() - if not value: + if value is None: logging.warning(f'Input {port.debug_name} not connected to an output') continue else: outputs.append('<{0}> {0}'.format(str(name))) value = port - # if isinstance(value, ArrayType): + # if isinstance(value, Array): # for index, subport in enumerate(value.ts): # s += "{}.{}[{}] <= {}\n".format(instance_backend_name, name, index, get_name(subport)) # else: value_name = get_name(dot, value) - if port.isinput(): + if port.is_input(): # s += "{}.{} <= {}\n".format(instance_backend_name, name, value_name) dot.edge(value_name, '{}:{}'.format(instance_backend_name, name)) else: @@ -80,12 +80,12 @@ def compiledefinition(dot, cls): # for now only allow Bit or Array(n, Bit) for name, port in cls.interface.ports.items(): - if isinstance(port, ArrayKind): - if not isinstance(port.T, BitKind): + if isinstance(port, Array): + if not issubclass(port.T, Bit): print('Error: Argument', port, 'must be a an Array(n,Bit)') for name, port in cls.interface.ports.items(): - # TODO: Check whether port.isinput() or .isoutput(). + # TODO: Check whether port.is_input() or .is_output(). dot.node(name, escape('{}\\n{}'.format(name, get_type(port))), shape='ellipse') @@ -93,7 +93,7 @@ def compiledefinition(dot, cls): # declare a wire for each instance output for instance in cls.instances: for port in instance.interface.ports.values(): - if port.isoutput(): + if port.is_output(): dot.node(get_name(dot, port), escape('{}\\n{}'.format(get_name(dot, port), get_type(port))), shape='none') @@ -105,7 +105,7 @@ def compiledefinition(dot, cls): # Assign to module output arguments. for input in cls.interface.inputs(): output = input.value() - if output: + if output is not None: iname = get_name(dot, input) oname = get_name(dot, output) dot.edge(oname, iname) diff --git a/magma/backend/firrtl.py b/magma/backend/firrtl.py index cadf938d1b..b3f68ec818 100644 --- a/magma/backend/firrtl.py +++ b/magma/backend/firrtl.py @@ -1,15 +1,15 @@ from collections import OrderedDict -from ..bit import BitType, VCC, GND -from ..array import ArrayKind, ArrayType +from ..bit import Bit, VCC, GND +from ..array import Array from ..clock import wiredefaultclock from ..compiler import make_compiler from .verilog import find def get_type(port): - if isinstance(port, ArrayType): + if isinstance(port, Array): width = port.N else: - assert isinstance(port, BitType) + assert isinstance(port, Bit) width = 1 return "UInt<{}>".format(width) @@ -17,7 +17,7 @@ def get_name(port): if port is VCC: return "UInt<1>(\"h1\")" if port is GND: return "UInt<1>(\"h0\")" - if isinstance(port, ArrayType): + if isinstance(port, Array): if not port.iswhole(port.ts): # the sequence of values is concantenated port = [get_name(i) for i in port.ts] @@ -32,19 +32,19 @@ def compileinstance(instance): instance_name = str(instance.name) s = "inst {} of {}\n".format(instance_name, str(instance.__class__.__name__)) for name, port in instance.interface.ports.items(): - if port.isinput(): + if port.is_input(): value = port.value() if not value: print('Warning (firrtl): input', str(port), 'not connected to an output') value = port else: value = port - # if isinstance(value, ArrayType): + # if isinstance(value, Array): # for index, subport in enumerate(value.ts): # s += "{}.{}[{}] <= {}\n".format(instance_name, name, index, get_name(subport)) # else: value_name = get_name(value) - if port.isinput(): + if port.is_input(): s += "{}.{} <= {}\n".format(instance_name, name, value_name) else: s += "{} <= {}.{}\n".format(value_name, instance_name, name) @@ -60,7 +60,7 @@ def compile_primitive(instance): port = outputs[0] args = [] for name, port in instance.interface.ports.items(): - if port.isinput(): + if port.is_input(): value = port.value() if not value: print('Warning (firrtl): input', str(port), 'not connected to an output') @@ -78,9 +78,9 @@ def compiledefinition(cls): s = 'module {} :\n'.format(cls.__name__) for name, port in cls.interface.ports.items(): - if port.isinput(): + if port.is_input(): direction = "output" - elif port.isoutput(): + elif port.is_output(): direction = "input" else: raise NotImplementedError() # Does FIRRTL have an inout? @@ -94,7 +94,7 @@ def compiledefinition(cls): # declare a wire for each instance output for instance in cls.instances: for port in instance.interface.ports.values(): - if port.isoutput(): + if port.is_output(): s += 'wire {} : {}\n'.format(get_name(port), get_type(port)) #print('compile instances') diff --git a/magma/backend/verilog.py b/magma/backend/verilog.py index b23d742452..20d2131d08 100644 --- a/magma/backend/verilog.py +++ b/magma/backend/verilog.py @@ -5,14 +5,14 @@ from collections import OrderedDict from collections.abc import Sequence from ..compiler import Compiler -from ..port import INPUT, OUTPUT, INOUT, flip +from ..port import flip from ..ref import DefnRef from ..compatibility import IntegerTypes -from ..bit import _BitType, _BitKind, VCC, GND -from ..clock import ClockType, EnableType, ResetType -from ..array import ArrayKind, ArrayType -from ..bits import SIntType -from ..tuple import TupleType +from ..bit import Digital, VCC, GND +from ..clock import Clock, Enable, Reset +from ..array import Array +from ..bits import SInt +from ..tuple import Tuple from ..is_definition import isdefinition from ..clock import wiredefaultclock import logging @@ -65,7 +65,7 @@ def vname(t): if t is VCC: return "1'b1" if t is GND: return "1'b0" - if isinstance(t, ArrayType): + if isinstance(t, Array): # print(t.ts) if not t.iswhole(t.ts): # the sequence of values is concantenated @@ -78,24 +78,24 @@ def vname(t): # return the verilog declaration for the data type def vdecl(t): - if isinstance(t, ArrayType): - signed = "signed " if isinstance(t, SIntType) else "" + if isinstance(t, Array): + signed = "signed " if isinstance(t, SInt) else "" return '{}[{}:{}]'.format(signed, t.N-1, 0) else: - assert isinstance(t, _BitType) + assert isinstance(t, Digital) return "" # return the verilog module args def vmoduleargs(self): def append(args, port, name): - if port.isinput(): d = OUTPUT - elif port.isoutput(): d = INPUT - else: d = INOUT + if port.is_input(): d = "output" + elif port.is_output(): d = "input" + else: d = "inout" args.append("%s %s %s" % (d, vdecl(port), name)) args = [] for name, port in self.ports.items(): - if isinstance(port, TupleType): + if isinstance(port, Tuple): for i in range(len(port)): append(args, port[i], vname(port[i])) else: @@ -118,14 +118,14 @@ def arg(k,v): if getattr(v, "debug_info", False) and get_codegen_debug_info(): filename, lineno, module = v.debug_info #print('arg', k, v,) - if v.isinput(): + if v.is_input(): # find the output connected to v w = v.value() - if not w: + if w is None: logging.warning(f'{v.debug_name} not connected') continue v = w - if isinstance(v, TupleType): + if isinstance(v, Tuple): for i in range(len(v)): args.append(arg('%s_%s' % (v[i].name.tuple.name, v[i].name.index), vname(v[i]))) @@ -160,8 +160,8 @@ def compiledefinition(cls): # for now only allow Bit or Array(n, Bit) for name, port in cls.interface.ports.items(): - if isinstance(port, (ArrayKind, ArrayType)): - if not isinstance(port.T, (_BitType, _BitKind)): + if isinstance(port, Array): + if not issubclass(port.T, Digital): raise Exception(f'Argument {cls.__name__}.{name} of type {type(port)} is not supported, the verilog backend only supports simple 1-d array of bits of the form Array(N, Bit)') @@ -190,11 +190,11 @@ def wire(port): # declare a wire for each instance output for instance in cls.instances: for port in instance.interface.ports.values(): - if isinstance(port, TupleType): + if isinstance(port, Tuple): for i in range(len(port)): s += wire(port[i]) else: - if not port.isinput(): + if not port.is_input(): s += wire(port) #print('compile instances') @@ -209,14 +209,14 @@ def wire(port): # assign to module output arguments for port in cls.interface.ports.values(): - if port.isinput(): + if port.is_input(): output = port.value() - if output: - if isinstance(output, TupleType): + if output is not None: + if isinstance(output, Tuple): for name, input in cls.interface.ports.items(): - if input.isinput(): + if input.is_input(): output = input.value() - assert isinstance(output, TupleType) + assert isinstance(output, Tuple) for i in range(len(input)): iname = vname(input[i]) oname = vname(output[i]) diff --git a/magma/bfloat.py b/magma/bfloat.py new file mode 100644 index 0000000000..93f30ff35f --- /dev/null +++ b/magma/bfloat.py @@ -0,0 +1,5 @@ +from .bits import Bits + + +class BFloat(Bits): + pass diff --git a/magma/bit.py b/magma/bit.py index 0139ed53c7..b42fbe78c1 100644 --- a/magma/bit.py +++ b/magma/bit.py @@ -1,94 +1,135 @@ -from abc import abstractmethod -from .logging import error -from .port import Port, INPUT, OUTPUT, INOUT -from .t import Type, Kind -from .compatibility import IntegerTypes -from .debug import debug_wire, get_callee_frame_info -from .port import report_wiring_error - -__all__ = ['_BitType', '_BitKind'] -__all__ += ['BitType', 'BitKind'] -__all__ += ['Bit', 'BitIn', 'BitOut', 'BitInOut'] -__all__ += ['VCC', 'GND', 'HIGH', 'LOW'] - - -class _BitType(Type): - """ - Each bit is associated with a Port. The Port keeps track of how bits are - wired together. - """ - - def __init__(self, *largs, **kwargs): - super(_BitType, self).__init__(*largs, **kwargs) - - self.port = Port(self) - - __ne__ = Type.__ne__ - __hash__ = Type.__hash__ - - def __call__(self, output): - return self.wire(output, get_callee_frame_info()) +""" +Definition of magma's Bit type +* Subtype of the Digital type +* Implementation of hwtypes.AbstractBit +""" +import typing as tp +import functools +from functools import lru_cache +import magma as m +from hwtypes.bit_vector_abc import AbstractBit, TypeFamily +from .t import Direction +from .digital import Digital, DigitalMeta, VCC, GND + + +def bit_cast(fn: tp.Callable[['Bit', 'Bit'], 'Bit']) -> \ + tp.Callable[['Bit', tp.Union['Bit', bool]], 'Bit']: + @functools.wraps(fn) + def wrapped(self: 'Bit', other: tp.Union['Bit', bool]) -> 'Bit': + if isinstance(other, Bit): + return fn(self, other) + try: + other = Bit(other) + except TypeError: + return NotImplemented + return fn(self, other) + return wrapped + + +class BitMeta(DigitalMeta): + pass + + +class Bit(Digital, AbstractBit, metaclass=BitMeta): + __hash__ = Digital.__hash__ + + @staticmethod + def get_family() -> TypeFamily: + return m._Family_ @classmethod - def isoriented(cls, direction): - return cls.direction == direction - - @debug_wire - def wire(i, o, debug_info): - # promote integer types to LOW/HIGH - if isinstance(o, IntegerTypes): - o = HIGH if o else LOW - - if not isinstance(o, _BitType): - report_wiring_error(f'Cannot wire {i.debug_name} (type={type(i)}) to {o} (type={type(o)}) because {o.debug_name} is not a _Bit', debug_info) - return - - i.port.wire(o.port, debug_info) - i.debug_info = debug_info - o.debug_info = debug_info + @lru_cache(maxsize=None) + def declare_unary_op(cls, op): + return m.circuit.DeclareCoreirCircuit(f"magma_Bit_{op}", + "I", m.In(m.Bit), + "O", m.Out(m.Bit), + coreir_name=op, + coreir_lib="corebit") - def unwire(i, o): - i.port.unwire(o.port) - - def driven(self): - return self.port.driven() - - def wired(self): - return self.port.wired() + @classmethod + @lru_cache(maxsize=None) + def declare_binary_op(cls, op): + return m.circuit.DeclareCoreirCircuit(f"magma_Bit_{op}", + "I0", m.In(m.Bit), + "I1", m.In(m.Bit), + "O", m.Out(m.Bit), + coreir_name=op, + coreir_lib="corebit") @classmethod - def flat_length(cls): - return 1 - - # return the input or output _Bit connected to this _Bit - def trace(self): - t = self.port.trace() - if t: - t = t.bit - return t - - # return the output _Bit connected to this input _Bit - def value(self): - t = self.port.value() - if t: - t = t.bit - return t - - def const(self): - return self is VCC or self is GND - - def getinst(self): - t = self.trace() - return t.name.inst if t else None - - def getgpio(self): - return self.getinst() - - # return the bits driven by this bit - def dependencies(self): - assert self.isoutput(), "Trying to get dependencies from output bit" - deps = map(lambda i: i.bit, self.port.wires.inputs) - return deps + @lru_cache(maxsize=None) + def declare_ite(cls, T): + t_str = str(T) + # Sanitize + t_str = t_str.replace("(", "_") + t_str = t_str.replace(")", "") + return m.circuit.DeclareCoreirCircuit(f"magma_Bit_ite_{t_str}", + "I0", m.In(T), + "I1", m.In(T), + "S", m.In(m.Bit), + "O", m.Out(T), + coreir_name="mux", + coreir_lib="corebit") + + def __init__(self, value=None, name=None): + super().__init__(name=name) + if value is None: + self._value = None + elif isinstance(value, Bit): + self._value = value._value + elif isinstance(value, bool): + self._value = value + elif isinstance(value, int): + if value not in {0, 1}: + raise ValueError('Bit must have value 0 or 1 not {}'.format(value)) + self._value = bool(value) + elif hasattr(value, '__bool__'): + self._value = bool(value) + else: + raise TypeError("Can't coerce {} to Bit".format(type(value))) + + @property + def direction(self): + return type(self).direction + + def __invert__(self): + # CoreIR uses not instead of invert name + return self.declare_unary_op("not")()(self) + + @bit_cast + def __eq__(self, other): + # CoreIR doesn't define an eq primitive for bits + return ~(self ^ other) + + @bit_cast + def __ne__(self, other): + # CoreIR doesn't define an ne primitive for bits + return self ^ other + + @bit_cast + def __and__(self, other): + return self.declare_binary_op("and")()(self, other) + + @bit_cast + def __or__(self, other): + return self.declare_binary_op("or")()(self, other) + + @bit_cast + def __xor__(self, other): + return self.declare_binary_op("xor")()(self, other) + + def ite(self, t_branch, f_branch): + type_ = type(t_branch) + if type_ != type(f_branch): + raise TypeError("ite expects same type for both branches") + # Note: coreir flips t/f cases + return self.declare_ite(type_)()(f_branch, t_branch, self) + + def __bool__(self) -> bool: + raise NotImplementedError("Converting magma bit to bool not supported") + + def __int__(self) -> int: + raise NotImplementedError("Converting magma bit to int not supported") def __repr__(self): if self is VCC: @@ -96,117 +137,9 @@ def __repr__(self): if self is GND: return '0' - return self.name.qualifiedname(sep='.') - - def flatten(self): - return [self] - - -class _BitKind(Kind): - def __init__(cls, name, bases, dct): - super(_BitKind, cls).__init__(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 - - return cls.direction == rhs.direction - - __ne__ = Kind.__ne__ - __hash__ = Kind.__hash__ - - def __str__(cls): - if cls.isinput(): - return 'In(_Bit)' - if cls.isoutput(): - return 'Out(_Bit)' - if cls.isinout(): - return 'InOut(_Bit)' - return '_Bit' - - def size(self): - return 1 - - @abstractmethod - def qualify(cls, direction): - pass - - @abstractmethod - def flip(cls): - pass - - def get_family(cls): - import magma as m - return m.get_family() - - -class BitType(_BitType): - __hash__ = Type.__hash__ - - -class BitKind(_BitKind): - def __eq__(cls, rhs): - if not isinstance(rhs, BitKind): - return False - - return cls.direction == rhs.direction - - __ne__ = _BitKind.__ne__ - __hash__ = _BitKind.__hash__ - - def __str__(cls): - if cls.isinput(): - return 'In(Bit)' - if cls.isoutput(): - return 'Out(Bit)' - if cls.isinout(): - return 'InOut(Bit)' - return 'Bit' - - def qualify(cls, direction): - if direction is None: - return Bit - elif direction == INPUT: - return BitIn - elif direction == OUTPUT: - return BitOut - elif direction == INOUT: - return BitInOut - return cls - - def flip(cls): - if cls.isoriented(INPUT): - return BitOut - elif cls.isoriented(OUTPUT): - return BitIn - return cls - - -def MakeBit(**kwargs): - return BitKind('Bit', (BitType,), kwargs) - - -Bit = MakeBit() -BitIn = MakeBit(direction=INPUT) -BitOut = MakeBit(direction=OUTPUT) -BitInOut = MakeBit(direction=INOUT) + return super().__repr__() -VCC = BitOut(name="VCC") -GND = BitOut(name="GND") - -HIGH = VCC -LOW = GND +BitIn = Bit[Direction.In] +BitOut = Bit[Direction.Out] +BitInOut = Bit[Direction.InOut] diff --git a/magma/bits.py b/magma/bits.py index 0a19fad34e..5f16ac9934 100644 --- a/magma/bits.py +++ b/magma/bits.py @@ -3,88 +3,65 @@ m.Bits[N] is roughly equivalent ot m.Array[N, T] """ -import weakref -from hwtypes import BitVector, SIntVector +from functools import lru_cache, wraps +import typing as tp +from hwtypes import BitVector +from hwtypes import AbstractBitVector, AbstractBitVectorMeta, AbstractBit, \ + InconsistentSizeError +import magma as m from .compatibility import IntegerTypes from .ref import AnonRef from .bit import Bit, VCC, GND -from .array import ArrayType, ArrayKind +from .array import Array, ArrayMeta from .debug import debug_wire +from .t import Type -__all__ = ['Bits', 'BitsType', 'BitsKind'] -__all__ += ['UInt', 'UIntType', 'UIntKind'] -__all__ += ['SInt', 'SIntType', 'SIntKind'] -__all__ += ['BFloat', 'BFloatKind'] +def _coerce(T: tp.Type['Bits'], val: tp.Any) -> 'Bits': + if not isinstance(val, Bits): + return T(val) + elif len(val) != len(T): + raise InconsistentSizeError('Inconsistent size') + else: + return val -class BitsKind(ArrayKind): - _class_cache = weakref.WeakValueDictionary() +def bits_cast(fn: tp.Callable[['Bits', 'Bits'], tp.Any]) -> \ + tp.Callable[['Bits', tp.Any], tp.Any]: + @wraps(fn) + def wrapped(self: 'Bits', other: tp.Any) -> tp.Any: + other = _coerce(type(self), other) + return fn(self, other) + return wrapped - def __str__(cls): - if not hasattr(cls, "T"): - return cls.__name__ - if cls.isinput(): - return "In(Bits[{}])".format(cls.N) - if cls.isoutput(): - return "Out(Bits[{}])".format(cls.N) - return "Bits[{}]".format(cls.N) +class BitsMeta(AbstractBitVectorMeta, ArrayMeta): + def __new__(mcs, name, bases, namespace, info=(None, None, None), **kwargs): + return ArrayMeta.__new__(mcs, name, bases, namespace, info, **kwargs) def __getitem__(cls, index): - if isinstance(index, tuple): - width, T = index - else: - width = index - T = Bit - if isinstance(width, Bits): - assert width.const() - # TODO: Move this logic to a method in BitsType - bit_type_to_constant_map = { - GND: 0, - VCC: 1 - } - width = BitVector[len(width)]([bit_type_to_constant_map[x] for x in - width]).as_uint() - try: - result = BitsKind._class_cache[width, T] - return result - except KeyError: - pass - bases = [cls] - bases = tuple(bases) - class_name = '{}[{}, {}]'.format(cls.__name__, width, T.__name__) - t = type(cls)(class_name, bases, dict(T=T, N=width)) - t.__module__ = cls.__module__ - BitsKind._class_cache[width, T] = t - return t - - def qualify(cls, direction): - if cls.T.isoriented(direction): - return cls - return Bits[cls.N, cls.T.qualify(direction)] - - def flip(cls): - return Bits[cls.N, cls.T.flip()] - -# def __call__(cls, value=None, *args, **kwargs): -# print(cls, cls.__dict__) -# if value is not None: -# if isinstance(value, (bool, IntegerTypes)): -# from .conversions import bits -# return bits(value, cls.N) -# else: -# raise ValueError("Bit can only be initialized with None, bool, " -# "or integer") -# return super().__call__(*args, **kwargs) - - def get_family(self): - import magma as m - return m.get_family() - - -class Bits(ArrayType, metaclass=BitsKind): + if isinstance(index, int): + index = (index, Bit) + return ArrayMeta.__getitem__(cls, index) + + def __repr__(cls): + return str(cls) + + def __str__(cls): + name = f"{cls.orig_name}[{cls.N}]" + if cls.is_input(): + name = f"In({name})" + elif cls.is_output(): + name = f"Out({name})" + elif cls.is_output(): + name = f"InOut({name})" + return name + + +class Bits(Array, AbstractBitVector, metaclass=BitsMeta): + __hash__ = Array.__hash__ + def __repr__(self): if not isinstance(self.name, AnonRef): return repr(self.name) @@ -108,245 +85,534 @@ def __int__(self): return BitVector[len(self)](self.bits()).as_int() @debug_wire - def wire(i, o, debug_info): - if isinstance(o, IntegerTypes): - if o.bit_length() > len(i): + def wire(self, other, debug_info): + if isinstance(other, IntegerTypes): + if other.bit_length() > len(self): raise ValueError( - f"Cannot convert integer {o} (bit_length={o.bit_length()}) to Bits({len(i)})") + f"Cannot convert integer {other} " + f"(bit_length={other.bit_length()}) to Bits ({len(self)})") from .conversions import bits - o = bits(o, len(i)) - super().wire(o, debug_info) + other = bits(other, len(self)) + super().wire(other, debug_info) + + @classmethod + def make_constant(cls, value, num_bits: tp.Optional[int] = None) -> \ + 'AbstractBitVector': + if num_bits is None: + return cls(value) + return cls.unsized_t[num_bits](value) + + def __setitem__(self, index: int, value: AbstractBit): + raise NotImplementedError() + + @classmethod + @lru_cache(maxsize=None) + def declare_unary_op(cls, op): + N = len(cls) + return m.circuit.DeclareCoreirCircuit(f"magma_Bits_{N}_{op}", + "I", m.In(cls), + "O", m.Out(cls), + coreir_name=op, + coreir_genargs={"width": N}, + coreir_lib="coreir") + + @classmethod + @lru_cache(maxsize=None) + def declare_binary_op(cls, op): + N = len(cls) + return m.circuit.DeclareCoreirCircuit(f"magma_Bits_{N}_{op}", + "I0", m.In(cls), + "I1", m.In(cls), + "O", m.Out(cls), + coreir_name=op, + coreir_genargs={"width": N}, + coreir_lib="coreir") + + @classmethod + @lru_cache(maxsize=None) + def declare_compare_op(cls, op): + N = len(cls) + return m.circuit.DeclareCoreirCircuit(f"magma_Bits_{N}_{op}", + "I0", m.In(cls), + "I1", m.In(cls), + "O", m.Out(m.Bit), + coreir_name=op, + coreir_genargs={"width": N}, + coreir_lib="coreir") + + @classmethod + @lru_cache(maxsize=None) + def declare_ite(cls, T): + t_str = str(T) + # Sanitize + t_str = t_str.replace("(", "_") + t_str = t_str.replace(")", "") + t_str = t_str.replace("[", "_") + t_str = t_str.replace("]", "") + N = len(cls) + return m.circuit.DeclareCoreirCircuit(f"magma_Bits_{N}_ite_{t_str}", + "I0", m.In(T), + "I1", m.In(T), + "S", m.In(m.Bit), + "O", m.Out(T), + coreir_name="mux", + coreir_genargs={"width": N}, + coreir_lib="coreir") + + def bvnot(self) -> 'AbstractBitVector': + return self.declare_unary_op("not")()(self) + + @bits_cast + def bvand(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("and")()(self, other) + + @bits_cast + def bvor(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("or")()(self, other) + + @bits_cast + def bvxor(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("xor")()(self, other) + + @bits_cast + def bvshl(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("shl")()(self, other) + + @bits_cast + def bvlshr(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("lshr")()(self, other) + + def bvashr(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + + def bvrol(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + + def bvror(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + + def bvcomp(self, other) -> 'AbstractBitVector[1]': + return Bits[1](self == other) + + def bveq(self, other) -> AbstractBit: + return self.declare_compare_op("eq")()(self, other) + + def bvult(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvule(self, other) -> AbstractBit: + # For wiring + if not self.is_output(): + return Type.__le__(self, other) + raise NotImplementedError() + + def bvugt(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvuge(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvslt(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvsle(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvsgt(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvsge(self, other) -> AbstractBit: + raise NotImplementedError() + + def bvneg(self) -> 'AbstractBitVector': + raise NotImplementedError() - def zext(self, value): - from .conversions import zext - t = zext(self, value) - return t + def adc(self, other, carry) -> tp.Tuple['AbstractBitVector', AbstractBit]: + raise NotImplementedError() - def __getitem__(self, key): - from .conversions import bits - result = super().__getitem__(key) - if isinstance(key, slice): - return bits(result) - return result + def ite(self, t_branch, f_branch) -> 'AbstractBitVector': + type_ = type(t_branch) + if type_ != type(f_branch): + raise TypeError("ite expects same type for both branches") + return self.declare_ite(type_)()(t_branch, f_branch, + self != self.make_constant(0)) + def bvadd(self, other) -> 'AbstractBitVector': + raise NotImplementedError() -BitsType = Bits + def bvsub(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + def bvmul(self, other) -> 'AbstractBitVector': + raise NotImplementedError() -# def Bits(N, T=None): -# if T is None: -# T = Bit -# assert isinstance(N, (IntegerTypes, BitsType)), (N, type(N)) -# if isinstance(N, BitsType): -# assert N.const() -# # TODO: Move this logic to a method in BitsType -# bit_type_to_constant_map = { -# GND: 0, -# VCC: 1 -# } -# N = BitVector([bit_type_to_constant_map[x] for x in N]).as_uint() -# name = 'Bits({})'.format(N) -# return BitsKind(name, (BitsType,), dict(N=N, T=T)) + def bvudiv(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + def bvurem(self, other) -> 'AbstractBitVector': + raise NotImplementedError() -class UIntKind(BitsKind): - _class_cache = weakref.WeakValueDictionary() + def bvsdiv(self, other) -> 'AbstractBitVector': + raise NotImplementedError() - def __getitem__(cls, index): - if isinstance(index, tuple): - width, T = index - else: - width = index - T = Bit - if isinstance(width, UInt): - assert width.const() - # TODO: Move this logic to a method in BitsType - bit_type_to_constant_map = { - GND: 0, - VCC: 1 - } - width = BitVector[len(width)]([bit_type_to_constant_map[x] for x in - width]).as_uint() + def bvsrem(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + + def repeat(self, other) -> 'AbstractBitVector': + r = int(other) + if r <= 0: + raise ValueError() + + return type(self).unsized_t[r * self.size](r * self.ts) + + def sext(self, other) -> 'AbstractBitVector': + raise NotImplementedError() + + def ext(self, other) -> 'AbstractBitVector': + return self.zext(other) + + def zext(self, other) -> 'AbstractBitVector': + ext = int(other) + if ext < 0: + raise ValueError() + + T = type(self).unsized_t + return self.concat(T[ext](0)) + + def __invert__(self): + return self.bvnot() + + def __and__(self, other): try: - return UIntKind._class_cache[width, T] - except KeyError: - pass - bases = [cls] - bases = tuple(bases) - class_name = '{}[{}, {}]'.format(cls.__name__, width, T) - t = type(cls)(class_name, bases, dict(T=T, N=width)) - t.__module__ = cls.__module__ - UIntKind._class_cache[width, T] = t - return t + return self.bvand(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def __str__(cls): - if cls.isinput(): - return "In(UInt[{}])".format(cls.N) - if cls.isoutput(): - return "Out(UInt[{}])".format(cls.N) - return "UInt[{}]".format(cls.N) + def __or__(self, other): + try: + return self.bvor(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def qualify(cls, direction): - if cls.T.isoriented(direction): - return cls - return UInt[cls.N, cls.T.qualify(direction)] + def __xor__(self, other): + try: + return self.bvxor(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def flip(cls): - return UInt[cls.N, cls.T.flip()] + def __lshift__(self, other): + try: + return self.bvshl(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + def __rshift__(self, other): + try: + return self.bvlshr(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -class UInt(Bits, metaclass=UIntKind): - def __repr__(self): - if not isinstance(self.name, AnonRef): - return repr(self.name) - ts = [repr(t) for t in self.ts] - return 'uint([{}])'.format(', '.join(ts)) + def __neg__(self): + return self.bvneg() - def __getitem__(self, key): - from .conversions import uint - result = super().__getitem__(key) - if isinstance(key, slice): - return uint(result) - return result + def __add__(self, other): + try: + return self.bvadd(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + def __sub__(self, other): + try: + return self.bvsub(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -# def UInt(N, T=None): -# if T is None: -# T = Bit -# assert isinstance(N, IntegerTypes) -# name = 'UInt({})'.format(N) -# return UIntKind(name, (UIntType,), dict(N=N, T=T)) + def __mul__(self, other): + try: + return self.bvmul(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + def __floordiv__(self, other): + try: + return self.bvudiv(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -class SIntKind(BitsKind): - _class_cache = weakref.WeakValueDictionary() - def __getitem__(cls, index): - if isinstance(index, tuple): - width, T = index - else: - width = index - T = Bit - if isinstance(width, SInt): - assert width.const() - # TODO: Move this logic to a method in BitsType - bit_type_to_constant_map = { - GND: 0, - VCC: 1 - } - width = BitVector[len(width)]([bit_type_to_constant_map[x] for x in - width]).as_sint() + def __truediv__(self, other): try: - return SIntKind._class_cache[width, T] - except KeyError: - pass - bases = [cls] - bases = tuple(bases) - class_name = '{}[{}, {}]'.format(cls.__name__, width, T) - t = type(cls)(class_name, bases, dict(T=T, N=width)) - t.__module__ = cls.__module__ - SIntKind._class_cache[width, T] = t - return t + return self.bvudiv(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def __str__(cls): - if cls.isinput(): - return "In(SInt[{}])".format(cls.N) - if cls.isoutput(): - return "Out(SInt[{}])".format(cls.N) - return "SInt[{}]".format(cls.N) + def __mod__(self, other): + try: + return self.bvurem(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def qualify(cls, direction): - if cls.T.isoriented(direction): - return cls - return SInt[cls.N, cls.T.qualify(direction)] + def __eq__(self, other): + try: + return self.bveq(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def flip(cls): - return SInt[cls.N, cls.T.flip()] + def __ne__(self, other): + try: + return self.bvne(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + def __ge__(self, other): + try: + return self.bvuge(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -class SInt(Bits, metaclass=SIntKind): - def __repr__(self): - if not isinstance(self.name, AnonRef): - return repr(self.name) - ts = [repr(t) for t in self.ts] - return 'sint([{}])'.format(', '.join(ts)) + def __gt__(self, other): + try: + return self.bvugt(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def __int__(self): - if not self.const(): - raise Exception("Can't call __int__ on a non-constant") - return SIntVector[len(self)](self.bits()).as_sint() + def __le__(self, other): + try: + return self.bvule(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def sext(self, value): - from .conversions import sext - return sext(self, value) + def __lt__(self, other): + try: + return self.bvult(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -UIntType = UInt -SIntType = SInt +BitsType = Bits -# def SInt(N, T=None): -# if T is None: -# T = Bit -# assert isinstance(N, IntegerTypes) -# name = 'SInt({})'.format(N) -# return SIntKind(name, (SIntType,), dict(N=N, T=T)) +class UInt(Bits): + @bits_cast + def bvult(self, other) -> AbstractBit: + return self.declare_compare_op("ult")()(self, other) -class BFloatKind(BitsKind): - _class_cache = weakref.WeakValueDictionary() + @bits_cast + def bvule(self, other) -> AbstractBit: + # For wiring + if self.is_input(): + return Type.__le__(self, other) + return self.declare_compare_op("ule")()(self, other) - def __getitem__(cls, index): - if isinstance(index, tuple): - width, T = index - else: - width = index - T = Bit - if isinstance(width, BFloat): - assert width.const() - # TODO: Move this logic to a method in BitsType - bit_type_to_constant_map = { - GND: 0, - VCC: 1 - } - width = BitVector[len(width)]([bit_type_to_constant_map[x] for x in - width]).as_uint() + @bits_cast + def bvugt(self, other) -> AbstractBit: + return self.declare_compare_op("ugt")()(self, other) + + @bits_cast + def bvuge(self, other) -> AbstractBit: + return self.declare_compare_op("uge")()(self, other) + + @bits_cast + def bvadd(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("add")()(self, other) + + @bits_cast + def bvsub(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("sub")()(self, other) + + @bits_cast + def bvmul(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("mul")()(self, other) + + @bits_cast + def bvudiv(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("udiv")()(self, other) + + @bits_cast + def bvurem(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("urem")()(self, other) + + def adc(self, other: 'Bits', carry: Bit) -> tp.Tuple['Bits', Bit]: + """ + add with carry + returns a two element tuple of the form (result, carry) + """ + T = type(self) + other = _coerce(T, other) + carry = _coerce(T.unsized_t[1], carry) + + a = self.zext(1) + b = other.zext(1) + c = carry.zext(T.size) + + res = a + b + c + return res[0:-1], res[-1] + + +class SInt(Bits): + @bits_cast + def bvslt(self, other) -> AbstractBit: + return self.declare_compare_op("slt")()(self, other) + + @bits_cast + def bvsle(self, other) -> AbstractBit: + # For wiring + if self.is_input(): + return Type.__le__(self, other) + return self.declare_compare_op("sle")()(self, other) + + @bits_cast + def bvsgt(self, other) -> AbstractBit: + return self.declare_compare_op("sgt")()(self, other) + + @bits_cast + def bvsge(self, other) -> AbstractBit: + return self.declare_compare_op("sge")()(self, other) + + @bits_cast + def bvadd(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("add")()(self, other) + + @bits_cast + def bvsub(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("sub")()(self, other) + + @bits_cast + def bvmul(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("mul")()(self, other) + + @bits_cast + def bvsdiv(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("sdiv")()(self, other) + + @bits_cast + def bvsrem(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("srem")()(self, other) + + def bvneg(self) -> 'AbstractBitVector': + return self.declare_unary_op("neg")()(self) + + @bits_cast + def bvashr(self, other) -> 'AbstractBitVector': + return self.declare_binary_op("ashr")()(self, other) + + def __mod__(self, other): try: - return BFloatKind._class_cache[width, T] - except KeyError: - pass - bases = [cls] - bases = tuple(bases) - class_name = '{}[{}, {}]'.format(cls.__name__, width, T) - t = type(cls)(class_name, bases, dict(T=T, N=width)) - t.__module__ = cls.__module__ - BFloatKind._class_cache[width, T] = t - return t + return self.bvsrem(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def __str__(cls): - if cls.isinput(): - return "In(BFloat[{}])".format(cls.N) - if cls.isoutput(): - return "Out(BFloat[{}])".format(cls.N) - return "BFloat[{}]".format(cls.N) + def __floordiv__(self, other): + try: + return self.bvsdiv(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + + def __truediv__(self, other): + try: + return self.bvsdiv(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def qualify(cls, direction): - if cls.T.isoriented(direction): - return cls - return BFloat[cls.N, cls.T.qualify(direction)] + def __ge__(self, other): + try: + return self.bvsge(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented - def flip(cls): - return BFloat[cls.N, cls.T.flip()] + def __gt__(self, other): + try: + return self.bvsgt(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + def __le__(self, other): + try: + return self.bvsle(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented -class BFloat(Bits, metaclass=BFloatKind): - def __repr__(self): - if not isinstance(self.name, AnonRef): - return repr(self.name) - ts = [repr(t) for t in self.ts] - return 'bfloat([{}])'.format(', '.join(ts)) - - def __getitem__(self, key): - from .conversions import bfloat - result = super().__getitem__(key) - if isinstance(key, slice): - return bfloat(result) - return result + def __lt__(self, other): + try: + return self.bvslt(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + + def __rshift__(self, other): + try: + return self.bvashr(other) + except InconsistentSizeError as e: + raise e from None + except TypeError: + return NotImplemented + + def adc(self, other: 'Bits', carry: Bit) -> tp.Tuple['Bits', Bit]: + """ + add with carry + returns a two element tuple of the form (result, carry) + """ + T = type(self) + other = _coerce(T, other) + carry = _coerce(T.unsized_t[1], carry) + + a = self.sext(1) + b = other.sext(1) + c = carry.zext(T.size) + + res = a + b + c + return res[0:-1], res[-1] + + def sext(self, other) -> 'AbstractBitVector': + ext = int(other) + if ext < 0: + raise ValueError() + + T = type(self).unsized_t + return self.concat(T[ext]([self[-1] for _ in range(ext)])) diff --git a/magma/braid.py b/magma/braid.py index 0f4a522eaf..af957ce2f2 100644 --- a/magma/braid.py +++ b/magma/braid.py @@ -25,9 +25,9 @@ def getdirection(args): a = args[0] if isinstance(a, list): a = a[0] - if a.isinput(): return INPUT - if a.isoutput(): return OUTPUT - if a.isinout(): return INOUT + if a.is_input(): return INPUT + if a.is_output(): return OUTPUT + if a.is_inout(): return INOUT return None # return a list of all the arguments @@ -35,7 +35,7 @@ def getdirection(args): def getargbydirection(interface, direction): args = [] for name, port in interface.ports.items(): - if port.isoriented(direction): + if port.is_oriented(direction): args.append(name) return args @@ -298,7 +298,7 @@ def compose(*circuits): def curry(circuit, prefix='I'): args = [] for name, port in circuit.interface.ports.items(): - if not port.wired() and name == prefix and port.isinput(): + if not port.wired() and name == prefix and port.is_input(): for i in range(len(port)): args.append('{}{}'.format(name, i)) args.append(port[i]) @@ -329,7 +329,7 @@ def uncurry(circuit, prefix='I'): uncurryargs = [] for name, port in circuit.interface.ports.items(): # should we insert the argument in the position of the first match? - if not port.wired() and name.startswith(prefix) and port.isinput(): + if not port.wired() and name.startswith(prefix) and port.is_input(): #print('uncurry', name) uncurryargs.append(port) else: diff --git a/magma/circuit.py b/magma/circuit.py index 95300afb0d..90f1212a36 100644 --- a/magma/circuit.py +++ b/magma/circuit.py @@ -1,32 +1,22 @@ import ast import textwrap -import sys -import six import inspect from functools import wraps -from . import cache_definition -import operator from collections import namedtuple, Counter + +import six +from . import cache_definition from .clock import ClockTypes from .interface import * from .wire import * -from .t import Flip -from .array import ArrayType -from .tuple import TupleType -from .bit import VCC, GND from .config import get_debug_mode from .debug import get_callee_frame_info, debug_info -from .logging import warning from .port import report_wiring_warning, report_wiring_error from .is_definition import isdefinition from magma.syntax.combinational import combinational from magma.syntax.sequential import sequential -from magma.syntax.combinational import combinational -from magma.syntax.sequential import sequential from magma.syntax.verilog import combinational_to_verilog, \ sequential_to_verilog -if sys.version_info > (3, 0): - from functools import reduce __all__ = ['AnonymousCircuitType'] __all__ += ['AnonymousCircuit'] @@ -458,7 +448,7 @@ def check_unconnected(self): for port in self.interface.ports.values(): if issubclass(type(port), ClockTypes): continue - if port.isinput() and not port.driven(): + if port.is_input() and not port.driven(): msg = f"Output port {self.name}.{port.name} not driven" report_wiring_error(msg, self.debug_info) @@ -466,7 +456,7 @@ def check_unconnected(self): for port in inst.interface.ports.values(): if issubclass(type(port), ClockTypes): continue - if port.isinput() and not port.driven(): + if port.is_input() and not port.driven(): msg = f"Input port {inst.name}.{port.name} not driven" report_wiring_error(msg, inst.debug_info) @@ -581,5 +571,18 @@ def wrapped(*args, **kwargs): # Store arguments to generate the circuit. result._generator_arguments = GeneratorArguments(args, kwargs) return result - return wrapped + + +default_port_mapping = { + "I": "in", + "I0": "in0", + "I1": "in1", + "O": "out", + "S": "sel", +} + + +def DeclareCoreirCircuit(*args, **kwargs): + return DeclareCircuit(*args, **kwargs, + renamed_ports=default_port_mapping) diff --git a/magma/clock.py b/magma/clock.py index be0a3bb9a4..64d4858ad0 100644 --- a/magma/clock.py +++ b/magma/clock.py @@ -1,189 +1,66 @@ -from .port import INPUT, OUTPUT, INOUT -from .t import In, Out, InOut -from .bit import Bit, _BitKind, _BitType +from .t import Direction, In +from .digital import DigitalMeta, Digital from .wire import wire -__all__ = ['ClockKind', 'ClockType'] -__all__ += ['Clock', 'ClockIn', 'ClockOut'] -__all__ += ['ResetKind', 'ResetType'] -__all__ += ['Reset', 'ResetIn', 'ResetOut'] - -__all__ += ['ResetNKind', 'ResetNType'] -__all__ += ['ResetN', 'ResetNIn', 'ResetNOut'] - -__all__ += ['AsyncResetKind', 'AsyncResetType'] -__all__ += ['AsyncReset', 'AsyncResetIn', 'AsyncResetOut'] - -__all__ += ['AsyncResetNKind', 'AsyncResetNType'] -__all__ += ['AsyncResetN', 'AsyncResetNIn', 'AsyncResetNOut'] - -__all__ += ['EnableKind', 'EnableType'] -__all__ += ['Enable', 'EnableIn', 'EnableOut'] +class Clock(Digital, metaclass=DigitalMeta): + pass -__all__ += ['ClockInterface', 'ClockTypes'] -__all__ += ['wireclock', 'wireclocktype', 'wiredefaultclock'] +ClockIn = Clock[Direction.In] +ClockOut = Clock[Direction.Out] +# synchronous reset, active high (i.e. reset when signal is 1) +class Reset(Digital, metaclass=DigitalMeta): + pass -class ClockKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(Clock)' - if cls.isoutput(): return 'Out(Clock)' - return 'Clock' - def qualify(cls, direction): - if direction is None: return Clock - elif direction == INPUT: return ClockIn - elif direction == OUTPUT: return ClockOut - return cls +ResetIn = Reset[Direction.In] +ResetOut = Reset[Direction.Out] - def flip(cls): - if cls.isoriented(INPUT): return ClockOut - elif cls.isoriented(OUTPUT): return ClockIn - return cls -class ClockType(_BitType): +# synchronous reset, active low (i.e. reset when signal is 0) +class ResetN(Digital, metaclass=DigitalMeta): pass -Clock = ClockKind('Clock', (ClockType,), {}) -ClockIn = ClockKind('Clock', (ClockType,), dict(direction=INPUT)) -ClockOut = ClockKind('Clock', (ClockType,), dict(direction=OUTPUT)) -# synchronous reset, active high (i.e. reset when signal is 1) -class ResetKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(Reset)' - if cls.isoutput(): return 'Out(Reset)' - return 'Reset' - - def qualify(cls, direction): - if direction is None: return Reset - elif direction == INPUT: return ResetIn - elif direction == OUTPUT: return ResetOut - return cls - - def flip(cls): - if cls.isoriented(INPUT): return ResetOut - elif cls.isoriented(OUTPUT): return ResetIn - return cls - -class ResetType(_BitType): - pass +ResetNIn = ResetN[Direction.In] +ResetNOut = ResetN[Direction.Out] -Reset = ResetKind('Reset', (ResetType,), {}) -ResetIn = ResetKind('Reset', (ResetType,), dict(direction=INPUT)) -ResetOut = ResetKind('Reset', (ResetType,), dict(direction=OUTPUT)) -# synchronous reset, active low (i.e. reset when signal is 0) -class ResetNKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(ResetN)' - if cls.isoutput(): return 'Out(ResetN)' - return 'ResetN' - - def qualify(cls, direction): - if direction is None: return ResetN - elif direction == INPUT: return ResetNIn - elif direction == OUTPUT: return ResetNOut - return cls - - def flip(cls): - if cls.isoriented(INPUT): return ResetNOut - elif cls.isoriented(OUTPUT): return ResetNIn - return cls - -class ResetNType(_BitType): +# asynchronous reset, active high (i.e. reset when signal is 1) +class AsyncReset(Digital, metaclass=DigitalMeta): pass -ResetN = ResetNKind('ResetN', (ResetNType,), {}) -ResetNIn = ResetNKind('ResetN', (ResetNType,), dict(direction=INPUT)) -ResetNOut = ResetNKind('ResetN', (ResetNType,), dict(direction=OUTPUT)) -# asynchronous reset, active high (i.e. reset when signal is 1) -class AsyncResetKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(AsyncReset)' - if cls.isoutput(): return 'Out(AsyncReset)' - return 'AsyncReset' - - def qualify(cls, direction): - if direction is None: return AsyncReset - elif direction == INPUT: return AsyncResetIn - elif direction == OUTPUT: return AsyncResetOut - return cls - - def flip(cls): - if cls.isoriented(INPUT): return AsyncResetOut - elif cls.isoriented(OUTPUT): return AsyncResetIn - return cls - -class AsyncResetType(_BitType): - pass +AsyncResetIn = AsyncReset[Direction.In] +AsyncResetOut = AsyncReset[Direction.Out] -AsyncReset = AsyncResetKind('AsyncReset', (AsyncResetType,), {}) -AsyncResetIn = AsyncResetKind('AsyncReset', (AsyncResetType,), dict(direction=INPUT)) -AsyncResetOut = AsyncResetKind('AsyncReset', (AsyncResetType,), dict(direction=OUTPUT)) # asynchronous reset, active low (i.e. reset when signal is 0) -class AsyncResetNKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(AsyncResetN)' - if cls.isoutput(): return 'Out(AsyncResetN)' - return 'AsyncResetN' - - def qualify(cls, direction): - if direction is None: return AsyncResetN - elif direction == INPUT: return AsyncResetNIn - elif direction == OUTPUT: return AsyncResetNOut - return cls - - def flip(cls): - if cls.isoriented(INPUT): return AsyncResetNOut - elif cls.isoriented(OUTPUT): return AsyncResetNIn - return cls - -class AsyncResetNType(_BitType): +class AsyncResetN(Digital, metaclass=DigitalMeta): pass -AsyncResetN = AsyncResetNKind('AsyncResetN', (AsyncResetNType,), {}) -AsyncResetNIn = AsyncResetNKind('AsyncResetN', (AsyncResetNType,), dict(direction=INPUT)) -AsyncResetNOut = AsyncResetNKind('AsyncResetN', (AsyncResetNType,), dict(direction=OUTPUT)) - -# Preset -# Clear - -class EnableKind(_BitKind): - def __str__(cls): - if cls.isinput(): return 'In(Enable)' - if cls.isoutput(): return 'Out(Enable)' - return 'Enable' - def qualify(cls, direction): - if direction is None: return Enable - elif direction == INPUT: return EnableIn - elif direction == OUTPUT: return EnableOut - return cls +AsyncResetNIn = AsyncResetN[Direction.In] +AsyncResetNOut = AsyncResetN[Direction.Out] - def flip(cls): - if cls.isoriented(INPUT): return EnableOut - elif cls.isoriented(OUTPUT): return EnableIn - return cls -class EnableType(_BitType): +# Preset +# Clear +class Enable(Digital, metaclass=DigitalMeta): pass -Enable = EnableKind('Enable', (EnableType,), {}) -EnableIn = EnableKind('Enable', (EnableType,), dict(direction=INPUT)) -EnableOut = EnableKind('Enable', (EnableType,), dict(direction=OUTPUT)) -ClockTypes = (ClockType, ResetType, AsyncResetType, AsyncResetNType, EnableType) +EnableIn = Enable[Direction.In] +EnableOut = Enable[Direction.Out] + +ClockTypes = (Clock, Reset, AsyncReset, Enable) -def ClockInterface(has_enable=False, has_reset=False, has_set=False, - has_ce=False, has_async_reset=False, - has_async_resetn=False): +def ClockInterface(has_enable=False, has_reset=False, has_ce=False, + has_async_reset=False, has_async_resetn=False): args = ['CLK', In(Clock)] has_enable |= has_ce if has_enable: @@ -198,24 +75,23 @@ def ClockInterface(has_enable=False, has_reset=False, has_set=False, def wireclocktype(defn, inst, clocktype): - #print('wiring clocks', str(defn), str(inst)) defnclk = [] - for name, port in defn.interface.ports.items(): - if isinstance(port, clocktype) and port.isoutput(): - #print('defn clock', port) - defnclk += [port] + for port in defn.interface.ports.values(): + if isinstance(port, clocktype) and port.is_output(): + defnclk += [port] if defnclk: - defnclk = defnclk[0] # wire first clock - for name, port in inst.interface.ports.items(): - if isinstance(port, clocktype) and port.isinput() and not port.driven(): - #print('inst clock', port) - wire(defnclk, port) + defnclk = defnclk[0] # wire first clock + for port in inst.interface.ports.values(): + if isinstance(port, clocktype) and port.is_input() and not port.driven(): + wire(defnclk, port) + def wiredefaultclock(defn, inst): - wireclocktype(defn, inst, ClockType) + wireclocktype(defn, inst, Clock) + def wireclock(define, circuit): - wireclocktype(define, circuit, ResetType) - wireclocktype(define, circuit, AsyncResetType) - wireclocktype(define, circuit, AsyncResetNType) - wireclocktype(define, circuit, EnableType) + wireclocktype(define, circuit, Reset) + wireclocktype(define, circuit, AsyncReset) + wireclocktype(define, circuit, AsyncResetN) + wireclocktype(define, circuit, Enable) diff --git a/magma/conversions.py b/magma/conversions.py index 8c77577180..1433ba91e6 100644 --- a/magma/conversions.py +++ b/magma/conversions.py @@ -1,17 +1,16 @@ import functools from collections.abc import Sequence from .compatibility import IntegerTypes -from .t import In, Out, InOut, INPUT, OUTPUT, INOUT -from .bit import _BitKind, _BitType, Bit, BitType, VCC, GND -from .clock import ClockType, Clock, \ - Reset, ResetType, \ - AsyncReset, AsyncResetType, \ - AsyncResetN, AsyncResetNType, \ - Enable, EnableType -from .array import ArrayType, Array, ArrayKind -from .bits import BitsType, Bits, UIntType, UInt, SIntType, SInt, UIntKind, \ - SIntKind, BFloat -from .tuple import TupleType, tuple_ as tuple_imported, TupleKind, namedtuple +from .t import In, Out, InOut, Direction +from .digital import Digital +from .bit import Bit, VCC, GND +from .digital import DigitalMeta +from .clock import Clock, Reset, AsyncReset, AsyncResetN, Enable +from .array import Array +from .bits import Bits, UInt, SInt +from .bfloat import BFloat +from .digital import Digital +from .tuple import Tuple, tuple_ as tuple_imported, namedtuple from .bitutils import int2seq import magma as m import hwtypes @@ -27,16 +26,15 @@ __all__ += ['concat', 'repeat'] __all__ += ['sext', 'zext'] - def can_convert_to_bit(value): - return isinstance(value, (_BitType, ArrayType, TupleType, IntegerTypes)) + return isinstance(value, (Digital, Array, Tuple, IntegerTypes)) def can_convert_to_bit_type(value): - return isinstance(value, (_BitKind, ArrayKind, TupleKind)) + return issubclass(value, (Digital, Array, Tuple)) -def convertbit(value, totype, T): +def convertbit(value, totype): if isinstance(value, totype): return value @@ -45,63 +43,63 @@ def convertbit(value, totype, T): "bit can only be used on a Bit, an Array, or an int" f"; not {type(value)}") - if isinstance(value, (ArrayType, TupleType)): + if isinstance(value, (Array, Tuple)): if len(value) != 1: raise ValueError( "bit can only be used on arrays and tuples of length 1" f"; not {type(value)}") value = value[0] - if not isinstance(value, _BitType): + if not isinstance(value, Digital): raise ValueError( "bit can only be used on arrays and tuples of bits" f"; not {type(value)}") - assert isinstance(value, (IntegerTypes, _BitType)) + assert isinstance(value, (IntegerTypes, Digital)) if isinstance(value, IntegerTypes): value = VCC if value else GND - if value.isinput(): - b = In(T)(name=value.name) - elif value.isoutput(): - b = Out(T)(name=value.name) + if value.is_input(): + b = In(totype)(name=value.name) + elif value.is_output(): + b = Out(totype)(name=value.name) else: - b = T() + b = totype() b.port = value.port return b def bit(value): - return convertbit(value, BitType, Bit) + return convertbit(value, Bit) def clock(value): - return convertbit(value, ClockType, Clock) + return convertbit(value, Clock) def reset(value): - return convertbit(value, ResetType, Reset) + return convertbit(value, Reset) def asyncreset(value): - return convertbit(value, AsyncResetType, AsyncReset) + return convertbit(value, AsyncReset) def asyncresetn(value): - return convertbit(value, AsyncResetNType, AsyncResetN) + return convertbit(value, AsyncResetN) def enable(value): - return convertbit(value, EnableType, Enable) + return convertbit(value, Enable) -def convertbits(value, n, totype, totypeconstructor, checkbit): +def convertbits(value, n, totype, checkbit): if isinstance(value, totype): if n is not None and n != len(value): raise ValueError("converting a value should not change the size, use concat, zext, or sext instead.") return value - convertible_types = (_BitType, TupleType, ArrayType, IntegerTypes, + convertible_types = (Digital, Tuple, Array, IntegerTypes, Sequence) if not isinstance(value, convertible_types): raise ValueError( @@ -115,7 +113,7 @@ def convertbits(value, n, totype, totypeconstructor, checkbit): ts = int2seq(value, n) elif isinstance(value, Sequence): ts = list(value) - elif isinstance(value, _BitType): + elif isinstance(value, Digital): if n is None: ts = [value] else: @@ -135,7 +133,7 @@ def convertbits(value, n, totype, totypeconstructor, checkbit): # check that they are all the same for t in Ts: if checkbit: - if not isinstance(t, _BitKind): + if not isinstance(t, DigitalMeta): raise ValueError( "bits can only be used on Arrays or Tuples containing bits" f", not : {t}") @@ -153,36 +151,36 @@ def convertbits(value, n, totype, totypeconstructor, checkbit): if convert_to_bit is True: ts = [bit(t) for t in ts] T = { - INPUT: In, - OUTPUT: Out, - INOUT: InOut + Direction.In: In, + Direction.Out: Out, + Direction.InOut: InOut }[T.direction](Bit) - return totypeconstructor[len(Ts), T](*ts) + return totype[len(Ts), T](*ts) def array(value, n=None): - return convertbits(value, n, ArrayType, Array, False) + return convertbits(value, n, Array, False) def bits(value, n=None): - return convertbits(value, n, BitsType, Bits, True) + return convertbits(value, n, Bits, True) def uint(value, n=None): - if isinstance(value, SIntType): + if isinstance(value, SInt): raise ValueError("uint cannot convert SInt") - return convertbits(value, n, UIntType, UInt, True) + return convertbits(value, n, UInt, True) def sint(value, n=None): - if isinstance(value, UIntType): + if isinstance(value, UInt): raise ValueError("uint cannot convert SInt") - return convertbits(value, n, SIntType, SInt, True) + return convertbits(value, n, SInt, True) def bfloat(value, n=None): - return convertbits(value, n, BFloat, BFloat, True) + return convertbits(value, n, BFloat, True) def concat(*arrays): @@ -196,7 +194,7 @@ def concat(*arrays): def repeat(value, n): - if isinstance(value, BitType): + if isinstance(value, Bit): repeats = bits(n * [value]) else: repeats = array(n * [value]) @@ -206,7 +204,7 @@ def repeat(value, n): def check_value_is_not_input(fn): @functools.wraps(fn) def wrapped(value, n): - if isinstance(value, m.Type) and not value.isoutput(): + if isinstance(value, m.Type) and not value.is_output(): raise Exception(f"{fn.__name__} only works with non input values") return fn(value, n) return wrapped @@ -214,29 +212,29 @@ def wrapped(value, n): # @check_value_is_not_input def zext(value, n): - assert isinstance(value, (UIntType, SIntType, BitsType)) or \ - isinstance(value, ArrayType) and isinstance(value.T, _BitKind) - if isinstance(value, UIntType): + assert isinstance(value, (UInt, SInt, Bits)) or \ + isinstance(value, Array) and isinstance(value.T, Digital) + if isinstance(value, UInt): zeros = uint(0, n) - elif isinstance(value, SIntType): + elif isinstance(value, SInt): zeros = sint(0, n) - elif isinstance(value, BitsType): + elif isinstance(value, Bits): zeros = bits(0, n) - elif isinstance(value, ArrayType): + elif isinstance(value, Array): zeros = array(0, n) result = concat(value, zeros) - if isinstance(value, UIntType): + if isinstance(value, UInt): return uint(result) - elif isinstance(value, SIntType): + elif isinstance(value, SInt): return sint(result) - elif isinstance(value, BitsType): + elif isinstance(value, Bits): return bits(result) return result # @check_value_is_not_input def sext(value, n): - assert isinstance(value, SIntType) + assert isinstance(value, SInt) return sint(concat(array(value), array(value[-1], n))) diff --git a/magma/digital.py b/magma/digital.py new file mode 100644 index 0000000000..d1d1bac92b --- /dev/null +++ b/magma/digital.py @@ -0,0 +1,196 @@ +import weakref +from abc import ABCMeta +from .t import Kind, Direction, Type +from .debug import debug_wire, get_callee_frame_info +from .port import report_wiring_error, Port +from .compatibility import IntegerTypes + + +class DigitalMeta(ABCMeta, Kind): + _class_cache = weakref.WeakValueDictionary() + + def __new__(cls, name, bases, namespace, info=(None, None), **kwargs): + # TODO: A lot of this code is shared with AbstractBitVectorMeta, we + # should refactor to reuse + if '_info_' in namespace: + raise TypeError( + 'class attribute _info_ is reversed by the type machinery') + + direction = info[1] + for base in bases: + if getattr(base, 'is_directed', False): + if direction is None: + direction = base.direction + elif direction != base.direction: + raise TypeError( + "Can't inherit from multiple different directions") + + namespace['_info_'] = info[0], direction + type_ = super().__new__(cls, name, bases, namespace, **kwargs) + if direction is None: + # class is unundirected so t.unundirected_t -> t + type_._info_ = type_, direction + elif info[0] is None: + # class inherited from directed types so there is no unundirected_t + type_._info_ = None, direction + + return type_ + + def __getitem__(cls, direction: Direction) -> 'DigitalMeta': + mcs = type(cls) + try: + return mcs._class_cache[cls, direction] + except KeyError: + pass + + if not isinstance(direction, Direction): + raise TypeError('Direction of Digital must be an instance of ' + 'm.Direction') + + if cls.is_directed: + if direction == cls.direction: + return cls + elif direction == direction.Flip: + if cls.direction == direction.In: + return cls[direction.Out] + elif cls.direction == direction.Out: + return cls[direction.In] + else: + # Flip of inout is inout + return cls + else: + return cls.undirected_t[direction] + + bases = [cls] + bases.extend(b[direction] for b in cls.__bases__ if isinstance(b, mcs)) + bases = tuple(bases) + orig_name = cls.__name__ + class_name = '{}[{}]'.format(orig_name, direction.name) + type_ = mcs(class_name, bases, {"orig_name": orig_name}, + info=(cls, direction)) + type_.__module__ = cls.__module__ + mcs._class_cache[cls, direction] = type_ + return type_ + + 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, Digital), type(value) + result(value) + return result + + def __repr__(cls): + return str(cls) + + def __str__(cls): + name = getattr(cls, "orig_name", cls.__name__) + if cls.is_input(): + name = f"In({name})" + elif cls.is_output(): + name = f"Out({name})" + elif cls.is_inout(): + name = f"InOut({name})" + return name + + @property + def undirected_t(cls) -> 'DigitalMeta': + t = cls._info_[0] + if t is not None: + return t + else: + raise AttributeError('type {} has no undirected_t'.format(cls)) + + @property + def direction(cls) -> int: + return cls._info_[1] + + @property + def is_directed(cls) -> bool: + return cls.direction is not None + + def __len__(cls): + return 1 + + def qualify(cls, direction): + return cls[direction] + + def flip(cls): + return cls.qualify(Direction.Flip) + + def __eq__(cls, rhs): + return cls is rhs + + __hash__ = type.__hash__ + + +class Digital(Type, metaclass=DigitalMeta): + def __init__(self, value=None, name=None): + super().__init__(name=name) + self.port = Port(self) + + @classmethod + def is_oriented(cls, direction): + return cls.direction == direction + + def __call__(self, output): + return self.wire(output, get_callee_frame_info()) + + @debug_wire + def wire(self, o, debug_info): + i = self + # promote integer types to LOW/HIGH + if isinstance(o, IntegerTypes): + o = HIGH if o else LOW + + if not isinstance(o, Digital): + report_wiring_error(f'Cannot wire {i.debug_name} (type={type(i)}) ' + f'to {o} (type={type(o)}) because ' + f'{o.debug_name} is not a Digital', debug_info) + return + + i.port.wire(o.port, debug_info) + i.debug_info = debug_info + o.debug_info = debug_info + + def wired(self): + return self.port.wired() + + # return the input or output Bit connected to this Bit + def trace(self): + t = self.port.trace() + if t: + t = t.bit + return t + + # return the output Bit connected to this input Bit + def value(self): + t = self.port.value() + if t: + t = t.bit + return t + + def driven(self): + return self.port.driven() + + def flatten(self): + return [self] + + def const(self): + return self is VCC or self is GND + + def unwire(i, o): + i.port.unwire(o.port) + + @classmethod + def flat_length(cls): + return 1 + + +VCC = Digital[Direction.Out](name="VCC") +GND = Digital[Direction.Out](name="GND") + +HIGH = VCC +LOW = GND diff --git a/magma/fromverilog.py b/magma/fromverilog.py index 8aa848acdf..710d3cd87b 100755 --- a/magma/fromverilog.py +++ b/magma/fromverilog.py @@ -10,8 +10,9 @@ import pyverilog.vparser.ast as pyverilog_ast from .t import In, Out, InOut -from .bit import Bit, _BitKind -from .bits import Bits, BitsKind +from .bit import Bit +from .bits import Bits +from .digital import Digital from .array import Array from .circuit import DeclareCircuit, DefineCircuit, EndDefine @@ -77,12 +78,12 @@ def sort(self): def convert(input_type, target_type): - if isinstance(input_type, _BitKind) and \ - isinstance(target_type, _BitKind) and \ + if issubclass(input_type, Digital) and \ + issubclass(target_type, Digital) and \ input_type.direction == target_type.direction: return target_type - if isinstance(input_type, BitsKind) and \ - isinstance(target_type, BitsKind) and \ + if issubclass(input_type, Bits) and \ + issubclass(target_type, Bits) and \ input_type.N == target_type.N and \ input_type.T.direction == target_type.T.direction: return target_type diff --git a/magma/frontend/coreir_.py b/magma/frontend/coreir_.py index 5d8b8d6f99..9de7f3b9af 100644 --- a/magma/frontend/coreir_.py +++ b/magma/frontend/coreir_.py @@ -1,7 +1,7 @@ from magma import cache_definition from magma.backend.coreir_ import CoreIRBackend, CoreIRContextSingleton from magma.circuit import DefineCircuitKind, Circuit -from magma import cache_definition, Clock, Array, BitIn, BitOut, Tuple +from magma import cache_definition, Clock, Array, BitIn, BitOut, Product from coreir.generator import Generator @cache_definition @@ -20,7 +20,8 @@ def GetMagmaContext(): def _get_ports_as_list(ports): - return [item for i in range(ports.N) for item in [ports.Ks[i], ports.Ts[i]]] + return [item for i in range(len(ports.keys())) for item in + [list(ports.keys())[i], list(ports.types())[i]]] def _get_ports(coreir_type, renamed_ports): @@ -39,7 +40,7 @@ def _get_ports(coreir_type, renamed_ports): name = "I" renamed_ports[name] = "in" elements[name] = _get_ports(item[1], renamed_ports) - return Tuple(**elements) + return Product.from_fields("anon", elements) elif (coreir_type.kind == "Named"): # exception to handle clock types, since other named types not handled if coreir_type.name in _coreirNamedTypeToPortDict: diff --git a/magma/interface.py b/magma/interface.py index e03536962a..8bd2bf594c 100644 --- a/magma/interface.py +++ b/magma/interface.py @@ -4,9 +4,9 @@ from .ref import AnonRef, InstRef, DefnRef from .t import Type, Kind from .port import INPUT, OUTPUT, INOUT -from .clock import ClockType, ClockTypes -from .array import ArrayType -from .tuple import TupleType +from .clock import Clock, ClockTypes +from .array import Array +from .tuple import Tuple from .compatibility import IntegerTypes, StringTypes @@ -52,10 +52,10 @@ def __str__(self): def __repr__(self): s = "" for name, input in self.ports.items(): - if not input.isinput(): + if not input.is_input(): continue output = input.value() - if isinstance(output, (ArrayType, TupleType)): + if isinstance(output, (Array, Tuple)): if not output.iswhole(output.ts): for i in range(len(input)): iname = repr(input[i]) @@ -93,13 +93,13 @@ def arguments(self): def inputs(self, include_clocks=False): """Return all the argument input ports.""" - fn = lambda port: port.isinput() and \ + fn = lambda port: port.is_input() and \ (not isinstance(port, ClockTypes) or include_clocks) return list(filter(fn, self.ports.values())) def outputs(self): """Return all the argument output ports.""" - return list(filter(lambda port: port.isoutput(), self.ports.values())) + return list(filter(lambda port: port.is_output(), self.ports.values())) def args(self): """Return all the arguments as name, port.""" @@ -115,12 +115,12 @@ def decl(self): def inputargs(self): """Return all the input arguments as name, port.""" return _flatten([name, port] for name, port in self.ports.items() - if port.isinput() and not isinstance(port, ClockTypes)) + if port.is_input() and not isinstance(port, ClockTypes)) def outputargs(self): """Return all the output arguments as name, port.""" return _flatten([name, port] for name, port in self.ports.items() - if port.isoutput()) + if port.is_output()) def clockargs(self): """Return all the clock arguments as name, port.""" diff --git a/magma/operators.py b/magma/operators.py index 0754a45f51..3abfefe06f 100644 --- a/magma/operators.py +++ b/magma/operators.py @@ -1,4 +1,4 @@ -from magma import _BitType, BitType, BitsType, UIntType, SIntType +from magma import Digital, Bit, Bits, UInt, SInt class MantleImportError(RuntimeError): @@ -34,7 +34,7 @@ def wrapped(self, other): for op in ("__eq__", "__ne__"): - setattr(_BitType, op, raise_mantle_import_error_binary) + setattr(Digital, op, raise_mantle_import_error_binary) for op in ( "__and__", @@ -52,12 +52,12 @@ def wrapped(self, other): "__ge__" ): if op == "__invert__": - setattr(_BitType, op, - define_raise_undefined_operator_error("_BitType", op, "unary")) + setattr(Digital, op, + define_raise_undefined_operator_error("Digital", op, "unary")) else: setattr( - _BitType, op, - define_raise_undefined_operator_error("_BitType", op, "binary")) + Digital, op, + define_raise_undefined_operator_error("Digital", op, "binary")) for op in ("__and__", @@ -66,9 +66,9 @@ def wrapped(self, other): "__invert__" ): if op == "__invert__": - setattr(BitType, op, raise_mantle_import_error_unary) + setattr(Bit, op, raise_mantle_import_error_unary) else: - setattr(BitType, op, raise_mantle_import_error_binary) + setattr(Bit, op, raise_mantle_import_error_binary) for op in ("__and__", @@ -79,9 +79,9 @@ def wrapped(self, other): "__rshift__", ): if op == "__invert__": - setattr(BitsType, op, raise_mantle_import_error_unary) + setattr(Bits, op, raise_mantle_import_error_unary) else: - setattr(BitsType, op, raise_mantle_import_error_binary) + setattr(Bits, op, raise_mantle_import_error_binary) for op in ("__add__", "__sub__", @@ -93,8 +93,8 @@ def wrapped(self, other): "__gt__", "__ge__" ): - setattr(BitsType, op, - define_raise_undefined_operator_error("BitsType", op, "binary")) + setattr(Bits, op, + define_raise_undefined_operator_error("Bits", op, "binary")) for op in ("__add__", "__sub__", @@ -106,5 +106,5 @@ def wrapped(self, other): "__gt__", "__ge__" ): - setattr(SIntType, op, raise_mantle_import_error_binary) - setattr(UIntType, op, raise_mantle_import_error_binary) + setattr(SInt, op, raise_mantle_import_error_binary) + setattr(UInt, op, raise_mantle_import_error_binary) diff --git a/magma/port.py b/magma/port.py index 3e505a6f0f..aaedc07c73 100644 --- a/magma/port.py +++ b/magma/port.py @@ -1,6 +1,7 @@ from .config import get_debug_mode from .logging import error, warning, get_source_line from .backend.util import make_relative +from .t import Direction __all__ = ['INPUT', 'OUTPUT', 'INOUT'] @@ -8,9 +9,9 @@ __all__ += ['Port'] -INPUT = 'input' -OUTPUT = 'output' -INOUT = 'inout' +INPUT = Direction.In +OUTPUT = Direction.Out +INOUT = Direction.InOut def _report_wiring_messgae(fn, message, debug_info): @@ -99,7 +100,7 @@ def connect( self, o, i , debug_info): """ if not o.anon(): - if o.bit.isinput(): + if o.bit.is_input(): report_wiring_error(f"Using `{o.bit.debug_name}` (an input) as " f"an output", debug_info) return @@ -115,7 +116,7 @@ def connect( self, o, i , debug_info): self.outputs.append(o) if not i.anon(): - if i.bit.isoutput(): + if i.bit.is_output(): report_wiring_error(f"Using `{i.bit.debug_name}` (an output) " f"as an input", debug_info) return @@ -129,11 +130,11 @@ def connect( self, o, i , debug_info): def check(self): for o in self.inputs: - if o.isoutput(): + if o.is_output(): error("Output in the wire inputs: {}".format(o)) for o in self.outputs: - if o.isinput(): + if o.is_input(): error("Input in the wire outputs: {}".format(o)) return False diff --git a/magma/product.py b/magma/product.py deleted file mode 100644 index 957461ab37..0000000000 --- a/magma/product.py +++ /dev/null @@ -1,15 +0,0 @@ -import dataclasses as dc -from hwtypes.adt_meta import ProductMeta -import magma as m -from collections import OrderedDict - - -class MagmaProductMeta(ProductMeta): - @classmethod - def _from_fields(mcs, fields, name, bases, ns, **kwargs): - assert fields - return m.Tuple(**fields) - - -class Product(metaclass=MagmaProductMeta): - pass diff --git a/magma/simulator/coreir_simulator.py b/magma/simulator/coreir_simulator.py index f9f329454d..d8f20da3eb 100644 --- a/magma/simulator/coreir_simulator.py +++ b/magma/simulator/coreir_simulator.py @@ -6,11 +6,11 @@ from ..frontend.coreir_ import GetMagmaContext from ..scope import Scope from ..ref import DefnRef, ArrayRef, TupleRef -from ..array import ArrayType -from ..tuple import TupleType -from ..bit import BitKind +from ..array import Array +from ..tuple import Tuple +from ..bit import Bit from ..bitutils import int2seq -from ..clock import ClockType +from ..clock import Clock from ..transforms import setup_clocks, flatten from ..circuit import CircuitType from ..uniquification import uniquification_pass, UniquificationMode @@ -58,7 +58,7 @@ def flattened_name(name): if isinstance(name, ArrayRef): array_name = flattened_name(name.array.name) # CoreIR simulator doesn't flatten array of bits - if isinstance(name.array.T, BitKind): + if issubclass(name.array.T, Bit): return f"{array_name}.{name.index}" else: return f"{array_name}_{name.index}" @@ -168,16 +168,16 @@ def __init__(self, circuit, clock, coreir_filename=None, context=None, os.remove(coreir_filename) def create_zeros_init(arrOrTuple): - if isinstance(arrOrTuple, ArrayType): + if isinstance(arrOrTuple, Array): return [create_zeros_init(el) for el in arrOrTuple.ts] - elif isinstance(arrOrTuple, TupleType): - return {k: create_zeros_init(v) for k,v in zip(arrOrTuple.Ks, arrOrTuple.ts)} + elif isinstance(arrOrTuple, Tuple): + return {k: create_zeros_init(v) for k,v in zip(arrOrTuple.keys(), arrOrTuple.values())} else: return 0 # Need to set values for all circuit inputs or interpreter crashes for topin in circuit.interface.outputs(): - if not isinstance(topin, ClockType): + if not isinstance(topin, Clock): arr = topin init = create_zeros_init(arr) @@ -190,7 +190,7 @@ def create_zeros_init(arrOrTuple): self.simulator_state.reset_circuit() for topin in circuit.interface.outputs(): - if isinstance(topin, ClockType): + if isinstance(topin, Clock): insts, ports = convert_to_coreir_path(topin, Scope()) self.simulator_state.set_clock_value(old_style_path(insts, ports), True, False) @@ -207,14 +207,14 @@ def get_value(self, bit, scope=None): return True if bit == VCC else False # Symbol table doesn't support arrays of arrays - if isinstance(bit, ArrayType) and (isinstance(bit[0], ArrayType) or isinstance(bit[0], TupleType)): + if isinstance(bit, Array) and (isinstance(bit[0], Array) or isinstance(bit[0], Tuple)): r = [] for arr in bit: r.append(self.get_value(arr, scope)) return r - elif isinstance(bit, TupleType): + elif isinstance(bit, Tuple): r = {} - for k,v in zip(bit.Ks, bit.ts): + for k,v in zip(bit.keys(), bit.values()): r[k] = self.get_value(v, scope) return r else: @@ -228,14 +228,14 @@ def get_value(self, bit, scope=None): def set_value(self, bit, newval, scope=None): if scope is None: scope = self.default_scope - if isinstance(bit, ArrayType) and len(newval) != len(bit): + if isinstance(bit, Array) and len(newval) != len(bit): raise ValueError(f"Excepted a value of lengh {len(bit)} not" f" {len(newval)}") - if isinstance(bit, ArrayType) and (isinstance(bit[0], ArrayType) or isinstance(bit[0], TupleType)): + if isinstance(bit, Array) and (isinstance(bit[0], Array) or isinstance(bit[0], Tuple)): for i, arr in enumerate(bit): self.set_value(arr, newval[i], scope) - elif isinstance(bit, TupleType): - for k,v in zip(bit.Ks, bit.ts): + elif isinstance(bit, Tuple): + for k,v in zip(bit.keys(), bit.values()): self.set_value(v, newval[k], scope) else: insts, ports = convert_to_coreir_path(bit, scope) diff --git a/magma/simulator/mdb.py b/magma/simulator/mdb.py index b3df8c5a4e..199c8f2b00 100644 --- a/magma/simulator/mdb.py +++ b/magma/simulator/mdb.py @@ -4,8 +4,8 @@ from ..is_definition import isdefinition from ..circuit import CircuitType, EndCircuit from ..scope import * -from ..array import ArrayType -from ..bit import BitType +from ..array import Array +from ..bit import Bit from ..bitutils import seq2int, int2seq from ..ref import InstRef, DefnRef from ..compatibility import builtins @@ -68,16 +68,16 @@ def describe_instance(inst): def describe_interface(interface): print("\nInterface Inputs:") for name, bit in interface.ports.items(): - if bit.isoutput(): - if isinstance(bit, ArrayType): + if bit.is_output(): + if isinstance(bit, Array): print(" Bit[" + str(len(bit)) + "]:" + name) else: print(" Bit: " + name) print("\nInterface Outputs:") for name, bit in interface.ports.items(): - if bit.isinput(): - if isinstance(bit, ArrayType): + if bit.is_input(): + if isinstance(bit, Array): print(" Bit[" + str(len(bit)) + "]:" + name) else: print(" Bit: " + name) @@ -110,7 +110,7 @@ def format_val(val, bit, raw): if raw: return "".join(['1' if e else '0' for e in reversed(val)]) else: - if not isinstance(bit, ArrayType) or isinstance(val, bool): + if not isinstance(bit, Array) or isinstance(val, bool): val = [val] return seq2int(val) @@ -355,7 +355,7 @@ def parse_print(self, arg, raw): print_err("Failed to print: {}".format(e)) return - if isinstance(printme, BitType) or isinstance(printme, ArrayType): + if isinstance(printme, Bit) or isinstance(printme, Array): self.log_val(printme, scope, raw) elif isinstance(printme, CircuitType): inst_desc = describe_instance(printme) + ": " @@ -429,7 +429,7 @@ def do_watch(self, arg): else: value = None - if not isinstance(watchme, BitType) and not isinstance(watchme, ArrayType): + if not isinstance(watchme, Bit) and not isinstance(watchme, Array): print_err("Can only watch bits or arrays") watch_num = self.simulator.add_watchpoint(watchme, scope, value) @@ -460,7 +460,7 @@ def do_display(self, arg): try: bit, scope = self.parse_circuit(arg) - if not isinstance(bit, BitType) and not isinstance(bit, ArrayType): + if not isinstance(bit, Bit) and not isinstance(bit, Array): raise SimulationConsoleException("Can only display bits or arrays") display_expr = DisplayExpr(bit, arg, scope) @@ -618,7 +618,7 @@ def do_waveform(self, arg): print_err("Invalid argument for waveform: {}".format(e)) return - if not isinstance(waveme, BitType) and not isinstance(waveme, ArrayType): + if not isinstance(waveme, Bit) and not isinstance(waveme, Array): print_err("Can only provide waveforms for wires") return diff --git a/magma/simulator/python_simulator.py b/magma/simulator/python_simulator.py index 8de3459e75..a0ebfa5b20 100644 --- a/magma/simulator/python_simulator.py +++ b/magma/simulator/python_simulator.py @@ -11,13 +11,13 @@ from ..transforms import flatten, setup_clocks from ..circuit import * from ..scope import * -from ..bit import VCC, GND, BitType, _BitType -from ..array import ArrayType -from ..bits import SIntType, BitsType, UIntType +from ..bit import VCC, GND, Bit, Digital +from ..array import Array +from ..bits import SInt, Bits, UInt from hwtypes import BitVector import hwtypes from ..bitutils import seq2int -from ..clock import ClockType +from ..clock import Clock __all__ = ['PythonSimulator'] @@ -39,10 +39,10 @@ def __init__(self, primitive, value_store): self.state_store = {} for bit in self.primitive.interface.ports.values(): - if not isinstance(bit, ArrayType): + if not isinstance(bit, Array): bit = [bit] for b in bit: - if b.isinput(): + if b.is_input(): self.inputs.append(b) else: self.outputs.append(b) @@ -93,14 +93,14 @@ def __init__(self): self.value_map = {} def value_initialized(self, bit): - if isinstance(bit, ArrayType): + if isinstance(bit, Array): for b in bit: if not self.value_initialized(b): return False return True - if bit.isinput(): + if bit.is_input(): bit = bit.value() if bit.const(): @@ -109,17 +109,17 @@ def value_initialized(self, bit): return bit in self.value_map def get_value(self, bit): - if isinstance(bit, ArrayType): + if isinstance(bit, Array): value = [self.get_value(b) for b in bit] - if isinstance(bit, SIntType): + if isinstance(bit, SInt): return BitVector[len(bit)](value).as_sint() - elif isinstance(bit, UIntType): + elif isinstance(bit, UInt): return BitVector[len(bit)](value).as_uint() - elif isinstance(bit, BitsType): + elif isinstance(bit, Bits): return BitVector[len(bit)](value) return value - if bit.isinput(): + if bit.is_input(): bit = bit.value() if bit.const(): @@ -128,18 +128,18 @@ def get_value(self, bit): return self.value_map[bit] def set_value(self, bit, newval): - if not bit.isoutput(): + if not bit.is_output(): raise TypeError("Can only call set value on an input") - if isinstance(bit, ArrayType): + if isinstance(bit, Array): if isinstance(newval, BitVector): newval = newval.as_bool_list() - elif isinstance(newval, BitsType): + elif isinstance(newval, Bits): if not newval.const(): - raise ValueError("Calling set_value with a BitsType only works with a constant") + raise ValueError("Calling set_value with a Bits only works with a constant") newval = newval.bits() - elif isinstance(bit, BitsType) and isinstance(newval, int): - if not isinstance(bit, SIntType) and newval < 0: + elif isinstance(bit, Bits) and isinstance(newval, int): + if not isinstance(bit, SInt) and newval < 0: raise ValueError(f"Can only set {bit} of type {type(bit)} with positive integer, not {newval}") newval = BitVector[len(bit)](newval).as_bool_list() elif not isinstance(newval, list): @@ -167,11 +167,11 @@ def __setup_primitives(self): return wrapped def initialize(self, bit): - if isinstance(bit, ArrayType): + if isinstance(bit, Array): for b in bit: self.initialize(b) else: - if bit.isoutput(): + if bit.is_output(): self.circuit_inputs.append(bit) self.value_store.set_value(bit, False) else: @@ -189,7 +189,7 @@ def __setup_circuit(self, clock): def __outputs_initialized(self): for bit in self.circuit_outputs: - assert bit.isinput() + assert bit.is_input() if not self.value_store.value_initialized(bit): return False @@ -261,8 +261,8 @@ def __step(self): def __init__(self, main_circuit, clock=None): if isinstance(main_circuit, CircuitType): raise ValueError("PythonSimulator must be called with a Circuit definition, not an instance") - if clock is not None and not isinstance(clock, ClockType): - raise ValueError("clock must be a ClockType or None") + if clock is not None and not isinstance(clock, Clock): + raise ValueError("clock must be a Clock or None") setup_clocks(main_circuit) self.main_circuit = main_circuit self.txfm = flatten(main_circuit) @@ -306,11 +306,11 @@ def set_value(self, bit, newval, scope=None): def is_circuit_input(self, value): """ Checks if `value` is in `self.circuit_inputs`. - If `value` is an `ArrayType`, it recursively checks the elements + If `value` is an `Array`, it recursively checks the elements """ - if isinstance(value, _BitType): + if isinstance(value, Digital): return any(value is x for x in self.circuit_inputs) - elif isinstance(value, ArrayType): + elif isinstance(value, Array): return all(self.is_circuit_input(elem) for elem in value) else: raise NotImplementedError(type(value)) @@ -381,9 +381,9 @@ def __call__(self, *largs): j = 0 for name, port in circuit.interface.ports.items(): - if port.isoutput(): + if port.is_output(): val = largs[j] - if isinstance(port, ArrayType): + if isinstance(port, Array): n = type(port).N val = BitVector[n](val) self.set_value(getattr(circuit, name), val) @@ -393,7 +393,7 @@ def __call__(self, *largs): outs = [] for name, port in circuit.interface.ports.items(): - if port.isinput(): + if port.is_input(): val = self.get_value(getattr(circuit, name)) val = seq2int(val) if isinstance(val, list) else int(val) outs.append(val) diff --git a/magma/syntax/sequential.py b/magma/syntax/sequential.py index c7dc0ae168..39e6560553 100644 --- a/magma/syntax/sequential.py +++ b/magma/syntax/sequential.py @@ -90,7 +90,7 @@ def visit_Return(self, node): elts.append(ast.Name(f"self_{name}_I", ast.Load())) else: for port in eval_value.interface.inputs(): - if isinstance(port, (m.ClockType, m.AsyncResetType)): + if isinstance(port, (m.Clock, m.AsyncReset)): continue elts.append(ast.Name(f"self_{name}_{port}", ast.Load())) if isinstance(node.value, ast.Tuple): @@ -171,7 +171,7 @@ def __call__(self, I): circuit_definition_template = """ -from magma import In, Out, Bit +from magma import Bit, Array, Tuple, Product, Bits, SInt, UInt def make_{circuit_name}(combinational): class {circuit_name}(m.Circuit): @@ -196,21 +196,21 @@ def gen_array_str(eval_type, eval_value, async_reset): def gen_reg_inst_str(eval_type, eval_value, async_reset): - if isinstance(eval_type, m._BitKind): + if issubclass(eval_type, m.Digital): n = None if isinstance(eval_value, (bool, int)): init = bool(eval_value) else: assert eval_value.name.name in ["GND", "VCC"], eval_value.name init = 0 if eval_value.name.name == "GND" else 1 - elif isinstance(eval_type, m.ArrayKind) and \ - isinstance(eval_type.T, m._BitKind): + elif issubclass(eval_type, m.Array) and \ + issubclass(eval_type.T, m.Digital): n = len(eval_type) init = int(eval_value) - elif isinstance(eval_type, m.ArrayKind): + elif issubclass(eval_type, m.Array): return f"{gen_array_str(eval_type, eval_value, async_reset)}" else: - raise NotADirectoryError((eval_type)) + raise NotImplementedError((eval_type)) return f"DefineRegister({n}, init={init}, has_async_reset={async_reset})()" @@ -327,13 +327,13 @@ def _sequential( comb_out_count += 1 else: for key, value in eval_value.interface.ports.items(): - if isinstance(value, (m.ClockType, m.AsyncResetType)): + if isinstance(value, (m.Clock, m.AsyncReset)): continue type_ = repr(type(value)) - if value.isoutput(): + if value.is_output(): circuit_combinational_args.append(f"self_{name}_{value}: m.{type_}") circuit_combinational_call_args.append(f"{name}.{value}") - if value.isinput(): + if value.is_input(): circuit_combinational_output_type.append(f"m.{type_}") comb_out_wiring.append(f"{name}.{value} <= comb_out[{comb_out_count}]\n") comb_out_count += 1 diff --git a/magma/syntax/verilog.py b/magma/syntax/verilog.py index 97f018b237..373f2df22d 100644 --- a/magma/syntax/verilog.py +++ b/magma/syntax/verilog.py @@ -44,11 +44,11 @@ def visit_Return(self, node): def to_type_str(type_): - if isinstance(type_, m.BitKind): + if issubclass(type_, m.Digital): return "bit" - elif isinstance(type_, m.UIntKind): + elif issubclass(type_, m.UInt): return "uint" - elif isinstance(type_, m.BitsKind): + elif issubclass(type_, m.Bits): return "bits" else: raise NotImplementedError(type_) @@ -73,8 +73,8 @@ def collect_names(tree, ctx=None): def get_io_width(type_): if type_ is m.Bit: return None - elif isinstance(type_, m.ArrayKind): - if isinstance(type_.T, m.ArrayKind): + elif isinstance(type_, m.ArrayMeta): + if isinstance(type_.T, m.ArrayMeta): elem_width = get_io_width(type_.T) if isinstance(elem_width, tuple): return (type_.N, ) + elem_width @@ -125,7 +125,7 @@ def process_func(defn_env, fn, circ_name, registers=None, debug=False): if not combinational: tree = RewriteSelfAttributes(registers).visit(tree) for name, info in registers.items(): - width = 1 if isinstance(info[3], m._BitKind) else len(info[3]) + width = 1 if isinstance(info[3], m.DigitalMeta) else len(info[3]) width_table["self_" + name + "_I"] = width type_table["self_" + name + "_I"] = to_type_str(info[2]) width_table["self_" + name + "_O"] = width diff --git a/magma/t.py b/magma/t.py index bc84168caa..65e7cb6a32 100644 --- a/magma/t.py +++ b/magma/t.py @@ -1,28 +1,41 @@ +import functools +import warnings +import enum +from abc import abstractmethod from .ref import Ref, AnonRef, DefnRef, InstRef -from .port import INOUT, INPUT, OUTPUT from .compatibility import IntegerTypes, StringTypes -__all__ = ['Type', 'Kind'] -__all__ += ['In', 'Out', 'InOut', 'Flip'] + +# From http://code.activestate.com/recipes/391367-deprecated/ +def deprecated(func): + """This is a decorator which can be used to mark functions + as deprecated. It will result in a warning being emmitted + when the function is used.""" + @functools.wraps(func) + def newFunc(*args, **kwargs): + warnings.warn("Call to deprecated function %s." % func.__name__, + category=DeprecationWarning, stacklevel=2) + return func(*args, **kwargs) + newFunc.__name__ = func.__name__ + newFunc.__doc__ = func.__doc__ + newFunc.__dict__.update(func.__dict__) + return newFunc + + +class Direction(enum.Enum): + In = 0 + Out = 1 + InOut = 2 + Flip = 3 class Type(object): def __init__(self, **kwargs): - # ref is int, str or tuple name = kwargs.get('name', None) if name is None or isinstance(name, str): - #print('creating name ref',name) name = AnonRef(name=name) - #print('using',name) - #assert isinstance(name, Ref) self.name = name - # subclasses only need to implement one of these methods - def __eq__(self, rhs): - return not (self != rhs) - def __ne__(self, rhs): - return not (self == rhs) - __hash__ = object.__hash__ def __repr__(self): @@ -37,24 +50,40 @@ def anon(self): # abstract method - must be implemented by subclasses @classmethod - def isoriented(cls, direction): - pass + def is_oriented(cls, direction): + raise NotImplementedError() @classmethod - def isinput(cls): - return cls.isoriented(INPUT) + def is_input(cls): + return cls.is_oriented(Direction.In) + + @classmethod + def is_output(cls): + return cls.is_oriented(Direction.Out) @classmethod - def isoutput(self): - return self.isoriented(OUTPUT) + def is_inout(cls): + return cls.is_oriented(Direction.InOut) @classmethod - def isinout(self): - return self.isoriented(INOUT) + @deprecated + def isoriented(cls, direction): + return cls.is_oriented(direction) @classmethod - def isbidir(self): - return False + @deprecated + def isinput(cls): + return cls.is_input() + + @classmethod + @deprecated + def isoutput(cls): + return cls.is_output() + + @classmethod + @deprecated + def isinout(cls): + return cls.is_inout() @property def debug_name(self): @@ -68,21 +97,16 @@ def debug_name(self): return f"{defn_str}{inst_str}{str(self)}" def __le__(self, other): - if not self.isoutput(): + if not self.is_output(): self.wire(other) else: raise TypeError(f"Cannot use <= to assign to output: {self.debug_name} (trying to assign {other.debug_name})") class Kind(type): - def __init__(cls, name, bases, dct): - type.__init__( cls, name, bases, dct) - # subclasses only need to implement one of these methods def __eq__(cls, rhs): - return not (cls != rhs) - def __ne__(cls, rhs): - return not (cls == rhs) + return cls is rhs __hash__ = type.__hash__ @@ -92,25 +116,25 @@ def __repr__(cls): def __str__(cls): return cls.__name__ - # abstract method - must be implemented by subclasses - def qualify(cls): - pass + @abstractmethod + def qualify(cls, direction): + raise NotImplementedError() - # abstract method - must be implemented by subclasses def flip(cls): - pass - - + return cls.qualify(Direction.Flip) def In(T): - return T.qualify(direction=INPUT) + return T.qualify(Direction.In) + def Out(T): - return T.qualify(direction=OUTPUT) + return T.qualify(Direction.Out) + def InOut(T): - return T.qualify(direction=INOUT) + return T.qualify(Direction.InOut) + def Flip(T): - return T.flip() + return T.qualify(Direction.Flip) diff --git a/magma/testing/coroutine.py b/magma/testing/coroutine.py index 124a0ceaf6..a59ddd66d3 100644 --- a/magma/testing/coroutine.py +++ b/magma/testing/coroutine.py @@ -49,7 +49,7 @@ def check(circuit, sim, number_of_cycles, inputs_generator=None): for name, port in circuit.interface.ports.items(): if name in ["CLK", "CE"]: continue # Skip clocks, TODO: Check the type - if port.isoutput(): # circuit input + if port.is_output(): # circuit input input_value = getattr(inputs_generator, name) inputs.append(input_value) simulator.set_value(getattr(circuit, name), input_value) @@ -64,7 +64,7 @@ def check(circuit, sim, number_of_cycles, inputs_generator=None): # Coroutine has an implicit __next__ call on construction so it already # is in it's initial state for name, port in circuit.interface.ports.items(): - if port.isinput(): # circuit output + if port.is_input(): # circuit output if getattr(sim, name) != BitVector(simulator.get_value(getattr(circuit, name))): print(f"Failed on cycle {cycle}, port {name}, expected {getattr(sim, name)}, got {BitVector(simulator.get_value(getattr(circuit, name)))}") failed = True @@ -80,7 +80,7 @@ def testvectors(circuit, sim, number_of_cycles, inputs_generator=None): for name, port in circuit.interface.ports.items(): if name in ["CLK", "CE"]: continue # Skip clocks, TODO: Check the type - if port.isoutput(): # circuit input + if port.is_output(): # circuit input input_value = getattr(inputs_generator, name) next_inputs.append(input_value) in_ports[name] = input_value @@ -95,7 +95,7 @@ def testvectors(circuit, sim, number_of_cycles, inputs_generator=None): for name, port in circuit.interface.ports.items(): if name == "CLK": continue - if port.isinput(): # circuit output + if port.is_input(): # circuit output out_ports[name] = getattr(sim, name) outputs.append(out_ports) inputs.append(in_ports) diff --git a/magma/transforms.py b/magma/transforms.py index c55ed0c2d6..63f5f339c9 100644 --- a/magma/transforms.py +++ b/magma/transforms.py @@ -2,8 +2,9 @@ from .circuit import DefineCircuit, EndCircuit, CopyInstance from .is_definition import isdefinition from .is_primitive import isprimitive +from .digital import Digital from .bit import * -from .clock import ClockType, EnableType, ResetType, AsyncResetType, wiredefaultclock +from .clock import Clock, Enable, Reset, AsyncReset, wiredefaultclock from .array import * from .wire import wire from .conversions import array @@ -27,7 +28,7 @@ def __init__(self, orig_circuit, transform_name): def get_new_bit(self, orig_bit, scope): assert isinstance(scope, Scope), "Second argument to get_new_bit should be an instance of Scope" - if isinstance(orig_bit, ArrayType): + if isinstance(orig_bit, Array): arr = [] for o in orig_bit: arr.append(self.get_new_bit(o, scope)) @@ -44,10 +45,9 @@ def get_new_bit(self, orig_bit, scope): raise MagmaTransformException("Could not find bit in transform mapping. bit={}, scope={}".format(orig_bit, scope)) def set_new_bit(self, orig_bit, orig_scope, new_bit): - assert isinstance(new_bit, - (BitType, ArrayType, ClockType, EnableType, ResetType, AsyncResetType)) + assert isinstance(new_bit, (Digital, Array)), type(new_bit) - if isinstance(orig_bit, ArrayType): + if isinstance(orig_bit, Array): # Map the individual bits for o, n in zip(orig_bit, new_bit): self.orig_to_new[QualifiedBit(bit=o, scope=orig_scope)] = n @@ -70,16 +70,16 @@ def get_primitives(outer_circuit, outer_scope): outerloc = QualifiedBit(bit=outerbit, scope=outer_scope) innerloc = QualifiedBit(bit=innerbit, scope=inner_scope) - if isinstance(outerbit, ArrayType): + if isinstance(outerbit, Array): for o, i in zip(outerbit, innerbit): oqual = QualifiedBit(bit=o, scope=outer_scope) iqual = QualifiedBit(bit=i, scope=inner_scope) - if o.isinput(): + if o.is_input(): mapping[iqual] = oqual else: mapping[oqual] = iqual - if outerbit.isinput(): + if outerbit.is_input(): mapping[innerloc] = outerloc else: mapping[outerloc] = innerloc @@ -124,7 +124,7 @@ def get_new_source(source_qual, primitive_map, old_circuit, new_circuit): defn = bitref.defn.name assert defn == old_circuit.name, f"Collapsed bit to circuit other than outermost, {defn} {old_circuit.name}" newsource = get_renamed_port(new_circuit, bitref.name) - elif isinstance(old_source, ArrayType): + elif isinstance(old_source, Array): # Must not be a whole array assert bitref.anon() @@ -145,8 +145,8 @@ def get_new_source(source_qual, primitive_map, old_circuit, new_circuit): return newsource def wire_new_bit(origbit, newbit, cur_scope, primitive_map, bit_map, old_circuit, flattened_circuit): - if isinstance(origbit, ArrayType): - assert isinstance(newbit, ArrayType) + if isinstance(origbit, Array): + assert isinstance(newbit, Array) for x, y in zip(origbit, newbit): wire_new_bit(x, y, cur_scope, primitive_map, bit_map, old_circuit, flattened_circuit) return @@ -155,7 +155,7 @@ def wire_new_bit(origbit, newbit, cur_scope, primitive_map, bit_map, old_circuit sourcebit = origbit.value() if sourcebit is None: - if isinstance(origbit, ArrayType): + if isinstance(origbit, Array): # TODO: Raise an exception for now, can we handle this case silently (ignore unwired ports)? raise MagmaTransformException("Calling `.value()` on Array returned None. Array = {}, values = {}. Likely an unwired port.".format(origbit, [b.value() for b in origbit.ts])) else: @@ -202,20 +202,20 @@ def flatten(circuit): orig_inst = qual_inst.instance for name, origbit in orig_inst.interface.ports.items(): - if origbit.isinput(): + if origbit.is_input(): newbit = new_inst.interface.ports[name] wire_new_bit(origbit, newbit, qual_inst.scope, primitive_map, bit_map, circuit, flattened_circuit) # Finally, wire up the circuit outputs new_circuit = flattened_circuit.circuit for name, origbit in circuit.interface.ports.items(): - if origbit.isinput(): # Circuit output + if origbit.is_input(): # Circuit output newbit = new_circuit.interface.ports[name] wire_new_bit(origbit, newbit, Scope(), primitive_map, bit_map, circuit, flattened_circuit) # Handle unwired inputs for name, origbit in circuit.interface.ports.items(): - if origbit.isoutput() and origbit.value() is None: + if origbit.is_output() and origbit.value() is None: newbit = new_circuit.interface.ports[name] flattened_circuit.set_new_bit(origbit, Scope(), newbit) diff --git a/magma/tuple.py b/magma/tuple.py index a8b4c03bb9..d2a89eaed0 100644 --- a/magma/tuple.py +++ b/magma/tuple.py @@ -1,14 +1,15 @@ from collections.abc import Sequence, Mapping from collections import OrderedDict +from hwtypes.adt import TupleMeta, Tuple, Product, ProductMeta +from hwtypes.util import TypedProperty, OrderedFrozenDict +import magma as m from .ref import AnonRef, TupleRef -from .t import Type, Kind +from .t import Type, Kind, Direction, deprecated from .compatibility import IntegerTypes from .bit import BitOut, VCC, GND from .debug import debug_wire, get_callee_frame_info from .port import report_wiring_error -__all__ = ['TupleType', 'TupleKind', 'Tuple'] - # # Create an Tuple # @@ -17,76 +18,97 @@ # Tuple(v0, v1, ..., vn) # - creates a new tuple value where each field equals vi # -class TupleType(Type): + +class TupleKind(TupleMeta, Kind): + def qualify(cls, direction): + new_fields = [] + for T in cls.fields: + new_fields.append(T.qualify(direction)) + return cls.unbound_t[new_fields] + + def __call__(cls, *args, **kwargs): + obj = cls.__new__(cls, *args) + obj.__init__(*args, **kwargs) + return obj + + @property + def N(cls): + return len(cls) + + +class Tuple(Type, Tuple, metaclass=TupleKind): def __init__(self, *largs, **kwargs): Type.__init__(self, **kwargs) # name= self.ts = [] if len(largs) > 0: - assert len(largs) == self.N - for i in range(self.N): - k = str(self.Ks[i]) - t = largs[i] - if isinstance(t, IntegerTypes): + assert len(largs) == len(self) + for k, t, T in zip(self.keys(), largs, self.types()): + if type(t) is bool: t = VCC if t else GND - assert type(t) == self.Ts[i] self.ts.append(t) - setattr(self, k, t) + if not isinstance(self, Product): + setattr(self, k, t) else: - for i in range(self.N): - k = str(self.Ks[i]) - T = self.Ts[i] - t = T(name=TupleRef(self,k)) + for k, T in zip(self.keys(), self.types()): + t = T(name=TupleRef(self, k)) self.ts.append(t) - setattr(self, k, t) + if not isinstance(self, Product): + setattr(self, k, t) __hash__ = Type.__hash__ + @classmethod + def is_oriented(cls, direction): + return all(v.is_oriented(direction) for v in cls.fields) + + @classmethod + @deprecated + def isoriented(cls, direction): + return cls.is_oriented(direction) + + @classmethod + def keys(cls): + return [str(i) for i in range(len(cls.fields))] + def __eq__(self, rhs): - if not isinstance(rhs, TupleType): return False + if not isinstance(rhs, Tuple): return False return self.ts == rhs.ts def __repr__(self): if not isinstance(self.name, AnonRef): return repr(self.name) ts = [repr(t) for t in self.ts] - kts = ['{}={}'.format(k, v) for k, v in zip(self.Ks, ts)] + kts = ['{}={}'.format(k, v) for k, v in zip(self.keys(), ts)] return 'tuple(dict({})'.format(', '.join(kts)) def __getitem__(self, key): - if key in self.Ks: - key = self.Ks.index(key) + if key in self.keys(): + key = list(self.keys()).index(key) return self.ts[key] def __len__(self): - return self.N + return len(type(self).fields) @classmethod def flat_length(cls): - return sum(T.flat_length() for T in cls.Ts) + return sum(T.flat_length() for T in cls.types()) def __call__(self, o): return self.wire(o, get_callee_frame_info()) - @classmethod - def isoriented(cls, direction): - for T in cls.Ts: - if not T.isoriented(direction): - return False - return True - @debug_wire def wire(i, o, debug_info): # print('Tuple.wire(', o, ', ', i, ')') - if not isinstance(o, TupleType): + if not isinstance(o, Tuple): report_wiring_error(f'Cannot wire {o.debug_name} (type={type(o)}) to {i.debug_name} (type={type(i)}) because {o.debug_name} is not a Tuple', debug_info) # noqa return - if i.Ks != o.Ks: - report_wiring_error(f'Cannot wire {o.debug_name} (type={type(o)}, keys={i.Ks}) to {i.debug_name} (type={type(i)}, keys={o.Ks}) because the tuples do not have the same keys', debug_info) # noqa + if i.keys() != o.keys(): + report_wiring_error(f'Cannot wire {o.debug_name} (type={type(o)}, keys={list(i.keys())}) to {i.debug_name} (type={type(i)}, keys={list(o.keys())}) because the tuples do not have the same keys', debug_info) # noqa return #if i.Ts != o.Ts: @@ -94,14 +116,14 @@ def wire(i, o, debug_info): # return for i_elem, o_elem in zip(i, o): - if o_elem.isinput(): + if o_elem.is_input(): o_elem.wire(i_elem, debug_info) else: i_elem.wire(o_elem, debug_info) def unwire(i, o): for i_elem, o_elem in zip(i, o): - if o_elem.isinput(): + if o_elem.is_input(): o_elem.unwire(i_elem, debug_info) else: i_elem.unwire(o_elem, debug_info) @@ -139,7 +161,7 @@ def iswhole(self, ts): for i in range(len(ts)): # elements should be numbered consecutively - if ts[i].name.index != self.Ks[i]: + if ts[i].name.index != list(self.keys())[i]: return False if len(ts) != len(ts[0].name.tuple): @@ -156,10 +178,10 @@ def trace(self): if t is None: return None - if len(ts) == self.N and self.iswhole(ts): + if len(ts) == len(self) and self.iswhole(ts): return ts[0].name.tuple - return tuple_(dict(zip(self.Ks,ts))) + return tuple_(dict(zip(self.keys(),ts))) def value(self): ts = [t.value() for t in self.ts] @@ -168,10 +190,10 @@ def value(self): if t is None: return None - if len(ts) == self.N and self.iswhole(ts): + if len(ts) == len(self) and self.iswhole(ts): return ts[0].name.tuple - return tuple_(dict(zip(self.Ks,ts))) + return tuple_(dict(zip(self.keys(),ts))) def flatten(self): return sum([t.flatten() for t in self.ts], []) @@ -183,115 +205,116 @@ def const(self): return True - def keys(self): - return self.Ks + @classmethod + def types(cls): + return cls.fields def values(self): return self.ts def items(self): - return zip(self.Ks, self.ts) + return zip(self.keys(), self.ts) -class TupleKind(Kind): - def __init__(cls, name, bases, dct): - super(TupleKind, cls).__init__(name, bases, dct) - cls.N = len(cls.Ks) - def __str__(cls): - args = [] - for i in range(cls.N): - args.append("%s=%s" % (cls.Ks[i], str(cls.Ts[i]))) - return "Tuple(%s)" % ",".join(args) +class ProductKind(ProductMeta, TupleKind, Kind): + __hash__ = type.__hash__ + + @classmethod + def _from_fields(mcs, fields, name, bases, ns, **kwargs): + + def _get_tuple_base(bases): + for base in bases: + if not isinstance(base, mcs) and isinstance(base, TupleMeta): + return base + r_base =_get_tuple_base(base.__bases__) + if r_base is not None: + return r_base + return None + + base = _get_tuple_base(bases)[tuple(fields.values())] + bases = *bases, base + + # field_name -> tuple index + idx_table = dict((k, i) for i,k in enumerate(fields.keys())) + + def _make_prop(field_type, idx): + @TypedProperty(field_type) + def prop(self): + return self[idx] + + @prop.setter + def prop(self, value): + self[idx] = value + + return prop + + # add properties to namespace + # build properties + for field_name, field_type in fields.items(): + assert field_name not in ns + idx = idx_table[field_name] + ns[field_name] = _make_prop(field_type, idx) + + # this is all really gross but I don't know how to do this cleanly + # need to build t so I can call super() in new and init + # need to exec to get proper signatures + t = TupleMeta.__new__(mcs, name, bases, ns, **kwargs) + + # not strictly necessary could iterative over class dict finding + # TypedProperty to reconstruct _field_table_ but that seems bad + t._field_table_ = OrderedFrozenDict(fields) + return t + + def qualify(cls, direction): + new_fields = OrderedDict() + for k, v in cls.field_dict.items(): + new_fields[k] = v.qualify(direction) + return cls.unbound_t.from_fields(cls.__name__, new_fields, cache=cls.is_cached) def __eq__(cls, rhs): - if not isinstance(rhs, TupleKind): return False + if not isinstance(rhs, ProductKind): + return False - if cls.Ks != rhs.Ks: return False - if cls.Ts != rhs.Ts: return False + for k, v in cls.field_dict.items(): + if getattr(rhs, k) != v: + return False return True - __ne__ = Kind.__ne__ - __hash__ = Kind.__hash__ - def __len__(cls): - return cls.N + return len(cls.fields) - def __getitem__(cls, key): - if key in cls.Ks: - key = cls.Ks.index(key) - return cls.Ts[key] + def __str__(cls): + s = "Tuple(" + s += ",".join(f'{k}={str(v)}' for k, v in cls.field_dict.items()) + s += ")" + return s - def size(cls): - n = 0 - for T in cls.Ts: - n += T.size() - return n - def qualify(cls, direction): - if cls.isoriented(direction): - return cls - return Tuple(OrderedDict(zip(cls.Ks, [T.qualify(direction) for T in cls.Ts]))) - - def flip(cls): - return Tuple(OrderedDict(zip(cls.Ks, [T.flip() for T in cls.Ts]))) +class Product(Tuple, metaclass=ProductKind): + @classmethod + def keys(cls): + return cls.field_dict.keys() + @classmethod + def types(cls): + return cls.fields -# -# Tuple(Mapping) -# Tuple(Sequence) -# -# *largs with largs being comprised of magma types -# Tuple(T0, T1, ..., Tn) -# -# **kwargs - only called if largs is empty -# Tuple(x=Bit, y=Bit) -> Tuple(**kwargs) -# -def Tuple(*largs, **kwargs): - if largs: - if isinstance(largs[0], Kind): - Ks = range(len(largs)) - Ts = largs - else: - largs = largs[0] - if isinstance(largs, Sequence): - Ks = range(len(largs)) - Ts = largs - elif isinstance(largs, Mapping): - Ks = list(largs.keys()) - Ts = list(largs.values()) - else: - assert False - else: - Ks = list(kwargs.keys()) - Ts = list(kwargs.values()) - - # check types and promote integers - for i in range(len(Ts)): - T = Ts[i] - if T in IntegerTypes: - T = BitOut - Ts[i] = T - if not isinstance(T, Kind): - raise ValueError(f'Tuples must contain magma types - got {T}') - - name = 'Tuple(%s)' % ", ".join([f"{k}: {t}" for k, t in zip(Ks, Ts)]) - return TupleKind(name, (TupleType,), dict(Ks=Ks, Ts=Ts)) from .bitutils import int2seq -from .array import ArrayType, Array -from .bit import _BitKind, _BitType, Bit, BitKind, BitType, VCC, GND +from .array import Array +from .bit import Digital, Bit, VCC, GND # # convert value to a tuple # *value = tuple from positional arguments # **kwargs = tuple from keyword arguments # -def tuple_(value, n=None): - if isinstance(value, TupleType): +def tuple_(value, n=None, t=Tuple): + if isinstance(value, t): return value - if not isinstance(value, (_BitType, ArrayType, IntegerTypes, Sequence, Mapping)): + if not isinstance(value, (Digital, Array, IntegerTypes, Sequence, Mapping)): raise ValueError( "bit can only be used on a Bit, an Array, or an int; not {}".format(type(value))) @@ -302,9 +325,9 @@ def tuple_(value, n=None): if n is None: n = max(value.bit_length(),1) value = int2seq(value, n) - elif isinstance(value, _BitType): + elif isinstance(value, Digital): value = [value] - elif isinstance(value, ArrayType): + elif isinstance(value, Array): value = [value[i] for i in range(len(value))] if isinstance(value, Sequence): @@ -316,9 +339,16 @@ def tuple_(value, n=None): for k, v in value.items(): args.append(v) decl[k] = type(v) + for a, d in zip(args, decl): + # bool types to Bit + if decl[d] is bool: + decl[d] = m.Digital + # Promote integer types to Bits + elif decl[d] in IntegerTypes: + decl[d] = m.Bits[max(a.bit_length(), 1)] - return Tuple(decl)(*args) + return type("anon", (t,), decl)(*args) def namedtuple(**kwargs): - return tuple_(kwargs) + return tuple_(kwargs, t=Product) diff --git a/magma/util.py b/magma/util.py index 71ab72ed85..6a5d1fa128 100644 --- a/magma/util.py +++ b/magma/util.py @@ -10,11 +10,11 @@ def BitOrBits(width): def pretty_str(t): - if isinstance(t, m.TupleKind): + if issubclass(t, m.Tuple): args = [] - for i in range(t.N): - key_str = str(t.Ks[i]) - val_str = pretty_str(t.Ts[i]) + for i in range(len(t)): + key_str = str(list(t.keys())[i]) + val_str = pretty_str(t.types()[i]) indent = " " * 4 val_str = f"\n{indent}".join(val_str.splitlines()) args.append(f"{key_str} = {val_str}") @@ -24,9 +24,9 @@ def pretty_str(t): # Insert first newline + indent and last newline result = "\n " + result + "\n" s = f"Tuple({result})" - elif isinstance(t, m.BitsKind): + elif issubclass(t, m.Bits): s = str(t) - elif isinstance(t, m.ArrayKind): + elif issubclass(t, m.Array): s = f"Array[{t.N}, {pretty_str(t.T)}]" else: s = str(t) diff --git a/magma/wire.py b/magma/wire.py index 6f994228c3..4624a4da99 100644 --- a/magma/wire.py +++ b/magma/wire.py @@ -7,7 +7,7 @@ @debug_wire -def wire(o, i, debug_info): +def wire(o, i, debug_info=None): # Wire(o, Circuit). if hasattr(i, 'interface'): i.wire(o, debug_info) @@ -26,9 +26,9 @@ def wire(o, i, debug_info): o = o[0] # If o is an input. - if not isinstance(o, IntegerTypes) and o.isinput(): + if not isinstance(o, IntegerTypes) and o.is_input(): # If i is not an input. - if isinstance(i, IntegerTypes) or not i.isinput(): + if isinstance(i, IntegerTypes) or not i.is_input(): # Flip i and o. i, o = o, i diff --git a/setup.py b/setup.py index 0b325550fa..7e09595c56 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='magma-lang', - version='1.0.26', + version='2.0.0', url='https://github.com/phanrahan/magma', license='MIT', maintainer='Lenny Truong', diff --git a/tests/test_circuit/test_declare.py b/tests/test_circuit/test_declare.py index d146dce5cb..bb95b0d86d 100644 --- a/tests/test_circuit/test_declare.py +++ b/tests/test_circuit/test_declare.py @@ -5,7 +5,7 @@ def test_declare_simple(): And2 = m.DeclareCircuit("And2", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) - assert isinstance(And2.I0, m.BitType) + assert isinstance(And2.I0, m.Bit) def test_declare_interface_polarity(): @@ -14,5 +14,5 @@ def test_declare_interface_polarity(): And2Defn = m.DefineCircuit("And2", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) - assert And2Decl.interface.ports["I0"].isinput() == \ - And2Defn.interface.ports["I0"].isinput() + assert And2Decl.interface.ports["I0"].is_input() == \ + And2Defn.interface.ports["I0"].is_input() diff --git a/tests/test_circuit/test_define.py b/tests/test_circuit/test_define.py index 07390f4df2..833a562261 100644 --- a/tests/test_circuit/test_define.py +++ b/tests/test_circuit/test_define.py @@ -150,9 +150,14 @@ def test_2d_array_error(caplog): assert str(e) == "Argument main.I of type Array[2, Array[3, Out(Bit)]] is not supported, the verilog backend only supports simple 1-d array of bits of the form Array(N, Bit)" # noqa +class XY(m.Product): + x = m.Bit + y = m.Bit + + @pytest.mark.parametrize("target,suffix", [("verilog", "v"), ("coreir", "json")]) -@pytest.mark.parametrize("T",[m.Bit, m.Bits[2], m.Array[2, m.Bit], m.Tuple(x=m.Bit, y=m.Bit)]) +@pytest.mark.parametrize("T",[m.Bit, m.Bits[2], m.Array[2, m.Bit], XY]) def test_anon_value(target, suffix, T): And2 = m.DeclareCircuit('And2', "I0", m.In(T), "I1", m.In(T), "O", m.Out(T)) diff --git a/tests/test_circuit/test_inspect.py b/tests/test_circuit/test_inspect.py index de89db7754..8243a5eace 100644 --- a/tests/test_circuit/test_inspect.py +++ b/tests/test_circuit/test_inspect.py @@ -30,7 +30,7 @@ def test_str_repr(): wire(Logic2.I0, And2_inst0.I0) wire(Logic2.I1, And2_inst0.I1) wire(And2_inst0.O, XOr2_inst0.I0) -wire(1, XOr2_inst0.I1) +wire(VCC, XOr2_inst0.I1) wire(XOr2_inst0.O, Logic2.O) EndCircuit()\ """ diff --git a/tests/test_coreir/test_coreir.py b/tests/test_coreir/test_coreir.py index 5e538c2884..f8246e71f5 100644 --- a/tests/test_coreir/test_coreir.py +++ b/tests/test_coreir/test_coreir.py @@ -41,9 +41,14 @@ def test_check_interface_tuple(): """ This should work with valid types """ + + class T(m.Product): + a = Bit + b = Array[7, Bit] + class TestCircuit2(Circuit): name = "TestCircuit2" - IO = ["I", In(Tuple(a=Bit, b=Array[7, Bit])), "O", Out(Tuple(a=Bit, b=Array[7, Bit]))] + IO = ["I", In(T), "O", Out(T)] @classmethod def definition(cls): wire(cls.I, cls.O) diff --git a/tests/test_coreir/test_coreir_tuple.py b/tests/test_coreir/test_coreir_tuple.py index e1fea01756..9e58b3981e 100644 --- a/tests/test_coreir/test_coreir_tuple.py +++ b/tests/test_coreir/test_coreir_tuple.py @@ -2,8 +2,12 @@ from magma.testing import check_files_equal +class T(m.Product): + I = m.In(m.Bit) + O = m.Out(m.Bit) + def def_foo(): - foo = m.DefineCircuit("Foo", "ifc", m.Tuple(I=m.In(m.Bit), O=m.Out(m.Bit))) + foo = m.DefineCircuit("Foo", "ifc", T) m.wire(foo.ifc.I, foo.ifc.O) m.EndCircuit() return foo @@ -15,15 +19,15 @@ def test_multi_direction_tuple(): assert check_files_equal(__file__, f"build/test_multi_direction_tuple.json", f"gold/test_multi_direction_tuple.json") - assert [T.isinput() for T in foo.interface.ports["ifc"].Ts] == \ + assert [T.is_input() for T in foo.interface.ports["ifc"].types()] == \ [False, True] - assert [T.isinput() for T in foo.IO.ports["ifc"].Ts] == \ + assert [T.is_input() for T in foo.IO.ports["ifc"].types()] == \ [True, False] def test_multi_direction_tuple_instance(): - bar = m.DefineCircuit("bar", "ifc", m.Tuple(I=m.In(m.Bit), O=m.Out(m.Bit))) + bar = m.DefineCircuit("bar", "ifc", T) foo_inst = def_foo()() m.wire(bar.ifc.I, foo_inst.ifc.I) m.wire(bar.ifc.O, foo_inst.ifc.O) @@ -35,7 +39,7 @@ def test_multi_direction_tuple_instance(): def test_multi_direction_tuple_instance_bulk(): - bar = m.DefineCircuit("bar", "ifc", m.Tuple(I=m.In(m.Bit), O=m.Out(m.Bit))) + bar = m.DefineCircuit("bar", "ifc", T) foo_inst = def_foo()() m.wire(bar.ifc, foo_inst.ifc) m.EndCircuit() @@ -45,10 +49,24 @@ def test_multi_direction_tuple_instance_bulk(): assert check_files_equal(__file__, f"build/test_multi_direction_tuple_instance_bulk.json", f"gold/test_multi_direction_tuple_instance.json") + +class AB(m.Product): + a = m.Bit + b = m.Bit + + +class Z(m.Product): + a = m.In(m.Bit) + b = m.Out(m.Bit) + + +class Bar(m.Product): + x = m.In(AB) + y = m.Out(AB) + z = Z + def test_nesting(): - bar = m.DefineCircuit("bar", "I", m.Tuple(x=m.In(m.Tuple(a=m.Bit, b=m.Bit)), - y=m.Out(m.Tuple(a=m.Bit, b=m.Bit)), - z=m.Tuple(a=m.In(m.Bit), b=m.Out(m.Bit)))) + bar = m.DefineCircuit("bar", "I", Bar) foo = def_foo() foo_inst0 = foo() foo_inst1 = foo() @@ -64,8 +82,14 @@ def test_nesting(): assert check_files_equal(__file__, f"build/test_nesting.json", f"gold/test_nesting.json") + +class IO(m.Product): + I = m.In(m.Bit) + O = m.Out(m.Bit) + + def test_array_nesting(): - T = m.Array[10, m.Tuple(I=m.In(m.Bit), O=m.Out(m.Bit))] + T = m.Array[10, IO] Foo = m.DefineCircuit("Foo", "IFC", T) for i in range(10): m.wire(Foo.IFC[i].I, Foo.IFC[i].O) @@ -76,7 +100,7 @@ def test_array_nesting(): def test_anon_tuple(): - foo = m.DefineCircuit("Foo", "ifc", m.Tuple(m.In(m.Bit), m.Out(m.Bit))) + foo = m.DefineCircuit("Foo", "ifc", m.Tuple[m.In(m.Bit), m.Out(m.Bit)]) m.wire(foo.ifc[0], foo.ifc[1]) m.EndCircuit() m.compile("build/test_anon_tuple", foo, output="coreir") @@ -85,7 +109,7 @@ def test_anon_tuple(): def test_nested_anon_tuple(): - foo = m.DefineCircuit("Foo", "ifc", m.Array[2, m.Tuple(m.In(m.Bit), m.Out(m.Bit))]) + foo = m.DefineCircuit("Foo", "ifc", m.Array[2, m.Tuple[m.In(m.Bit), m.Out(m.Bit)]]) m.wire(foo.ifc[0][0], foo.ifc[1][1]) m.wire(foo.ifc[1][0], foo.ifc[0][1]) m.EndCircuit() @@ -95,7 +119,7 @@ def test_nested_anon_tuple(): def test_anon_tuple_nested_array(): - foo = m.DefineCircuit("Foo", "ifc", m.Tuple(m.In(m.Bits[2]), m.Out(m.Bits[2]))) + foo = m.DefineCircuit("Foo", "ifc", m.Tuple[m.In(m.Bits[2]), m.Out(m.Bits[2])]) m.wire(foo.ifc[0][0], foo.ifc[1][1]) m.wire(foo.ifc[0][1], foo.ifc[1][0]) m.EndCircuit() diff --git a/tests/test_coreir/test_linking.py b/tests/test_coreir/test_linking.py index 2c1f29820f..44ad613c12 100644 --- a/tests/test_coreir/test_linking.py +++ b/tests/test_coreir/test_linking.py @@ -14,11 +14,11 @@ @coreir_typegen def smax_type_gen(width: int): - return Tuple( - in0=m.Array[width, m.In(m.Bit)], - in1=m.Array[width, m.In(m.BitIn)], - out=m.Array[width, m.In(m.Bit)] - ) + class T(m.Product): + in0 = m.Array[width, m.In(m.Bit)] + in1 = m.Array[width, m.In(m.BitIn)] + out = m.Array[width, m.In(m.Bit)] + return T def test_declare_generator(): diff --git a/tests/test_operators.py b/tests/test_operators.py deleted file mode 100644 index 9c38abe556..0000000000 --- a/tests/test_operators.py +++ /dev/null @@ -1,83 +0,0 @@ -import magma as m -from magma.operators import MantleImportError -from common import DeclareAnd -import pytest -from magma.testing import check_files_equal - - -def test_error(): - circ = m.DefineCircuit("test", "a", m.In(m.Bits[4]), "b", m.Out(m.Bits[4])) - try: - ~circ.a - assert False, \ - "Operator should throw an error since mantle is not imported" - except MantleImportError: - pass - - -@pytest.mark.parametrize("width", [None, 3]) -@pytest.mark.parametrize("output", ["verilog", "coreir"]) -def test_assign(width, output): - T = m.util.BitOrBits(width) - name = f"test_assign_operator_{width}_{output}" - circ = m.DefineCircuit(name, "a", m.In(T), "b", m.In(T), - "c", m.Out(T)) - and2 = DeclareAnd(width)() - and2.I0 <= circ.a - and2.I1 <= circ.b - circ.c <= and2.O - m.EndDefine() - - m.compile(f"build/{name}", circ, output) - suffix = "v" if output == "verilog" else "json" - assert check_files_equal(__file__, f"build/{name}.{suffix}", - f"gold/{name}.{suffix}") - - - -@pytest.mark.parametrize("width", [None, 3]) -@pytest.mark.parametrize("output", ["verilog", "coreir"]) -def test_assign_to_var(width, output): - T = m.util.BitOrBits(width) - name = f"test_assign_operator2_{width}_{output}" - circ = m.DefineCircuit(name, "a", m.In(T), "b", m.In(T), - "c", m.Out(T)) - and2 = DeclareAnd(width)() - c, I0, I1 = and2.I0, and2.I1, circ.c - I0 <= circ.a - I1 <= circ.b - c <= and2.O - m.EndDefine() - - m.compile(f"build/{name}", circ, output) - suffix = "v" if output == "verilog" else "json" - assert check_files_equal(__file__, f"build/{name}.{suffix}", - f"gold/{name}.{suffix}") - - -@pytest.mark.parametrize("width", [None, 3]) -def test_assign_error_0(width): - T = m.util.BitOrBits(width) - name = f"test_assign_operator_{width}" - circ = m.DefineCircuit(name, "a", m.In(T), "b", m.In(T), - "c", m.Out(T)) - and2 = DeclareAnd(width)() - try: - and2.O <= circ.a - assert False, "Should raise type error" - except TypeError as e: - assert str(e) == f"Cannot use <= to assign to output: {and2.O.debug_name} (trying to assign {circ.a.debug_name})" - - -@pytest.mark.parametrize("width", [None, 3]) -def test_assign_error_1(width): - T = m.util.BitOrBits(width) - name = f"test_assign_operator_{width}" - circ = m.DefineCircuit(name, "a", m.In(T), "b", m.In(T), - "c", m.Out(T)) - and2 = DeclareAnd(width)() - try: - circ.a <= and2.O - assert False, "Should raise type error" - except TypeError as e: - assert str(e) == f"Cannot use <= to assign to output: {circ.a.debug_name} (trying to assign {and2.O.debug_name})" diff --git a/tests/test_simulator/test_tuple.py b/tests/test_simulator/test_tuple.py index 80d595cb39..217b6147d9 100644 --- a/tests/test_simulator/test_tuple.py +++ b/tests/test_simulator/test_tuple.py @@ -15,7 +15,10 @@ def test_simulator_tuple(): scope = Scope() inDims = [2, width] tupleEl = Array[inDims[1], Bit] - nestedTuples = Array[inDims[0], Tuple(sel=tupleEl, data=tupleEl)] + class T(Product): + sel = tupleEl + data = tupleEl + nestedTuples = Array[inDims[0], T] tupleValues = {'sel':int2seq(testValInt, width), 'data':int2seq(testValInt+20, width)} inType = In(nestedTuples) outType = Out(Array[2*inDims[0], tupleEl]) diff --git a/tests/test_syntax/gold/RdPtr.json b/tests/test_syntax/gold/RdPtr.json index f1b373f33a..9d97ef069b 100644 --- a/tests/test_syntax/gold/RdPtr.json +++ b/tests/test_syntax/gold/RdPtr.json @@ -47,23 +47,23 @@ "Mux2_x10_inst0":{ "modref":"global.Mux2_x10" }, - "add_inst0":{ - "genref":"coreir.add", - "genargs":{"width":["Int",10]} - }, "const_1_10":{ "genref":"coreir.const", "genargs":{"width":["Int",10]}, "modargs":{"value":[["BitVector",10],"10'h001"]} + }, + "magma_Bits_10_add_inst0":{ + "genref":"coreir.add", + "genargs":{"width":["Int",10]} } }, "connections":[ ["self.self_rd_ptr_O","Mux2_x10_inst0.I0"], - ["add_inst0.out","Mux2_x10_inst0.I1"], + ["magma_Bits_10_add_inst0.out","Mux2_x10_inst0.I1"], ["self.O0","Mux2_x10_inst0.O"], ["self.read","Mux2_x10_inst0.S"], - ["self.self_rd_ptr_O","add_inst0.in0"], - ["const_1_10.out","add_inst0.in1"], + ["magma_Bits_10_add_inst0.in1","const_1_10.out"], + ["self.self_rd_ptr_O","magma_Bits_10_add_inst0.in0"], ["self.self_rd_ptr_O","self.O1"] ] } diff --git a/tests/test_syntax/gold/RdPtr.v b/tests/test_syntax/gold/RdPtr.v index e8528fd5c1..4c991e9c3f 100644 --- a/tests/test_syntax/gold/RdPtr.v +++ b/tests/test_syntax/gold/RdPtr.v @@ -22,11 +22,11 @@ endmodule module RdPtr_comb (output [9:0] O0, output [9:0] O1, input read, input [9:0] self_rd_ptr_O); wire [9:0] Mux2_x10_inst0_O; -wire [9:0] add_inst0_out; wire [9:0] const_1_10_out; -Mux2_x10 Mux2_x10_inst0(.I0(self_rd_ptr_O), .I1(add_inst0_out), .O(Mux2_x10_inst0_O), .S(read)); -coreir_add #(.width(10)) add_inst0(.in0(self_rd_ptr_O), .in1(const_1_10_out), .out(add_inst0_out)); +wire [9:0] magma_Bits_10_add_inst0_out; +Mux2_x10 Mux2_x10_inst0(.I0(self_rd_ptr_O), .I1(magma_Bits_10_add_inst0_out), .O(Mux2_x10_inst0_O), .S(read)); coreir_const #(.value(10'h001), .width(10)) const_1_10(.out(const_1_10_out)); +coreir_add #(.width(10)) magma_Bits_10_add_inst0(.in0(self_rd_ptr_O), .in1(const_1_10_out), .out(magma_Bits_10_add_inst0_out)); assign O0 = Mux2_x10_inst0_O; assign O1 = self_rd_ptr_O; endmodule diff --git a/tests/test_syntax/gold/RegisterMode.json b/tests/test_syntax/gold/RegisterMode.json index ac71d65bda..7bb2ac078f 100644 --- a/tests/test_syntax/gold/RegisterMode.json +++ b/tests/test_syntax/gold/RegisterMode.json @@ -175,80 +175,101 @@ "genargs":{"width":["Int",2]}, "modargs":{"value":[["BitVector",2],"2'h1"]} }, - "eq_inst0":{ + "magma_Bit_not_inst0":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst1":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst2":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst3":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst4":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst5":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst6":{ + "modref":"corebit.not" + }, + "magma_Bit_xor_inst0":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst1":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst2":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst3":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst4":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst5":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst6":{ + "modref":"corebit.xor" + }, + "magma_Bits_2_eq_inst0":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst1":{ + "magma_Bits_2_eq_inst1":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst10":{ + "magma_Bits_2_eq_inst10":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst11":{ + "magma_Bits_2_eq_inst11":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst12":{ + "magma_Bits_2_eq_inst12":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst13":{ + "magma_Bits_2_eq_inst13":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst14":{ + "magma_Bits_2_eq_inst2":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst15":{ + "magma_Bits_2_eq_inst3":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst16":{ + "magma_Bits_2_eq_inst4":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst17":{ - "modref":"corebit.and" - }, - "eq_inst18":{ - "modref":"corebit.and" - }, - "eq_inst19":{ - "modref":"corebit.and" - }, - "eq_inst2":{ + "magma_Bits_2_eq_inst5":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst20":{ - "modref":"corebit.and" - }, - "eq_inst3":{ + "magma_Bits_2_eq_inst6":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst4":{ + "magma_Bits_2_eq_inst7":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst5":{ + "magma_Bits_2_eq_inst8":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst6":{ - "modref":"corebit.and" - }, - "eq_inst7":{ - "modref":"corebit.and" - }, - "eq_inst8":{ - "modref":"corebit.and" - }, - "eq_inst9":{ + "magma_Bits_2_eq_inst9":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} } @@ -257,112 +278,119 @@ ["self.clk_en","Mux2_inst0.I0"], ["bit_const_0_None.out","Mux2_inst0.I1"], ["Mux2_inst1.I0","Mux2_inst0.O"], - ["eq_inst1.out","Mux2_inst0.S"], + ["magma_Bits_2_eq_inst1.out","Mux2_inst0.S"], ["bit_const_0_None.out","Mux2_inst1.I1"], ["Mux2_inst2.I0","Mux2_inst1.O"], - ["eq_inst4.out","Mux2_inst1.S"], + ["magma_Bits_2_eq_inst4.out","Mux2_inst1.S"], ["bit_const_1_None.out","Mux2_inst2.I1"], - ["eq_inst7.out","Mux2_inst2.S"], + ["magma_Bit_not_inst1.out","Mux2_inst2.S"], ["self.clk_en","Mux2_inst3.I0"], ["bit_const_0_None.out","Mux2_inst3.I1"], ["Mux2_inst4.I0","Mux2_inst3.O"], - ["eq_inst10.out","Mux2_inst3.S"], + ["magma_Bits_2_eq_inst7.out","Mux2_inst3.S"], ["bit_const_0_None.out","Mux2_inst4.I1"], ["Mux2_inst5.I0","Mux2_inst4.O"], - ["eq_inst14.out","Mux2_inst4.S"], + ["magma_Bits_2_eq_inst11.out","Mux2_inst4.S"], ["bit_const_1_None.out","Mux2_inst5.I1"], ["self.O1","Mux2_inst5.O"], - ["eq_inst18.out","Mux2_inst5.S"], + ["magma_Bit_not_inst4.out","Mux2_inst5.S"], ["self.value","Mux2_x4_inst0.I0"], ["self.value","Mux2_x4_inst0.I1"], ["Mux2_x4_inst2.I0","Mux2_x4_inst0.O"], - ["eq_inst0.out","Mux2_x4_inst0.S"], + ["magma_Bits_2_eq_inst0.out","Mux2_x4_inst0.S"], ["self.self_register_O","Mux2_x4_inst1.I0"], ["self.self_register_O","Mux2_x4_inst1.I1"], ["Mux2_x4_inst3.I0","Mux2_x4_inst1.O"], - ["eq_inst2.out","Mux2_x4_inst1.S"], + ["magma_Bits_2_eq_inst2.out","Mux2_x4_inst1.S"], ["Mux2_x4_inst7.O","Mux2_x4_inst10.I0"], ["self.const_","Mux2_x4_inst10.I1"], ["Mux2_x4_inst13.I0","Mux2_x4_inst10.O"], - ["eq_inst15.out","Mux2_x4_inst10.S"], + ["magma_Bits_2_eq_inst12.out","Mux2_x4_inst10.S"], ["Mux2_x4_inst8.O","Mux2_x4_inst11.I0"], ["self.self_register_O","Mux2_x4_inst11.I1"], ["Mux2_x4_inst14.I0","Mux2_x4_inst11.O"], - ["eq_inst16.out","Mux2_x4_inst11.S"], + ["magma_Bits_2_eq_inst13.out","Mux2_x4_inst11.S"], ["Mux2_x4_inst9.O","Mux2_x4_inst12.I0"], ["self.config_data","Mux2_x4_inst12.I1"], ["self.O0","Mux2_x4_inst12.O"], - ["eq_inst17.out","Mux2_x4_inst12.S"], + ["magma_Bit_not_inst3.out","Mux2_x4_inst12.S"], ["self.self_register_O","Mux2_x4_inst13.I1"], ["self.O2","Mux2_x4_inst13.O"], - ["eq_inst19.out","Mux2_x4_inst13.S"], + ["magma_Bit_not_inst5.out","Mux2_x4_inst13.S"], ["self.self_register_O","Mux2_x4_inst14.I1"], ["self.O3","Mux2_x4_inst14.O"], - ["eq_inst20.out","Mux2_x4_inst14.S"], + ["magma_Bit_not_inst6.out","Mux2_x4_inst14.S"], ["self.value","Mux2_x4_inst2.I1"], ["Mux2_x4_inst4.I0","Mux2_x4_inst2.O"], - ["eq_inst3.out","Mux2_x4_inst2.S"], + ["magma_Bits_2_eq_inst3.out","Mux2_x4_inst2.S"], ["self.self_register_O","Mux2_x4_inst3.I1"], ["Mux2_x4_inst5.I0","Mux2_x4_inst3.O"], - ["eq_inst5.out","Mux2_x4_inst3.S"], + ["magma_Bits_2_eq_inst5.out","Mux2_x4_inst3.S"], ["self.config_data","Mux2_x4_inst4.I1"], - ["eq_inst6.out","Mux2_x4_inst4.S"], + ["magma_Bit_not_inst0.out","Mux2_x4_inst4.S"], ["self.self_register_O","Mux2_x4_inst5.I1"], - ["eq_inst8.out","Mux2_x4_inst5.S"], + ["magma_Bit_not_inst2.out","Mux2_x4_inst5.S"], ["self.value","Mux2_x4_inst6.I0"], ["self.value","Mux2_x4_inst6.I1"], ["Mux2_x4_inst9.I0","Mux2_x4_inst6.O"], - ["eq_inst9.out","Mux2_x4_inst6.S"], + ["magma_Bits_2_eq_inst6.out","Mux2_x4_inst6.S"], ["self.self_register_O","Mux2_x4_inst7.I0"], ["self.value","Mux2_x4_inst7.I1"], - ["eq_inst11.out","Mux2_x4_inst7.S"], + ["magma_Bits_2_eq_inst8.out","Mux2_x4_inst7.S"], ["self.self_register_O","Mux2_x4_inst8.I0"], ["self.self_register_O","Mux2_x4_inst8.I1"], - ["eq_inst12.out","Mux2_x4_inst8.S"], + ["magma_Bits_2_eq_inst9.out","Mux2_x4_inst8.S"], ["self.value","Mux2_x4_inst9.I1"], - ["eq_inst13.out","Mux2_x4_inst9.S"], - ["eq_inst17.in1","bit_const_1_None.out"], - ["eq_inst18.in1","bit_const_1_None.out"], - ["eq_inst19.in1","bit_const_1_None.out"], - ["eq_inst20.in1","bit_const_1_None.out"], - ["eq_inst6.in1","bit_const_1_None.out"], - ["eq_inst7.in1","bit_const_1_None.out"], - ["eq_inst8.in1","bit_const_1_None.out"], - ["eq_inst13.in1","const_0_2.out"], - ["eq_inst14.in1","const_0_2.out"], - ["eq_inst15.in1","const_0_2.out"], - ["eq_inst16.in1","const_0_2.out"], - ["eq_inst3.in1","const_0_2.out"], - ["eq_inst4.in1","const_0_2.out"], - ["eq_inst5.in1","const_0_2.out"], - ["eq_inst0.in1","const_1_2.out"], - ["eq_inst1.in1","const_1_2.out"], - ["eq_inst10.in1","const_1_2.out"], - ["eq_inst11.in1","const_1_2.out"], - ["eq_inst12.in1","const_1_2.out"], - ["eq_inst2.in1","const_1_2.out"], - ["eq_inst9.in1","const_1_2.out"], - ["self.mode","eq_inst0.in0"], - ["self.mode","eq_inst1.in0"], - ["self.mode","eq_inst10.in0"], - ["self.mode","eq_inst11.in0"], - ["self.mode","eq_inst12.in0"], - ["self.mode","eq_inst13.in0"], - ["self.mode","eq_inst14.in0"], - ["self.mode","eq_inst15.in0"], - ["self.mode","eq_inst16.in0"], - ["self.config_we","eq_inst17.in0"], - ["self.config_we","eq_inst18.in0"], - ["self.config_we","eq_inst19.in0"], - ["self.mode","eq_inst2.in0"], - ["self.config_we","eq_inst20.in0"], - ["self.mode","eq_inst3.in0"], - ["self.mode","eq_inst4.in0"], - ["self.mode","eq_inst5.in0"], - ["self.config_we","eq_inst6.in0"], - ["self.config_we","eq_inst7.in0"], - ["self.config_we","eq_inst8.in0"], - ["self.mode","eq_inst9.in0"] + ["magma_Bits_2_eq_inst10.out","Mux2_x4_inst9.S"], + ["magma_Bit_xor_inst0.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst1.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst2.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst3.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst4.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst5.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst6.in1","bit_const_1_None.out"], + ["magma_Bits_2_eq_inst10.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst11.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst12.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst13.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst3.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst4.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst5.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst0.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst1.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst2.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst6.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst7.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst8.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst9.in1","const_1_2.out"], + ["magma_Bit_xor_inst0.out","magma_Bit_not_inst0.in"], + ["magma_Bit_xor_inst1.out","magma_Bit_not_inst1.in"], + ["magma_Bit_xor_inst2.out","magma_Bit_not_inst2.in"], + ["magma_Bit_xor_inst3.out","magma_Bit_not_inst3.in"], + ["magma_Bit_xor_inst4.out","magma_Bit_not_inst4.in"], + ["magma_Bit_xor_inst5.out","magma_Bit_not_inst5.in"], + ["magma_Bit_xor_inst6.out","magma_Bit_not_inst6.in"], + ["self.config_we","magma_Bit_xor_inst0.in0"], + ["self.config_we","magma_Bit_xor_inst1.in0"], + ["self.config_we","magma_Bit_xor_inst2.in0"], + ["self.config_we","magma_Bit_xor_inst3.in0"], + ["self.config_we","magma_Bit_xor_inst4.in0"], + ["self.config_we","magma_Bit_xor_inst5.in0"], + ["self.config_we","magma_Bit_xor_inst6.in0"], + ["self.mode","magma_Bits_2_eq_inst0.in0"], + ["self.mode","magma_Bits_2_eq_inst1.in0"], + ["self.mode","magma_Bits_2_eq_inst10.in0"], + ["self.mode","magma_Bits_2_eq_inst11.in0"], + ["self.mode","magma_Bits_2_eq_inst12.in0"], + ["self.mode","magma_Bits_2_eq_inst13.in0"], + ["self.mode","magma_Bits_2_eq_inst2.in0"], + ["self.mode","magma_Bits_2_eq_inst3.in0"], + ["self.mode","magma_Bits_2_eq_inst4.in0"], + ["self.mode","magma_Bits_2_eq_inst5.in0"], + ["self.mode","magma_Bits_2_eq_inst6.in0"], + ["self.mode","magma_Bits_2_eq_inst7.in0"], + ["self.mode","magma_Bits_2_eq_inst8.in0"], + ["self.mode","magma_Bits_2_eq_inst9.in0"] ] }, "Register_comb":{ diff --git a/tests/test_syntax/gold/RegisterMode.v b/tests/test_syntax/gold/RegisterMode.v index 0b29d9c55e..644a7190df 100644 --- a/tests/test_syntax/gold/RegisterMode.v +++ b/tests/test_syntax/gold/RegisterMode.v @@ -18,12 +18,16 @@ module coreir_const #(parameter width = 1, parameter value = 1) (output [width-1 assign out = value; endmodule -module corebit_const #(parameter value = 1) (output out); - assign out = value; +module corebit_xor (input in0, input in1, output out); + assign out = in0 ^ in1; +endmodule + +module corebit_not (input in, output out); + assign out = ~in; endmodule -module corebit_and (input in0, input in1, output out); - assign out = in0 & in1; +module corebit_const #(parameter value = 1) (output out); + assign out = value; endmodule module Register_comb (output [3:0] O0, output [3:0] O1, input en, input [3:0] self_value_O, input [3:0] value); @@ -68,73 +72,87 @@ wire bit_const_0_None_out; wire bit_const_1_None_out; wire [1:0] const_0_2_out; wire [1:0] const_1_2_out; -wire eq_inst0_out; -wire eq_inst1_out; -wire eq_inst10_out; -wire eq_inst11_out; -wire eq_inst12_out; -wire eq_inst13_out; -wire eq_inst14_out; -wire eq_inst15_out; -wire eq_inst16_out; -wire eq_inst17_out; -wire eq_inst18_out; -wire eq_inst19_out; -wire eq_inst2_out; -wire eq_inst20_out; -wire eq_inst3_out; -wire eq_inst4_out; -wire eq_inst5_out; -wire eq_inst6_out; -wire eq_inst7_out; -wire eq_inst8_out; -wire eq_inst9_out; -Mux2 Mux2_inst0(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst0_O), .S(eq_inst1_out)); -Mux2 Mux2_inst1(.I0(Mux2_inst0_O), .I1(bit_const_0_None_out), .O(Mux2_inst1_O), .S(eq_inst4_out)); -Mux2 Mux2_inst2(.I0(Mux2_inst1_O), .I1(bit_const_1_None_out), .O(Mux2_inst2_O), .S(eq_inst7_out)); -Mux2 Mux2_inst3(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst3_O), .S(eq_inst10_out)); -Mux2 Mux2_inst4(.I0(Mux2_inst3_O), .I1(bit_const_0_None_out), .O(Mux2_inst4_O), .S(eq_inst14_out)); -Mux2 Mux2_inst5(.I0(Mux2_inst4_O), .I1(bit_const_1_None_out), .O(Mux2_inst5_O), .S(eq_inst18_out)); -Mux2_x4 Mux2_x4_inst0(.I0(value), .I1(value), .O(Mux2_x4_inst0_O), .S(eq_inst0_out)); -Mux2_x4 Mux2_x4_inst1(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst1_O), .S(eq_inst2_out)); -Mux2_x4 Mux2_x4_inst10(.I0(Mux2_x4_inst7_O), .I1(const_), .O(Mux2_x4_inst10_O), .S(eq_inst15_out)); -Mux2_x4 Mux2_x4_inst11(.I0(Mux2_x4_inst8_O), .I1(self_register_O), .O(Mux2_x4_inst11_O), .S(eq_inst16_out)); -Mux2_x4 Mux2_x4_inst12(.I0(Mux2_x4_inst9_O), .I1(config_data), .O(Mux2_x4_inst12_O), .S(eq_inst17_out)); -Mux2_x4 Mux2_x4_inst13(.I0(Mux2_x4_inst10_O), .I1(self_register_O), .O(Mux2_x4_inst13_O), .S(eq_inst19_out)); -Mux2_x4 Mux2_x4_inst14(.I0(Mux2_x4_inst11_O), .I1(self_register_O), .O(Mux2_x4_inst14_O), .S(eq_inst20_out)); -Mux2_x4 Mux2_x4_inst2(.I0(Mux2_x4_inst0_O), .I1(value), .O(Mux2_x4_inst2_O), .S(eq_inst3_out)); -Mux2_x4 Mux2_x4_inst3(.I0(Mux2_x4_inst1_O), .I1(self_register_O), .O(Mux2_x4_inst3_O), .S(eq_inst5_out)); -Mux2_x4 Mux2_x4_inst4(.I0(Mux2_x4_inst2_O), .I1(config_data), .O(Mux2_x4_inst4_O), .S(eq_inst6_out)); -Mux2_x4 Mux2_x4_inst5(.I0(Mux2_x4_inst3_O), .I1(self_register_O), .O(Mux2_x4_inst5_O), .S(eq_inst8_out)); -Mux2_x4 Mux2_x4_inst6(.I0(value), .I1(value), .O(Mux2_x4_inst6_O), .S(eq_inst9_out)); -Mux2_x4 Mux2_x4_inst7(.I0(self_register_O), .I1(value), .O(Mux2_x4_inst7_O), .S(eq_inst11_out)); -Mux2_x4 Mux2_x4_inst8(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst8_O), .S(eq_inst12_out)); -Mux2_x4 Mux2_x4_inst9(.I0(Mux2_x4_inst6_O), .I1(value), .O(Mux2_x4_inst9_O), .S(eq_inst13_out)); +wire magma_Bit_not_inst0_out; +wire magma_Bit_not_inst1_out; +wire magma_Bit_not_inst2_out; +wire magma_Bit_not_inst3_out; +wire magma_Bit_not_inst4_out; +wire magma_Bit_not_inst5_out; +wire magma_Bit_not_inst6_out; +wire magma_Bit_xor_inst0_out; +wire magma_Bit_xor_inst1_out; +wire magma_Bit_xor_inst2_out; +wire magma_Bit_xor_inst3_out; +wire magma_Bit_xor_inst4_out; +wire magma_Bit_xor_inst5_out; +wire magma_Bit_xor_inst6_out; +wire magma_Bits_2_eq_inst0_out; +wire magma_Bits_2_eq_inst1_out; +wire magma_Bits_2_eq_inst10_out; +wire magma_Bits_2_eq_inst11_out; +wire magma_Bits_2_eq_inst12_out; +wire magma_Bits_2_eq_inst13_out; +wire magma_Bits_2_eq_inst2_out; +wire magma_Bits_2_eq_inst3_out; +wire magma_Bits_2_eq_inst4_out; +wire magma_Bits_2_eq_inst5_out; +wire magma_Bits_2_eq_inst6_out; +wire magma_Bits_2_eq_inst7_out; +wire magma_Bits_2_eq_inst8_out; +wire magma_Bits_2_eq_inst9_out; +Mux2 Mux2_inst0(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst0_O), .S(magma_Bits_2_eq_inst1_out)); +Mux2 Mux2_inst1(.I0(Mux2_inst0_O), .I1(bit_const_0_None_out), .O(Mux2_inst1_O), .S(magma_Bits_2_eq_inst4_out)); +Mux2 Mux2_inst2(.I0(Mux2_inst1_O), .I1(bit_const_1_None_out), .O(Mux2_inst2_O), .S(magma_Bit_not_inst1_out)); +Mux2 Mux2_inst3(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst3_O), .S(magma_Bits_2_eq_inst7_out)); +Mux2 Mux2_inst4(.I0(Mux2_inst3_O), .I1(bit_const_0_None_out), .O(Mux2_inst4_O), .S(magma_Bits_2_eq_inst11_out)); +Mux2 Mux2_inst5(.I0(Mux2_inst4_O), .I1(bit_const_1_None_out), .O(Mux2_inst5_O), .S(magma_Bit_not_inst4_out)); +Mux2_x4 Mux2_x4_inst0(.I0(value), .I1(value), .O(Mux2_x4_inst0_O), .S(magma_Bits_2_eq_inst0_out)); +Mux2_x4 Mux2_x4_inst1(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst1_O), .S(magma_Bits_2_eq_inst2_out)); +Mux2_x4 Mux2_x4_inst10(.I0(Mux2_x4_inst7_O), .I1(const_), .O(Mux2_x4_inst10_O), .S(magma_Bits_2_eq_inst12_out)); +Mux2_x4 Mux2_x4_inst11(.I0(Mux2_x4_inst8_O), .I1(self_register_O), .O(Mux2_x4_inst11_O), .S(magma_Bits_2_eq_inst13_out)); +Mux2_x4 Mux2_x4_inst12(.I0(Mux2_x4_inst9_O), .I1(config_data), .O(Mux2_x4_inst12_O), .S(magma_Bit_not_inst3_out)); +Mux2_x4 Mux2_x4_inst13(.I0(Mux2_x4_inst10_O), .I1(self_register_O), .O(Mux2_x4_inst13_O), .S(magma_Bit_not_inst5_out)); +Mux2_x4 Mux2_x4_inst14(.I0(Mux2_x4_inst11_O), .I1(self_register_O), .O(Mux2_x4_inst14_O), .S(magma_Bit_not_inst6_out)); +Mux2_x4 Mux2_x4_inst2(.I0(Mux2_x4_inst0_O), .I1(value), .O(Mux2_x4_inst2_O), .S(magma_Bits_2_eq_inst3_out)); +Mux2_x4 Mux2_x4_inst3(.I0(Mux2_x4_inst1_O), .I1(self_register_O), .O(Mux2_x4_inst3_O), .S(magma_Bits_2_eq_inst5_out)); +Mux2_x4 Mux2_x4_inst4(.I0(Mux2_x4_inst2_O), .I1(config_data), .O(Mux2_x4_inst4_O), .S(magma_Bit_not_inst0_out)); +Mux2_x4 Mux2_x4_inst5(.I0(Mux2_x4_inst3_O), .I1(self_register_O), .O(Mux2_x4_inst5_O), .S(magma_Bit_not_inst2_out)); +Mux2_x4 Mux2_x4_inst6(.I0(value), .I1(value), .O(Mux2_x4_inst6_O), .S(magma_Bits_2_eq_inst6_out)); +Mux2_x4 Mux2_x4_inst7(.I0(self_register_O), .I1(value), .O(Mux2_x4_inst7_O), .S(magma_Bits_2_eq_inst8_out)); +Mux2_x4 Mux2_x4_inst8(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst8_O), .S(magma_Bits_2_eq_inst9_out)); +Mux2_x4 Mux2_x4_inst9(.I0(Mux2_x4_inst6_O), .I1(value), .O(Mux2_x4_inst9_O), .S(magma_Bits_2_eq_inst10_out)); corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); corebit_const #(.value(1)) bit_const_1_None(.out(bit_const_1_None_out)); coreir_const #(.value(2'h0), .width(2)) const_0_2(.out(const_0_2_out)); coreir_const #(.value(2'h1), .width(2)) const_1_2(.out(const_1_2_out)); -coreir_eq #(.width(2)) eq_inst0(.in0(mode), .in1(const_1_2_out), .out(eq_inst0_out)); -coreir_eq #(.width(2)) eq_inst1(.in0(mode), .in1(const_1_2_out), .out(eq_inst1_out)); -coreir_eq #(.width(2)) eq_inst10(.in0(mode), .in1(const_1_2_out), .out(eq_inst10_out)); -coreir_eq #(.width(2)) eq_inst11(.in0(mode), .in1(const_1_2_out), .out(eq_inst11_out)); -coreir_eq #(.width(2)) eq_inst12(.in0(mode), .in1(const_1_2_out), .out(eq_inst12_out)); -coreir_eq #(.width(2)) eq_inst13(.in0(mode), .in1(const_0_2_out), .out(eq_inst13_out)); -coreir_eq #(.width(2)) eq_inst14(.in0(mode), .in1(const_0_2_out), .out(eq_inst14_out)); -coreir_eq #(.width(2)) eq_inst15(.in0(mode), .in1(const_0_2_out), .out(eq_inst15_out)); -coreir_eq #(.width(2)) eq_inst16(.in0(mode), .in1(const_0_2_out), .out(eq_inst16_out)); -corebit_and eq_inst17(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst17_out)); -corebit_and eq_inst18(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst18_out)); -corebit_and eq_inst19(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst19_out)); -coreir_eq #(.width(2)) eq_inst2(.in0(mode), .in1(const_1_2_out), .out(eq_inst2_out)); -corebit_and eq_inst20(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst20_out)); -coreir_eq #(.width(2)) eq_inst3(.in0(mode), .in1(const_0_2_out), .out(eq_inst3_out)); -coreir_eq #(.width(2)) eq_inst4(.in0(mode), .in1(const_0_2_out), .out(eq_inst4_out)); -coreir_eq #(.width(2)) eq_inst5(.in0(mode), .in1(const_0_2_out), .out(eq_inst5_out)); -corebit_and eq_inst6(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst6_out)); -corebit_and eq_inst7(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst7_out)); -corebit_and eq_inst8(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst8_out)); -coreir_eq #(.width(2)) eq_inst9(.in0(mode), .in1(const_1_2_out), .out(eq_inst9_out)); +corebit_not magma_Bit_not_inst0(.in(magma_Bit_xor_inst0_out), .out(magma_Bit_not_inst0_out)); +corebit_not magma_Bit_not_inst1(.in(magma_Bit_xor_inst1_out), .out(magma_Bit_not_inst1_out)); +corebit_not magma_Bit_not_inst2(.in(magma_Bit_xor_inst2_out), .out(magma_Bit_not_inst2_out)); +corebit_not magma_Bit_not_inst3(.in(magma_Bit_xor_inst3_out), .out(magma_Bit_not_inst3_out)); +corebit_not magma_Bit_not_inst4(.in(magma_Bit_xor_inst4_out), .out(magma_Bit_not_inst4_out)); +corebit_not magma_Bit_not_inst5(.in(magma_Bit_xor_inst5_out), .out(magma_Bit_not_inst5_out)); +corebit_not magma_Bit_not_inst6(.in(magma_Bit_xor_inst6_out), .out(magma_Bit_not_inst6_out)); +corebit_xor magma_Bit_xor_inst0(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst0_out)); +corebit_xor magma_Bit_xor_inst1(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst1_out)); +corebit_xor magma_Bit_xor_inst2(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst2_out)); +corebit_xor magma_Bit_xor_inst3(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst3_out)); +corebit_xor magma_Bit_xor_inst4(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst4_out)); +corebit_xor magma_Bit_xor_inst5(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst5_out)); +corebit_xor magma_Bit_xor_inst6(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst6_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst0(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst0_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst1(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst1_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst10(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst10_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst11(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst11_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst12(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst12_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst13(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst13_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst2(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst2_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst3(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst3_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst4(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst4_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst5(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst5_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst6(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst6_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst7(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst7_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst8(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst8_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst9(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst9_out)); assign O0 = Mux2_x4_inst12_O; assign O1 = Mux2_inst5_O; assign O2 = Mux2_x4_inst13_O; diff --git a/tests/test_syntax/gold/RegisterModeARST.json b/tests/test_syntax/gold/RegisterModeARST.json index 886e24c911..98b55add71 100644 --- a/tests/test_syntax/gold/RegisterModeARST.json +++ b/tests/test_syntax/gold/RegisterModeARST.json @@ -179,80 +179,101 @@ "genargs":{"width":["Int",2]}, "modargs":{"value":[["BitVector",2],"2'h1"]} }, - "eq_inst0":{ + "magma_Bit_not_inst0":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst1":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst2":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst3":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst4":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst5":{ + "modref":"corebit.not" + }, + "magma_Bit_not_inst6":{ + "modref":"corebit.not" + }, + "magma_Bit_xor_inst0":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst1":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst2":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst3":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst4":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst5":{ + "modref":"corebit.xor" + }, + "magma_Bit_xor_inst6":{ + "modref":"corebit.xor" + }, + "magma_Bits_2_eq_inst0":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst1":{ + "magma_Bits_2_eq_inst1":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst10":{ + "magma_Bits_2_eq_inst10":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst11":{ + "magma_Bits_2_eq_inst11":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst12":{ + "magma_Bits_2_eq_inst12":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst13":{ + "magma_Bits_2_eq_inst13":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst14":{ + "magma_Bits_2_eq_inst2":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst15":{ + "magma_Bits_2_eq_inst3":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst16":{ + "magma_Bits_2_eq_inst4":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst17":{ - "modref":"corebit.and" - }, - "eq_inst18":{ - "modref":"corebit.and" - }, - "eq_inst19":{ - "modref":"corebit.and" - }, - "eq_inst2":{ + "magma_Bits_2_eq_inst5":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst20":{ - "modref":"corebit.and" - }, - "eq_inst3":{ + "magma_Bits_2_eq_inst6":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst4":{ + "magma_Bits_2_eq_inst7":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst5":{ + "magma_Bits_2_eq_inst8":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} }, - "eq_inst6":{ - "modref":"corebit.and" - }, - "eq_inst7":{ - "modref":"corebit.and" - }, - "eq_inst8":{ - "modref":"corebit.and" - }, - "eq_inst9":{ + "magma_Bits_2_eq_inst9":{ "genref":"coreir.eq", "genargs":{"width":["Int",2]} } @@ -261,112 +282,119 @@ ["self.clk_en","Mux2_inst0.I0"], ["bit_const_0_None.out","Mux2_inst0.I1"], ["Mux2_inst1.I0","Mux2_inst0.O"], - ["eq_inst1.out","Mux2_inst0.S"], + ["magma_Bits_2_eq_inst1.out","Mux2_inst0.S"], ["bit_const_0_None.out","Mux2_inst1.I1"], ["Mux2_inst2.I0","Mux2_inst1.O"], - ["eq_inst4.out","Mux2_inst1.S"], + ["magma_Bits_2_eq_inst4.out","Mux2_inst1.S"], ["bit_const_1_None.out","Mux2_inst2.I1"], - ["eq_inst7.out","Mux2_inst2.S"], + ["magma_Bit_not_inst1.out","Mux2_inst2.S"], ["self.clk_en","Mux2_inst3.I0"], ["bit_const_0_None.out","Mux2_inst3.I1"], ["Mux2_inst4.I0","Mux2_inst3.O"], - ["eq_inst10.out","Mux2_inst3.S"], + ["magma_Bits_2_eq_inst7.out","Mux2_inst3.S"], ["bit_const_0_None.out","Mux2_inst4.I1"], ["Mux2_inst5.I0","Mux2_inst4.O"], - ["eq_inst14.out","Mux2_inst4.S"], + ["magma_Bits_2_eq_inst11.out","Mux2_inst4.S"], ["bit_const_1_None.out","Mux2_inst5.I1"], ["self.O1","Mux2_inst5.O"], - ["eq_inst18.out","Mux2_inst5.S"], + ["magma_Bit_not_inst4.out","Mux2_inst5.S"], ["self.value","Mux2_x4_inst0.I0"], ["self.value","Mux2_x4_inst0.I1"], ["Mux2_x4_inst2.I0","Mux2_x4_inst0.O"], - ["eq_inst0.out","Mux2_x4_inst0.S"], + ["magma_Bits_2_eq_inst0.out","Mux2_x4_inst0.S"], ["self.self_register_O","Mux2_x4_inst1.I0"], ["self.self_register_O","Mux2_x4_inst1.I1"], ["Mux2_x4_inst3.I0","Mux2_x4_inst1.O"], - ["eq_inst2.out","Mux2_x4_inst1.S"], + ["magma_Bits_2_eq_inst2.out","Mux2_x4_inst1.S"], ["Mux2_x4_inst7.O","Mux2_x4_inst10.I0"], ["self.const_","Mux2_x4_inst10.I1"], ["Mux2_x4_inst13.I0","Mux2_x4_inst10.O"], - ["eq_inst15.out","Mux2_x4_inst10.S"], + ["magma_Bits_2_eq_inst12.out","Mux2_x4_inst10.S"], ["Mux2_x4_inst8.O","Mux2_x4_inst11.I0"], ["self.self_register_O","Mux2_x4_inst11.I1"], ["Mux2_x4_inst14.I0","Mux2_x4_inst11.O"], - ["eq_inst16.out","Mux2_x4_inst11.S"], + ["magma_Bits_2_eq_inst13.out","Mux2_x4_inst11.S"], ["Mux2_x4_inst9.O","Mux2_x4_inst12.I0"], ["self.config_data","Mux2_x4_inst12.I1"], ["self.O0","Mux2_x4_inst12.O"], - ["eq_inst17.out","Mux2_x4_inst12.S"], + ["magma_Bit_not_inst3.out","Mux2_x4_inst12.S"], ["self.self_register_O","Mux2_x4_inst13.I1"], ["self.O2","Mux2_x4_inst13.O"], - ["eq_inst19.out","Mux2_x4_inst13.S"], + ["magma_Bit_not_inst5.out","Mux2_x4_inst13.S"], ["self.self_register_O","Mux2_x4_inst14.I1"], ["self.O3","Mux2_x4_inst14.O"], - ["eq_inst20.out","Mux2_x4_inst14.S"], + ["magma_Bit_not_inst6.out","Mux2_x4_inst14.S"], ["self.value","Mux2_x4_inst2.I1"], ["Mux2_x4_inst4.I0","Mux2_x4_inst2.O"], - ["eq_inst3.out","Mux2_x4_inst2.S"], + ["magma_Bits_2_eq_inst3.out","Mux2_x4_inst2.S"], ["self.self_register_O","Mux2_x4_inst3.I1"], ["Mux2_x4_inst5.I0","Mux2_x4_inst3.O"], - ["eq_inst5.out","Mux2_x4_inst3.S"], + ["magma_Bits_2_eq_inst5.out","Mux2_x4_inst3.S"], ["self.config_data","Mux2_x4_inst4.I1"], - ["eq_inst6.out","Mux2_x4_inst4.S"], + ["magma_Bit_not_inst0.out","Mux2_x4_inst4.S"], ["self.self_register_O","Mux2_x4_inst5.I1"], - ["eq_inst8.out","Mux2_x4_inst5.S"], + ["magma_Bit_not_inst2.out","Mux2_x4_inst5.S"], ["self.value","Mux2_x4_inst6.I0"], ["self.value","Mux2_x4_inst6.I1"], ["Mux2_x4_inst9.I0","Mux2_x4_inst6.O"], - ["eq_inst9.out","Mux2_x4_inst6.S"], + ["magma_Bits_2_eq_inst6.out","Mux2_x4_inst6.S"], ["self.self_register_O","Mux2_x4_inst7.I0"], ["self.value","Mux2_x4_inst7.I1"], - ["eq_inst11.out","Mux2_x4_inst7.S"], + ["magma_Bits_2_eq_inst8.out","Mux2_x4_inst7.S"], ["self.self_register_O","Mux2_x4_inst8.I0"], ["self.self_register_O","Mux2_x4_inst8.I1"], - ["eq_inst12.out","Mux2_x4_inst8.S"], + ["magma_Bits_2_eq_inst9.out","Mux2_x4_inst8.S"], ["self.value","Mux2_x4_inst9.I1"], - ["eq_inst13.out","Mux2_x4_inst9.S"], - ["eq_inst17.in1","bit_const_1_None.out"], - ["eq_inst18.in1","bit_const_1_None.out"], - ["eq_inst19.in1","bit_const_1_None.out"], - ["eq_inst20.in1","bit_const_1_None.out"], - ["eq_inst6.in1","bit_const_1_None.out"], - ["eq_inst7.in1","bit_const_1_None.out"], - ["eq_inst8.in1","bit_const_1_None.out"], - ["eq_inst13.in1","const_0_2.out"], - ["eq_inst14.in1","const_0_2.out"], - ["eq_inst15.in1","const_0_2.out"], - ["eq_inst16.in1","const_0_2.out"], - ["eq_inst3.in1","const_0_2.out"], - ["eq_inst4.in1","const_0_2.out"], - ["eq_inst5.in1","const_0_2.out"], - ["eq_inst0.in1","const_1_2.out"], - ["eq_inst1.in1","const_1_2.out"], - ["eq_inst10.in1","const_1_2.out"], - ["eq_inst11.in1","const_1_2.out"], - ["eq_inst12.in1","const_1_2.out"], - ["eq_inst2.in1","const_1_2.out"], - ["eq_inst9.in1","const_1_2.out"], - ["self.mode","eq_inst0.in0"], - ["self.mode","eq_inst1.in0"], - ["self.mode","eq_inst10.in0"], - ["self.mode","eq_inst11.in0"], - ["self.mode","eq_inst12.in0"], - ["self.mode","eq_inst13.in0"], - ["self.mode","eq_inst14.in0"], - ["self.mode","eq_inst15.in0"], - ["self.mode","eq_inst16.in0"], - ["self.config_we","eq_inst17.in0"], - ["self.config_we","eq_inst18.in0"], - ["self.config_we","eq_inst19.in0"], - ["self.mode","eq_inst2.in0"], - ["self.config_we","eq_inst20.in0"], - ["self.mode","eq_inst3.in0"], - ["self.mode","eq_inst4.in0"], - ["self.mode","eq_inst5.in0"], - ["self.config_we","eq_inst6.in0"], - ["self.config_we","eq_inst7.in0"], - ["self.config_we","eq_inst8.in0"], - ["self.mode","eq_inst9.in0"] + ["magma_Bits_2_eq_inst10.out","Mux2_x4_inst9.S"], + ["magma_Bit_xor_inst0.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst1.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst2.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst3.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst4.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst5.in1","bit_const_1_None.out"], + ["magma_Bit_xor_inst6.in1","bit_const_1_None.out"], + ["magma_Bits_2_eq_inst10.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst11.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst12.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst13.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst3.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst4.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst5.in1","const_0_2.out"], + ["magma_Bits_2_eq_inst0.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst1.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst2.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst6.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst7.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst8.in1","const_1_2.out"], + ["magma_Bits_2_eq_inst9.in1","const_1_2.out"], + ["magma_Bit_xor_inst0.out","magma_Bit_not_inst0.in"], + ["magma_Bit_xor_inst1.out","magma_Bit_not_inst1.in"], + ["magma_Bit_xor_inst2.out","magma_Bit_not_inst2.in"], + ["magma_Bit_xor_inst3.out","magma_Bit_not_inst3.in"], + ["magma_Bit_xor_inst4.out","magma_Bit_not_inst4.in"], + ["magma_Bit_xor_inst5.out","magma_Bit_not_inst5.in"], + ["magma_Bit_xor_inst6.out","magma_Bit_not_inst6.in"], + ["self.config_we","magma_Bit_xor_inst0.in0"], + ["self.config_we","magma_Bit_xor_inst1.in0"], + ["self.config_we","magma_Bit_xor_inst2.in0"], + ["self.config_we","magma_Bit_xor_inst3.in0"], + ["self.config_we","magma_Bit_xor_inst4.in0"], + ["self.config_we","magma_Bit_xor_inst5.in0"], + ["self.config_we","magma_Bit_xor_inst6.in0"], + ["self.mode","magma_Bits_2_eq_inst0.in0"], + ["self.mode","magma_Bits_2_eq_inst1.in0"], + ["self.mode","magma_Bits_2_eq_inst10.in0"], + ["self.mode","magma_Bits_2_eq_inst11.in0"], + ["self.mode","magma_Bits_2_eq_inst12.in0"], + ["self.mode","magma_Bits_2_eq_inst13.in0"], + ["self.mode","magma_Bits_2_eq_inst2.in0"], + ["self.mode","magma_Bits_2_eq_inst3.in0"], + ["self.mode","magma_Bits_2_eq_inst4.in0"], + ["self.mode","magma_Bits_2_eq_inst5.in0"], + ["self.mode","magma_Bits_2_eq_inst6.in0"], + ["self.mode","magma_Bits_2_eq_inst7.in0"], + ["self.mode","magma_Bits_2_eq_inst8.in0"], + ["self.mode","magma_Bits_2_eq_inst9.in0"] ] }, "Register_comb":{ diff --git a/tests/test_syntax/gold/RegisterModeARST.v b/tests/test_syntax/gold/RegisterModeARST.v index f0a511b01c..4ad7106a8d 100644 --- a/tests/test_syntax/gold/RegisterModeARST.v +++ b/tests/test_syntax/gold/RegisterModeARST.v @@ -21,12 +21,16 @@ module coreir_const #(parameter width = 1, parameter value = 1) (output [width-1 assign out = value; endmodule -module corebit_const #(parameter value = 1) (output out); - assign out = value; +module corebit_xor (input in0, input in1, output out); + assign out = in0 ^ in1; +endmodule + +module corebit_not (input in, output out); + assign out = ~in; endmodule -module corebit_and (input in0, input in1, output out); - assign out = in0 & in1; +module corebit_const #(parameter value = 1) (output out); + assign out = value; endmodule module Register_comb (output [3:0] O0, output [3:0] O1, input en, input [3:0] self_value_O, input [3:0] value); @@ -71,73 +75,87 @@ wire bit_const_0_None_out; wire bit_const_1_None_out; wire [1:0] const_0_2_out; wire [1:0] const_1_2_out; -wire eq_inst0_out; -wire eq_inst1_out; -wire eq_inst10_out; -wire eq_inst11_out; -wire eq_inst12_out; -wire eq_inst13_out; -wire eq_inst14_out; -wire eq_inst15_out; -wire eq_inst16_out; -wire eq_inst17_out; -wire eq_inst18_out; -wire eq_inst19_out; -wire eq_inst2_out; -wire eq_inst20_out; -wire eq_inst3_out; -wire eq_inst4_out; -wire eq_inst5_out; -wire eq_inst6_out; -wire eq_inst7_out; -wire eq_inst8_out; -wire eq_inst9_out; -Mux2 Mux2_inst0(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst0_O), .S(eq_inst1_out)); -Mux2 Mux2_inst1(.I0(Mux2_inst0_O), .I1(bit_const_0_None_out), .O(Mux2_inst1_O), .S(eq_inst4_out)); -Mux2 Mux2_inst2(.I0(Mux2_inst1_O), .I1(bit_const_1_None_out), .O(Mux2_inst2_O), .S(eq_inst7_out)); -Mux2 Mux2_inst3(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst3_O), .S(eq_inst10_out)); -Mux2 Mux2_inst4(.I0(Mux2_inst3_O), .I1(bit_const_0_None_out), .O(Mux2_inst4_O), .S(eq_inst14_out)); -Mux2 Mux2_inst5(.I0(Mux2_inst4_O), .I1(bit_const_1_None_out), .O(Mux2_inst5_O), .S(eq_inst18_out)); -Mux2_x4 Mux2_x4_inst0(.I0(value), .I1(value), .O(Mux2_x4_inst0_O), .S(eq_inst0_out)); -Mux2_x4 Mux2_x4_inst1(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst1_O), .S(eq_inst2_out)); -Mux2_x4 Mux2_x4_inst10(.I0(Mux2_x4_inst7_O), .I1(const_), .O(Mux2_x4_inst10_O), .S(eq_inst15_out)); -Mux2_x4 Mux2_x4_inst11(.I0(Mux2_x4_inst8_O), .I1(self_register_O), .O(Mux2_x4_inst11_O), .S(eq_inst16_out)); -Mux2_x4 Mux2_x4_inst12(.I0(Mux2_x4_inst9_O), .I1(config_data), .O(Mux2_x4_inst12_O), .S(eq_inst17_out)); -Mux2_x4 Mux2_x4_inst13(.I0(Mux2_x4_inst10_O), .I1(self_register_O), .O(Mux2_x4_inst13_O), .S(eq_inst19_out)); -Mux2_x4 Mux2_x4_inst14(.I0(Mux2_x4_inst11_O), .I1(self_register_O), .O(Mux2_x4_inst14_O), .S(eq_inst20_out)); -Mux2_x4 Mux2_x4_inst2(.I0(Mux2_x4_inst0_O), .I1(value), .O(Mux2_x4_inst2_O), .S(eq_inst3_out)); -Mux2_x4 Mux2_x4_inst3(.I0(Mux2_x4_inst1_O), .I1(self_register_O), .O(Mux2_x4_inst3_O), .S(eq_inst5_out)); -Mux2_x4 Mux2_x4_inst4(.I0(Mux2_x4_inst2_O), .I1(config_data), .O(Mux2_x4_inst4_O), .S(eq_inst6_out)); -Mux2_x4 Mux2_x4_inst5(.I0(Mux2_x4_inst3_O), .I1(self_register_O), .O(Mux2_x4_inst5_O), .S(eq_inst8_out)); -Mux2_x4 Mux2_x4_inst6(.I0(value), .I1(value), .O(Mux2_x4_inst6_O), .S(eq_inst9_out)); -Mux2_x4 Mux2_x4_inst7(.I0(self_register_O), .I1(value), .O(Mux2_x4_inst7_O), .S(eq_inst11_out)); -Mux2_x4 Mux2_x4_inst8(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst8_O), .S(eq_inst12_out)); -Mux2_x4 Mux2_x4_inst9(.I0(Mux2_x4_inst6_O), .I1(value), .O(Mux2_x4_inst9_O), .S(eq_inst13_out)); +wire magma_Bit_not_inst0_out; +wire magma_Bit_not_inst1_out; +wire magma_Bit_not_inst2_out; +wire magma_Bit_not_inst3_out; +wire magma_Bit_not_inst4_out; +wire magma_Bit_not_inst5_out; +wire magma_Bit_not_inst6_out; +wire magma_Bit_xor_inst0_out; +wire magma_Bit_xor_inst1_out; +wire magma_Bit_xor_inst2_out; +wire magma_Bit_xor_inst3_out; +wire magma_Bit_xor_inst4_out; +wire magma_Bit_xor_inst5_out; +wire magma_Bit_xor_inst6_out; +wire magma_Bits_2_eq_inst0_out; +wire magma_Bits_2_eq_inst1_out; +wire magma_Bits_2_eq_inst10_out; +wire magma_Bits_2_eq_inst11_out; +wire magma_Bits_2_eq_inst12_out; +wire magma_Bits_2_eq_inst13_out; +wire magma_Bits_2_eq_inst2_out; +wire magma_Bits_2_eq_inst3_out; +wire magma_Bits_2_eq_inst4_out; +wire magma_Bits_2_eq_inst5_out; +wire magma_Bits_2_eq_inst6_out; +wire magma_Bits_2_eq_inst7_out; +wire magma_Bits_2_eq_inst8_out; +wire magma_Bits_2_eq_inst9_out; +Mux2 Mux2_inst0(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst0_O), .S(magma_Bits_2_eq_inst1_out)); +Mux2 Mux2_inst1(.I0(Mux2_inst0_O), .I1(bit_const_0_None_out), .O(Mux2_inst1_O), .S(magma_Bits_2_eq_inst4_out)); +Mux2 Mux2_inst2(.I0(Mux2_inst1_O), .I1(bit_const_1_None_out), .O(Mux2_inst2_O), .S(magma_Bit_not_inst1_out)); +Mux2 Mux2_inst3(.I0(clk_en), .I1(bit_const_0_None_out), .O(Mux2_inst3_O), .S(magma_Bits_2_eq_inst7_out)); +Mux2 Mux2_inst4(.I0(Mux2_inst3_O), .I1(bit_const_0_None_out), .O(Mux2_inst4_O), .S(magma_Bits_2_eq_inst11_out)); +Mux2 Mux2_inst5(.I0(Mux2_inst4_O), .I1(bit_const_1_None_out), .O(Mux2_inst5_O), .S(magma_Bit_not_inst4_out)); +Mux2_x4 Mux2_x4_inst0(.I0(value), .I1(value), .O(Mux2_x4_inst0_O), .S(magma_Bits_2_eq_inst0_out)); +Mux2_x4 Mux2_x4_inst1(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst1_O), .S(magma_Bits_2_eq_inst2_out)); +Mux2_x4 Mux2_x4_inst10(.I0(Mux2_x4_inst7_O), .I1(const_), .O(Mux2_x4_inst10_O), .S(magma_Bits_2_eq_inst12_out)); +Mux2_x4 Mux2_x4_inst11(.I0(Mux2_x4_inst8_O), .I1(self_register_O), .O(Mux2_x4_inst11_O), .S(magma_Bits_2_eq_inst13_out)); +Mux2_x4 Mux2_x4_inst12(.I0(Mux2_x4_inst9_O), .I1(config_data), .O(Mux2_x4_inst12_O), .S(magma_Bit_not_inst3_out)); +Mux2_x4 Mux2_x4_inst13(.I0(Mux2_x4_inst10_O), .I1(self_register_O), .O(Mux2_x4_inst13_O), .S(magma_Bit_not_inst5_out)); +Mux2_x4 Mux2_x4_inst14(.I0(Mux2_x4_inst11_O), .I1(self_register_O), .O(Mux2_x4_inst14_O), .S(magma_Bit_not_inst6_out)); +Mux2_x4 Mux2_x4_inst2(.I0(Mux2_x4_inst0_O), .I1(value), .O(Mux2_x4_inst2_O), .S(magma_Bits_2_eq_inst3_out)); +Mux2_x4 Mux2_x4_inst3(.I0(Mux2_x4_inst1_O), .I1(self_register_O), .O(Mux2_x4_inst3_O), .S(magma_Bits_2_eq_inst5_out)); +Mux2_x4 Mux2_x4_inst4(.I0(Mux2_x4_inst2_O), .I1(config_data), .O(Mux2_x4_inst4_O), .S(magma_Bit_not_inst0_out)); +Mux2_x4 Mux2_x4_inst5(.I0(Mux2_x4_inst3_O), .I1(self_register_O), .O(Mux2_x4_inst5_O), .S(magma_Bit_not_inst2_out)); +Mux2_x4 Mux2_x4_inst6(.I0(value), .I1(value), .O(Mux2_x4_inst6_O), .S(magma_Bits_2_eq_inst6_out)); +Mux2_x4 Mux2_x4_inst7(.I0(self_register_O), .I1(value), .O(Mux2_x4_inst7_O), .S(magma_Bits_2_eq_inst8_out)); +Mux2_x4 Mux2_x4_inst8(.I0(self_register_O), .I1(self_register_O), .O(Mux2_x4_inst8_O), .S(magma_Bits_2_eq_inst9_out)); +Mux2_x4 Mux2_x4_inst9(.I0(Mux2_x4_inst6_O), .I1(value), .O(Mux2_x4_inst9_O), .S(magma_Bits_2_eq_inst10_out)); corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); corebit_const #(.value(1)) bit_const_1_None(.out(bit_const_1_None_out)); coreir_const #(.value(2'h0), .width(2)) const_0_2(.out(const_0_2_out)); coreir_const #(.value(2'h1), .width(2)) const_1_2(.out(const_1_2_out)); -coreir_eq #(.width(2)) eq_inst0(.in0(mode), .in1(const_1_2_out), .out(eq_inst0_out)); -coreir_eq #(.width(2)) eq_inst1(.in0(mode), .in1(const_1_2_out), .out(eq_inst1_out)); -coreir_eq #(.width(2)) eq_inst10(.in0(mode), .in1(const_1_2_out), .out(eq_inst10_out)); -coreir_eq #(.width(2)) eq_inst11(.in0(mode), .in1(const_1_2_out), .out(eq_inst11_out)); -coreir_eq #(.width(2)) eq_inst12(.in0(mode), .in1(const_1_2_out), .out(eq_inst12_out)); -coreir_eq #(.width(2)) eq_inst13(.in0(mode), .in1(const_0_2_out), .out(eq_inst13_out)); -coreir_eq #(.width(2)) eq_inst14(.in0(mode), .in1(const_0_2_out), .out(eq_inst14_out)); -coreir_eq #(.width(2)) eq_inst15(.in0(mode), .in1(const_0_2_out), .out(eq_inst15_out)); -coreir_eq #(.width(2)) eq_inst16(.in0(mode), .in1(const_0_2_out), .out(eq_inst16_out)); -corebit_and eq_inst17(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst17_out)); -corebit_and eq_inst18(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst18_out)); -corebit_and eq_inst19(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst19_out)); -coreir_eq #(.width(2)) eq_inst2(.in0(mode), .in1(const_1_2_out), .out(eq_inst2_out)); -corebit_and eq_inst20(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst20_out)); -coreir_eq #(.width(2)) eq_inst3(.in0(mode), .in1(const_0_2_out), .out(eq_inst3_out)); -coreir_eq #(.width(2)) eq_inst4(.in0(mode), .in1(const_0_2_out), .out(eq_inst4_out)); -coreir_eq #(.width(2)) eq_inst5(.in0(mode), .in1(const_0_2_out), .out(eq_inst5_out)); -corebit_and eq_inst6(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst6_out)); -corebit_and eq_inst7(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst7_out)); -corebit_and eq_inst8(.in0(config_we), .in1(bit_const_1_None_out), .out(eq_inst8_out)); -coreir_eq #(.width(2)) eq_inst9(.in0(mode), .in1(const_1_2_out), .out(eq_inst9_out)); +corebit_not magma_Bit_not_inst0(.in(magma_Bit_xor_inst0_out), .out(magma_Bit_not_inst0_out)); +corebit_not magma_Bit_not_inst1(.in(magma_Bit_xor_inst1_out), .out(magma_Bit_not_inst1_out)); +corebit_not magma_Bit_not_inst2(.in(magma_Bit_xor_inst2_out), .out(magma_Bit_not_inst2_out)); +corebit_not magma_Bit_not_inst3(.in(magma_Bit_xor_inst3_out), .out(magma_Bit_not_inst3_out)); +corebit_not magma_Bit_not_inst4(.in(magma_Bit_xor_inst4_out), .out(magma_Bit_not_inst4_out)); +corebit_not magma_Bit_not_inst5(.in(magma_Bit_xor_inst5_out), .out(magma_Bit_not_inst5_out)); +corebit_not magma_Bit_not_inst6(.in(magma_Bit_xor_inst6_out), .out(magma_Bit_not_inst6_out)); +corebit_xor magma_Bit_xor_inst0(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst0_out)); +corebit_xor magma_Bit_xor_inst1(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst1_out)); +corebit_xor magma_Bit_xor_inst2(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst2_out)); +corebit_xor magma_Bit_xor_inst3(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst3_out)); +corebit_xor magma_Bit_xor_inst4(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst4_out)); +corebit_xor magma_Bit_xor_inst5(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst5_out)); +corebit_xor magma_Bit_xor_inst6(.in0(config_we), .in1(bit_const_1_None_out), .out(magma_Bit_xor_inst6_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst0(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst0_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst1(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst1_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst10(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst10_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst11(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst11_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst12(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst12_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst13(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst13_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst2(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst2_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst3(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst3_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst4(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst4_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst5(.in0(mode), .in1(const_0_2_out), .out(magma_Bits_2_eq_inst5_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst6(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst6_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst7(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst7_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst8(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst8_out)); +coreir_eq #(.width(2)) magma_Bits_2_eq_inst9(.in0(mode), .in1(const_1_2_out), .out(magma_Bits_2_eq_inst9_out)); assign O0 = Mux2_x4_inst12_O; assign O1 = Mux2_inst5_O; assign O2 = Mux2_x4_inst13_O; diff --git a/tests/test_syntax/gold/return_tuple.json b/tests/test_syntax/gold/return_tuple.json index da9d111ee0..3e6767dfef 100644 --- a/tests/test_syntax/gold/return_tuple.json +++ b/tests/test_syntax/gold/return_tuple.json @@ -15,4 +15,4 @@ } } } -} \ No newline at end of file +} diff --git a/tests/test_syntax/test_combinational.py b/tests/test_syntax/test_combinational.py index a1fb9894e1..973ebe281a 100644 --- a/tests/test_syntax/test_combinational.py +++ b/tests/test_syntax/test_combinational.py @@ -41,7 +41,7 @@ def Mux(height=2, width=None, **kwargs): def get_length(value): - if isinstance(value, m._BitType): + if isinstance(value, m.Digital): return None elif isinstance(value, m.ArrayType): return len(value) @@ -153,15 +153,20 @@ def return_py_tuple(I: m.Bits[2]) -> (m.Bit, m.Bit): def test_return_magma_tuple(target): @m.circuit.combinational - def return_magma_tuple(I: m.Bits[2]) -> m.Tuple(m.Bit, m.Bit): + def return_magma_tuple(I: m.Bits[2]) -> m.Tuple[m.Bit, m.Bit]: return m.tuple_([I[0], I[1]]) compile_and_check("return_magma_tuple", return_magma_tuple.circuit_definition, target) def test_return_magma_named_tuple(target): + + class O(m.Product): + x = m.Bit + y = m.Bit + @m.circuit.combinational - def return_magma_named_tuple(I: m.Bits[2]) -> m.Tuple(x=m.Bit, y=m.Bit): + def return_magma_named_tuple(I: m.Bits[2]) -> O: return m.namedtuple(x=I[0], y=I[1]) compile_and_check("return_magma_named_tuple", return_magma_named_tuple.circuit_definition, target) diff --git a/tests/test_syntax/test_sequential.py b/tests/test_syntax/test_sequential.py index b4c05827e7..06bb0bb21d 100644 --- a/tests/test_syntax/test_sequential.py +++ b/tests/test_syntax/test_sequential.py @@ -4,22 +4,10 @@ from collections.abc import Sequence import coreir import ast_tools +from magma.circuit import DeclareCoreirCircuit ast_tools.stack._SKIP_FRAME_DEBUG_FAIL = True -default_port_mapping = { - "I": "in", - "I0": "in0", - "I1": "in1", - "O": "out", - "S": "sel", -} - - -def DeclareCoreirCircuit(*args, **kwargs): - return m.DeclareCircuit(*args, **kwargs, - renamed_ports=default_port_mapping) - @m.cache_definition def DefineCoreirReg(width, init=0, has_reset=False, T=m.Bits): @@ -212,25 +200,6 @@ def __call__(self, I: m.Bits[2]) -> m.Bits[2]: def test_multiple_return(target, async_reset): T = m.Bits[4] - m._BitType.__eq__ = lambda x, y: DeclareCoreirCircuit( - "eq", - *["I0", m.In(m.Bit), - "I1", m.In(m.Bit), - "O", m.Out(m.Bit)], - coreir_name="and", - coreir_lib="corebit" - )()(x, y) - - m.BitsType.__eq__ = lambda x, y: DeclareCoreirCircuit( - "eq", - *["I0", m.In(m.Bits[len(x)]), - "I1", m.In(m.Bits[len(x)]), - "O", m.Out(m.Bit)], - coreir_genargs={"width": len(x)}, - coreir_name="eq", - coreir_lib="coreir" - )()(x, y) - @m.circuit.sequential(async_reset=async_reset) class Register: def __init__(self): @@ -264,6 +233,7 @@ def __call__(self, mode: m.Bits[2], const_: T, value: T, clk_en: m.Bit, reg_val = self.register(value, clk_en) return reg_val, reg_val + print(repr(type(RegisterMode.instances[1]))) compile_and_check("RegisterMode" + ("ARST" if async_reset else ""), RegisterMode, target) @@ -284,15 +254,6 @@ def __call__(self, I: m.Array[15, m.Bits[1024]]) -> \ def test_rd_ptr(target): - m.UIntType.__add__ = lambda x, y: DeclareCoreirCircuit( - "add", - *["I0", m.In(m.UInt[len(x)]), - "I1", m.In(m.UInt[len(x)]), - "O", m.Out(m.UInt[len(x)])], - coreir_name="add", - coreir_genargs={"width": len(x)}, - coreir_lib="coreir" - )()(x, y) @m.circuit.sequential(async_reset=True) class RdPtr: def __init__(self): diff --git a/tests/test_syntax/test_to_verilog.py b/tests/test_syntax/test_to_verilog.py index faa7444ad5..ca3c0796f8 100644 --- a/tests/test_syntax/test_to_verilog.py +++ b/tests/test_syntax/test_to_verilog.py @@ -44,6 +44,7 @@ def test_simple_alu(): # Test with fault if available import fault tester = fault.Tester(SimpleALU) + tester.circuit.CLK = 0 ops = [operator.add, operator.sub, operator.mul, operator.floordiv] for i, op in enumerate(ops): tester.circuit.config_ = i diff --git a/tests/test_type/gold/TestBitInvert.v b/tests/test_type/gold/TestBitInvert.v new file mode 100644 index 0000000000..c0ce44c1b0 --- /dev/null +++ b/tests/test_type/gold/TestBitInvert.v @@ -0,0 +1,10 @@ +module corebit_not (input in, output out); + assign out = ~in; +endmodule + +module TestInvert (input I, output O); +wire magma_Bit_not_inst0_out; +corebit_not magma_Bit_not_inst0(.in(I), .out(magma_Bit_not_inst0_out)); +assign O = magma_Bit_not_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBitand.v b/tests/test_type/gold/TestBitand.v new file mode 100644 index 0000000000..9fca1f62b3 --- /dev/null +++ b/tests/test_type/gold/TestBitand.v @@ -0,0 +1,10 @@ +module corebit_and (input in0, input in1, output out); + assign out = in0 & in1; +endmodule + +module TestBinary (input I0, input I1, output O); +wire magma_Bit_and_inst0_out; +corebit_and magma_Bit_and_inst0(.in0(I0), .in1(I1), .out(magma_Bit_and_inst0_out)); +assign O = magma_Bit_and_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBiteq.v b/tests/test_type/gold/TestBiteq.v new file mode 100644 index 0000000000..891126e9e0 --- /dev/null +++ b/tests/test_type/gold/TestBiteq.v @@ -0,0 +1,16 @@ +module corebit_xor (input in0, input in1, output out); + assign out = in0 ^ in1; +endmodule + +module corebit_not (input in, output out); + assign out = ~in; +endmodule + +module TestBinary (input I0, input I1, output O); +wire magma_Bit_not_inst0_out; +wire magma_Bit_xor_inst0_out; +corebit_not magma_Bit_not_inst0(.in(magma_Bit_xor_inst0_out), .out(magma_Bit_not_inst0_out)); +corebit_xor magma_Bit_xor_inst0(.in0(I0), .in1(I1), .out(magma_Bit_xor_inst0_out)); +assign O = magma_Bit_not_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBitite.v b/tests/test_type/gold/TestBitite.v new file mode 100644 index 0000000000..bd45b8b1d3 --- /dev/null +++ b/tests/test_type/gold/TestBitite.v @@ -0,0 +1,10 @@ +module corebit_mux (input in0, input in1, input sel, output out); + assign out = sel ? in1 : in0; +endmodule + +module TestITE (input I0, input I1, output O, input S); +wire magma_Bit_ite_Out_Bit_inst0_out; +corebit_mux magma_Bit_ite_Out_Bit_inst0(.in0(I1), .in1(I0), .out(magma_Bit_ite_Out_Bit_inst0_out), .sel(S)); +assign O = magma_Bit_ite_Out_Bit_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBitne.v b/tests/test_type/gold/TestBitne.v new file mode 100644 index 0000000000..a57a92a636 --- /dev/null +++ b/tests/test_type/gold/TestBitne.v @@ -0,0 +1,10 @@ +module corebit_xor (input in0, input in1, output out); + assign out = in0 ^ in1; +endmodule + +module TestBinary (input I0, input I1, output O); +wire magma_Bit_xor_inst0_out; +corebit_xor magma_Bit_xor_inst0(.in0(I0), .in1(I1), .out(magma_Bit_xor_inst0_out)); +assign O = magma_Bit_xor_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBitor.v b/tests/test_type/gold/TestBitor.v new file mode 100644 index 0000000000..dd4f869f2c --- /dev/null +++ b/tests/test_type/gold/TestBitor.v @@ -0,0 +1,10 @@ +module corebit_or (input in0, input in1, output out); + assign out = in0 | in1; +endmodule + +module TestBinary (input I0, input I1, output O); +wire magma_Bit_or_inst0_out; +corebit_or magma_Bit_or_inst0(.in0(I0), .in1(I1), .out(magma_Bit_or_inst0_out)); +assign O = magma_Bit_or_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1ITE.v b/tests/test_type/gold/TestBits1ITE.v new file mode 100644 index 0000000000..826095d8e7 --- /dev/null +++ b/tests/test_type/gold/TestBits1ITE.v @@ -0,0 +1,28 @@ +module coreir_mux #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, input sel, output [width-1:0] out); + assign out = sel ? in1 : in0; +endmodule + +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module coreir_const #(parameter width = 1, parameter value = 1) (output [width-1:0] out); + assign out = value; +endmodule + +module corebit_not (input in, output out); + assign out = ~in; +endmodule + +module TestITE (input [0:0] I0, input [0:0] I1, output [0:0] O, input [0:0] S); +wire [0:0] const_0_1_out; +wire magma_Bit_not_inst0_out; +wire magma_Bits_1_eq_inst0_out; +wire [0:0] magma_Bits_1_ite_Out_Bits_1_inst0_out; +coreir_const #(.value(1'h0), .width(1)) const_0_1(.out(const_0_1_out)); +corebit_not magma_Bit_not_inst0(.in(magma_Bits_1_eq_inst0_out), .out(magma_Bit_not_inst0_out)); +coreir_eq #(.width(1)) magma_Bits_1_eq_inst0(.in0(S), .in1(const_0_1_out), .out(magma_Bits_1_eq_inst0_out)); +coreir_mux #(.width(1)) magma_Bits_1_ite_Out_Bits_1_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_ite_Out_Bits_1_inst0_out), .sel(magma_Bit_not_inst0_out)); +assign O = magma_Bits_1_ite_Out_Bits_1_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1Invert.v b/tests/test_type/gold/TestBits1Invert.v new file mode 100644 index 0000000000..5bb17e44e1 --- /dev/null +++ b/tests/test_type/gold/TestBits1Invert.v @@ -0,0 +1,10 @@ +module coreir_not #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = ~in; +endmodule + +module TestInvert (input [0:0] I, output [0:0] O); +wire [0:0] magma_Bits_1_not_inst0_out; +coreir_not #(.width(1)) magma_Bits_1_not_inst0(.in(I), .out(magma_Bits_1_not_inst0_out)); +assign O = magma_Bits_1_not_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1and.v b/tests/test_type/gold/TestBits1and.v new file mode 100644 index 0000000000..e3a7a5d518 --- /dev/null +++ b/tests/test_type/gold/TestBits1and.v @@ -0,0 +1,10 @@ +module coreir_and #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 & in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_and_inst0_out; +coreir_and #(.width(1)) magma_Bits_1_and_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_and_inst0_out)); +assign O = magma_Bits_1_and_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1bvcomp.v b/tests/test_type/gold/TestBits1bvcomp.v new file mode 100644 index 0000000000..3c0c3cc3e5 --- /dev/null +++ b/tests/test_type/gold/TestBits1bvcomp.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire magma_Bits_1_eq_inst0_out; +coreir_eq #(.width(1)) magma_Bits_1_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_eq_inst0_out)); +assign O = magma_Bits_1_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1eq.v b/tests/test_type/gold/TestBits1eq.v new file mode 100644 index 0000000000..f6374bab9e --- /dev/null +++ b/tests/test_type/gold/TestBits1eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_eq_inst0_out; +coreir_eq #(.width(1)) magma_Bits_1_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_eq_inst0_out)); +assign O = magma_Bits_1_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1ext.v b/tests/test_type/gold/TestBits1ext.v new file mode 100644 index 0000000000..2a41c94916 --- /dev/null +++ b/tests/test_type/gold/TestBits1ext.v @@ -0,0 +1,10 @@ +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestExt (input [0:0] I, output [3:0] O); +wire bit_const_0_None_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +assign O = {bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits1lshr.v b/tests/test_type/gold/TestBits1lshr.v new file mode 100644 index 0000000000..c10039a5d3 --- /dev/null +++ b/tests/test_type/gold/TestBits1lshr.v @@ -0,0 +1,10 @@ +module coreir_lshr #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 >> in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_lshr_inst0_out; +coreir_lshr #(.width(1)) magma_Bits_1_lshr_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_lshr_inst0_out)); +assign O = magma_Bits_1_lshr_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1or.v b/tests/test_type/gold/TestBits1or.v new file mode 100644 index 0000000000..d3dbbc9591 --- /dev/null +++ b/tests/test_type/gold/TestBits1or.v @@ -0,0 +1,10 @@ +module coreir_or #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 | in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_or_inst0_out; +coreir_or #(.width(1)) magma_Bits_1_or_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_or_inst0_out)); +assign O = magma_Bits_1_or_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1shl.v b/tests/test_type/gold/TestBits1shl.v new file mode 100644 index 0000000000..e58ed25d18 --- /dev/null +++ b/tests/test_type/gold/TestBits1shl.v @@ -0,0 +1,10 @@ +module coreir_shl #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 << in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_shl_inst0_out; +coreir_shl #(.width(1)) magma_Bits_1_shl_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_shl_inst0_out)); +assign O = magma_Bits_1_shl_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits1x4Repeat.v b/tests/test_type/gold/TestBits1x4Repeat.v new file mode 100644 index 0000000000..c678109665 --- /dev/null +++ b/tests/test_type/gold/TestBits1x4Repeat.v @@ -0,0 +1,4 @@ +module TestRepeat (input [0:0] I, output [3:0] O); +assign O = {I[0],I[0],I[0],I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits1x7Repeat.v b/tests/test_type/gold/TestBits1x7Repeat.v new file mode 100644 index 0000000000..a0b09cb2ec --- /dev/null +++ b/tests/test_type/gold/TestBits1x7Repeat.v @@ -0,0 +1,4 @@ +module TestRepeat (input [0:0] I, output [6:0] O); +assign O = {I[0],I[0],I[0],I[0],I[0],I[0],I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits1xor.v b/tests/test_type/gold/TestBits1xor.v new file mode 100644 index 0000000000..5a7b16885e --- /dev/null +++ b/tests/test_type/gold/TestBits1xor.v @@ -0,0 +1,10 @@ +module coreir_xor #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 ^ in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_xor_inst0_out; +coreir_xor #(.width(1)) magma_Bits_1_xor_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_xor_inst0_out)); +assign O = magma_Bits_1_xor_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3ITE.v b/tests/test_type/gold/TestBits3ITE.v new file mode 100644 index 0000000000..47dd6765a1 --- /dev/null +++ b/tests/test_type/gold/TestBits3ITE.v @@ -0,0 +1,28 @@ +module coreir_mux #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, input sel, output [width-1:0] out); + assign out = sel ? in1 : in0; +endmodule + +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module coreir_const #(parameter width = 1, parameter value = 1) (output [width-1:0] out); + assign out = value; +endmodule + +module corebit_not (input in, output out); + assign out = ~in; +endmodule + +module TestITE (input [2:0] I0, input [2:0] I1, output [2:0] O, input [2:0] S); +wire [2:0] const_0_3_out; +wire magma_Bit_not_inst0_out; +wire magma_Bits_3_eq_inst0_out; +wire [2:0] magma_Bits_3_ite_Out_Bits_3_inst0_out; +coreir_const #(.value(3'h0), .width(3)) const_0_3(.out(const_0_3_out)); +corebit_not magma_Bit_not_inst0(.in(magma_Bits_3_eq_inst0_out), .out(magma_Bit_not_inst0_out)); +coreir_eq #(.width(3)) magma_Bits_3_eq_inst0(.in0(S), .in1(const_0_3_out), .out(magma_Bits_3_eq_inst0_out)); +coreir_mux #(.width(3)) magma_Bits_3_ite_Out_Bits_3_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_ite_Out_Bits_3_inst0_out), .sel(magma_Bit_not_inst0_out)); +assign O = magma_Bits_3_ite_Out_Bits_3_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3Invert.v b/tests/test_type/gold/TestBits3Invert.v new file mode 100644 index 0000000000..d5b7ae6441 --- /dev/null +++ b/tests/test_type/gold/TestBits3Invert.v @@ -0,0 +1,10 @@ +module coreir_not #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = ~in; +endmodule + +module TestInvert (input [2:0] I, output [2:0] O); +wire [2:0] magma_Bits_3_not_inst0_out; +coreir_not #(.width(3)) magma_Bits_3_not_inst0(.in(I), .out(magma_Bits_3_not_inst0_out)); +assign O = magma_Bits_3_not_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3and.v b/tests/test_type/gold/TestBits3and.v new file mode 100644 index 0000000000..9a096b1897 --- /dev/null +++ b/tests/test_type/gold/TestBits3and.v @@ -0,0 +1,10 @@ +module coreir_and #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 & in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_and_inst0_out; +coreir_and #(.width(3)) magma_Bits_3_and_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_and_inst0_out)); +assign O = magma_Bits_3_and_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3bvcomp.v b/tests/test_type/gold/TestBits3bvcomp.v new file mode 100644 index 0000000000..627e6773c5 --- /dev/null +++ b/tests/test_type/gold/TestBits3bvcomp.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [0:0] O); +wire magma_Bits_3_eq_inst0_out; +coreir_eq #(.width(3)) magma_Bits_3_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_eq_inst0_out)); +assign O = magma_Bits_3_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3eq.v b/tests/test_type/gold/TestBits3eq.v new file mode 100644 index 0000000000..2a4bd21c11 --- /dev/null +++ b/tests/test_type/gold/TestBits3eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_eq_inst0_out; +coreir_eq #(.width(3)) magma_Bits_3_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_eq_inst0_out)); +assign O = magma_Bits_3_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3ext.v b/tests/test_type/gold/TestBits3ext.v new file mode 100644 index 0000000000..3f65fc399b --- /dev/null +++ b/tests/test_type/gold/TestBits3ext.v @@ -0,0 +1,10 @@ +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestExt (input [2:0] I, output [5:0] O); +wire bit_const_0_None_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +assign O = {bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,I[2],I[1],I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits3lshr.v b/tests/test_type/gold/TestBits3lshr.v new file mode 100644 index 0000000000..93605fccb1 --- /dev/null +++ b/tests/test_type/gold/TestBits3lshr.v @@ -0,0 +1,10 @@ +module coreir_lshr #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 >> in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_lshr_inst0_out; +coreir_lshr #(.width(3)) magma_Bits_3_lshr_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_lshr_inst0_out)); +assign O = magma_Bits_3_lshr_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3or.v b/tests/test_type/gold/TestBits3or.v new file mode 100644 index 0000000000..9bdfd131c5 --- /dev/null +++ b/tests/test_type/gold/TestBits3or.v @@ -0,0 +1,10 @@ +module coreir_or #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 | in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_or_inst0_out; +coreir_or #(.width(3)) magma_Bits_3_or_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_or_inst0_out)); +assign O = magma_Bits_3_or_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3shl.v b/tests/test_type/gold/TestBits3shl.v new file mode 100644 index 0000000000..4bbc98c676 --- /dev/null +++ b/tests/test_type/gold/TestBits3shl.v @@ -0,0 +1,10 @@ +module coreir_shl #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 << in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_shl_inst0_out; +coreir_shl #(.width(3)) magma_Bits_3_shl_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_shl_inst0_out)); +assign O = magma_Bits_3_shl_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBits3x4Repeat.v b/tests/test_type/gold/TestBits3x4Repeat.v new file mode 100644 index 0000000000..9b3c689633 --- /dev/null +++ b/tests/test_type/gold/TestBits3x4Repeat.v @@ -0,0 +1,4 @@ +module TestRepeat (input [2:0] I, output [11:0] O); +assign O = {I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits3x7Repeat.v b/tests/test_type/gold/TestBits3x7Repeat.v new file mode 100644 index 0000000000..6a6e6d158a --- /dev/null +++ b/tests/test_type/gold/TestBits3x7Repeat.v @@ -0,0 +1,4 @@ +module TestRepeat (input [2:0] I, output [20:0] O); +assign O = {I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0],I[2],I[1],I[0]}; +endmodule + diff --git a/tests/test_type/gold/TestBits3xor.v b/tests/test_type/gold/TestBits3xor.v new file mode 100644 index 0000000000..5842e6bc65 --- /dev/null +++ b/tests/test_type/gold/TestBits3xor.v @@ -0,0 +1,10 @@ +module coreir_xor #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 ^ in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_xor_inst0_out; +coreir_xor #(.width(3)) magma_Bits_3_xor_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_xor_inst0_out)); +assign O = magma_Bits_3_xor_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestBitxor.v b/tests/test_type/gold/TestBitxor.v new file mode 100644 index 0000000000..a57a92a636 --- /dev/null +++ b/tests/test_type/gold/TestBitxor.v @@ -0,0 +1,10 @@ +module corebit_xor (input in0, input in1, output out); + assign out = in0 ^ in1; +endmodule + +module TestBinary (input I0, input I1, output O); +wire magma_Bit_xor_inst0_out; +corebit_xor magma_Bit_xor_inst0(.in0(I0), .in1(I1), .out(magma_Bit_xor_inst0_out)); +assign O = magma_Bit_xor_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3Negate.v b/tests/test_type/gold/TestSInt3Negate.v new file mode 100644 index 0000000000..ee260c339a --- /dev/null +++ b/tests/test_type/gold/TestSInt3Negate.v @@ -0,0 +1,10 @@ +module coreir_neg #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = -in; +endmodule + +module TestNegate (input [2:0] I, output [2:0] O); +wire [2:0] magma_Bits_3_neg_inst0_out; +coreir_neg #(.width(3)) magma_Bits_3_neg_inst0(.in(I), .out(magma_Bits_3_neg_inst0_out)); +assign O = magma_Bits_3_neg_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3adc.v b/tests/test_type/gold/TestSInt3adc.v new file mode 100644 index 0000000000..f1cbe4b2ed --- /dev/null +++ b/tests/test_type/gold/TestSInt3adc.v @@ -0,0 +1,19 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestBinary (input CIN, output COUT, input [2:0] I0, input [2:0] I1, output [2:0] O); +wire bit_const_0_None_out; +wire [3:0] magma_Bits_4_add_inst0_out; +wire [3:0] magma_Bits_4_add_inst1_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +coreir_add #(.width(4)) magma_Bits_4_add_inst0(.in0({I0[2],I0[2],I0[1],I0[0]}), .in1({I1[2],I1[2],I1[1],I1[0]}), .out(magma_Bits_4_add_inst0_out)); +coreir_add #(.width(4)) magma_Bits_4_add_inst1(.in0(magma_Bits_4_add_inst0_out), .in1({bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,CIN}), .out(magma_Bits_4_add_inst1_out)); +assign COUT = magma_Bits_4_add_inst1_out[3]; +assign O = {magma_Bits_4_add_inst1_out[2],magma_Bits_4_add_inst1_out[1],magma_Bits_4_add_inst1_out[0]}; +endmodule + diff --git a/tests/test_type/gold/TestSInt3add.v b/tests/test_type/gold/TestSInt3add.v new file mode 100644 index 0000000000..f4efdf2917 --- /dev/null +++ b/tests/test_type/gold/TestSInt3add.v @@ -0,0 +1,10 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_add_inst0_out; +coreir_add #(.width(3)) magma_Bits_3_add_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_add_inst0_out)); +assign O = magma_Bits_3_add_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3ashr.v b/tests/test_type/gold/TestSInt3ashr.v new file mode 100644 index 0000000000..7c137e220c --- /dev/null +++ b/tests/test_type/gold/TestSInt3ashr.v @@ -0,0 +1,10 @@ +module coreir_ashr #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = $signed(in0) >>> in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_ashr_inst0_out; +coreir_ashr #(.width(3)) magma_Bits_3_ashr_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_ashr_inst0_out)); +assign O = magma_Bits_3_ashr_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3eq.v b/tests/test_type/gold/TestSInt3eq.v new file mode 100644 index 0000000000..2a4bd21c11 --- /dev/null +++ b/tests/test_type/gold/TestSInt3eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_eq_inst0_out; +coreir_eq #(.width(3)) magma_Bits_3_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_eq_inst0_out)); +assign O = magma_Bits_3_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3mul.v b/tests/test_type/gold/TestSInt3mul.v new file mode 100644 index 0000000000..54be1a9759 --- /dev/null +++ b/tests/test_type/gold/TestSInt3mul.v @@ -0,0 +1,10 @@ +module coreir_mul #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 * in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_mul_inst0_out; +coreir_mul #(.width(3)) magma_Bits_3_mul_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_mul_inst0_out)); +assign O = magma_Bits_3_mul_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3neg.v b/tests/test_type/gold/TestSInt3neg.v new file mode 100644 index 0000000000..ee260c339a --- /dev/null +++ b/tests/test_type/gold/TestSInt3neg.v @@ -0,0 +1,10 @@ +module coreir_neg #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = -in; +endmodule + +module TestNegate (input [2:0] I, output [2:0] O); +wire [2:0] magma_Bits_3_neg_inst0_out; +coreir_neg #(.width(3)) magma_Bits_3_neg_inst0(.in(I), .out(magma_Bits_3_neg_inst0_out)); +assign O = magma_Bits_3_neg_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3sdiv.v b/tests/test_type/gold/TestSInt3sdiv.v new file mode 100644 index 0000000000..cbc09e366e --- /dev/null +++ b/tests/test_type/gold/TestSInt3sdiv.v @@ -0,0 +1,10 @@ +module coreir_sdiv #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = $signed(in0) / $signed(in1); +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_sdiv_inst0_out; +coreir_sdiv #(.width(3)) magma_Bits_3_sdiv_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sdiv_inst0_out)); +assign O = magma_Bits_3_sdiv_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3sge.v b/tests/test_type/gold/TestSInt3sge.v new file mode 100644 index 0000000000..8d475ca212 --- /dev/null +++ b/tests/test_type/gold/TestSInt3sge.v @@ -0,0 +1,10 @@ +module coreir_sge #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) >= $signed(in1); +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_sge_inst0_out; +coreir_sge #(.width(3)) magma_Bits_3_sge_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sge_inst0_out)); +assign O = magma_Bits_3_sge_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3sgt.v b/tests/test_type/gold/TestSInt3sgt.v new file mode 100644 index 0000000000..7b2645874d --- /dev/null +++ b/tests/test_type/gold/TestSInt3sgt.v @@ -0,0 +1,10 @@ +module coreir_sgt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) > $signed(in1); +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_sgt_inst0_out; +coreir_sgt #(.width(3)) magma_Bits_3_sgt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sgt_inst0_out)); +assign O = magma_Bits_3_sgt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3sle.v b/tests/test_type/gold/TestSInt3sle.v new file mode 100644 index 0000000000..2f00f1d26b --- /dev/null +++ b/tests/test_type/gold/TestSInt3sle.v @@ -0,0 +1,10 @@ +module coreir_sle #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) <= $signed(in1); +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_sle_inst0_out; +coreir_sle #(.width(3)) magma_Bits_3_sle_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sle_inst0_out)); +assign O = magma_Bits_3_sle_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3slt.v b/tests/test_type/gold/TestSInt3slt.v new file mode 100644 index 0000000000..77d45e1721 --- /dev/null +++ b/tests/test_type/gold/TestSInt3slt.v @@ -0,0 +1,10 @@ +module coreir_slt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) < $signed(in1); +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_slt_inst0_out; +coreir_slt #(.width(3)) magma_Bits_3_slt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_slt_inst0_out)); +assign O = magma_Bits_3_slt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3srem.v b/tests/test_type/gold/TestSInt3srem.v new file mode 100644 index 0000000000..c4658d8d9f --- /dev/null +++ b/tests/test_type/gold/TestSInt3srem.v @@ -0,0 +1,7 @@ +// Module `srem` defined externally +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_srem_inst0_out; +coreir_srem__width3 magma_Bits_3_srem_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_srem_inst0_out)); +assign O = magma_Bits_3_srem_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt3sub.v b/tests/test_type/gold/TestSInt3sub.v new file mode 100644 index 0000000000..e33cb3502b --- /dev/null +++ b/tests/test_type/gold/TestSInt3sub.v @@ -0,0 +1,10 @@ +module coreir_sub #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 - in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_sub_inst0_out; +coreir_sub #(.width(3)) magma_Bits_3_sub_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sub_inst0_out)); +assign O = magma_Bits_3_sub_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7Negate.v b/tests/test_type/gold/TestSInt7Negate.v new file mode 100644 index 0000000000..7a625c8536 --- /dev/null +++ b/tests/test_type/gold/TestSInt7Negate.v @@ -0,0 +1,10 @@ +module coreir_neg #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = -in; +endmodule + +module TestNegate (input [6:0] I, output [6:0] O); +wire [6:0] magma_Bits_7_neg_inst0_out; +coreir_neg #(.width(7)) magma_Bits_7_neg_inst0(.in(I), .out(magma_Bits_7_neg_inst0_out)); +assign O = magma_Bits_7_neg_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7adc.v b/tests/test_type/gold/TestSInt7adc.v new file mode 100644 index 0000000000..0adb6188a0 --- /dev/null +++ b/tests/test_type/gold/TestSInt7adc.v @@ -0,0 +1,19 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestBinary (input CIN, output COUT, input [6:0] I0, input [6:0] I1, output [6:0] O); +wire bit_const_0_None_out; +wire [7:0] magma_Bits_8_add_inst0_out; +wire [7:0] magma_Bits_8_add_inst1_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +coreir_add #(.width(8)) magma_Bits_8_add_inst0(.in0({I0[6],I0[6],I0[5],I0[4],I0[3],I0[2],I0[1],I0[0]}), .in1({I1[6],I1[6],I1[5],I1[4],I1[3],I1[2],I1[1],I1[0]}), .out(magma_Bits_8_add_inst0_out)); +coreir_add #(.width(8)) magma_Bits_8_add_inst1(.in0(magma_Bits_8_add_inst0_out), .in1({bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,CIN}), .out(magma_Bits_8_add_inst1_out)); +assign COUT = magma_Bits_8_add_inst1_out[7]; +assign O = {magma_Bits_8_add_inst1_out[6],magma_Bits_8_add_inst1_out[5],magma_Bits_8_add_inst1_out[4],magma_Bits_8_add_inst1_out[3],magma_Bits_8_add_inst1_out[2],magma_Bits_8_add_inst1_out[1],magma_Bits_8_add_inst1_out[0]}; +endmodule + diff --git a/tests/test_type/gold/TestSInt7add.v b/tests/test_type/gold/TestSInt7add.v new file mode 100644 index 0000000000..d9774e04b1 --- /dev/null +++ b/tests/test_type/gold/TestSInt7add.v @@ -0,0 +1,10 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_add_inst0_out; +coreir_add #(.width(7)) magma_Bits_7_add_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_add_inst0_out)); +assign O = magma_Bits_7_add_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7ashr.v b/tests/test_type/gold/TestSInt7ashr.v new file mode 100644 index 0000000000..3f00d02c10 --- /dev/null +++ b/tests/test_type/gold/TestSInt7ashr.v @@ -0,0 +1,10 @@ +module coreir_ashr #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = $signed(in0) >>> in1; +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_ashr_inst0_out; +coreir_ashr #(.width(7)) magma_Bits_7_ashr_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_ashr_inst0_out)); +assign O = magma_Bits_7_ashr_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7eq.v b/tests/test_type/gold/TestSInt7eq.v new file mode 100644 index 0000000000..69a7317d15 --- /dev/null +++ b/tests/test_type/gold/TestSInt7eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output O); +wire magma_Bits_7_eq_inst0_out; +coreir_eq #(.width(7)) magma_Bits_7_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_eq_inst0_out)); +assign O = magma_Bits_7_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7mul.v b/tests/test_type/gold/TestSInt7mul.v new file mode 100644 index 0000000000..9755f55ecf --- /dev/null +++ b/tests/test_type/gold/TestSInt7mul.v @@ -0,0 +1,10 @@ +module coreir_mul #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 * in1; +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_mul_inst0_out; +coreir_mul #(.width(7)) magma_Bits_7_mul_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_mul_inst0_out)); +assign O = magma_Bits_7_mul_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7neg.v b/tests/test_type/gold/TestSInt7neg.v new file mode 100644 index 0000000000..7a625c8536 --- /dev/null +++ b/tests/test_type/gold/TestSInt7neg.v @@ -0,0 +1,10 @@ +module coreir_neg #(parameter width = 1) (input [width-1:0] in, output [width-1:0] out); + assign out = -in; +endmodule + +module TestNegate (input [6:0] I, output [6:0] O); +wire [6:0] magma_Bits_7_neg_inst0_out; +coreir_neg #(.width(7)) magma_Bits_7_neg_inst0(.in(I), .out(magma_Bits_7_neg_inst0_out)); +assign O = magma_Bits_7_neg_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7sdiv.v b/tests/test_type/gold/TestSInt7sdiv.v new file mode 100644 index 0000000000..1e87867663 --- /dev/null +++ b/tests/test_type/gold/TestSInt7sdiv.v @@ -0,0 +1,10 @@ +module coreir_sdiv #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = $signed(in0) / $signed(in1); +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_sdiv_inst0_out; +coreir_sdiv #(.width(7)) magma_Bits_7_sdiv_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_sdiv_inst0_out)); +assign O = magma_Bits_7_sdiv_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7sge.v b/tests/test_type/gold/TestSInt7sge.v new file mode 100644 index 0000000000..ea5f329673 --- /dev/null +++ b/tests/test_type/gold/TestSInt7sge.v @@ -0,0 +1,10 @@ +module coreir_sge #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) >= $signed(in1); +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output O); +wire magma_Bits_7_sge_inst0_out; +coreir_sge #(.width(7)) magma_Bits_7_sge_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_sge_inst0_out)); +assign O = magma_Bits_7_sge_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7sgt.v b/tests/test_type/gold/TestSInt7sgt.v new file mode 100644 index 0000000000..8c7575aea8 --- /dev/null +++ b/tests/test_type/gold/TestSInt7sgt.v @@ -0,0 +1,10 @@ +module coreir_sgt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) > $signed(in1); +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output O); +wire magma_Bits_7_sgt_inst0_out; +coreir_sgt #(.width(7)) magma_Bits_7_sgt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_sgt_inst0_out)); +assign O = magma_Bits_7_sgt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7sle.v b/tests/test_type/gold/TestSInt7sle.v new file mode 100644 index 0000000000..e9850ee7a4 --- /dev/null +++ b/tests/test_type/gold/TestSInt7sle.v @@ -0,0 +1,10 @@ +module coreir_sle #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) <= $signed(in1); +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output O); +wire magma_Bits_7_sle_inst0_out; +coreir_sle #(.width(7)) magma_Bits_7_sle_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_sle_inst0_out)); +assign O = magma_Bits_7_sle_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7slt.v b/tests/test_type/gold/TestSInt7slt.v new file mode 100644 index 0000000000..efe5f37c18 --- /dev/null +++ b/tests/test_type/gold/TestSInt7slt.v @@ -0,0 +1,10 @@ +module coreir_slt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = $signed(in0) < $signed(in1); +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output O); +wire magma_Bits_7_slt_inst0_out; +coreir_slt #(.width(7)) magma_Bits_7_slt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_slt_inst0_out)); +assign O = magma_Bits_7_slt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7srem.v b/tests/test_type/gold/TestSInt7srem.v new file mode 100644 index 0000000000..272d545884 --- /dev/null +++ b/tests/test_type/gold/TestSInt7srem.v @@ -0,0 +1,7 @@ +// Module `srem` defined externally +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_srem_inst0_out; +coreir_srem__width7 magma_Bits_7_srem_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_srem_inst0_out)); +assign O = magma_Bits_7_srem_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestSInt7sub.v b/tests/test_type/gold/TestSInt7sub.v new file mode 100644 index 0000000000..ccc2b51901 --- /dev/null +++ b/tests/test_type/gold/TestSInt7sub.v @@ -0,0 +1,10 @@ +module coreir_sub #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 - in1; +endmodule + +module TestBinary (input [6:0] I0, input [6:0] I1, output [6:0] O); +wire [6:0] magma_Bits_7_sub_inst0_out; +coreir_sub #(.width(7)) magma_Bits_7_sub_inst0(.in0(I0), .in1(I1), .out(magma_Bits_7_sub_inst0_out)); +assign O = magma_Bits_7_sub_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1adc.v b/tests/test_type/gold/TestUInt1adc.v new file mode 100644 index 0000000000..7d2f42b70c --- /dev/null +++ b/tests/test_type/gold/TestUInt1adc.v @@ -0,0 +1,19 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestBinary (input CIN, output COUT, input [0:0] I0, input [0:0] I1, output [0:0] O); +wire bit_const_0_None_out; +wire [1:0] magma_Bits_2_add_inst0_out; +wire [1:0] magma_Bits_2_add_inst1_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +coreir_add #(.width(2)) magma_Bits_2_add_inst0(.in0({bit_const_0_None_out,I0[0]}), .in1({bit_const_0_None_out,I1[0]}), .out(magma_Bits_2_add_inst0_out)); +coreir_add #(.width(2)) magma_Bits_2_add_inst1(.in0(magma_Bits_2_add_inst0_out), .in1({bit_const_0_None_out,CIN}), .out(magma_Bits_2_add_inst1_out)); +assign COUT = magma_Bits_2_add_inst1_out[1]; +assign O = magma_Bits_2_add_inst1_out[0]; +endmodule + diff --git a/tests/test_type/gold/TestUInt1add.v b/tests/test_type/gold/TestUInt1add.v new file mode 100644 index 0000000000..7800b89626 --- /dev/null +++ b/tests/test_type/gold/TestUInt1add.v @@ -0,0 +1,10 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_add_inst0_out; +coreir_add #(.width(1)) magma_Bits_1_add_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_add_inst0_out)); +assign O = magma_Bits_1_add_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1eq.v b/tests/test_type/gold/TestUInt1eq.v new file mode 100644 index 0000000000..f6374bab9e --- /dev/null +++ b/tests/test_type/gold/TestUInt1eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_eq_inst0_out; +coreir_eq #(.width(1)) magma_Bits_1_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_eq_inst0_out)); +assign O = magma_Bits_1_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1mul.v b/tests/test_type/gold/TestUInt1mul.v new file mode 100644 index 0000000000..963ef966c6 --- /dev/null +++ b/tests/test_type/gold/TestUInt1mul.v @@ -0,0 +1,10 @@ +module coreir_mul #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 * in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_mul_inst0_out; +coreir_mul #(.width(1)) magma_Bits_1_mul_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_mul_inst0_out)); +assign O = magma_Bits_1_mul_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1sub.v b/tests/test_type/gold/TestUInt1sub.v new file mode 100644 index 0000000000..97220d186c --- /dev/null +++ b/tests/test_type/gold/TestUInt1sub.v @@ -0,0 +1,10 @@ +module coreir_sub #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 - in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_sub_inst0_out; +coreir_sub #(.width(1)) magma_Bits_1_sub_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_sub_inst0_out)); +assign O = magma_Bits_1_sub_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1udiv.v b/tests/test_type/gold/TestUInt1udiv.v new file mode 100644 index 0000000000..32caac780a --- /dev/null +++ b/tests/test_type/gold/TestUInt1udiv.v @@ -0,0 +1,10 @@ +module coreir_udiv #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 / in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_udiv_inst0_out; +coreir_udiv #(.width(1)) magma_Bits_1_udiv_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_udiv_inst0_out)); +assign O = magma_Bits_1_udiv_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1uge.v b/tests/test_type/gold/TestUInt1uge.v new file mode 100644 index 0000000000..bc5c82a21c --- /dev/null +++ b/tests/test_type/gold/TestUInt1uge.v @@ -0,0 +1,10 @@ +module coreir_uge #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 >= in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_uge_inst0_out; +coreir_uge #(.width(1)) magma_Bits_1_uge_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_uge_inst0_out)); +assign O = magma_Bits_1_uge_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1ugt.v b/tests/test_type/gold/TestUInt1ugt.v new file mode 100644 index 0000000000..0f7839aa7a --- /dev/null +++ b/tests/test_type/gold/TestUInt1ugt.v @@ -0,0 +1,10 @@ +module coreir_ugt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 > in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_ugt_inst0_out; +coreir_ugt #(.width(1)) magma_Bits_1_ugt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_ugt_inst0_out)); +assign O = magma_Bits_1_ugt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1ule.v b/tests/test_type/gold/TestUInt1ule.v new file mode 100644 index 0000000000..6a22409263 --- /dev/null +++ b/tests/test_type/gold/TestUInt1ule.v @@ -0,0 +1,10 @@ +module coreir_ule #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 <= in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_ule_inst0_out; +coreir_ule #(.width(1)) magma_Bits_1_ule_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_ule_inst0_out)); +assign O = magma_Bits_1_ule_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1ult.v b/tests/test_type/gold/TestUInt1ult.v new file mode 100644 index 0000000000..e5319f057c --- /dev/null +++ b/tests/test_type/gold/TestUInt1ult.v @@ -0,0 +1,10 @@ +module coreir_ult #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 < in1; +endmodule + +module TestBinary (input [0:0] I0, input [0:0] I1, output O); +wire magma_Bits_1_ult_inst0_out; +coreir_ult #(.width(1)) magma_Bits_1_ult_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_ult_inst0_out)); +assign O = magma_Bits_1_ult_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt1urem.v b/tests/test_type/gold/TestUInt1urem.v new file mode 100644 index 0000000000..5e62db1652 --- /dev/null +++ b/tests/test_type/gold/TestUInt1urem.v @@ -0,0 +1,7 @@ +// Module `urem` defined externally +module TestBinary (input [0:0] I0, input [0:0] I1, output [0:0] O); +wire [0:0] magma_Bits_1_urem_inst0_out; +coreir_urem__width1 magma_Bits_1_urem_inst0(.in0(I0), .in1(I1), .out(magma_Bits_1_urem_inst0_out)); +assign O = magma_Bits_1_urem_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3adc.v b/tests/test_type/gold/TestUInt3adc.v new file mode 100644 index 0000000000..b37bf0d80b --- /dev/null +++ b/tests/test_type/gold/TestUInt3adc.v @@ -0,0 +1,19 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module corebit_const #(parameter value = 1) (output out); + assign out = value; +endmodule + +module TestBinary (input CIN, output COUT, input [2:0] I0, input [2:0] I1, output [2:0] O); +wire bit_const_0_None_out; +wire [3:0] magma_Bits_4_add_inst0_out; +wire [3:0] magma_Bits_4_add_inst1_out; +corebit_const #(.value(0)) bit_const_0_None(.out(bit_const_0_None_out)); +coreir_add #(.width(4)) magma_Bits_4_add_inst0(.in0({bit_const_0_None_out,I0[2],I0[1],I0[0]}), .in1({bit_const_0_None_out,I1[2],I1[1],I1[0]}), .out(magma_Bits_4_add_inst0_out)); +coreir_add #(.width(4)) magma_Bits_4_add_inst1(.in0(magma_Bits_4_add_inst0_out), .in1({bit_const_0_None_out,bit_const_0_None_out,bit_const_0_None_out,CIN}), .out(magma_Bits_4_add_inst1_out)); +assign COUT = magma_Bits_4_add_inst1_out[3]; +assign O = {magma_Bits_4_add_inst1_out[2],magma_Bits_4_add_inst1_out[1],magma_Bits_4_add_inst1_out[0]}; +endmodule + diff --git a/tests/test_type/gold/TestUInt3add.v b/tests/test_type/gold/TestUInt3add.v new file mode 100644 index 0000000000..f4efdf2917 --- /dev/null +++ b/tests/test_type/gold/TestUInt3add.v @@ -0,0 +1,10 @@ +module coreir_add #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 + in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_add_inst0_out; +coreir_add #(.width(3)) magma_Bits_3_add_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_add_inst0_out)); +assign O = magma_Bits_3_add_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3eq.v b/tests/test_type/gold/TestUInt3eq.v new file mode 100644 index 0000000000..2a4bd21c11 --- /dev/null +++ b/tests/test_type/gold/TestUInt3eq.v @@ -0,0 +1,10 @@ +module coreir_eq #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 == in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_eq_inst0_out; +coreir_eq #(.width(3)) magma_Bits_3_eq_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_eq_inst0_out)); +assign O = magma_Bits_3_eq_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3mul.v b/tests/test_type/gold/TestUInt3mul.v new file mode 100644 index 0000000000..54be1a9759 --- /dev/null +++ b/tests/test_type/gold/TestUInt3mul.v @@ -0,0 +1,10 @@ +module coreir_mul #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 * in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_mul_inst0_out; +coreir_mul #(.width(3)) magma_Bits_3_mul_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_mul_inst0_out)); +assign O = magma_Bits_3_mul_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3sub.v b/tests/test_type/gold/TestUInt3sub.v new file mode 100644 index 0000000000..e33cb3502b --- /dev/null +++ b/tests/test_type/gold/TestUInt3sub.v @@ -0,0 +1,10 @@ +module coreir_sub #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 - in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_sub_inst0_out; +coreir_sub #(.width(3)) magma_Bits_3_sub_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_sub_inst0_out)); +assign O = magma_Bits_3_sub_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3udiv.v b/tests/test_type/gold/TestUInt3udiv.v new file mode 100644 index 0000000000..ea4630d94e --- /dev/null +++ b/tests/test_type/gold/TestUInt3udiv.v @@ -0,0 +1,10 @@ +module coreir_udiv #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output [width-1:0] out); + assign out = in0 / in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_udiv_inst0_out; +coreir_udiv #(.width(3)) magma_Bits_3_udiv_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_udiv_inst0_out)); +assign O = magma_Bits_3_udiv_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3uge.v b/tests/test_type/gold/TestUInt3uge.v new file mode 100644 index 0000000000..cf26ad9c0d --- /dev/null +++ b/tests/test_type/gold/TestUInt3uge.v @@ -0,0 +1,10 @@ +module coreir_uge #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 >= in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_uge_inst0_out; +coreir_uge #(.width(3)) magma_Bits_3_uge_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_uge_inst0_out)); +assign O = magma_Bits_3_uge_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3ugt.v b/tests/test_type/gold/TestUInt3ugt.v new file mode 100644 index 0000000000..d0bffb90b7 --- /dev/null +++ b/tests/test_type/gold/TestUInt3ugt.v @@ -0,0 +1,10 @@ +module coreir_ugt #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 > in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_ugt_inst0_out; +coreir_ugt #(.width(3)) magma_Bits_3_ugt_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_ugt_inst0_out)); +assign O = magma_Bits_3_ugt_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3ule.v b/tests/test_type/gold/TestUInt3ule.v new file mode 100644 index 0000000000..e136d6900a --- /dev/null +++ b/tests/test_type/gold/TestUInt3ule.v @@ -0,0 +1,10 @@ +module coreir_ule #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 <= in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_ule_inst0_out; +coreir_ule #(.width(3)) magma_Bits_3_ule_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_ule_inst0_out)); +assign O = magma_Bits_3_ule_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3ult.v b/tests/test_type/gold/TestUInt3ult.v new file mode 100644 index 0000000000..601bd28def --- /dev/null +++ b/tests/test_type/gold/TestUInt3ult.v @@ -0,0 +1,10 @@ +module coreir_ult #(parameter width = 1) (input [width-1:0] in0, input [width-1:0] in1, output out); + assign out = in0 < in1; +endmodule + +module TestBinary (input [2:0] I0, input [2:0] I1, output O); +wire magma_Bits_3_ult_inst0_out; +coreir_ult #(.width(3)) magma_Bits_3_ult_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_ult_inst0_out)); +assign O = magma_Bits_3_ult_inst0_out; +endmodule + diff --git a/tests/test_type/gold/TestUInt3urem.v b/tests/test_type/gold/TestUInt3urem.v new file mode 100644 index 0000000000..8b915aa241 --- /dev/null +++ b/tests/test_type/gold/TestUInt3urem.v @@ -0,0 +1,7 @@ +// Module `urem` defined externally +module TestBinary (input [2:0] I0, input [2:0] I1, output [2:0] O); +wire [2:0] magma_Bits_3_urem_inst0_out; +coreir_urem__width3 magma_Bits_3_urem_inst0(.in0(I0), .in1(I1), .out(magma_Bits_3_urem_inst0_out)); +assign O = magma_Bits_3_urem_inst0_out; +endmodule + diff --git a/tests/test_type/gold/test_AsyncResetN_cast.v b/tests/test_type/gold/test_AsyncResetN[Out]_cast.v similarity index 100% rename from tests/test_type/gold/test_AsyncResetN_cast.v rename to tests/test_type/gold/test_AsyncResetN[Out]_cast.v diff --git a/tests/test_type/gold/test_AsyncReset_cast.v b/tests/test_type/gold/test_AsyncReset[Out]_cast.v similarity index 100% rename from tests/test_type/gold/test_AsyncReset_cast.v rename to tests/test_type/gold/test_AsyncReset[Out]_cast.v diff --git a/tests/test_type/test_array.py b/tests/test_type/test_array.py index 8d892a6e67..889f9674a7 100644 --- a/tests/test_type/test_array.py +++ b/tests/test_type/test_array.py @@ -1,4 +1,5 @@ from magma import * +import pytest Array2 = Array[2,Bit] Array4 = Array[4,Bit] @@ -72,7 +73,7 @@ def test_array2d(): A24 = Array[2,Array[4,Bit]] print(A24) - assert isinstance(A24, ArrayKind) + assert isinstance(A24, ArrayMeta) assert A24 == Array[2,Array4] @@ -83,31 +84,37 @@ def test_array2d(): print(a[0]) assert isinstance(a[0], ArrayType) print(a[0][0]) - assert isinstance(a[0][0], BitType) + assert isinstance(a[0][0], Bit) def test_construct(): - a1 = array([1,1]) + a1 = Array[2, Bit]([1,1]) print(type(a1)) assert isinstance(a1, ArrayType) + a1 = Array[2, Bit](0x3) + assert a1 == m.array([VCC, VCC]) + + with pytest.raises(TypeError): + a1 = Array[2, Array[3, Bit]](0x3) + def test_whole(): Reg2 = DefineCircuit("Reg2", "I0", In(Array2), "I1", In(Array2)) a = Reg2.I0 - a1 = array([a[0], a[1]]) + a1 = Array[2, Bit]([a[0], a[1]]) print((a1.iswhole(a1.ts))) reg2 = Reg2() a = reg2.I0 b = reg2.I1 - a1 = array([a[0], a[1]]) + a1 = Array[2, Bit]([a[0], a[1]]) print((a1.iswhole(a1.ts))) - a2 = array([a[0], b[1]]) + a2 = Array[2, Bit]([a[0], b[1]]) print((a2.iswhole(a2.ts))) - a3 = array([0,1]) + a3 = Array[2, Bit]([0,1]) print((a3.iswhole(a3.ts))) a4 = a3[:1] diff --git a/tests/test_type/test_bit.py b/tests/test_type/test_bit.py index a60736685d..4156adf090 100644 --- a/tests/test_type/test_bit.py +++ b/tests/test_type/test_bit.py @@ -1,39 +1,36 @@ +import pytest import magma as m -from magma import Bit, BitIn, BitOut, BitType, BitKind, In, Out, Flip, VCC, \ - GND, wire +from magma import In, Out, Flip +from magma.testing import check_files_equal +from magma.bit import Bit, VCC, GND, Digital +import operator +BitIn = In(Bit) +BitOut = Out(Bit) def test_bit(): - assert issubclass(Bit, BitType) - assert isinstance(Bit, BitKind) + assert m.Bit == m.Bit + assert m.BitIn == m.BitIn + assert m.BitOut == m.BitOut - assert issubclass(BitIn, BitType) - assert isinstance(BitIn, BitKind) + assert m.Bit != m.BitIn + assert m.Bit != m.BitOut + assert m.BitIn != m.BitOut - assert issubclass(BitOut, BitType) - assert isinstance(BitOut, BitKind) - - assert Bit == Bit - assert BitIn == BitIn - assert BitOut == BitOut - - assert Bit != BitIn - assert Bit != BitOut - assert BitIn != BitOut - - assert str(Bit) == 'Bit' - assert str(BitIn) == 'In(Bit)' - assert str(BitOut) == 'Out(Bit)' + assert str(m.Bit) == 'Bit' + assert str(m.BitIn) == 'In(Bit)' + assert str(m.BitOut) == 'Out(Bit)' def test_bit_flip(): + bout = Out(Bit) bin = In(Bit) assert bout == BitOut assert bin == BitIn bin = In(BitIn) - bout = Out(BitIn) + bout = Out(BitOut) assert bout == BitOut assert bin == BitIn @@ -50,35 +47,35 @@ def test_bit_flip(): def test_bit_val(): b = BitIn(name="a") - assert isinstance(b, BitType) + assert isinstance(b, Bit) assert isinstance(b, BitIn) - assert b.isinput() + assert b.is_input() assert str(b) == "a" assert isinstance(b, BitIn) - assert b.isinput() + assert b.is_input() b = BitOut(name="a") - assert b.isoutput() + assert b.is_output() assert str(b) == "a" - assert isinstance(b, BitType) + assert isinstance(b, Bit) assert isinstance(b, BitOut) - assert b.isoutput() + assert b.is_output() b = Bit(name="a") assert str(b) == "a" - assert isinstance(b, BitType) assert isinstance(b, Bit) - assert not b.isinput() - assert not b.isoutput() - assert not b.isinout() + assert isinstance(b, Bit) + assert not b.is_input() + assert not b.is_output() + assert not b.is_inout() def test_vcc(): assert str(VCC) == "VCC" - assert isinstance(VCC, BitOut) + assert isinstance(VCC, Digital) assert str(GND) == "GND" - assert isinstance(GND, BitOut) + assert isinstance(GND, Digital) assert VCC is VCC assert VCC is not GND @@ -87,13 +84,13 @@ def test_vcc(): def test_wire1(): b0 = BitOut(name='b0') - assert b0.isoutput() + assert b0.is_output() b1 = BitIn(name='b1') - assert b1.isinput() + assert b1.is_input() print('wire(b0,b1)') - wire(b0, b1) + m.wire(b0, b1) assert b0.port.wires is b1.port.wires # wires = b0.port.wires @@ -114,13 +111,13 @@ def test_wire1(): def test_wire2(): b0 = BitOut(name='b0') - assert b0.isoutput() + assert b0.is_output() b1 = BitIn(name='b1') - assert b1.isinput() + assert b1.is_input() print('wire(b1,b0)') - wire(b1, b0) + m.wire(b1, b0) assert b0.port.wires is b1.port.wires # wires = b0.port.wires @@ -145,7 +142,7 @@ def test_wire3(): b1 = Bit(name='b1') print('wire(b0,b1)') - wire(b0, b1) + m.wire(b0, b1) assert b0.port.wires is b1.port.wires # wires = b0.port.wires @@ -169,7 +166,7 @@ def test_wire4(): b1 = BitIn(name='b1') print('wire(b0,b1)') - wire(b0, b1) + m.wire(b0, b1) # assert b0.port.wires is b1.port.wires # wires = b0.port.wires @@ -194,7 +191,7 @@ def test_wire5(): b1 = BitOut(name='b1') print('wire(b0,b1)') - wire(b0, b1) + m.wire(b0, b1) # assert b0.port.wires is b1.port.wires # wires = b0.port.wires @@ -214,8 +211,118 @@ def test_wire5(): assert b1.value() is None -def test_const(): - zero = Bit(0) - one = Bit(1) - assert zero.name.name == "GND" - assert one.name.name == "VCC" +def test_invert(): + class TestInvert(m.Circuit): + IO = ["I", m.In(m.Bit), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + io.O <= ~io.I + + assert repr(TestInvert) == """\ +TestInvert = DefineCircuit("TestInvert", "I", In(Bit), "O", Out(Bit)) +magma_Bit_not_inst0 = magma_Bit_not() +wire(TestInvert.I, magma_Bit_not_inst0.in) +wire(magma_Bit_not_inst0.out, TestInvert.O) +EndCircuit()\ +""" + m.compile("build/TestBitInvert", TestInvert, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBitInvert.v", + f"gold/TestBitInvert.v") + + +@pytest.mark.parametrize("op", ["and_", "or_", "xor"]) +def test_binary(op): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + clean_op = op.replace("_", "") + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \ +"O", Out(Bit)) +magma_Bit_{clean_op}_inst0 = magma_Bit_{clean_op}() +wire(TestBinary.I0, magma_Bit_{clean_op}_inst0.in0) +wire(TestBinary.I1, magma_Bit_{clean_op}_inst0.in1) +wire(magma_Bit_{clean_op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestBit{clean_op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBit{clean_op}.v", + f"gold/TestBit{clean_op}.v") + + +def test_eq(): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + # Nasty precidence issue with <= operator means we need parens here + io.O <= (io.I0 == io.I1) + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \ +"O", Out(Bit)) +magma_Bit_not_inst0 = magma_Bit_not() +magma_Bit_xor_inst0 = magma_Bit_xor() +wire(magma_Bit_xor_inst0.out, magma_Bit_not_inst0.in) +wire(TestBinary.I0, magma_Bit_xor_inst0.in0) +wire(TestBinary.I1, magma_Bit_xor_inst0.in1) +wire(magma_Bit_not_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestBiteq", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBiteq.v", + f"gold/TestBiteq.v") + + +def test_ne(): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + # Nasty precidence issue with <= operator means we need parens here + io.O <= (io.I0 != io.I1) + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \ +"O", Out(Bit)) +magma_Bit_xor_inst0 = magma_Bit_xor() +wire(TestBinary.I0, magma_Bit_xor_inst0.in0) +wire(TestBinary.I1, magma_Bit_xor_inst0.in1) +wire(magma_Bit_xor_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestBitne", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBitne.v", + f"gold/TestBitne.v") + + +def test_ite(): + class TestITE(m.Circuit): + IO = ["I0", m.In(m.Bit), "I1", m.In(m.Bit), "S", m.In(m.Bit), + "O", m.Out(m.Bit)] + @classmethod + def definition(io): + io.O <= io.S.ite(io.I0, io.I1) + + assert repr(TestITE) == """\ +TestITE = DefineCircuit("TestITE", "I0", In(Bit), "I1", In(Bit), "S", In(Bit), \ +"O", Out(Bit)) +magma_Bit_ite_Out_Bit_inst0 = magma_Bit_ite_Out_Bit() +wire(TestITE.I1, magma_Bit_ite_Out_Bit_inst0.in0) +wire(TestITE.I0, magma_Bit_ite_Out_Bit_inst0.in1) +wire(TestITE.S, magma_Bit_ite_Out_Bit_inst0.sel) +wire(magma_Bit_ite_Out_Bit_inst0.out, TestITE.O) +EndCircuit()\ +""" + m.compile(f"build/TestBitite", TestITE, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBitite.v", + f"gold/TestBitite.v") + + +@pytest.mark.parametrize("op", [int, bool]) +def test_errors(op): + with pytest.raises(NotImplementedError): + op(m.Bit(name="b")) diff --git a/tests/test_type/test_bits.py b/tests/test_type/test_bits.py index a8e52efe90..fba0632a84 100644 --- a/tests/test_type/test_bits.py +++ b/tests/test_type/test_bits.py @@ -2,7 +2,10 @@ Test the `m.Bits` type """ +import operator +import pytest import magma as m +from magma.testing import check_files_equal ARRAY2 = m.Array[2, m.Bit] ARRAY4 = m.Array[4, m.Bit] @@ -39,10 +42,10 @@ def test_val(): assert m.Flip(bits_4_out) == bits_4_in a_0 = bits_4_out(name='a0') - print(a_0) + print(a_0, type(a_0)) a_1 = bits_4_in(name='a1') - print(a_1) + print(a_1, type(a_1)) a_1.wire(a_0) @@ -50,7 +53,7 @@ def test_val(): assert b_0 is a_1[0], "getitem failed" a_3 = a_1[0:2] - assert a_3 == a_1[0:2], "getitem of slice failed" + assert all(a is b for a, b in zip(a_3, a_1[0:2])), "getitem of slice failed" def test_flip(): @@ -98,7 +101,15 @@ def test_const(): """ data = m.Bits[16] zero = data(0) - assert zero == m.bits(0, 16) + + def check_equal(x, y): + return all(a is b for a, b in zip(x, y)) + + assert check_equal(zero, m.bits(0, 16)) + + assert check_equal(data(16), m.Bits[16].make_constant(16)) + assert check_equal(m.Bits[4](0xe), m.Bits[16].make_constant(0xe, 4)) + assert check_equal(m.Bits[4](0xe), m.Bits.make_constant(0xe, 4)) def test_setitem_bfloat(): @@ -130,6 +141,168 @@ def definition(io): wire(TestCircuit.I[12], TestCircuit.O[12]) wire(TestCircuit.I[13], TestCircuit.O[13]) wire(TestCircuit.I[14], TestCircuit.O[14]) -wire(0, TestCircuit.O[15]) +wire(GND, TestCircuit.O[15]) EndCircuit()\ """ # noqa + + +@pytest.mark.parametrize("n", [1, 3]) +def test_invert(n): + class TestInvert(m.Circuit): + IO = ["I", m.In(m.Bits[n]), "O", m.Out(m.Bits[n])] + @classmethod + def definition(io): + io.O <= ~io.I + + assert repr(TestInvert) == f"""\ +TestInvert = DefineCircuit("TestInvert", "I", In(Bits[{n}]), "O", Out(Bits[{n}])) +magma_Bits_{n}_not_inst0 = magma_Bits_{n}_not() +wire(TestInvert.I, magma_Bits_{n}_not_inst0.in) +wire(magma_Bits_{n}_not_inst0.out, TestInvert.O) +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}Invert", TestInvert, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}Invert.v", + f"gold/TestBits{n}Invert.v") + + +@pytest.mark.parametrize("n", [1, 3]) +@pytest.mark.parametrize("op", ["and_", "or_", "xor", "lshift", "rshift"]) +def test_binary(op, n): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bits[n]), "I1", m.In(m.Bits[n]), "O", m.Out(m.Bits[n])] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + magma_op = op.replace("_", "") + magma_op = magma_op.replace("lshift", "shl") + magma_op = magma_op.replace("rshift", "lshr") + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bits[{n}]), "I1", In(Bits[{n}]), \ +"O", Out(Bits[{n}])) +magma_Bits_{n}_{magma_op}_inst0 = magma_Bits_{n}_{magma_op}() +wire(TestBinary.I0, magma_Bits_{n}_{magma_op}_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_{magma_op}_inst0.in1) +wire(magma_Bits_{n}_{magma_op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}{magma_op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}{magma_op}.v", + f"gold/TestBits{n}{magma_op}.v") + + +@pytest.mark.parametrize("n", [1, 3]) +def test_ite(n): + class TestITE(m.Circuit): + IO = ["I0", m.In(m.Bits[n]), "I1", m.In(m.Bits[n]), "S", m.In(m.Bits[n]), + "O", m.Out(m.Bits[n])] + @classmethod + def definition(io): + io.O <= io.S.ite(io.I0, io.I1) + + gnd_wires = '\n'.join(f'wire(GND, magma_Bits_{n}_eq_inst0.in1[{i}])' for i in range(n)) + assert repr(TestITE) == f"""\ +TestITE = DefineCircuit("TestITE", "I0", In(Bits[{n}]), "I1", In(Bits[{n}]), "S", In(Bits[{n}]), "O", Out(Bits[{n}])) +magma_Bit_not_inst0 = magma_Bit_not() +magma_Bits_{n}_eq_inst0 = magma_Bits_{n}_eq() +magma_Bits_{n}_ite_Out_Bits_{n}_inst0 = magma_Bits_{n}_ite_Out_Bits_{n}() +wire(magma_Bits_{n}_eq_inst0.out, magma_Bit_not_inst0.in) +wire(TestITE.S, magma_Bits_{n}_eq_inst0.in0) +{gnd_wires} +wire(TestITE.I0, magma_Bits_{n}_ite_Out_Bits_{n}_inst0.in0) +wire(TestITE.I1, magma_Bits_{n}_ite_Out_Bits_{n}_inst0.in1) +wire(magma_Bit_not_inst0.out, magma_Bits_{n}_ite_Out_Bits_{n}_inst0.sel) +wire(magma_Bits_{n}_ite_Out_Bits_{n}_inst0.out, TestITE.O) +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}ITE", TestITE, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}ITE.v", + f"gold/TestBits{n}ITE.v") + + +@pytest.mark.parametrize("n", [1, 3]) +def test_eq(n): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bits[n]), "I1", m.In(m.Bits[n]), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + # Nasty precidence issue with <= operator means we need parens here + io.O <= (io.I0 == io.I1) + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bits[{n}]), "I1", In(Bits[{n}]), "O", Out(Bit)) +magma_Bits_{n}_eq_inst0 = magma_Bits_{n}_eq() +wire(TestBinary.I0, magma_Bits_{n}_eq_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_eq_inst0.in1) +wire(magma_Bits_{n}_eq_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}eq", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}eq.v", + f"gold/TestBits{n}eq.v") + + +@pytest.mark.parametrize("n", [1, 3]) +def test_zext(n): + class TestExt(m.Circuit): + IO = ["I", m.In(m.Bits[n]), "O", m.Out(m.Bits[n + 3])] + @classmethod + def definition(io): + # Nasty precidence issue with <= operator means we need parens here + io.O <= io.I.zext(3) + + i_wires = '\n'.join(f'wire(TestExt.I[{i}], TestExt.O[{i}])' for i in range(n)) + gnd_wires = '\n'.join(f'wire(GND, TestExt.O[{i + n}])' for i in range(3)) + assert repr(TestExt) == f"""\ +TestExt = DefineCircuit("TestExt", "I", In(Bits[{n}]), "O", Out(Bits[{n + 3}])) +{i_wires} +{gnd_wires} +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}ext", TestExt, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}ext.v", + f"gold/TestBits{n}ext.v") + + +@pytest.mark.parametrize("n", [1, 3]) +def test_bvcomp(n): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.Bits[n]), "I1", m.In(m.Bits[n]), "O", m.Out(m.Bits[1])] + @classmethod + def definition(io): + # Nasty precidence issue with <= operator means we need parens here + io.O <= io.I0.bvcomp(io.I1) + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(Bits[{n}]), "I1", In(Bits[{n}]), "O", Out(Bits[1])) +magma_Bits_{n}_eq_inst0 = magma_Bits_{n}_eq() +wire(TestBinary.I0, magma_Bits_{n}_eq_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_eq_inst0.in1) +wire(magma_Bits_{n}_eq_inst0.out, TestBinary.O[0]) +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}bvcomp", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}bvcomp.v", + f"gold/TestBits{n}bvcomp.v") + + +@pytest.mark.parametrize("n", [1, 3]) +@pytest.mark.parametrize("x", [4, 7]) +def test_repeat(n, x): + class TestRepeat(m.Circuit): + IO = ["I", m.In(m.Bits[n]), "O", m.Out(m.Bits[n * x])] + @classmethod + def definition(io): + io.O <= io.I.repeat(x) + + wires = "\n".join(f"wire(TestRepeat.I[{i}], TestRepeat.O[{i + j * n}])" + for j in range(x) for i in range(n)) + assert repr(TestRepeat) == f"""\ +TestRepeat = DefineCircuit("TestRepeat", "I", In(Bits[{n}]), "O", Out(Bits[{n * x}])) +{wires} +EndCircuit()\ +""" + m.compile(f"build/TestBits{n}x{x}Repeat", TestRepeat, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestBits{n}x{x}Repeat.v", + f"gold/TestBits{n}x{x}Repeat.v") diff --git a/tests/test_type/test_clock.py b/tests/test_type/test_clock.py index 0920ac4398..1e37a71e68 100644 --- a/tests/test_type/test_clock.py +++ b/tests/test_type/test_clock.py @@ -1,27 +1,32 @@ -import pytest import tempfile +import pytest import magma as m from magma.testing import check_files_equal from magma import In, Out, Flip, \ - Clock, ClockType, ClockKind, \ - Reset, ResetType, ResetKind, reset, \ - Enable, EnableType, EnableKind, enable, \ - AsyncReset, AsyncResetType, AsyncResetKind, \ + Clock, \ + Reset, reset, \ + Enable, enable, \ + AsyncReset, \ DeclareCircuit, DefineCircuit, EndCircuit, \ Bit, bit, wire, compile +from magma.digital import DigitalMeta + + def test_clock(): - assert isinstance(Clock, ClockKind) + assert isinstance(Clock, DigitalMeta) assert Clock == Clock + assert not (Clock != Clock) assert str(Clock) == 'Clock' + def test_clock_flip(): ClockOut = Out(Clock) - assert isinstance(ClockOut, ClockKind) + assert issubclass(ClockOut, Clock) assert str(ClockOut) == 'Out(Clock)' ClockIn = In(Clock) - assert isinstance(ClockIn, ClockKind) + assert issubclass(ClockIn, Clock) assert str(ClockIn) == 'In(Clock)' clockin = In(ClockIn) @@ -39,26 +44,29 @@ def test_clock_flip(): assert clockout == ClockOut assert clockin == ClockIn + def test_clock_val(): b = Clock(name="a") assert str(b) == "a" - assert isinstance(b, ClockType) assert isinstance(b, Clock) - assert not b.isinput() - assert not b.isoutput() + assert not b.is_input() + assert not b.is_output() + def test_reset(): - assert isinstance(Reset, ResetKind) + assert isinstance(Reset, DigitalMeta) assert Reset == Reset + assert not (Reset != Reset) assert str(Reset) == 'Reset' + def test_reset_flip(): ResetOut = Out(Reset) - assert isinstance(ResetOut, ResetKind) + assert issubclass(ResetOut, Reset) assert str(ResetOut) == 'Out(Reset)' ResetIn = In(Reset) - assert isinstance(ResetIn, ResetKind) + assert issubclass(ResetIn, Reset) assert str(ResetIn) == 'In(Reset)' resetin = In(ResetIn) @@ -76,27 +84,30 @@ def test_reset_flip(): assert resetout == ResetOut assert resetin == ResetIn + def test_reset_val(): b = Reset(name="a") assert str(b) == "a" - assert isinstance(b, ResetType) assert isinstance(b, Reset) - assert not b.isinput() - assert not b.isoutput() - assert not b.isinout() + assert not b.is_input() + assert not b.is_output() + assert not b.is_inout() + def test_enable(): - assert isinstance(Enable, EnableKind) + assert isinstance(Enable, DigitalMeta) assert Enable == Enable + assert not (Enable != Enable) assert str(Enable) == 'Enable' + def test_enable_flip(): EnableOut = Out(Enable) - assert isinstance(EnableOut, EnableKind) + assert issubclass(EnableOut, Enable) assert str(EnableOut) == 'Out(Enable)' EnableIn = In(Enable) - assert isinstance(EnableIn, EnableKind) + assert issubclass(EnableIn, Enable) assert str(EnableIn) == 'In(Enable)' enablein = In(EnableIn) @@ -114,13 +125,14 @@ def test_enable_flip(): assert enableout == EnableOut assert enablein == EnableIn + def test_enable_val(): b = Enable(name="a") assert str(b) == "a" - assert isinstance(b, EnableType) assert isinstance(b, Enable) - assert not b.isinput() - assert not b.isoutput() + assert not b.is_input() + assert not b.is_output() + @pytest.mark.parametrize("T", [Clock, AsyncReset]) def test_coreir_wrap(T): @@ -186,12 +198,12 @@ class Inst(m.Circuit): class AsyncResetTest(m.Circuit): IO = ['I', m.BitIn, 'I_Arr', m.In(m.Array[3, Bit]), - 'O', T, "O_Tuple", m.Tuple(R=T, B=Out(Bit)), + 'O', T, "O_Tuple", m.Product.from_fields("anon", {"R":T, "B":Out(Bit)}), "O_Arr", m.Array[2, T], 'T_in', In(T), 'Bit_out', Out(Bit), 'T_Arr_in', In(m.Array[2, T]), 'Bit_Arr_out', Out(m.Array[3, Bit]), - 'T_Tuple_in', In(m.Tuple(T=T)), + 'T_Tuple_in', In(m.Product.from_fields("anon", {"T":T})), 'Bit_Arr_out', Out(m.Array[4, Bit])] @classmethod diff --git a/tests/test_type/test_conversions.py b/tests/test_type/test_conversions.py index 93fe8ef5a2..3bec9e4525 100644 --- a/tests/test_type/test_conversions.py +++ b/tests/test_type/test_conversions.py @@ -3,111 +3,113 @@ from collections import OrderedDict from magma import \ GND, VCC, \ - bit, BitType, \ - clock, ClockType, \ - reset, ResetType, \ - enable, EnableType, \ - array, ArrayType, \ - bits, BitsType, \ - uint, UIntType, \ - sint, SIntType, \ - tuple_, TupleType, \ - zext, sext + bit, Bit, \ + clock, Clock, \ + reset, Reset, \ + enable, Enable, \ + array, Array, \ + bits, Bits, \ + uint, UInt, \ + sint, SInt, \ + zext, sext, \ + tuple_, Tuple, \ + namedtuple, Product from magma.bitutils import seq2int import magma as m def test_bit(): - assert isinstance(bit(0), BitType) - assert isinstance(bit(1), BitType) - assert isinstance(bit(VCC), BitType) - assert isinstance(bit(GND), BitType) - assert isinstance(bit(bit(0)), BitType) - assert isinstance(bit(clock(0)), BitType) - assert isinstance(bit(reset(0)), BitType) - assert isinstance(bit(enable(0)), BitType) - assert isinstance(bit(bits(0,1)), BitType) - assert isinstance(bit(uint(0,1)), BitType) - assert isinstance(bit(sint(0,1)), BitType) + assert isinstance(bit(0), Bit) + assert isinstance(bit(1), Bit) + assert isinstance(bit(VCC), Bit) + assert isinstance(bit(GND), Bit) + assert isinstance(bit(bit(0)), Bit) + assert isinstance(bit(clock(0)), Bit) + assert isinstance(bit(reset(0)), Bit) + assert isinstance(bit(enable(0)), Bit) + assert isinstance(bit(bits(0,1)), Bit) + assert isinstance(bit(uint(0,1)), Bit) + assert isinstance(bit(sint(0,1)), Bit) def test_enable(): - assert isinstance(enable(0), EnableType) - assert isinstance(enable(1), EnableType) - assert isinstance(enable(VCC), EnableType) - assert isinstance(enable(GND), EnableType) - assert isinstance(enable(bit(0)), EnableType) - assert isinstance(enable(clock(0)), EnableType) - assert isinstance(enable(reset(0)), EnableType) - assert isinstance(enable(enable(0)), EnableType) - assert isinstance(enable(bits(0,1)), EnableType) - assert isinstance(enable(uint(0,1)), EnableType) - assert isinstance(enable(sint(0,1)), EnableType) + assert isinstance(enable(0), Enable) + assert isinstance(enable(1), Enable) + assert isinstance(enable(VCC), Enable) + assert isinstance(enable(GND), Enable) + assert isinstance(enable(bit(0)), Enable) + assert isinstance(enable(clock(0)), Enable) + assert isinstance(enable(reset(0)), Enable) + assert isinstance(enable(enable(0)), Enable) + assert isinstance(enable(bits(0,1)), Enable) + assert isinstance(enable(uint(0,1)), Enable) + assert isinstance(enable(sint(0,1)), Enable) def test_reset(): - assert isinstance(reset(0), ResetType) - assert isinstance(reset(1), ResetType) - assert isinstance(reset(VCC), ResetType) - assert isinstance(reset(GND), ResetType) - assert isinstance(reset(bit(0)), ResetType) - assert isinstance(reset(clock(0)), ResetType) - assert isinstance(reset(enable(0)), ResetType) - assert isinstance(reset(reset(0)), ResetType) - assert isinstance(reset(bits(0,1)), ResetType) - assert isinstance(reset(uint(0,1)), ResetType) - assert isinstance(reset(sint(0,1)), ResetType) + assert isinstance(reset(0), Reset) + assert isinstance(reset(1), Reset) + assert isinstance(reset(VCC), Reset) + assert isinstance(reset(GND), Reset) + assert isinstance(reset(bit(0)), Reset) + assert isinstance(reset(clock(0)), Reset) + assert isinstance(reset(enable(0)), Reset) + assert isinstance(reset(reset(0)), Reset) + assert isinstance(reset(bits(0,1)), Reset) + assert isinstance(reset(uint(0,1)), Reset) + assert isinstance(reset(sint(0,1)), Reset) def test_clock(): - assert isinstance(clock(0), ClockType) - assert isinstance(clock(1), ClockType) - assert isinstance(clock(VCC), ClockType) - assert isinstance(clock(GND), ClockType) - assert isinstance(clock(bit(0)), ClockType) - assert isinstance(clock(clock(0)), ClockType) - assert isinstance(clock(reset(0)), ClockType) - assert isinstance(clock(enable(0)), ClockType) - assert isinstance(clock(bits(0,1)), ClockType) - assert isinstance(clock(uint(0,1)), ClockType) - assert isinstance(clock(sint(0,1)), ClockType) + assert isinstance(clock(0), Clock) + assert isinstance(clock(1), Clock) + assert isinstance(clock(VCC), Clock) + assert isinstance(clock(GND), Clock) + assert isinstance(clock(bit(0)), Clock) + assert isinstance(clock(clock(0)), Clock) + assert isinstance(clock(reset(0)), Clock) + assert isinstance(clock(enable(0)), Clock) + assert isinstance(clock(bits(0,1)), Clock) + assert isinstance(clock(uint(0,1)), Clock) + assert isinstance(clock(sint(0,1)), Clock) def test_array(): - assert isinstance(array(1,4), ArrayType) - assert isinstance(array([1,0,0,0]), ArrayType) - assert isinstance(array(VCC), ArrayType) - assert isinstance(array(array(1,4)), ArrayType) - assert isinstance(array(uint(1,4)), ArrayType) - assert isinstance(array(sint(1,4)), ArrayType) + assert isinstance(array(1,4), Array) + assert isinstance(array([1,0,0,0]), Array) + assert isinstance(array(VCC), Array) + assert isinstance(array(array(1,4)), Array) + assert isinstance(array(uint(1,4)), Array) + assert isinstance(array(sint(1,4)), Array) def test_bits(): - assert isinstance(bits(1,4), BitsType) - assert isinstance(bits([1,0,0,0]), BitsType) - assert isinstance(bits(VCC), BitsType) - assert isinstance(bits(array(1,4)), BitsType) - assert isinstance(bits(uint(1,4)), BitsType) - assert isinstance(bits(sint(1,4)), BitsType) + assert isinstance(bits(1,4), Bits) + assert isinstance(bits([1,0,0,0]), Bits) + assert isinstance(bits(VCC), Bits) + assert isinstance(bits(array(1,4)), Bits) + assert isinstance(bits(uint(1,4)), Bits) + assert isinstance(bits(sint(1,4)), Bits) def test_uint(): - assert isinstance(uint(1,4), UIntType) - assert isinstance(uint([1,0,0,0]), UIntType) - assert isinstance(uint(VCC), UIntType) - assert isinstance(uint(array(1,4)), UIntType) - assert isinstance(uint(bits(1,4)), UIntType) - #assert isinstance(uint(sint(1,4)), UIntType) + assert isinstance(uint(1,4), UInt) + assert isinstance(uint([1,0,0,0]), UInt) + assert isinstance(uint(VCC), UInt) + assert isinstance(uint(array(1,4)), UInt) + assert isinstance(uint(bits(1,4)), UInt) + #assert isinstance(uint(sint(1,4)), UInt) def test_sint(): - assert isinstance(sint(1,4), SIntType) - assert isinstance(sint([1,0,0,0]), SIntType) - assert isinstance(sint(VCC), SIntType) - assert isinstance(sint(array(1,4)), SIntType) - assert isinstance(sint(bits(1,4)), SIntType) - #assert isinstance(sint(sint(1,4)), SIntType) - -def test_tuple(): - assert isinstance(tuple_(OrderedDict(x=0, y=1)), TupleType) - assert isinstance(tuple_([0,1]), TupleType) - assert isinstance(tuple_(VCC), TupleType) - assert isinstance(tuple_(array(1,4)), TupleType) - assert isinstance(tuple_(bits(1,4)), TupleType) - assert isinstance(tuple_(sint(1,4)), TupleType) - assert isinstance(tuple_(uint(1,4)), TupleType) + assert isinstance(sint(1,4), SInt) + assert isinstance(sint([1,0,0,0]), SInt) + assert isinstance(sint(VCC), SInt) + assert isinstance(sint(array(1,4)), SInt) + assert isinstance(sint(bits(1,4)), SInt) + #assert isinstance(sint(sint(1,4)), SInt) + + +def test_tuple_product(): + assert isinstance(namedtuple(x=False, y=True), Product) + assert isinstance(tuple_([0,1]), Tuple) + assert isinstance(tuple_(VCC), Tuple) + assert isinstance(tuple_(array(1,4)), Tuple) + assert isinstance(tuple_(bits(1,4)), Tuple) + assert isinstance(tuple_(sint(1,4)), Tuple) + assert isinstance(tuple_(uint(1,4)), Tuple) @pytest.mark.parametrize("type_,value", @@ -117,7 +119,7 @@ def test_zext(type_, value): value = abs(value) in_ = type_(value, 16) # TODO(rsetaluri): Ideally, zext(bits) should return an object of type - # BitsType, instead it returns an object of type ArrayType. For now, we wrap + # Bits, instead it returns an object of type Array. For now, we wrap # the result of zext() in bits(). out = type_(zext(in_, 16)) assert len(out.bits()) == 32 @@ -134,7 +136,7 @@ def test_zext(type_, value): def test_sext(value): in_ = sint(value, 16) # TODO(rsetaluri): Ideally, zext(sint) should return an object of type - # SintType, instead it returns an object of type ArrayType. For now, we wrap + # SintType, instead it returns an object of type Array. For now, we wrap # the result of zext() in sint(). out = sint(sext(in_, 16)) assert len(out.bits()) == 32 diff --git a/tests/test_type/test_enum.py b/tests/test_type/test_enum.py index b65e21def2..4c019309f7 100644 --- a/tests/test_type/test_enum.py +++ b/tests/test_type/test_enum.py @@ -4,11 +4,12 @@ def test_enum(): class State(m.Enum): - zero=0 - one=1 - two=2 + zero = 0 + one = 1 + two = 2 - circuit = m.DefineCircuit('enum_test', "I", m.In(State), "O", m.Out(m.Array[2, State])) + circuit = m.DefineCircuit('enum_test', "I", m.In(State), + "O", m.Out(m.Array[2, State])) m.wire(circuit.I, circuit.O[0]) m.wire(State.zero, circuit.O[1]) m.EndDefine() @@ -18,11 +19,12 @@ class State(m.Enum): def test_enum_max_value(): class State(m.Enum): - zero=0 - one=1 - four=4 + zero = 0 + one = 1 + four = 4 - circuit = m.DefineCircuit('enum_test_max_value', "I", m.In(State), "O", m.Out(m.Array[2, State])) + circuit = m.DefineCircuit('enum_test_max_value', "I", m.In(State), + "O", m.Out(m.Array[2, State])) m.wire(circuit.I, circuit.O[0]) m.wire(State.four, circuit.O[1]) m.EndDefine() diff --git a/tests/test_type/test_new_types.py b/tests/test_type/test_new_types.py index e1d0a7bc82..c4dd583c83 100644 --- a/tests/test_type/test_new_types.py +++ b/tests/test_type/test_new_types.py @@ -8,13 +8,16 @@ def test_new_types(output): def Coordinate(num_bits): return m.Bits[num_bits] - # Parametrized types should be implemented using a type constructure # TODO: Add suport for isinstance(t, Polygon), need to rework to use class # structure or at least autogenerate a PolygonType (or document how to # subclass and create a new Type/Kind) def Point2D(num_bits): - return m.Tuple(x=Coordinate(num_bits), y=Coordinate(num_bits)) + class Point2D(m.Product): + x = Coordinate(num_bits) + y = Coordinate(num_bits) + + return Point2D def Polygon(num_vertices, num_bits): return m.Array[num_vertices, Point2D(num_bits)] diff --git a/tests/test_type/test_pretty_print.py b/tests/test_type/test_pretty_print.py index de35dbde27..867acfafb7 100644 --- a/tests/test_type/test_pretty_print.py +++ b/tests/test_type/test_pretty_print.py @@ -1,8 +1,13 @@ import magma as m +class t(m.Product): + a = m.Bit + b = m.Bit + c = m.Bit + + def test_pretty_print_tuple(): - t = m.Tuple(a=m.Bit, b=m.Bit, c=m.Bit) assert m.util.pretty_str(t) == """\ Tuple( a = Bit, @@ -13,8 +18,10 @@ def test_pretty_print_tuple(): def test_pretty_print_tuple_recursive(): - t = m.Tuple(a=m.Bit, b=m.Bit, c=m.Bit) - u = m.Tuple(x=t, y=t) + + class u(m.Product): + x = t + y = t assert m.util.pretty_str(u) == """\ Tuple( x = Tuple( @@ -32,7 +39,6 @@ def test_pretty_print_tuple_recursive(): def test_pretty_print_array_of_tuple(): - t = m.Tuple(a=m.Bit, b=m.Bit, c=m.Bit) u = m.Array[3, t] assert m.util.pretty_str(u) == """\ Array[3, Tuple( @@ -44,8 +50,14 @@ def test_pretty_print_array_of_tuple(): def test_pretty_print_array_of_nested_tuple(): - t = m.Tuple(a=m.Bits[5], b=m.UInt[3], c=m.SInt[4]) - u = m.Tuple(x=t, y=t) + class t(m.Product): + a = m.Bits[5] + b = m.UInt[3] + c = m.SInt[4] + + class u(m.Product): + x = t + y = t v = m.Array[3, u] assert m.util.pretty_str(v) == """\ Array[3, Tuple( diff --git a/tests/test_type/test_sint.py b/tests/test_type/test_sint.py index 6a7d8a0630..f7b526201f 100644 --- a/tests/test_type/test_sint.py +++ b/tests/test_type/test_sint.py @@ -1,3 +1,6 @@ +import operator +import pytest +from magma.testing import check_files_equal from magma import * Array2 = Array[2,Bit] @@ -69,4 +72,122 @@ def test_flip(): def test_construct(): a1 = sint([1,1]) print(type(a1)) - assert isinstance(a1, SIntType) + assert isinstance(a1, SInt) + + +@pytest.mark.parametrize("n", [7, 3]) +@pytest.mark.parametrize("op", ["eq", "lt", "le", "gt", "ge"]) +def test_compare(n, op): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.SInt[n]), "I1", m.In(m.SInt[n]), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + op = { + "eq": "eq", + "le": "sle", + "lt": "slt", + "ge": "sge", + "gt": "sgt" + }[op] + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(SInt[{n}]), "I1", In(SInt[{n}]), "O", Out(Bit)) +magma_Bits_{n}_{op}_inst0 = magma_Bits_{n}_{op}() +wire(TestBinary.I0, magma_Bits_{n}_{op}_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_{op}_inst0.in1) +wire(magma_Bits_{n}_{op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestSInt{n}{op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestSInt{n}{op}.v", + f"gold/TestSInt{n}{op}.v") + + +@pytest.mark.parametrize("n", [7, 3]) +@pytest.mark.parametrize("op", ["add", "sub", "mul", "floordiv", "mod", "rshift"]) +def test_binary(n, op): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.SInt[n]), "I1", m.In(m.SInt[n]), "O", m.Out(m.SInt[n])] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + if op == "floordiv": + op = "sdiv" + elif op == "mod": + op = "srem" + elif op == "rshift": + op = "ashr" + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(SInt[{n}]), "I1", In(SInt[{n}]), "O", Out(SInt[{n}])) +magma_Bits_{n}_{op}_inst0 = magma_Bits_{n}_{op}() +wire(TestBinary.I0, magma_Bits_{n}_{op}_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_{op}_inst0.in1) +wire(magma_Bits_{n}_{op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestSInt{n}{op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestSInt{n}{op}.v", + f"gold/TestSInt{n}{op}.v") + + +@pytest.mark.parametrize("n", [7, 3]) +def test_adc(n): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.SInt[n]), "I1", m.In(m.SInt[n]), "CIN", m.In(m.Bit), "O", m.Out(m.SInt[n]), "COUT", m.Out(m.Bit)] + @classmethod + def definition(io): + result, carry = io.I0.adc(io.I1, io.CIN) + io.O <= result + io.COUT <= carry + + in0_wires = "\n".join(f"wire(TestBinary.I0[{i}], magma_Bits_{n + 1}_add_inst0.in0[{i}])" + for i in range(n)) + in0_wires += f"\nwire(TestBinary.I0[{n - 1}], magma_Bits_{n + 1}_add_inst0.in0[{n}])" + + in1_wires = "\n".join(f"wire(TestBinary.I1[{i}], magma_Bits_{n + 1}_add_inst0.in1[{i}])" + for i in range(n)) + in1_wires += f"\nwire(TestBinary.I1[{n - 1}], magma_Bits_{n + 1}_add_inst0.in1[{n}])" + + carry_wires = "\n".join(f"wire(GND, magma_Bits_{n + 1}_add_inst1.in1[{i + 1}])" for i in range(n)) + + out_wires = "\n".join(f"wire(magma_Bits_{n + 1}_add_inst1.out[{i}], TestBinary.O[{i}])" + for i in range(n)) + out_wires += f"\nwire(magma_Bits_{n + 1}_add_inst1.out[{n}], TestBinary.COUT)" + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(SInt[{n}]), "I1", In(SInt[{n}]), "CIN", In(Bit), "O", Out(SInt[{n}]), "COUT", Out(Bit)) +magma_Bits_{n + 1}_add_inst0 = magma_Bits_{n + 1}_add() +magma_Bits_{n + 1}_add_inst1 = magma_Bits_{n + 1}_add() +{in0_wires} +{in1_wires} +wire(magma_Bits_{n + 1}_add_inst0.out, magma_Bits_{n + 1}_add_inst1.in0) +wire(TestBinary.CIN, magma_Bits_{n + 1}_add_inst1.in1[0]) +{carry_wires} +{out_wires} +EndCircuit()\ +""" + m.compile(f"build/TestSInt{n}adc", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestSInt{n}adc.v", + f"gold/TestSInt{n}adc.v") + + +@pytest.mark.parametrize("n", [7, 3]) +def test_negate(n): + class TestNegate(m.Circuit): + IO = ["I", m.In(m.SInt[n]), "O", m.Out(m.SInt[n])] + @classmethod + def definition(io): + io.O <= -io.I + + assert repr(TestNegate) == f"""\ +TestNegate = DefineCircuit("TestNegate", "I", In(SInt[{n}]), "O", Out(SInt[{n}])) +magma_Bits_{n}_neg_inst0 = magma_Bits_{n}_neg() +wire(TestNegate.I, magma_Bits_{n}_neg_inst0.in) +wire(magma_Bits_{n}_neg_inst0.out, TestNegate.O) +EndCircuit()\ +""" + m.compile(f"build/TestSInt{n}neg", TestNegate, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestSInt{n}neg.v", + f"gold/TestSInt{n}neg.v") diff --git a/tests/test_type/test_tuple.py b/tests/test_type/test_tuple.py index 41958a6f41..6de5406459 100644 --- a/tests/test_type/test_tuple.py +++ b/tests/test_type/test_tuple.py @@ -4,38 +4,43 @@ def test_pair(): # types - A2 = Tuple(Bit, Bit) + A2 = Tuple[Bit, Bit] print(A2) - assert isinstance(A2, TupleKind) + assert isinstance(A2, TupleMeta) print(str(A2)) assert A2 == A2 - B2 = Tuple(In(Bit), In(Bit)) - assert isinstance(B2, TupleKind) + B2 = Tuple[In(Bit), In(Bit)] + assert isinstance(B2, TupleMeta) assert B2 == B2 - C2 = Tuple(Out(Bit), Out(Bit)) - assert isinstance(C2, TupleKind) + C2 = Tuple[Out(Bit), Out(Bit)] + assert isinstance(C2, TupleMeta) #assert str(C2) == 'Tuple(x=Out(Bit),y=Out(Bit))' assert C2 == C2 def test_dict(): # types - - A2 = Tuple(x=Bit, y=Bit) + class A2(Product): + x = Bit + y = Bit print(A2) - assert isinstance(A2, TupleKind) + assert isinstance(A2, ProductMeta) print(str(A2)) #assert str(A2) == 'Tuple(x=Bit,y=Bit)' assert A2 == A2 - B2 = Tuple(x=In(Bit), y=In(Bit)) - assert isinstance(B2, TupleKind) + class B2(Product): + x = In(Bit) + y = In(Bit) + assert isinstance(B2, ProductMeta) #assert str(B2) == 'Tuple(x=In(Bit),y=In(Bit))' assert B2 == B2 - C2 = Tuple(x=Out(Bit), y=Out(Bit)) - assert isinstance(C2, TupleKind) + class C2(Product): + x = Out(Bit) + y = Out(Bit) + assert isinstance(C2, ProductMeta) #assert str(C2) == 'Tuple(x=Out(Bit),y=Out(Bit))' assert C2 == C2 @@ -44,18 +49,20 @@ def test_dict(): assert B2 != C2 def test_flip(): - Tuple2 = Tuple(x=In(Bit), y=Out(Bit)) - print(Tuple2) - print(Flip(Tuple2)) + class Product2(Product): + x = In(Bit) + y = Out(Bit) + print(Product2) + print(Flip(Product2)) - Tin = In(Tuple2) - Tout = Out(Tuple2) + Tin = In(Product2) + Tout = Out(Product2) print(Tin) print(Tout) - assert Tin != Tuple2 - assert Tout != Tuple2 + assert Tin != Product2 + assert Tout != Product2 assert Tin != Tout T = In(Tout) @@ -73,12 +80,14 @@ def test_flip(): #print(T) def test_wire(): - Tuple2 = Tuple(x=Bit, y=Bit) + class Product2(Product): + x = Bit + y = Bit - t0 = Tuple2(name='t0') + t0 = Product2(name='t0') #assert t0.direction is None - t1 = Tuple2(name='t1') + t1 = Product2(name='t1') #assert t1.direction is None wire(t0, t1) @@ -107,36 +116,37 @@ def test_wire(): print('outputs:', [str(p) for p in wires.outputs]) def test_val(): - A2 = Tuple(x=Bit, y=Bit) + class A2(Product): + x = Bit + y = Bit # constructor a = A2(name='a') print('created A2') - assert isinstance(a, TupleType) + assert isinstance(a, Product) assert str(a) == 'a' # selectors print('a["x"]') b = a['x'] - assert isinstance(b, BitType) + assert isinstance(b, Bit) assert str(b) == 'a.x' print('a.x') b = a.x - assert isinstance(b, BitType) + assert isinstance(b, Bit) assert str(b) == 'a.x' def test_nested(): # Test for https://github.com/phanrahan/magma/issues/445 def hierIO(): - dictIO = { - "baseIO": baseIO(), - "ctr": m.In(m.Bit) - } - return m.Tuple(**dictIO) + class dictIO(Product): + baseIO = make_baseIO() + ctr = m.In(m.Bit) + return dictIO def DefineCtrModule(): class ctrModule(m.Circuit): @@ -144,17 +154,16 @@ class ctrModule(m.Circuit): IO = ["ctr",m.In(m.Bit)] return ctrModule - def baseIO(): - dictIO = { - "in0":m.In(m.Bit), - "out0":m.Out(m.Bit) - } - return m.Tuple(**dictIO) + def make_baseIO(): + class dictIO(Product): + in0 = m.In(m.Bit), + out0 = m.Out(m.Bit) + return dictIO def DefineBaseModule(): class baseModule(m.Circuit): name = "base_module" - IO = ["baseIO",baseIO()] + IO = ["baseIO",make_baseIO()] return baseModule def DefineHier(): @@ -175,7 +184,7 @@ def definition(io): def test_tuple_nested_tuple_value(): def IFC0(params): - return m.Tuple(**{ + return m.Product.from_fields("IFC0", { "port0": m.In(m.Bits[params['param0']]), "port1": m.In(m.Bits[params['param0']]), "port2": m.In(m.Array[params['param0'], m.Bits[2]]), @@ -190,7 +199,7 @@ def IFC0(params): def IFC1(params): dictOut = {"port4": m.Out(m.Bit)} - return m.Tuple(**dictOut) + return m.Product.from_fields("IFC1", dictOut) def DefineMyCircuit(params): class MyCircuit(m.Circuit): @@ -210,5 +219,5 @@ def definition(io): def test_flat_length(): - a = m.Tuple(x=m.Bits[5], y=m.Bits[3], z=m.Bit) + a = m.Product.from_fields("anon", dict(x=m.Bits[5], y=m.Bits[3], z=m.Bit)) assert a.flat_length() == 9 diff --git a/tests/test_type/test_type_errors.py b/tests/test_type/test_type_errors.py index a10a09723e..6be721f01a 100644 --- a/tests/test_type/test_type_errors.py +++ b/tests/test_type/test_type_errors.py @@ -41,22 +41,27 @@ def test_bit_to_array(caplog): buf = Buf() wire(buf.I, main.O) assert "\n".join(x.msg for x in caplog.records) == """\ -\033[1mtests/test_type/test_type_errors.py:36: Cannot wire main.buf.I (type=In(Bit)) to main.O (type=Array[7, In(Bit)]) because main.buf.I is not an Array +\033[1mtests/test_type/test_type_errors.py:42: Cannot wire main.buf.I (type=In(Bit)) to main.O (type=Array[7, In(Bit)]) because main.buf.I is not an Array wire(buf.I, main.O) """ m.config.set_debug_mode(False) +class I(m.Product): + a = Bit + b = Bit + + def test_tuple_to_array(caplog): m.config.set_debug_mode(True) - Buf = DeclareCircuit('Buf', "I", In(Tuple(a=Bit,b=Bit)), "O", Out(Array[8, Bit])) + Buf = DeclareCircuit('Buf', "I", In(I), "O", Out(Array[8, Bit])) main = DefineCircuit("main", "I", In(Bit), "O", Out(Bit)) buf = Buf() wire(main.O, buf.I) assert "\n".join(x.msg for x in caplog.records) == """\ -\033[1mtests/test_type/test_type_errors.py:57: Cannot wire main.O (type=In(Bit)) to main.buf.I (type=Tuple(a=In(Bit),b=In(Bit))) because main.O is not a Tuple +\033[1mtests/test_type/test_type_errors.py:62: Cannot wire main.O (type=In(Bit)) to main.buf.I (type=Tuple(a=In(Bit),b=In(Bit))) because main.O is not a Tuple wire(main.O, buf.I) """ m.config.set_debug_mode(False) @@ -64,14 +69,18 @@ def test_tuple_to_array(caplog): def test_bad_tuples(caplog): m.config.set_debug_mode(True) - Buf = DeclareCircuit('Buf', "I", In(Tuple(a=Bit,b=Bit)), "O", Out(Array[8, Bit])) + class O(m.Product): + c = m.In(m.Bit) + d = m.In(m.Bit) + + Buf = DeclareCircuit('Buf', "I", In(I), "O", Out(Array[8, Bit])) - main = DefineCircuit("main", "I", In(Bit), "O", Out(Tuple(c=Bit,d=Bit))) + main = DefineCircuit("main", "I", In(Bit), "O", Out(O)) buf = Buf() wire(main.O, buf.I) assert "\n".join(x.msg for x in caplog.records) == """\ -\033[1mtests/test_type/test_type_errors.py:72: Cannot wire main.O (type=Tuple(c=In(Bit),d=In(Bit)), keys=['a', 'b']) to main.buf.I (type=Tuple(a=In(Bit),b=In(Bit)), keys=['c', 'd']) because the tuples do not have the same keys +\033[1mtests/test_type/test_type_errors.py:81: Cannot wire main.O (type=Tuple(c=In(Bit),d=In(Bit)), keys=['a', 'b']) to main.buf.I (type=Tuple(a=In(Bit),b=In(Bit)), keys=['c', 'd']) because the tuples do not have the same keys wire(main.O, buf.I) """ m.config.set_debug_mode(False) @@ -86,7 +95,7 @@ def test_bit_to_array(caplog): buf = Buf() wire(buf.I, main.O) assert "\n".join(x.msg for x in caplog.records) == """\ -\033[1mtests/test_type/test_type_errors.py:87: Cannot wire main.O (type=In(Bit)) to I (type=Array[8, In(Bit)]) because main.buf.I is not a _Bit +\033[1mtests/test_type/test_type_errors.py:96: Cannot wire main.O (type=In(Bit)) to I (type=Array[8, In(Bit)]) because main.buf.I is not a Digital wire(buf.I, main.O) """ m.config.set_debug_mode(False) diff --git a/tests/test_type/test_uint.py b/tests/test_type/test_uint.py index bdfe66123d..136b1b6e44 100644 --- a/tests/test_type/test_uint.py +++ b/tests/test_type/test_uint.py @@ -1,3 +1,6 @@ +from magma.testing import check_files_equal +import operator +import pytest from magma import * Array2 = Array[2,Bit] @@ -69,4 +72,100 @@ def test_flip(): def test_construct(): a1 = uint([1,1]) print(type(a1)) - assert isinstance(a1, UIntType) + assert isinstance(a1, UInt) + + +@pytest.mark.parametrize("n", [1, 3]) +@pytest.mark.parametrize("op", ["eq", "lt", "le", "gt", "ge"]) +def test_compare(n, op): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.UInt[n]), "I1", m.In(m.UInt[n]), "O", m.Out(m.Bit)] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + op = { + "eq": "eq", + "le": "ule", + "lt": "ult", + "ge": "uge", + "gt": "ugt" + }[op] + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(UInt[{n}]), "I1", In(UInt[{n}]), "O", Out(Bit)) +magma_Bits_{n}_{op}_inst0 = magma_Bits_{n}_{op}() +wire(TestBinary.I0, magma_Bits_{n}_{op}_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_{op}_inst0.in1) +wire(magma_Bits_{n}_{op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestUInt{n}{op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestUInt{n}{op}.v", + f"gold/TestUInt{n}{op}.v") + + +@pytest.mark.parametrize("n", [1, 3]) +@pytest.mark.parametrize("op", ["add", "sub", "mul", "floordiv", "mod"]) +def test_binary(n, op): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.UInt[n]), "I1", m.In(m.UInt[n]), "O", m.Out(m.UInt[n])] + @classmethod + def definition(io): + io.O <= getattr(operator, op)(io.I0, io.I1) + + if op == "floordiv": + op = "udiv" + elif op == "mod": + op = "urem" + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(UInt[{n}]), "I1", In(UInt[{n}]), "O", Out(UInt[{n}])) +magma_Bits_{n}_{op}_inst0 = magma_Bits_{n}_{op}() +wire(TestBinary.I0, magma_Bits_{n}_{op}_inst0.in0) +wire(TestBinary.I1, magma_Bits_{n}_{op}_inst0.in1) +wire(magma_Bits_{n}_{op}_inst0.out, TestBinary.O) +EndCircuit()\ +""" + m.compile(f"build/TestUInt{n}{op}", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestUInt{n}{op}.v", + f"gold/TestUInt{n}{op}.v") + + +@pytest.mark.parametrize("n", [1, 3]) +def test_adc(n): + class TestBinary(m.Circuit): + IO = ["I0", m.In(m.UInt[n]), "I1", m.In(m.UInt[n]), "CIN", m.In(m.Bit), "O", m.Out(m.UInt[n]), "COUT", m.Out(m.Bit)] + @classmethod + def definition(io): + result, carry = io.I0.adc(io.I1, io.CIN) + io.O <= result + io.COUT <= carry + + in0_wires = "\n".join(f"wire(TestBinary.I0[{i}], magma_Bits_{n + 1}_add_inst0.in0[{i}])" + for i in range(n)) + in0_wires += f"\nwire(GND, magma_Bits_{n + 1}_add_inst0.in0[{n}])" + + in1_wires = "\n".join(f"wire(TestBinary.I1[{i}], magma_Bits_{n + 1}_add_inst0.in1[{i}])" + for i in range(n)) + in1_wires += f"\nwire(GND, magma_Bits_{n + 1}_add_inst0.in1[{n}])" + + carry_wires = "\n".join(f"wire(GND, magma_Bits_{n + 1}_add_inst1.in1[{i + 1}])" for i in range(n)) + + out_wires = "\n".join(f"wire(magma_Bits_{n + 1}_add_inst1.out[{i}], TestBinary.O[{i}])" + for i in range(n)) + out_wires += f"\nwire(magma_Bits_{n + 1}_add_inst1.out[{n}], TestBinary.COUT)" + + assert repr(TestBinary) == f"""\ +TestBinary = DefineCircuit("TestBinary", "I0", In(UInt[{n}]), "I1", In(UInt[{n}]), "CIN", In(Bit), "O", Out(UInt[{n}]), "COUT", Out(Bit)) +magma_Bits_{n + 1}_add_inst0 = magma_Bits_{n + 1}_add() +magma_Bits_{n + 1}_add_inst1 = magma_Bits_{n + 1}_add() +{in0_wires} +{in1_wires} +wire(magma_Bits_{n + 1}_add_inst0.out, magma_Bits_{n + 1}_add_inst1.in0) +wire(TestBinary.CIN, magma_Bits_{n + 1}_add_inst1.in1[0]) +{carry_wires} +{out_wires} +EndCircuit()\ +""" + m.compile(f"build/TestUInt{n}adc", TestBinary, output="coreir-verilog") + assert check_files_equal(__file__, f"build/TestUInt{n}adc.v", + f"gold/TestUInt{n}adc.v") diff --git a/tests/test_uniquify.py b/tests/test_uniquify.py index 9aad5e9140..1f34919643 100644 --- a/tests/test_uniquify.py +++ b/tests/test_uniquify.py @@ -81,9 +81,14 @@ def DeclareCoreirCircuit(*args, **kwargs): renamed_ports=default_port_mapping) Mux2x6 = m.DefineCircuit("Mux2x6", "I0", m.In(m.Bits[6]), "I1", m.In(m.Bits[6]), "S", m.In(m.Bit), "O", m.Out(m.Bits[6])) + + class I(m.Product): + data = m.Array[2, m.Bits[6]] + sel = m.Bits[m.bitutils.clog2(2)] + + mux = DeclareCoreirCircuit(f"coreir_commonlib_mux{2}x{6}", - *["I", m.In(m.Tuple(data=m.Array[2, m.Bits[6]], - sel=m.Bits[m.bitutils.clog2(2)])), + *["I", m.In(I), "O", m.Out(m.Bits[6])], coreir_name="muxn", coreir_lib="commonlib", diff --git a/tests/test_verilog/test_from_file.py b/tests/test_verilog/test_from_file.py index dcdbc6a206..41752a6833 100644 --- a/tests/test_verilog/test_from_file.py +++ b/tests/test_verilog/test_from_file.py @@ -12,17 +12,17 @@ def check_port(definition, port, type, direction): port = getattr(definition, port) assert isinstance(port, type) if direction == "input": - assert port.isoutput() + assert port.is_output() elif direction == "output": - assert port.isinput() + assert port.is_input() else: raise NotImplementedError(direction) def check_rxmod(RXMOD): - check_port(RXMOD, "RX", m.BitType, "input") - check_port(RXMOD, "CLK", m.BitType, "input") - check_port(RXMOD, "data", m.ArrayType, "output") - check_port(RXMOD, "valid", m.BitType, "output") + check_port(RXMOD, "RX", m.Bit, "input") + check_port(RXMOD, "CLK", m.Bit, "input") + check_port(RXMOD, "data", m.Array, "output") + check_port(RXMOD, "valid", m.Bit, "output") m.compile("build/test_rxmod", RXMOD, output="verilog") assert m.testing.check_files_equal(__file__, "build/test_rxmod.v", @@ -210,16 +210,11 @@ def test_from_verilog_external_modules_duplicate(): def _test_nd_array_port(verilog): - try: - [top] = m.DefineFromVerilog(verilog) - assert len(top.interface.ports) == 1 - assert "inp" in top.interface.ports - - # Not sure why the following doesn't work, using repr as a workaround. - #assert type(top.inp) is m.In(m.Array[4, m.Array[2, m.Bits[8]]]) - assert repr(type(top.inp)) == "Array[4, Array[2, Bits[8, Bit]]]" - except pyverilog.vparser.plyparser.ParseError: - pytest.skip("Parsing ND array failed, requires pyverilog branch, skipping test") + [top] = m.DefineFromVerilog(verilog) + assert len(top.interface.ports) == 1 + assert "inp" in top.interface.ports + + assert type(top.inp) is m.Out(m.Array[4, m.Array[2, m.Bits[8]]]) def test_nd_array_port_list(): diff --git a/tools/xdl/xdlrcviz.py b/tools/xdl/xdlrcviz.py index 9b8dfd2d4d..a6a3aa81ab 100644 --- a/tools/xdl/xdlrcviz.py +++ b/tools/xdl/xdlrcviz.py @@ -102,4 +102,4 @@ def quote(x): try: p.save() except: - print("Failed to save %s" % p.name) \ No newline at end of file + print("Failed to save %s" % p.name)