11# amaranth: UnusedElaboratable=no
22
33# SPDX-License-Identifier: BSD-2-Clause
4+ import copy
45import logging
56import os
67import re
@@ -71,23 +72,31 @@ def elaborate(self, platform):
7172class SiliconPlatformPort (io .PortLike ):
7273 def __init__ (self ,
7374 name : str ,
74- port_desc : PortDesc ,
75- * ,
76- invert : bool = False ):
75+ port_desc : PortDesc ):
7776 self ._port_desc = port_desc
78- self ._invert = invert
79- self ._name = name
8077 width = port_desc .width
8178
79+ if 'invert' in port_desc .iomodel :
80+ if isinstance (port_desc .iomodel ['invert' ], bool ):
81+ self ._invert = [port_desc .iomodel ['invert' ]]* width
82+ else :
83+ self ._invert = port_desc .iomodel ['invert' ]
84+ else :
85+ self ._invert = [False ]* width
86+
87+ self ._name = name
88+
8289 # Initialize signal attributes to None
8390 self ._i = None
8491 self ._ie = None
8592 self ._o = None
8693 self ._oe = None
94+ self ._ie = None
8795
8896 # Create signals based on direction
8997 if self .direction in (io .Direction .Input , io .Direction .Bidir ):
90- self ._i = Signal (self ._port_desc .width , name = f"{ self ._name } __i" )
98+ self ._i = Signal (width , name = f"{ self ._name } $i" )
99+ self ._ie = Signal (width , name = f"{ self ._name } $inp_dis" , init = - 1 )
91100 if self .direction in (io .Direction .Output , io .Direction .Bidir ):
92101 self ._o = Signal (width , name = f"{ self ._name } $o" )
93102
@@ -104,17 +113,13 @@ def __init__(self,
104113 self ._oes = Signal (width , name = f"{ self ._name } $oe" , init = init_oe )
105114 self ._oe = self ._oes
106115
107- elif self .direction is io .Direction .Output :
108- # Always create an _oe for output ports
109- self ._oe = Signal (1 , name = f"{ self ._name } __oe" , init = - 1 )
110-
111- logger .debug (f"Created SiliconPlatformPort { self ._name } , invert={ invert } with port description:\n { pformat (self ._port_desc )} " )
116+ logger .debug (f"Created SiliconPlatformPort { self ._name } , with port description:\n { pformat (self ._port_desc )} " )
112117
113118 def wire (self , m : Module , interface : PureInterface ):
114119 assert self .direction == interface .signature .direction #type: ignore
115120 if hasattr (interface , '_i' ):
116121 m .d .comb += interface .i .eq (self .i ) # type: ignore
117- for d in ['_o' , '_oe' ]:
122+ for d in ['_o' , '_oe' , '_ie' ]:
118123 if hasattr (interface , d ):
119124 m .d .comb += getattr (self , d ).eq (getattr (interface , d ))
120125 # wire user side _oe to _oes if necessary
@@ -134,6 +139,21 @@ def instantiate_toplevel(self):
134139 ports .append ((f"io${ self ._name } $oe" , self ._oe , PortDirection .Output ))
135140 return ports
136141
142+ def wire_up (self , m , wire ):
143+ inv_mask = sum (inv << bit for bit , inv in enumerate (self .invert ))
144+ if hasattr (wire , 'i' ):
145+ m .d .comb += wire .i .eq (self .i ^ inv_mask )
146+ if hasattr (wire , 'o' ):
147+ m .d .comb += self .o .eq (wire .o ^ inv_mask )
148+ if hasattr (wire , 'oe' ):
149+ m .d .comb += self .oe .eq (wire .oe )
150+
151+ if hasattr (wire , 'ie' ):
152+ m .d .comb += self .ie .eq (wire .ie )
153+ elif hasattr (wire , 'oe' ):
154+ m .d .comb += self .ie .eq (wire .oe )
155+
156+
137157 @property
138158 def name (self ) -> str :
139159 return self ._name
@@ -168,6 +188,13 @@ def oe(self):
168188 "output enable signal" )
169189 return self ._oe
170190
191+ @property
192+ def ie (self ):
193+ if self ._ie is None :
194+ raise AttributeError ("SiliconPlatformPort with input direction does not have an "
195+ "input enable signal" )
196+ return self ._ie
197+
171198 @property
172199 def direction (self ):
173200 return self ._port_desc .iomodel ['direction' ]
@@ -195,14 +222,16 @@ def __getitem__(self, key):
195222 return NotImplemented
196223
197224 def __invert__ (self ):
198- result = SiliconPlatformPort (self ._name , self ._port_desc , invert = not self .invert )
225+ new_port_desc = copy .deepcopy (self ._port_desc )
226+ new_port_desc .iomodel ['invert' ] = tuple ([ not i for i in self .invert ])
227+ result = SiliconPlatformPort (self ._name , new_port_desc )
199228 return result
200229
201230 def __add__ (self , other ):
202231 return NotImplemented
203232
204233 def __repr__ (self ):
205- return (f"SiliconPlatformPort(name={ self ._name } , invert= { self . _invert } , iomode ={ self .iomodel } )" )
234+ return (f"SiliconPlatformPort(name={ self ._name } , iomodel ={ self .iomodel } )" )
206235
207236
208237class Sky130Port (SiliconPlatformPort ):
@@ -243,26 +272,24 @@ class Sky130Port(SiliconPlatformPort):
243272 # TODO: slew rate, hold points
244273 def __init__ (self ,
245274 name : str ,
246- port_desc : PortDesc ,
247- * ,
248- invert : bool = False ):
249- super ().__init__ (name , port_desc , invert = invert )
275+ port_desc : PortDesc ):
276+ super ().__init__ (name , port_desc )
250277
251278 width = port_desc .width
252279
253280 # keep a list of signals we create
254281 self ._signals = []
255282
256- # Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie ``)
283+ # Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie_n ``)
257284 self ._oe_n = None
258- self ._ie = None
259285
260286 if self ._oe is not None :
261287 self ._oe_n = Signal (self ._oe .shape ().width , name = f"{ self ._name } $oeb" )
262288 self ._signals .append ((self ._oe_n , PortDirection .Output ))
263- if self ._i is not None :
264- self ._ie = Signal (self ._i .shape ().width , name = f"{ self ._name } $inp_dis" )
265- self ._signals .append ((self ._ie , PortDirection .Output ))
289+
290+ if self ._ie is not None :
291+ self ._ie_n = Signal (self ._ie .shape ().width , name = f"{ self ._name } $inp_dis" )
292+ self ._signals .append ((self ._ie_n , PortDirection .Output ))
266293
267294 # Port Configuration
268295 # Input voltage trip level
@@ -318,12 +345,19 @@ def instantiate_toplevel(self):
318345 ports .append ((f"io${ s .name } " , s , d ))
319346 return ports
320347
321- @property
322- def ie (self ):
323- if self ._ie is None :
324- raise AttributeError ("SiliconPlatformPort with input direction does not have an "
325- "input enable signal" )
326- return self ._ie
348+ def wire_up (self , m , wire ):
349+ super ().wire_up (m , wire )
350+ # wire up oe_n = ~oe
351+ if self ._oe is not None :
352+ assert self ._oe_n is not None
353+ m .d .comb += self ._oe_n .eq (~ self ._oe )
354+
355+ if self ._ie is not None :
356+ assert self ._ie_n is not None
357+ m .d .comb += self ._ie_n .eq (~ self ._ie )
358+
359+ if hasattr (wire , 'drive_mode' ):
360+ m .d .comb += self .drive_mode .eq (wire .drive_mode )
327361
328362 @property
329363 def drive_mode (self ):
@@ -334,11 +368,13 @@ def drive_mode(self):
334368 #TODO: trip selection
335369
336370 def __invert__ (self ):
337- result = Sky130Port (self ._name , self ._port_desc , invert = not self .invert )
371+ new_port_desc = copy .deepcopy (self ._port_desc )
372+ new_port_desc .iomodel ['invert' ] = tuple ([ not i for i in self .invert ])
373+ result = SiliconPlatformPort (self ._name , new_port_desc )
338374 return result
339375
340376 def __repr__ (self ):
341- return (f"Sky130Port(name={ self ._name } , invert= { self . _invert } , iomode ={ self .iomodel } )" )
377+ return (f"Sky130Port(name={ self ._name } , iomodel ={ self .iomodel } )" )
342378
343379
344380
@@ -356,18 +392,17 @@ def elaborate(self, platform):
356392 raise TypeError (f"Cannot elaborate SiliconPlatform buffer with port { self .port !r} " )
357393
358394 m = Module ()
359-
395+ invert = sum ( bit << idx for idx , bit in enumerate ( self . port . invert ))
360396 if self .direction is not io .Direction .Input :
361- if self . port . invert :
397+ if invert != 0 :
362398 o_inv = Signal .like (self .o )
363- m .d .comb += o_inv .eq (~ self .o )
399+ m .d .comb += o_inv .eq (self .o ^ invert )
364400 else :
365401 o_inv = self .o
366-
367402 if self .direction is not io .Direction .Output :
368- if self . port . invert :
403+ if invert :
369404 i_inv = Signal .like (self .i )
370- m .d .comb += self .i .eq (~ i_inv )
405+ m .d .comb += self .i .eq (i_inv ^ invert )
371406 else :
372407 i_inv = self .i
373408
0 commit comments