1
1
from collections import defaultdict
2
2
from amaranth import *
3
- from amaranth .lib import enum , wiring
3
+ from amaranth .lib import enum , wiring , meta
4
4
from amaranth .lib .wiring import In , Out , flipped
5
5
from amaranth .utils import ceil_log2
6
6
7
7
from ..memory import MemoryMap
8
8
9
9
10
- __all__ = ["Element" , "Signature" , "Interface" , "Decoder" , "Multiplexer" ]
10
+ __all__ = ["Element" , "Signature" , "Annotation" , " Interface" , "Decoder" , "Multiplexer" ]
11
11
12
12
13
13
class Element (wiring .PureInterface ):
@@ -113,6 +113,32 @@ def create(self, *, path=None, src_loc_at=0):
113
113
"""
114
114
return Element (self .width , self .access , path = path , src_loc_at = 1 + src_loc_at )
115
115
116
+ def annotations (self , element , / ):
117
+ """Get annotations of a compatible CSR element.
118
+
119
+ Parameters
120
+ ----------
121
+ element : :class:`Element`
122
+ A CSR element compatible with this signature.
123
+
124
+ Returns
125
+ -------
126
+ iterator of :class:`meta.Annotation`
127
+ Annotations attached to ``element``.
128
+
129
+ Raises
130
+ ------
131
+ :exc:`TypeError`
132
+ If ``element`` is not an :class:`Element` object.
133
+ :exc:`ValueError`
134
+ If ``element.signature`` is not equal to ``self``.
135
+ """
136
+ if not isinstance (element , Element ):
137
+ raise TypeError (f"Element must be a csr.Element object, not { element !r} " )
138
+ if element .signature != self :
139
+ raise ValueError (f"Element signature is not equal to this signature" )
140
+ return (* super ().annotations (element ), Element .Annotation (element .signature ))
141
+
116
142
def __eq__ (self , other ):
117
143
"""Compare signatures.
118
144
@@ -125,6 +151,64 @@ def __eq__(self, other):
125
151
def __repr__ (self ):
126
152
return f"csr.Element.Signature({ self .members !r} )"
127
153
154
+ class Annotation (meta .Annotation ):
155
+ schema = {
156
+ "$schema" : "https://json-schema.org/draft/2020-12/schema" ,
157
+ "$id" : "https://amaranth-lang.org/schema/amaranth-soc/0.1/csr/element.json" ,
158
+ "type" : "object" ,
159
+ "properties" : {
160
+ "width" : {
161
+ "type" : "integer" ,
162
+ "minimum" : 0 ,
163
+ },
164
+ "access" : {
165
+ "enum" : ["r" , "w" , "rw" ],
166
+ },
167
+ },
168
+ "additionalProperties" : False ,
169
+ "required" : [
170
+ "width" ,
171
+ "access" ,
172
+ ],
173
+ }
174
+
175
+ """Peripheral-side CSR signature annotation.
176
+
177
+ Parameters
178
+ ----------
179
+ origin : :class:`Element.Signature`
180
+ The signature described by this annotation instance.
181
+
182
+ Raises
183
+ ------
184
+ :exc:`TypeError`
185
+ If ``origin`` is not a :class:`Element.Signature`.
186
+ """
187
+ def __init__ (self , origin ):
188
+ if not isinstance (origin , Element .Signature ):
189
+ raise TypeError (f"Origin must be a csr.Element.Signature object, not { origin !r} " )
190
+ self ._origin = origin
191
+
192
+ @property
193
+ def origin (self ):
194
+ return self ._origin
195
+
196
+ def as_json (self ):
197
+ """Translate to JSON.
198
+
199
+ Returns
200
+ -------
201
+ :class:`dict`
202
+ A JSON representation of :attr:`~Element.Annotation.origin`, describing its width
203
+ and access mode.
204
+ """
205
+ instance = {
206
+ "width" : self .origin .width ,
207
+ "access" : self .origin .access .value ,
208
+ }
209
+ self .validate (instance )
210
+ return instance
211
+
128
212
"""Peripheral-side CSR interface.
129
213
130
214
A low-level interface to a single atomically readable and writable register in a peripheral.
@@ -244,6 +328,35 @@ def create(self, *, path=None, src_loc_at=0):
244
328
return Interface (addr_width = self .addr_width , data_width = self .data_width ,
245
329
path = path , src_loc_at = 1 + src_loc_at )
246
330
331
+ def annotations (self , interface , / ):
332
+ """Get annotations of a compatible CSR bus interface.
333
+
334
+ Parameters
335
+ ----------
336
+ interface : :class:`Interface`
337
+ A CSR bus interface compatible with this signature.
338
+
339
+ Returns
340
+ -------
341
+ iterator of :class:`meta.Annotation`
342
+ Annotations attached to ``interface``.
343
+
344
+ Raises
345
+ ------
346
+ :exc:`TypeError`
347
+ If ``interface`` is not an :class:`Interface` object.
348
+ :exc:`ValueError`
349
+ If ``interface.signature`` is not equal to ``self``.
350
+ """
351
+ if not isinstance (interface , Interface ):
352
+ raise TypeError (f"Interface must be a csr.Interface object, not { interface !r} " )
353
+ if interface .signature != self :
354
+ raise ValueError (f"Interface signature is not equal to this signature" )
355
+ annotations = [* super ().annotations (interface ), Annotation (interface .signature )]
356
+ if interface ._memory_map is not None :
357
+ annotations .append (interface ._memory_map .annotation )
358
+ return annotations
359
+
247
360
def __eq__ (self , other ):
248
361
"""Compare signatures.
249
362
@@ -257,6 +370,66 @@ def __repr__(self):
257
370
return f"csr.Signature({ self .members !r} )"
258
371
259
372
373
+ class Annotation (meta .Annotation ):
374
+ schema = {
375
+ "$schema" : "https://json-schema.org/draft/2020-12/schema" ,
376
+ "$id" : "https://amaranth-lang.org/schema/amaranth-soc/0.1/csr/bus.json" ,
377
+ "type" : "object" ,
378
+ "properties" : {
379
+ "addr_width" : {
380
+ "type" : "integer" ,
381
+ "minimum" : 0 ,
382
+ },
383
+ "data_width" : {
384
+ "type" : "integer" ,
385
+ "minimum" : 0 ,
386
+ },
387
+ },
388
+ "additionalProperties" : False ,
389
+ "required" : [
390
+ "addr_width" ,
391
+ "data_width" ,
392
+ ],
393
+ }
394
+
395
+ """CPU-side CSR signature annotation.
396
+
397
+ Parameters
398
+ ----------
399
+ origin : :class:`Signature`
400
+ The signature described by this annotation instance.
401
+
402
+ Raises
403
+ ------
404
+ :exc:`TypeError`
405
+ If ``origin`` is not a :class:`Signature`.
406
+ """
407
+ def __init__ (self , origin ):
408
+ if not isinstance (origin , Signature ):
409
+ raise TypeError (f"Origin must be a csr.Signature object, not { origin !r} " )
410
+ self ._origin = origin
411
+
412
+ @property
413
+ def origin (self ):
414
+ return self ._origin
415
+
416
+ def as_json (self ):
417
+ """Translate to JSON.
418
+
419
+ Returns
420
+ -------
421
+ :class:`dict`
422
+ A JSON representation of :attr:`~Annotation.origin`, describing its address width
423
+ and data width.
424
+ """
425
+ instance = {
426
+ "addr_width" : self .origin .addr_width ,
427
+ "data_width" : self .origin .data_width ,
428
+ }
429
+ self .validate (instance )
430
+ return instance
431
+
432
+
260
433
class Interface (wiring .PureInterface ):
261
434
"""CPU-side CSR interface.
262
435
0 commit comments