1 from migen
.fhdl
.structure
import *
2 from migen
.fhdl
.tracer
import get_obj_var_name
4 from functools
import reduce
5 from operator
import or_
8 (DIR_NONE
, DIR_S_TO_M
, DIR_M_TO_S
) = range(3)
10 # Possible layout elements:
12 # 2. (name, size, direction)
13 # 3. (name, sublayout)
14 # size can be an int, or a (int, bool) tuple for signed numbers
15 # sublayout must be a list
18 def set_layout_parameters(layout
, **layout_dict
):
20 if isinstance(p
, str):
30 if isinstance(f
[1], (int, tuple, str)): # cases 1/2
32 r
.append((f
[0], resolve(f
[1]), f
[2]))
34 r
.append((f
[0], resolve(f
[1])))
35 elif isinstance(f
[1], list): # case 3
36 r
.append((f
[0], set_layout_parameters(f
[1], **layout_dict
)))
42 def layout_len(layout
):
45 if isinstance(f
[1], (int, tuple)): # cases 1/2
47 fname
, fsize
, fdirection
= f
50 elif isinstance(f
[1], list): # case 3
52 fsize
= layout_len(fsublayout
)
55 if isinstance(fsize
, tuple):
62 def layout_get(layout
, name
):
69 def layout_partial(layout
, *elements
):
72 path_s
= path
.split("/")
77 name
, copy_ref
= layout_get(copy_ref
, hop
)
79 name
, insert_ref
= layout_get(insert_ref
, hop
)
82 insert_ref
.append((hop
, new_insert_ref
))
83 insert_ref
= new_insert_ref
84 insert_ref
.append(layout_get(copy_ref
, last
))
89 def __init__(self
, layout
, name
=None):
90 self
.name
= get_obj_var_name(name
, "")
94 prefix
= self
.name
+ "_"
98 if isinstance(f
[1], (int, tuple)): # cases 1/2
100 fname
, fsize
, fdirection
= f
103 finst
= Signal(fsize
, name
=prefix
+ fname
)
104 elif isinstance(f
[1], list): # case 3
105 fname
, fsublayout
= f
106 finst
= Record(fsublayout
, prefix
+ fname
)
109 setattr(self
, fname
, finst
)
112 return [getattr(self
, f
[0]).eq(getattr(other
, f
[0]))
113 for f
in self
.layout
if hasattr(other
, f
[0])]
116 for f
in self
.layout
:
117 e
= getattr(self
, f
[0])
118 if isinstance(e
, Signal
):
123 elif isinstance(e
, Record
):
124 yield from e
.iter_flat()
129 return [signal
for signal
, direction
in self
.iter_flat()]
132 return Cat(*self
.flatten())
134 def connect(self
, *slaves
, leave_out
=set()):
135 if isinstance(leave_out
, str):
136 leave_out
= {leave_out}
138 for f
in self
.layout
:
140 if field
not in leave_out
:
141 self_e
= getattr(self
, field
)
142 if isinstance(self_e
, Signal
):
144 if direction
== DIR_M_TO_S
:
145 r
+= [getattr(slave
, field
).eq(self_e
) for slave
in slaves
]
146 elif direction
== DIR_S_TO_M
:
147 r
.append(self_e
.eq(reduce(or_
, [getattr(slave
, field
) for slave
in slaves
])))
152 r
+= self_e
.connect(getattr(slave
, field
), leave_out
=leave_out
)
155 def connect_flat(self
, *slaves
):
157 iter_slaves
= [slave
.iter_flat() for slave
in slaves
]
158 for m_signal
, m_direction
in self
.iter_flat():
159 if m_direction
== DIR_M_TO_S
:
160 for iter_slave
in iter_slaves
:
161 s_signal
, s_direction
= next(iter_slave
)
162 assert(s_direction
== DIR_M_TO_S
)
163 r
.append(s_signal
.eq(m_signal
))
164 elif m_direction
== DIR_S_TO_M
:
166 for iter_slave
in iter_slaves
:
167 s_signal
, s_direction
= next(iter_slave
)
168 assert(s_direction
== DIR_S_TO_M
)
169 s_signals
.append(s_signal
)
170 r
.append(m_signal
.eq(reduce(or_
, s_signals
)))
176 return layout_len(self
.layout
)
179 return "<Record " + ":".join(f
[0] for f
in self
.layout
) + " at " + hex(id(self
)) + ">"