Adding version stuff.
diff --git a/scripts/python-skywater-pdk/skywater_pdk/base.py b/scripts/python-skywater-pdk/skywater_pdk/base.py
index c86cde2..65c51a7 100644
--- a/scripts/python-skywater-pdk/skywater_pdk/base.py
+++ b/scripts/python-skywater-pdk/skywater_pdk/base.py
@@ -21,15 +21,29 @@
>>> t = list(parse_filename('sky130_fd_io-top_ground_padonlyv2-tt_1p80V_3p30V_3p30V_25C.wrap.lib'))
>>> t.pop(0)
- Cell(name='top_ground_padonlyv2', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.io, name=None))
+ Cell(name='top_ground_padonlyv2', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.io, name=None, version=None))
>>> t.pop(0)
'tt_1p80V_3p30V_3p30V_25C'
>>> t.pop(0)
'wrap.lib'
+ >>> t = list(parse_filename('v0.10.0/sky130_fd_sc_hdll-a211o-tt_1p80V_3p30V_3p30V_25C.wrap.json'))
+ >>> t.pop(0)
+ Cell(name='a211o', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hdll', version=LibraryVersion(milestone=0, major=10, minor=0, commits=0, hash='')))
+ >>> t.pop(0)
+ 'tt_1p80V_3p30V_3p30V_25C'
+ >>> t.pop(0)
+ 'wrap.json'
"""
dirname, filename = os.path.split(pathname)
+
+ dirbase, dirversion = os.path.split(dirname)
+ try:
+ version = LibraryVersion.parse(dirversion)
+ except TypeError:
+ version = None
+
if '.' in filename:
basename, extension = filename.split('.', 1)
else:
@@ -37,13 +51,98 @@
extension = ''
basename = basename.replace('-', SEPERATOR)
- library, cell, extra = basename.split(SEPERATOR, 3)
- return (Cell.parse(library+SEPERATOR+cell), extra, extension)
+ bits = basename.split(SEPERATOR, 3)
+ if len(bits) in (1, 2):
+ library = Library.parse(bits.pop(0))
+ extra = ""
+ if bits:
+ extra = bits.pop(0)
+ if version:
+ library.version = version
+ elif len(bits) == 3:
+ library = Cell.parse(bits[0]+SEPERATOR+bits[1])
+ if version:
+ library.library.version = version
+ extra = bits[2]
+ else:
+ raise NotImplementedError()
+
+ return (library, extra, extension)
SEPERATOR = "__"
+@dataclass(order=True, frozen=True)
+class LibraryVersion:
+ """
+
+ >>> v0 = LibraryVersion.parse("v0.0.0")
+ >>> v0
+ LibraryVersion(milestone=0, major=0, minor=0, commits=0, hash='')
+ >>> v1a = LibraryVersion.parse("v0.0.0-10-g123abc")
+ >>> v1a
+ LibraryVersion(milestone=0, major=0, minor=0, commits=10, hash='123abc')
+ >>> v1b = LibraryVersion.parse("v0.0.0-4-g123abc")
+ >>> v1b
+ LibraryVersion(milestone=0, major=0, minor=0, commits=4, hash='123abc')
+ >>> v2 = LibraryVersion.parse("v0.0.2")
+ >>> v2
+ LibraryVersion(milestone=0, major=0, minor=2, commits=0, hash='')
+ >>> v3 = LibraryVersion.parse("v0.2.0")
+ >>> v3
+ LibraryVersion(milestone=0, major=2, minor=0, commits=0, hash='')
+ >>> v4 = LibraryVersion.parse("v0.0.10")
+ >>> v4
+ LibraryVersion(milestone=0, major=0, minor=10, commits=0, hash='')
+ >>> v0 < v1a
+ True
+ >>> v1a < v2
+ True
+ >>> v0 < v2
+ True
+ >>> l = [v1a, v2, v3, v1b, v0, v2]
+ >>> l.sort()
+ >>> [i.fullname for i in l]
+ ['0.0.0', '0.0.0-4-g123abc', '0.0.0-10-g123abc', '0.0.2', '0.0.2', '0.2.0']
+ """
+ milestone: int = 0
+ major: int = 0
+ minor: int = 0
+
+ commits: Optional[int] = 0
+ hash: Optional[str] = ''
+
+ @classmethod
+ def parse(cls, s):
+ if not s.startswith('v'):
+ raise TypeError("Unknown version: {}".format(s))
+ kw = {}
+ if '-' in s:
+ git_bits = s.split('-')
+ if len(git_bits) != 3:
+ raise TypeError("Unparsable git version: {}".format(s))
+ s = git_bits[0]
+ kw['commits'] = int(git_bits[1])
+ assert git_bits[2].startswith('g'), git_bits[2]
+ kw['hash'] = git_bits[2][1:]
+ kw['milestone'], kw['major'], kw['minor'] = (
+ int(i) for i in s[1:].split('.'))
+ return cls(**kw)
+
+ def as_tuple(self):
+ return (self.milestone, self.major, self.minor, self.commits, minor)
+
+ @property
+ def fullname(self):
+ o = []
+ s = "{}.{}.{}".format(
+ self.milestone, self.major, self.minor)
+ if self.commits:
+ s += "-{}-g{}".format(self.commits, self.hash)
+ return s
+
+
class LibraryNode(Enum):
SKY130 = "SkyWater 130nm"
@@ -119,7 +218,7 @@
>>> l = Library.parse("sky130_fd_sc_hd")
>>> l
- Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd')
+ Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=None)
>>> l.fullname
'sky130_fd_sc_hd'
>>> l.source.fullname
@@ -129,7 +228,7 @@
>>> l = Library.parse("sky130_rrr_sc_hd")
>>> l
- Library(node=LibraryNode.SKY130, source=LibrarySource('rrr'), type=LibraryType.sc, name='hd')
+ Library(node=LibraryNode.SKY130, source=LibrarySource('rrr'), type=LibraryType.sc, name='hd', version=None)
>>> l.fullname
'sky130_rrr_sc_hd'
>>> l.source.fullname
@@ -142,6 +241,7 @@
source: LibrarySource
type: LibraryType
name: Optional[str] = None
+ version: Optional[LibraryVersion] = None
@property
def fullname(self):
@@ -179,7 +279,7 @@
"""
>>> c = Cell.parse("sky130_fd_sc_hd__abc")
>>> c
- Cell(name='abc', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd'))
+ Cell(name='abc', library=Library(node=LibraryNode.SKY130, source=LibrarySource('fd'), type=LibraryType.sc, name='hd', version=None))
>>> c.fullname
'sky130_fd_sc_hd__abc'
diff --git a/scripts/python-skywater-pdk/skywater_pdk/corners.py b/scripts/python-skywater-pdk/skywater_pdk/corners.py
index 46c78de..d43c7d6 100644
--- a/scripts/python-skywater-pdk/skywater_pdk/corners.py
+++ b/scripts/python-skywater-pdk/skywater_pdk/corners.py
@@ -62,6 +62,17 @@
nointpr = 'No internal power'
lv = 'Low voltage'
ccsnoise = 'Composite Current Source Noise'
+ ns5 = '5 nanoseconds'
+ pwr = 'Power'
+
+ @classmethod
+ def parse(cls, s):
+ if s == "5ns":
+ return cls.ns5
+ elif hasattr(cls, s):
+ return getattr(cls, s)
+ else:
+ raise TypeError("Unknown CornerFlags: {}".format(s))
def __repr__(self):
return 'CornerType.'+self.name
@@ -85,10 +96,34 @@
>>> parse_filename('sky130_fd_io-top_ground_padonlyv2-tt_1p80V_3p30V_3p30V_25C.wrap.lib')
Corner(volts=[1.8, 3.3, 3.3], temps=[25], flags=[], types=[CornerType.t, CornerType.t])
+ >>> parse_filename('sky130_fd_sc_ms-tt_1p80V_100C.wrap.json')
+ Corner(volts=[1.8], temps=[100], flags=[], types=[CornerType.t, CornerType.t])
+
+ >>> parse_filename('sky130_fd_sc_ms-tt_1p80V_100C.wrap.lib')
+ Corner(volts=[1.8], temps=[100], flags=[], types=[CornerType.t, CornerType.t])
+
+ >>> parse_filename('sky130_fd_sc_ms-tt_1p80V_25C_ccsnoise.wrap.json')
+ Corner(volts=[1.8], temps=[25], flags=[CornerType.ccsnoise], types=[CornerType.t, CornerType.t])
+
+ >>> parse_filename('sky130_fd_sc_ms-wp_1p56V_n40C_5ns.wrap.json')
+ Corner(volts=[1.56], temps=[-40], flags=[CornerType.ns5], types=[CornerType.f, CornerType.s])
+
+ >>> parse_filename('sky130_fd_sc_ms-wp_1p65V_n40C.wrap.json')
+ Corner(volts=[1.65], temps=[-40], flags=[], types=[CornerType.f, CornerType.s])
+
+ >>> parse_filename('sky130_fd_sc_ms-wp_1p95V_85C_pwr.wrap.lib')
+ Corner(volts=[1.95], temps=[85], flags=[CornerType.pwr], types=[CornerType.f, CornerType.s])
+
+ >>> parse_filename('sky130_fd_sc_ms-wp_1p95V_n40C_ccsnoise.wrap.json')
+ Corner(volts=[1.95], temps=[-40], flags=[CornerType.ccsnoise], types=[CornerType.f, CornerType.s])
+
+ >>> parse_filename('sky130_fd_sc_ms-wp_1p95V_n40C_pwr.wrap.lib')
+ Corner(volts=[1.95], temps=[-40], flags=[CornerType.pwr], types=[CornerType.f, CornerType.s])
+
"""
cell, extra, extension = base_parse_filename(pathname)
- if extension not in ('', 'lib', 'wrap.lib'):
+ if extension not in ('', 'lib', 'wrap.lib', 'wrap.json'):
raise ValueError('Not possible to extract corners from: {!r}'.format(extension))
if not extra:
@@ -109,11 +144,14 @@
elif TEMP_REGEX.match(b):
assert b.endswith('C'), b
kw['temps'].append(int(b[:-1].replace('n', '-')))
- elif hasattr(CornerFlag, b):
- kw['flags'].append(getattr(CornerFlag, b))
else:
- assert 'types' not in kw, (kw, b)
- kw['types'] = CornerType.parse(b)
+ try:
+ kw['flags'].append(CornerFlag.parse(b))
+ except TypeError as e:
+ if 'types' not in kw:
+ kw['types'] = CornerType.parse(b)
+ else:
+ raise
return Corner(**kw)