@@ -25,6 +25,8 @@ def _remap_pin_assigns_list(
2525
2626 If invert_remapping is True, the remapping dict is inverted before applying.
2727 Assigns not present in the remapping dict are passed unchanged, eg for non-pin-assigns like bundle containers.
28+
29+ Internal utility.
2830 """
2931 if invert_remapping :
3032 remapping = {v : k for k , v in remapping .items ()}
@@ -60,7 +62,10 @@ def _generator_pin_dict(self) -> Dict[str, Port]:
6062
6163 For Vector-typed IO ports, this generates the subports and must be authoritative.
6264 This cannot be used with anything else that generates vector sub-ports.
63- This must be a GeneratorBlock."""
65+ This must be a GeneratorBlock.
66+
67+ Internal utility.
68+ """
6469 assert isinstance (self , GeneratorBlock )
6570
6671 pin_dict : Dict [str , Port ] = {}
@@ -93,7 +98,10 @@ def _remap_to_footprint_pinning(
9398 """Generates pinning that can be passed into a footprint, given the pin assign dict from _remap_pin_assigns_list
9499 and pin dict from _generator_pin_dict.
95100
96- This requires all pins to be assigned."""
101+ This requires all pins to be assigned.
102+
103+ Internal utility.
104+ """
97105 pinning : Dict [str , HasPassivePort ] = {}
98106
99107 for name , assign in pin_assigns .items ():
@@ -109,7 +117,10 @@ def _remap_to_footprint_pinning(
109117 @staticmethod
110118 def _remap_assigns_to_value (assigns : Dict [str , Tuple [Optional [str ], Optional [str ]]]) -> List [str ]:
111119 """Given a dict of pin assigns from _remap_pinning_assigns, returns a list of assign strings
112- for use in self.actual_pin_assigns"""
120+ for use in self.actual_pin_assigns.
121+
122+ Internal utility.
123+ """
113124 pin_assigns : List [str ] = []
114125 for name , assign in assigns .items ():
115126 if assign [0 ] is not None and assign [1 ] is not None :
@@ -137,3 +148,42 @@ def _make_pinning(
137148 fixed_pinning .update (self ._remap_to_footprint_pinning (remapped_pin_assigns , pin_dict ))
138149 self .assign (self .actual_pin_assigns , self ._remap_assigns_to_value (remapped_pin_assigns ))
139150 return fixed_pinning
151+
152+
153+ class BaseIoControllerWrapper (BaseIoController ):
154+ """Base class for a block that contains a BaseIoControllerWrapped as the physical footprint
155+ as well as a non-physical device model.
156+
157+ This provides utilities to remap pin assignments from the device specification to the model.
158+ """
159+
160+ def _export_tap_ios_inner (self , inner : "BaseIoController" ) -> None :
161+ """Export-taps all IO ports from some inner BaseIoController.
162+ This must be a SubboardBlock to support the export_tap connection.
163+ This must be called in contents() or generate(), after IOs have been defined."""
164+ from ..core .Blocks import BlockElaborationState
165+
166+ assert isinstance (self , WrapperSubboardBlock )
167+ assert self ._elaboration_state in (
168+ BlockElaborationState .contents ,
169+ BlockElaborationState .generate ,
170+ ), "can only run in contents() or generate()"
171+
172+ inner_ios_by_type = {self ._type_of_io (io_port ): io_port for io_port in inner ._io_ports }
173+ for self_io in self ._io_ports :
174+ self_io_type = self ._type_of_io (self_io )
175+ assert self_io_type in inner_ios_by_type , f"inner missing IO of type { self_io_type } "
176+ inner_io = inner_ios_by_type [self_io_type ]
177+ self .export_tap (self_io , inner_io )
178+
179+ def _make_model_pinning (self , remapping : Dict [str , str ], device_assigns : List [str ]) -> List [str ]:
180+ """Remaps my own assigns (pinned in device-space) to model-space.
181+
182+ Requires _generator_param_all_ios, so all the IOs names are available.
183+ """
184+
185+ BaseIoControllerWrapped ._remap_assigns_to_value (
186+ BaseIoControllerWrapped ._remap_pin_assigns_list (
187+ Xiao_Rp2040_Device ._PIN_REMAPPING , self .get (self .pin_assigns ), invert_remapping = True
188+ )
189+ ),
0 commit comments