11from collections import defaultdict
22from amaranth import *
3- from amaranth .lib import enum , wiring
3+ from amaranth .lib import enum , wiring , meta
44from amaranth .lib .wiring import In , Out , flipped
55from amaranth .utils import ceil_log2
66
77from ..memory import MemoryMap
88
99
10- __all__ = ["Element" , "Signature" , "Interface" , "Decoder" , "Multiplexer" ]
10+ __all__ = ["Element" , "Signature" , "Annotation" , " Interface" , "Decoder" , "Multiplexer" ]
1111
1212
1313class Element (wiring .PureInterface ):
@@ -113,6 +113,32 @@ def create(self, *, path=None, src_loc_at=0):
113113 """
114114 return Element (self .width , self .access , path = path , src_loc_at = 1 + src_loc_at )
115115
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+
116142 def __eq__ (self , other ):
117143 """Compare signatures.
118144
@@ -125,6 +151,64 @@ def __eq__(self, other):
125151 def __repr__ (self ):
126152 return f"csr.Element.Signature({ self .members !r} )"
127153
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+
128212 """Peripheral-side CSR interface.
129213
130214 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):
244328 return Interface (addr_width = self .addr_width , data_width = self .data_width ,
245329 path = path , src_loc_at = 1 + src_loc_at )
246330
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+
247360 def __eq__ (self , other ):
248361 """Compare signatures.
249362
@@ -257,6 +370,66 @@ def __repr__(self):
257370 return f"csr.Signature({ self .members !r} )"
258371
259372
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+
260433class Interface (wiring .PureInterface ):
261434 """CPU-side CSR interface.
262435
0 commit comments