Skip to content
Permalink

Comparing changes

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

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a90748303c73
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0f2c7e716132
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Dec 18, 2018

  1. compat: import genlib.record from Migen.

    whitequark committed Dec 18, 2018
    Copy the full SHA
    0f2c7e7 View commit details
Showing with 201 additions and 2 deletions.
  1. +1 −1 nmigen/compat/__init__.py
  2. +195 −0 nmigen/compat/genlib/record.py
  3. +2 −1 nmigen/hdl/xfrm.py
  4. +3 −0 nmigen/tracer.py
2 changes: 1 addition & 1 deletion nmigen/compat/__init__.py
Original file line number Diff line number Diff line change
@@ -7,5 +7,5 @@

from .sim import *

# from .genlib.record import *
from .genlib.record import *
from .genlib.fsm import *
195 changes: 195 additions & 0 deletions nmigen/compat/genlib/record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
from ...tracer import *
from ..fhdl.structure import *

from functools import reduce
from operator import or_


(DIR_NONE, DIR_S_TO_M, DIR_M_TO_S) = range(3)

# Possible layout elements:
# 1. (name, size)
# 2. (name, size, direction)
# 3. (name, sublayout)
# size can be an int, or a (int, bool) tuple for signed numbers
# sublayout must be a list


def set_layout_parameters(layout, **layout_dict):
def resolve(p):
if isinstance(p, str):
try:
return layout_dict[p]
except KeyError:
return p
else:
return p

r = []
for f in layout:
if isinstance(f[1], (int, tuple, str)): # cases 1/2
if len(f) == 3:
r.append((f[0], resolve(f[1]), f[2]))
else:
r.append((f[0], resolve(f[1])))
elif isinstance(f[1], list): # case 3
r.append((f[0], set_layout_parameters(f[1], **layout_dict)))
else:
raise TypeError
return r


def layout_len(layout):
r = 0
for f in layout:
if isinstance(f[1], (int, tuple)): # cases 1/2
if len(f) == 3:
fname, fsize, fdirection = f
else:
fname, fsize = f
elif isinstance(f[1], list): # case 3
fname, fsublayout = f
fsize = layout_len(fsublayout)
else:
raise TypeError
if isinstance(fsize, tuple):
r += fsize[0]
else:
r += fsize
return r


def layout_get(layout, name):
for f in layout:
if f[0] == name:
return f
raise KeyError(name)


def layout_partial(layout, *elements):
r = []
for path in elements:
path_s = path.split("/")
last = path_s.pop()
copy_ref = layout
insert_ref = r
for hop in path_s:
name, copy_ref = layout_get(copy_ref, hop)
try:
name, insert_ref = layout_get(insert_ref, hop)
except KeyError:
new_insert_ref = []
insert_ref.append((hop, new_insert_ref))
insert_ref = new_insert_ref
insert_ref.append(layout_get(copy_ref, last))
return r


class Record:
def __init__(self, layout, name=None, **kwargs):
try:
self.name = get_var_name()
except NameNotFound:
self.name = ""
self.layout = layout

if self.name:
prefix = self.name + "_"
else:
prefix = ""
for f in self.layout:
if isinstance(f[1], (int, tuple)): # cases 1/2
if(len(f) == 3):
fname, fsize, fdirection = f
else:
fname, fsize = f
finst = Signal(fsize, name=prefix + fname, **kwargs)
elif isinstance(f[1], list): # case 3
fname, fsublayout = f
finst = Record(fsublayout, prefix + fname, **kwargs)
else:
raise TypeError
setattr(self, fname, finst)

def eq(self, other):
return [getattr(self, f[0]).eq(getattr(other, f[0]))
for f in self.layout if hasattr(other, f[0])]

def iter_flat(self):
for f in self.layout:
e = getattr(self, f[0])
if isinstance(e, Signal):
if len(f) == 3:
yield e, f[2]
else:
yield e, DIR_NONE
elif isinstance(e, Record):
yield from e.iter_flat()
else:
raise TypeError

def flatten(self):
return [signal for signal, direction in self.iter_flat()]

def raw_bits(self):
return Cat(*self.flatten())

def connect(self, *slaves, keep=None, omit=None):
if keep is None:
_keep = set([f[0] for f in self.layout])
elif isinstance(keep, list):
_keep = set(keep)
else:
_keep = keep
if omit is None:
_omit = set()
elif isinstance(omit, list):
_omit = set(omit)
else:
_omit = omit

_keep = _keep - _omit

r = []
for f in self.layout:
field = f[0]
self_e = getattr(self, field)
if isinstance(self_e, Signal):
if field in _keep:
direction = f[2]
if direction == DIR_M_TO_S:
r += [getattr(slave, field).eq(self_e) for slave in slaves]
elif direction == DIR_S_TO_M:
r.append(self_e.eq(reduce(or_, [getattr(slave, field) for slave in slaves])))
else:
raise TypeError
else:
for slave in slaves:
r += self_e.connect(getattr(slave, field), keep=keep, omit=omit)
return r

def connect_flat(self, *slaves):
r = []
iter_slaves = [slave.iter_flat() for slave in slaves]
for m_signal, m_direction in self.iter_flat():
if m_direction == DIR_M_TO_S:
for iter_slave in iter_slaves:
s_signal, s_direction = next(iter_slave)
assert(s_direction == DIR_M_TO_S)
r.append(s_signal.eq(m_signal))
elif m_direction == DIR_S_TO_M:
s_signals = []
for iter_slave in iter_slaves:
s_signal, s_direction = next(iter_slave)
assert(s_direction == DIR_S_TO_M)
s_signals.append(s_signal)
r.append(m_signal.eq(reduce(or_, s_signals)))
else:
raise TypeError
return r

def __len__(self):
return layout_len(self.layout)

def __repr__(self):
return "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"
3 changes: 2 additions & 1 deletion nmigen/hdl/xfrm.py
Original file line number Diff line number Diff line change
@@ -74,7 +74,8 @@ def on_value(self, value):
new_value = self.on_Slice(value)
elif type(value) is Part:
new_value = self.on_Part(value)
elif type(value) is Cat:
elif isinstance(value, Cat):
# Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
new_value = self.on_Cat(value)
elif type(value) is Repl:
new_value = self.on_Repl(value)
3 changes: 3 additions & 0 deletions nmigen/tracer.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@
from opcode import opname


__all__ = ["NameNotFound", "get_var_name"]


class NameNotFound(Exception):
pass