Skip to content

Commit df3a45b

Browse files
committedMar 12, 2016
intersonnect/stream: simplify Converter (now only works on raw bits) and add StrideConverter to handle first-level user fields
1 parent 9f74894 commit df3a45b

File tree

2 files changed

+93
-62
lines changed

2 files changed

+93
-62
lines changed
 

Diff for: ‎misoc/cores/liteeth_mini/mac/core.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ def __init__(self, phy, dw, endianness="big",
6666
# Converters
6767
if dw != phy.dw:
6868
reverse = endianness == "big"
69-
tx_converter = stream.Converter(eth_phy_layout(dw),
69+
tx_converter = stream.StrideConverter(eth_phy_layout(dw),
7070
eth_phy_layout(phy.dw),
7171
reverse=reverse)
72-
rx_converter = stream.Converter(eth_phy_layout(phy.dw),
72+
rx_converter = stream.StrideConverter(eth_phy_layout(phy.dw),
7373
eth_phy_layout(dw),
7474
reverse=reverse)
7575
self.submodules += ClockDomainsRenamer("eth_tx")(tx_converter)

Diff for: ‎misoc/interconnect/stream.py

+91-60
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,16 @@ def __init__(self, layout_from, layout_to, ratio, reverse):
165165
]
166166

167167
# data path
168+
source_payload_raw_bits = Signal(len(source.payload.raw_bits()))
168169
cases = {}
169170
for i in range(ratio):
170171
n = ratio-i-1 if reverse else i
171-
cases[i] = []
172-
for name, width in layout_from:
173-
src = getattr(self.sink, name)
174-
dst = getattr(self.source, name)[n*width:(n+1)*width]
175-
cases[i].append(dst.eq(src))
176-
self.sync += If(load_part, Case(demux, cases))
172+
width = len(sink.payload.raw_bits())
173+
src = sink.payload.raw_bits()
174+
dst = source_payload_raw_bits[n*width:(n+1)*width]
175+
cases[i] = dst.eq(src)
176+
self.sync += If(load_part, Case(demux, cases))
177+
self.comb += source.payload.raw_bits().eq(source_payload_raw_bits)
177178

178179

179180
class _DownConverter(Module):
@@ -202,79 +203,109 @@ def __init__(self, layout_from, layout_to, ratio, reverse):
202203
)
203204

204205
# data path
206+
sink_payload_raw_bits = Signal(len(sink.payload.raw_bits()))
207+
self.comb += sink_payload_raw_bits.eq(sink.payload.raw_bits())
205208
cases = {}
206209
for i in range(ratio):
207210
n = ratio-i-1 if reverse else i
208-
cases[i] = []
209-
for name, width in layout_to:
210-
src = getattr(self.sink, name)[n*width:(n+1)*width]
211-
dst = getattr(self.source, name)
212-
cases[i].append(dst.eq(src))
213-
self.comb += Case(mux, cases).makedefault()
211+
width = len(source.payload.raw_bits())
212+
src = sink_payload_raw_bits[n*width:(n+1)*width]
213+
dst = source.payload.raw_bits()
214+
cases[i] = dst.eq(src)
215+
self.comb += Case(mux, cases).makedefault(),
214216

215217

216218
class _IdentityConverter(Module):
217219
def __init__(self, layout_from, layout_to, ratio, reverse):
218-
self.sink = Endpoint(layout_from)
219-
self.source = Endpoint(layout_to)
220+
self.sink = sink = Endpoint(layout_from)
221+
self.source = source = Endpoint(layout_to)
220222

221223
# # #
222224

223-
self.comb += self.sink.connect(self.source)
225+
self.comb += sink.connect(source)
224226

225227

226228
def _get_converter_ratio(layout_from, layout_to):
227-
if len(layout_from) != len(layout_to):
228-
raise ValueError("Incompatible layouts (number of elements)")
229-
230-
converter = None
231-
ratio = None
232-
for f_from, f_to in zip(layout_from, layout_to):
233-
name_from, width_from = f_from
234-
name_to, width_to = f_to
235-
236-
# check layouts
237-
if not isinstance(width_to, int) or not isinstance(width_to, int):
238-
raise ValueError("Sublayouts are not supported")
239-
if name_from != name_to:
240-
raise ValueError("Incompatible layouts (field names)")
241-
242-
# get current converter/ratio
243-
if width_from > width_to:
244-
current_converter = _DownConverter
245-
if width_from % width_to:
246-
raise ValueError("Ratio must be an int")
247-
current_ratio = width_from//width_to
248-
elif width_from < width_to:
249-
current_converter = _UpConverter
250-
if width_to % width_from:
251-
raise ValueError("Ratio must be an int")
252-
current_ratio = width_to//width_from
253-
else:
254-
current_converter = _IdentityConverter
255-
current_ratio = 1
229+
width_from = len(Endpoint(layout_from).payload.raw_bits())
230+
width_to = len(Endpoint(layout_to).payload.raw_bits())
231+
232+
if width_from > width_to:
233+
converter_cls = _DownConverter
234+
if width_from % width_to:
235+
raise ValueError("Ratio must be an int")
236+
ratio = width_from//width_to
237+
elif width_from < width_to:
238+
converter_cls = _UpConverter
239+
if width_to % width_from:
240+
raise ValueError("Ratio must be an int")
241+
ratio = width_to//width_from
242+
else:
243+
converter_cls = _IdentityConverter
244+
ratio = 1
245+
246+
return converter_cls, ratio
256247

257-
# check converter
258-
if converter is None:
259-
converter = current_converter
260-
if current_converter != converter:
261-
raise ValueError("Incoherent layout fields (converter type)")
262248

263-
# check ratio
264-
if ratio is None:
265-
ratio = current_ratio
266-
if current_ratio != ratio:
267-
raise ValueError("Incoherent layout fields (ratio)")
249+
class Converter(Module):
250+
def __init__(self, layout_from, layout_to, reverse=False):
251+
self.cls, self.ratio = _get_converter_ratio(layout_from, layout_to)
268252

269-
return converter, ratio
253+
# # #
270254

255+
converter = self.cls(layout_from, layout_to, self.ratio, reverse)
256+
self.submodules += converter
271257

272-
class Converter(Module):
258+
self.sink, self.source = converter.sink, converter.source
259+
260+
261+
class StrideConverter(Module):
273262
def __init__(self, layout_from, layout_to, reverse=False):
274-
converter, ratio = _get_converter_ratio(layout_from, layout_to)
263+
self.sink = sink = Endpoint(layout_from)
264+
self.source = source = Endpoint(layout_to)
275265

276266
# # #
277267

278-
self.submodules.converter = converter(layout_from, layout_to,
279-
ratio, reverse)
280-
self.sink, self.source = self.converter.sink, self.converter.source
268+
width_from = len(sink.payload.raw_bits())
269+
width_to = len(source.payload.raw_bits())
270+
271+
converter = Converter([("data", width_from)],
272+
[("data", width_to)],
273+
reverse)
274+
self.submodules += converter
275+
276+
# cast sink to converter.sink (user fields --> raw bits)
277+
self.comb += [
278+
converter.sink.stb.eq(sink.stb),
279+
converter.sink.eop.eq(sink.eop),
280+
sink.ack.eq(converter.sink.ack)
281+
]
282+
if converter.cls == _DownConverter:
283+
ratio = converter.ratio
284+
for i in range(ratio):
285+
j = 0
286+
for name, width in layout_to:
287+
src = getattr(sink, name)[i*width:(i+1)*width]
288+
dst = converter.sink.data[i*width_to+j:i*width_to+j+width]
289+
self.comb += dst.eq(src)
290+
j += width
291+
else:
292+
self.comb += converter.sink.data.eq(sink.payload.raw_bits())
293+
294+
295+
# cast converter.source to source (raw bits --> user fields)
296+
self.comb += [
297+
source.stb.eq(converter.source.stb),
298+
source.eop.eq(converter.source.eop),
299+
converter.source.ack.eq(source.ack)
300+
]
301+
if converter.cls == _UpConverter:
302+
ratio = converter.ratio
303+
for i in range(ratio):
304+
j = 0
305+
for name, width in layout_from:
306+
src = converter.source.data[i*width_from+j:i*width_from+j+width]
307+
dst = getattr(source, name)[i*width:(i+1)*width]
308+
self.comb += dst.eq(src)
309+
j += width
310+
else:
311+
self.comb += source.payload.raw_bits().eq(converter.source.data)

3 commit comments

Comments
 (3)

sbourdeauducq commented on Mar 13, 2016

@sbourdeauducq
Member

What I meant is that the Converter should only be able to operate on layouts that are of the form [("data", nbits)]. It could create its endpoints itself, and take only the bit sizes (integers) as parameter.

sbourdeauducq commented on Mar 13, 2016

@sbourdeauducq
Member

This way you do not have to call raw_bits anywhere in the converter, and the addition of the chunks fields is easier.

enjoy-digital commented on Mar 13, 2016

@enjoy-digital
ContributorAuthor

ok that's fine. I just did the changes and will test/commit it tomorrow.

Please sign in to comment.