litex/migen/genlib/record.py

128 lines
3.2 KiB
Python
Raw Normal View History

2012-01-06 05:20:44 -05:00
from migen.fhdl.structure import *
2013-04-01 15:53:33 -04:00
from migen.fhdl.tracer import get_obj_var_name
from migen.genlib.misc import optree
(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 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
2013-04-10 13:12:42 -04:00
raise KeyError(name)
2013-04-01 15:53:33 -04:00
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
2012-01-06 05:20:44 -05:00
class Record:
2013-04-01 15:53:33 -04:00
def __init__(self, layout, name=None):
self.name = get_obj_var_name(name, "")
self.layout = layout
2012-01-16 13:38:14 -05:00
if self.name:
prefix = self.name + "_"
else:
prefix = ""
2013-04-01 15:53:33 -04:00
for f in self.layout:
if isinstance(f[1], (int, tuple)): # cases 1/2
if(len(f) == 3):
fname, fsize, fdirection = f
2012-01-09 13:16:11 -05:00
else:
2013-04-01 15:53:33 -04:00
fname, fsize = f
finst = Signal(fsize, name=prefix + fname)
elif isinstance(f[1], list): # case 3
fname, fsublayout = f
finst = Record(fsublayout, prefix + fname)
2012-01-06 05:20:44 -05:00
else:
2013-04-01 15:53:33 -04:00
raise TypeError
setattr(self, fname, finst)
2012-01-06 05:20:44 -05:00
2013-03-23 19:50:33 -04:00
def eq(self, other):
2013-04-01 15:53:33 -04:00
return [getattr(self, f[0]).eq(getattr(other, f[0]))
for f in self.layout if hasattr(other, f[0])]
2012-01-06 05:20:44 -05:00
2013-04-01 15:53:33 -04:00
def flatten(self):
r = []
for f in self.layout:
e = getattr(self, f[0])
2012-01-06 05:20:44 -05:00
if isinstance(e, Signal):
2013-04-01 15:53:33 -04:00
r.append(e)
2012-01-06 05:20:44 -05:00
elif isinstance(e, Record):
2013-04-01 15:53:33 -04:00
r += e.flatten()
2012-01-09 13:16:11 -05:00
else:
raise TypeError
2013-04-01 15:53:33 -04:00
return r
def raw_bits(self):
return Cat(*self.flatten())
def connect(self, *slaves, match_by_position=False):
if match_by_position:
iters = [iter(slave.layout) for slave in slaves]
else:
iters = [iter(self.layout) for slave in slaves]
2013-04-01 15:53:33 -04:00
r = []
for f in self.layout:
field = f[0]
self_e = getattr(self, field)
if isinstance(self_e, Signal):
direction = f[2]
if direction == DIR_M_TO_S:
r += [getattr(slave, next(it)[0]).eq(self_e) for slave, it in zip(slaves, iters)]
2013-04-01 15:53:33 -04:00
elif direction == DIR_S_TO_M:
r.append(self_e.eq(optree("|", [getattr(slave, next(it)[0])
for slave, it in zip(slaves, iters)])))
2013-04-01 15:53:33 -04:00
else:
raise TypeError
else:
for slave, it in zip(slaves, iters):
r += self_e.connect(getattr(slave, next(it)[0]),
match_by_position=match_by_position)
2013-04-01 15:53:33 -04:00
return r
def __len__(self):
return layout_len(self.layout)
2012-01-06 18:33:28 -05:00
def __repr__(self):
2013-04-01 15:53:33 -04:00
return "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">"