@@ -201,29 +201,44 @@ def __call__(self, target):
201201 """
202202 return View (self , target )
203203
204- def _convert_to_int (self , value ):
205- """Convert ``value``, which may be a dict or an array of field values, to an integer using
206- the representation defined by this layout.
204+ def const (self , init ):
205+ """Convert a constant initializer to a constant.
207206
208- This method is private because Amaranth does not currently have a concept of
209- a constant initializer; this requires an RFC. It will be renamed or removed
210- in a future version.
207+ Converts ``init``, which may be a sequence or a mapping of field values, to a constant.
208+
209+ Returns
210+ -------
211+ :class:`Const`
212+ A constant that has the same value as a view with this layout that was initialized with
213+ an all-zero value and had every field assigned to the corresponding value in the order
214+ in which they appear in ``init``.
211215 """
212- if isinstance (value , Mapping ):
213- iterator = value .items ()
214- elif isinstance (value , Sequence ):
215- iterator = enumerate (value )
216+ if init is None :
217+ iterator = iter (())
218+ elif isinstance (init , Mapping ):
219+ iterator = init .items ()
220+ elif isinstance (init , Sequence ):
221+ iterator = enumerate (init )
216222 else :
217- raise TypeError ("Layout initializer must be a mapping or a sequence, not {!r}"
218- .format (value ))
223+ raise TypeError ("Layout constant initializer must be a mapping or a sequence, not {!r}"
224+ .format (init ))
219225
220226 int_value = 0
221227 for key , key_value in iterator :
222228 field = self [key ]
223- if isinstance (field .shape , Layout ):
224- key_value = field .shape ._convert_to_int (key_value )
225- int_value |= Const (key_value , Shape .cast (field .shape )).value << field .offset
226- return int_value
229+ cast_field_shape = Shape .cast (field .shape )
230+ if isinstance (field .shape , ShapeCastable ):
231+ key_value = Const .cast (field .shape .const (key_value ))
232+ if key_value .shape () != cast_field_shape :
233+ raise ValueError ("Constant returned by {!r}.const() must have the shape that "
234+ "it casts to, {!r}, and not {!r}"
235+ .format (field .shape , cast_field_shape ,
236+ key_value .shape ()))
237+ else :
238+ key_value = Const (key_value , cast_field_shape )
239+ int_value &= ~ (((1 << cast_field_shape .width ) - 1 ) << field .offset )
240+ int_value |= key_value .value << field .offset
241+ return Const (int_value , self .as_shape ())
227242
228243
229244class StructLayout (Layout ):
@@ -617,13 +632,9 @@ def __init__(self, layout, target=None, *, name=None, reset=None, reset_less=Non
617632 "the {} bit(s) wide view layout"
618633 .format (len (cast_target ), cast_layout .size ))
619634 else :
620- if reset is None :
621- reset = 0
622- else :
623- reset = cast_layout ._convert_to_int (reset )
624635 if reset_less is None :
625636 reset_less = False
626- cast_target = Signal (cast_layout , name = name , reset = reset , reset_less = reset_less ,
637+ cast_target = Signal (layout , name = name , reset = reset , reset_less = reset_less ,
627638 attrs = attrs , decoder = decoder , src_loc_at = src_loc_at + 1 )
628639 self .__orig_layout = layout
629640 self .__layout = cast_layout
@@ -774,6 +785,9 @@ def as_shape(cls):
774785 .format (cls .__module__ , cls .__qualname__ ))
775786 return cls .__layout
776787
788+ def const (cls , init ):
789+ return cls .as_shape ().const (init )
790+
777791
778792class _Aggregate (View , metaclass = _AggregateMeta ):
779793 def __init__ (self , target = None , * , name = None , reset = None , reset_less = None ,
0 commit comments