Skip to content

Commit f1a35b5

Browse files
committed
wip (wishbone)
1 parent 7089aa1 commit f1a35b5

File tree

3 files changed

+247
-62
lines changed

3 files changed

+247
-62
lines changed

amaranth_soc/wishbone/bus.py

Lines changed: 178 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -42,62 +42,71 @@ class Signature(wiring.Signature):
4242
of the Wishbone signals. The ``RST_I`` and ``CLK_I`` signals are provided as a part of
4343
the clock domain that drives the interface.
4444
45-
Parameters
46-
----------
47-
addr_width : int
45+
The correspondence between the Amaranth-SoC signals and the Wishbone signals changes depending
46+
on whether the interface acts as an initiator or a target.
47+
48+
Arguments
49+
---------
50+
addr_width : :class:`int`
4851
Width of the address signal.
49-
data_width : int
52+
data_width : :class:`int`
5053
Width of the data signals ("port size" in Wishbone terminology).
5154
One of 8, 16, 32, 64.
52-
granularity : int
55+
granularity : :class:`int`
5356
Granularity of select signals ("port granularity" in Wishbone terminology).
5457
One of 8, 16, 32, 64.
5558
Optional. If ``None`` (by default), the granularity is equal to ``data_width``.
56-
features : iter(:class:`Feature`)
59+
features : iterable of :class:`Feature`
5760
Selects additional signals that will be a part of this interface.
5861
Optional.
5962
60-
Interface attributes
61-
--------------------
62-
The correspondence between the Amaranth-SoC signals and the Wishbone signals changes depending
63-
on whether the interface acts as an initiator or a target.
64-
65-
adr : Signal(addr_width)
63+
Attributes
64+
----------
65+
adr : :pc:`unsigned(addr_width)`
6666
Corresponds to Wishbone signal ``ADR_O`` (initiator) or ``ADR_I`` (target).
67-
dat_w : Signal(data_width)
67+
dat_w : :pc:`unsigned(data_width)`
6868
Corresponds to Wishbone signal ``DAT_O`` (initiator) or ``DAT_I`` (target).
69-
dat_r : Signal(data_width)
69+
dat_r : :pc:`unsigned(data_width)`
7070
Corresponds to Wishbone signal ``DAT_I`` (initiator) or ``DAT_O`` (target).
71-
sel : Signal(data_width // granularity)
71+
sel : :pc:`unsigned(data_width // granularity)`
7272
Corresponds to Wishbone signal ``SEL_O`` (initiator) or ``SEL_I`` (target).
73-
cyc : Signal()
73+
cyc : :pc:`unsigned(1)`
7474
Corresponds to Wishbone signal ``CYC_O`` (initiator) or ``CYC_I`` (target).
75-
stb : Signal()
75+
stb : :pc:`unsigned(1)`
7676
Corresponds to Wishbone signal ``STB_O`` (initiator) or ``STB_I`` (target).
77-
we : Signal()
77+
we : :pc:`unsigned(1)`
7878
Corresponds to Wishbone signal ``WE_O`` (initiator) or ``WE_I`` (target).
79-
ack : Signal()
79+
ack : :pc:`unsigned(1)`
8080
Corresponds to Wishbone signal ``ACK_I`` (initiator) or ``ACK_O`` (target).
81-
err : Signal()
81+
err : :pc:`unsigned(1)`
8282
Optional. Corresponds to Wishbone signal ``ERR_I`` (initiator) or ``ERR_O`` (target).
83-
rty : Signal()
83+
rty : :pc:`unsigned(1)`
8484
Optional. Corresponds to Wishbone signal ``RTY_I`` (initiator) or ``RTY_O`` (target).
85-
stall : Signal()
85+
stall : :pc:`unsigned(1)`
8686
Optional. Corresponds to Wishbone signal ``STALL_I`` (initiator) or ``STALL_O`` (target).
87-
lock : Signal()
87+
lock : :pc:`unsigned(1)`
8888
Optional. Corresponds to Wishbone signal ``LOCK_O`` (initiator) or ``LOCK_I`` (target).
8989
Amaranth-SoC Wishbone support assumes that initiators that don't want bus arbitration to
9090
happen in between two transactions need to use ``lock`` feature to guarantee this. An
9191
initiator without the ``lock`` feature may be arbitrated in between two transactions even
9292
if ``cyc`` is kept high.
93-
cti : Signal()
93+
cti : :pc:`unsigned(1)`
9494
Optional. Corresponds to Wishbone signal ``CTI_O`` (initiator) or ``CTI_I`` (target).
95-
bte : Signal()
95+
bte : :pc:`unsigned(1)`
9696
Optional. Corresponds to Wishbone signal ``BTE_O`` (initiator) or ``BTE_I`` (target).
9797
9898
Raises
9999
------
100-
See :meth:`Signature.check_parameters`.
100+
:exc:`TypeError`
101+
If ``addr_width`` is not an integer greater than or equal to 0.
102+
:exc:`ValueError`
103+
If ``data_width`` is not 8, 16, 32 or 64.
104+
:exc:`ValueError`
105+
If ``granularity`` is not 8, 16, 32 or 64.
106+
:exc:`ValueError`
107+
If ``granularity`` is greater than ``data_width``.
108+
:exc:`ValueError`
109+
If ``features`` contains other values than :class:`Feature` members.
101110
"""
102111
def __init__(self, *, addr_width, data_width, granularity=None, features=frozenset()):
103112
if granularity is None:
@@ -136,18 +145,42 @@ def __init__(self, *, addr_width, data_width, granularity=None, features=frozens
136145

137146
@property
138147
def addr_width(self):
148+
"""Width of the address signal.
149+
150+
Returns
151+
-------
152+
:class:`int`
153+
"""
139154
return self._addr_width
140155

141156
@property
142157
def data_width(self):
158+
"""Width of the data signals ("port size" in Wishbone terminology).
159+
160+
Returns
161+
-------
162+
One of 8, 16, 32, 64.
163+
"""
143164
return self._data_width
144165

145166
@property
146167
def granularity(self):
168+
"""Granularity of select signals ("port granularity" in Wishbone terminology).
169+
170+
Returns
171+
-------
172+
One of 8, 16, 32, 64.
173+
"""
147174
return self._granularity
148175

149176
@property
150177
def features(self):
178+
"""Additional signals that will be a part of this interface.
179+
180+
Returns
181+
-------
182+
:class:`frozenset` of :class:`Feature`
183+
"""
151184
return self._features
152185

153186
@classmethod
@@ -186,7 +219,7 @@ def create(self, *, path=None, src_loc_at=0):
186219
187220
Returns
188221
-------
189-
An :class:`Interface` object using this signature.
222+
:class:`Interface`
190223
"""
191224
return Interface(addr_width=self.addr_width, data_width=self.data_width,
192225
granularity=self.granularity, features=self.features,
@@ -211,31 +244,37 @@ def __repr__(self):
211244
class Interface(wiring.PureInterface):
212245
"""Wishbone bus interface.
213246
214-
Note that the data width of the underlying memory map of the interface is equal to port
215-
granularity, not port size. If port granularity is less than port size, then the address width
216-
of the underlying memory map is extended to reflect that.
247+
.. note::
217248
218-
Parameters
219-
----------
249+
The data width of the underlying :class:`MemoryMap` of the interface is equal to port
250+
granularity, not port size. If port granularity is less than port size, then the address
251+
width of the underlying memory map is extended to reflect that.
252+
253+
Arguments
254+
---------
220255
addr_width : :class:`int`
221256
Width of the address signal. See :class:`Signature`.
222257
data_width : :class:`int`
223258
Width of the data signals. See :class:`Signature`.
224259
granularity : :class:`int`
225260
Granularity of select signals. Optional. See :class:`Signature`.
226-
features : iter(:class:`Feature`)
261+
features : iterable of :class:`Feature`
227262
Describes additional signals of this interface. Optional. See :class:`Signature`.
228263
path : iter(:class:`str`)
229264
Path to this Wishbone interface. Optional. See :class:`wiring.PureInterface`.
230265
231-
Attributes
232-
----------
233-
memory_map: :class:`MemoryMap`
234-
Memory map of the bus. Optional.
235-
236266
Raises
237267
------
238-
See :meth:`Signature.check_parameters`.
268+
:exc:`TypeError`
269+
If ``addr_width`` is not an integer greater than or equal to 0.
270+
:exc:`ValueError`
271+
If ``data_width`` is not 8, 16, 32 or 64.
272+
:exc:`ValueError`
273+
If ``granularity`` is not 8, 16, 32 or 64.
274+
:exc:`ValueError`
275+
If ``granularity`` is greater than ``data_width``.
276+
:exc:`ValueError`
277+
If ``features`` contains other values than :class:`Feature` members.
239278
"""
240279
def __init__(self, *, addr_width, data_width, granularity=None, features=frozenset(),
241280
path=None, src_loc_at=0):
@@ -246,22 +285,54 @@ def __init__(self, *, addr_width, data_width, granularity=None, features=frozens
246285

247286
@property
248287
def addr_width(self):
288+
"""Width of the address signal.
289+
290+
Returns
291+
-------
292+
:class:`int`
293+
"""
249294
return self.signature.addr_width
250295

251296
@property
252297
def data_width(self):
298+
"""Width of the data signals ("port size" in Wishbone terminology).
299+
300+
Returns
301+
-------
302+
One of 8, 16, 32, 64.
303+
"""
253304
return self.signature.data_width
254305

255306
@property
256307
def granularity(self):
308+
"""Granularity of select signals ("port granularity" in Wishbone terminology).
309+
310+
Returns
311+
-------
312+
One of 8, 16, 32, 64.
313+
"""
257314
return self.signature.granularity
258315

259316
@property
260317
def features(self):
318+
"""Additional signals that are part of this interface.
319+
320+
Returns
321+
-------
322+
:class:`frozenset` of :class:`Feature`
323+
"""
261324
return self.signature.features
262325

263326
@property
264327
def memory_map(self):
328+
"""Memory map of the bus.
329+
330+
.. todo:: setter
331+
332+
Returns
333+
-------
334+
:class:`MemoryMap` or ``None``
335+
"""
265336
if self._memory_map is None:
266337
raise AttributeError(f"{self!r} does not have a memory map")
267338
return self._memory_map
@@ -291,20 +362,20 @@ class Decoder(wiring.Component):
291362
292363
An address decoder for subordinate Wishbone buses.
293364
294-
Parameters
295-
----------
365+
Arguments
366+
---------
296367
addr_width : :class:`int`
297368
Address width. See :class:`Signature`.
298369
data_width : :class:`int`
299370
Data width. See :class:`Signature`.
300371
granularity : :class:`int`
301372
Granularity. See :class:`Signature`
302-
features : iter(:class:`Feature`)
373+
features : iterable of :class:`Feature`
303374
Optional signal set. See :class:`Signature`.
304-
alignment : int, power-of-2 exponent
305-
Window alignment. Optional. See :class:`..memory.MemoryMap`.
375+
alignment : :class:`int`, power-of-2 exponent
376+
Window alignment. Optional. See :class:`~..memory.MemoryMap`.
306377
name : :class:`str`
307-
Window name. Optional. See :class:`..memory.MemoryMap`.
378+
Window name. Optional. See :class:`~..memory.MemoryMap`.
308379
309380
Attributes
310381
----------
@@ -326,20 +397,56 @@ def align_to(self, alignment):
326397
"""Align the implicit address of the next window.
327398
328399
See :meth:`MemoryMap.align_to` for details.
400+
401+
Returns
402+
-------
403+
:class:`int`
404+
Implicit next address.
329405
"""
330406
return self.bus.memory_map.align_to(alignment)
331407

332408
def add(self, sub_bus, *, addr=None, sparse=False):
333409
"""Add a window to a subordinate bus.
334410
335-
The decoder can perform either sparse or dense address translation. If dense address
336-
translation is used (the default), the subordinate bus must have the same data width as
337-
the decoder; the window will be contiguous. If sparse address translation is used,
338-
the subordinate bus may have data width less than the data width of the decoder;
339-
the window may be discontiguous. In either case, the granularity of the subordinate bus
340-
must be equal to or less than the granularity of the decoder.
411+
See :meth:`MemoryMap.add_window` for details.
412+
413+
.. note::
414+
415+
The :class:`Decoder` can perform either *sparse* or *dense* address translation:
416+
417+
- If dense address translation is used (the default), the subordinate bus must have
418+
the same data width as the :class:`Decoder`; the window will be contiguous.
419+
- If sparse address translation is used, the subordinate bus may have data width less
420+
than the data width of the :class:`Decoder`; the window may be discontiguous.
421+
422+
In either case, the granularity of the subordinate bus must be equal to or less than
423+
the granularity of the :class:`Decoder`.
341424
342-
See :meth:`MemoryMap.add_resource` for details.
425+
.. todo:: include exceptions raised in :meth:`MemoryMap.add_window`
426+
427+
Returns
428+
-------
429+
:class:`tuple` of (:class:`int`, :class:`int`, :class:`int`)
430+
A tuple ``(start, end, ratio)`` describing the address range assigned to the window.
431+
When bridging buses of unequal data width, ``ratio`` is the amount of contiguous
432+
addresses on the narrower bus that are accessed for each transaction on the wider bus.
433+
Otherwise, it is always 1.
434+
435+
Raises
436+
------
437+
:exc:`TypeError`
438+
If the subordinate bus is not an instance of :class:`Interface`.
439+
:exc:`ValueError`
440+
If the subordinate bus granularity is greater than the :class:`Decoder` granularity.
441+
:exc:`ValueError`
442+
If dense address translation is used and the subordinate bus data width is not equal
443+
to the :class:`Decoder` data width.
444+
:exc:`ValueError`
445+
If sparse address translation is used and the subordinate bus data width is not the
446+
equal to the subordinate bus granularity.
447+
:exc:`ValueError`
448+
If the subordinate bus as an optional output signal that is not present in the
449+
:class:`Decoder` interface.
343450
"""
344451
if isinstance(sub_bus, wiring.FlippedInterface):
345452
sub_bus_unflipped = flipped(sub_bus)
@@ -425,15 +532,15 @@ class Arbiter(wiring.Component):
425532
426533
A round-robin arbiter for initiators accessing a shared Wishbone bus.
427534
428-
Parameters
429-
----------
430-
addr_width : int
535+
Arguments
536+
---------
537+
addr_width : :class:`int`
431538
Address width. See :class:`Signature`.
432-
data_width : int
539+
data_width : :class:`int`
433540
Data width. See :class:`Signature`.
434-
granularity : int
541+
granularity : :class:`int`
435542
Granularity. See :class:`Signature`
436-
features : iter(:class:`Feature`)
543+
features : iterable of :class:`Feature`
437544
Optional signal set. See :class:`Signature`.
438545
439546
Attributes
@@ -449,9 +556,19 @@ def __init__(self, *, addr_width, data_width, granularity=None, features=frozens
449556
def add(self, intr_bus):
450557
"""Add an initiator bus to the arbiter.
451558
452-
The initiator bus must have the same address width and data width as the arbiter. The
453-
granularity of the initiator bus must be greater than or equal to the granularity of
454-
the arbiter.
559+
Raises
560+
------
561+
:exc:`TypeError`
562+
If iniatator bus is not an instance of :class:`Interface`.
563+
:exc:`ValueError`
564+
If the initiator bus address width is not equal to the :class:`Arbiter` address width.
565+
:exc:`ValueError`
566+
If the initiator bus granularity is lesser than the :class:`Arbiter` granularity.
567+
:exc:`ValueError`
568+
If the initiator bus data width is not equal to the :class:`Arbiter` data width.
569+
:exc:`ValueError`
570+
If the :class:`Arbiter` has an optional output signal that is not present in the
571+
initiator bus.
455572
"""
456573
if not isinstance(intr_bus, Interface):
457574
raise TypeError(f"Initiator bus must be an instance of wishbone.Interface, not "

docs/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ System on Chip toolkit
66
This manual is a work in progress and is seriously incomplete!
77

88
.. toctree::
9-
:maxdepth: 1
9+
:maxdepth: 2
1010

1111
memory
12+
wishbone/bus

0 commit comments

Comments
 (0)