Skip to content

Commit 139c002

Browse files
committed
csr.reg: defer Field creation until Register.__init__().
Before this commit, a Register whose fields were variable annotations couldn't be instantiated more than once, as the latter belonged to the global scope. The Field class is now a factory for user-defined field components, instead of a base class. Every FieldMap or FieldArray sharing a Field will use a different instance of its component, obtained from Field.create(). Also: * update to follow RFCs 37 and 38 * docstring and diagnostics improvements.
1 parent 4b60d22 commit 139c002

File tree

3 files changed

+661
-399
lines changed

3 files changed

+661
-399
lines changed

amaranth_soc/csr/field.py

Lines changed: 90 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,92 @@
11
from amaranth import *
2+
from amaranth.lib import wiring
3+
from amaranth.lib.wiring import In, Out
24

3-
from .reg import Field
5+
from .reg import FieldPort
46

57

68
__all__ = ["R", "W", "RW", "RW1C", "RW1S"]
79

810

9-
class R(Field):
10-
__doc__ = Field._doc_template.format(
11-
description="""
12-
A read-only field.
13-
""".strip(),
14-
parameters="",
15-
attributes="""
11+
class R(wiring.Component):
12+
"""A read-only field.
13+
14+
Parameters
15+
----------
16+
shape : :ref:`shape-castable <lang-shapecasting>`
17+
Shape of the field.
18+
19+
Interface attributes
20+
--------------------
21+
port : :class:`FieldPort`
22+
Field port.
1623
r_data : Signal(shape)
1724
Read data. Drives the :attr:`~FieldPort.r_data` signal of ``port``.
18-
""".strip())
19-
25+
"""
2026
def __init__(self, shape):
21-
super().__init__(shape, access="r")
22-
self.r_data = Signal(shape)
27+
super().__init__({
28+
"port": In(FieldPort.Signature(shape, access="r")),
29+
"r_data": In(shape),
30+
})
2331

2432
def elaborate(self, platform):
2533
m = Module()
2634
m.d.comb += self.port.r_data.eq(self.r_data)
2735
return m
2836

2937

30-
class W(Field):
31-
__doc__ = Field._doc_template.format(
32-
description="""
33-
A write-only field.
34-
""".strip(),
35-
parameters="",
36-
attributes="""
38+
class W(wiring.Component):
39+
"""A write-only field.
40+
41+
Parameters
42+
----------
43+
shape : :ref:`shape-castable <lang-shapecasting>`
44+
Shape of the field.
45+
46+
Interface attributes
47+
--------------------
48+
port : :class:`FieldPort`
49+
Field port.
3750
w_data : Signal(shape)
3851
Write data. Driven by the :attr:`~FieldPort.w_data` signal of ``port``.
39-
""".strip())
40-
52+
"""
4153
def __init__(self, shape):
42-
super().__init__(shape, access="w")
43-
self.w_data = Signal(shape)
54+
super().__init__({
55+
"port": In(FieldPort.Signature(shape, access="w")),
56+
"w_data": Out(shape),
57+
})
4458

4559
def elaborate(self, platform):
4660
m = Module()
4761
m.d.comb += self.w_data.eq(self.port.w_data)
4862
return m
4963

5064

51-
class RW(Field):
52-
__doc__ = Field._doc_template.format(
53-
description="""
54-
A read/write field with built-in storage.
65+
class RW(wiring.Component):
66+
"""A read/write field with built-in storage.
5567
5668
Storage is updated with the value of ``port.w_data`` one clock cycle after ``port.w_stb`` is
5769
asserted.
58-
""".strip(),
59-
parameters="""
70+
71+
Parameters
72+
----------
73+
shape : :ref:`shape-castable <lang-shapecasting>`
74+
Shape of the field.
6075
reset : :class:`int`
6176
Storage reset value.
62-
""",
63-
attributes="""
77+
78+
Interface attributes
79+
--------------------
80+
port : :class:`FieldPort`
81+
Field port.
6482
data : Signal(shape)
6583
Storage output.
66-
""".strip())
67-
84+
"""
6885
def __init__(self, shape, *, reset=0):
69-
super().__init__(shape, access="rw")
70-
self.data = Signal(shape)
86+
super().__init__({
87+
"port": In(FieldPort.Signature(shape, access="rw")),
88+
"data": Out(shape),
89+
})
7190
self._storage = Signal(shape, reset=reset)
7291
self._reset = reset
7392

@@ -89,32 +108,37 @@ def elaborate(self, platform):
89108
return m
90109

91110

92-
class RW1C(Field):
93-
__doc__ = Field._doc_template.format(
94-
description="""
95-
A read/write-one-to-clear field with built-in storage.
111+
class RW1C(wiring.Component):
112+
"""A read/write-one-to-clear field with built-in storage.
96113
97114
Storage bits are:
98115
* cleared by high bits in ``port.w_data``, one clock cycle after ``port.w_stb`` is asserted;
99116
* set by high bits in ``set``, one clock cycle after they are asserted.
100117
101118
If a storage bit is set and cleared on the same clock cycle, setting it has precedence.
102-
""".strip(),
103-
parameters="""
119+
120+
Parameters
121+
----------
122+
shape : :ref:`shape-castable <lang-shapecasting>`
123+
Shape of the field.
104124
reset : :class:`int`
105125
Storage reset value.
106-
""",
107-
attributes="""
126+
127+
Interface attributes
128+
--------------------
129+
port : :class:`FieldPort`
130+
Field port.
108131
data : Signal(shape)
109132
Storage output.
110133
set : Signal(shape)
111134
Mask to set storage bits.
112-
""".strip())
113-
135+
"""
114136
def __init__(self, shape, *, reset=0):
115-
super().__init__(shape, access="rw")
116-
self.data = Signal(shape)
117-
self.set = Signal(shape)
137+
super().__init__({
138+
"port": In(FieldPort.Signature(shape, access="rw")),
139+
"data": Out(shape),
140+
"set": In(shape),
141+
})
118142
self._storage = Signal(shape, reset=reset)
119143
self._reset = reset
120144

@@ -139,31 +163,37 @@ def elaborate(self, platform):
139163
return m
140164

141165

142-
class RW1S(Field):
143-
__doc__ = Field._doc_template.format(
144-
description="""
145-
A read/write-one-to-set field with built-in storage.
166+
class RW1S(wiring.Component):
167+
"""A read/write-one-to-set field with built-in storage.
146168
147169
Storage bits are:
148170
* set by high bits in ``port.w_data``, one clock cycle after ``port.w_stb`` is asserted;
149171
* cleared by high bits in ``clear``, one clock cycle after they are asserted.
150172
151173
If a storage bit is set and cleared on the same clock cycle, setting it has precedence.
152-
""".strip(),
153-
parameters="""
174+
175+
Parameters
176+
----------
177+
shape : :ref:`shape-castable <lang-shapecasting>`
178+
Shape of the field.
154179
reset : :class:`int`
155180
Storage reset value.
156-
""",
157-
attributes="""
181+
182+
Interface attributes
183+
--------------------
184+
port : :class:`FieldPort`
185+
Field port.
158186
data : Signal(shape)
159187
Storage output.
160188
clear : Signal(shape)
161189
Mask to clear storage bits.
162-
""".strip())
190+
"""
163191
def __init__(self, shape, *, reset=0):
164-
super().__init__(shape, access="rw")
165-
self.data = Signal(shape)
166-
self.clear = Signal(shape)
192+
super().__init__({
193+
"port": In(FieldPort.Signature(shape, access="rw")),
194+
"clear": In(shape),
195+
"data": Out(shape),
196+
})
167197
self._storage = Signal(shape, reset=reset)
168198
self._reset = reset
169199

0 commit comments

Comments
 (0)