Skip to content

Instantly share code, notes, and snippets.

@olofk
Created February 3, 2022 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olofk/a31e94c834e3de6cb20c5424cd27e7bb to your computer and use it in GitHub Desktop.
Save olofk/a31e94c834e3de6cb20c5424cd27e7bb to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import io
import os
import shutil
import sys
import tarfile
import urllib.request
class Symbiflow:
def __init__(self, cache_root):
self.cache_root = cache_root
def is_cached(self, name):
#Get link to package
linkname=f"symbiflow-{name}_test-latest"
url = f"https://storage.googleapis.com/symbiflow-arch-defs-gha/"
with urllib.request.urlopen(url+linkname) as f:
linkfile = f.read()
#Got link. If local linkfile exists and is equal to the one just downloaded
# we assume to be up to date
cached_link_file = os.path.join(cache_root, linkname)
uptodate = False
if os.path.exists(cached_link_file) and linkfile == open(cached_link_file,'rb').read():
uptodate = True
else:
#Link file is not up to date. Use downloaded as new link file
open(cached_link_file, 'wb').write(linkfile)
self.linkfile = linkfile
return uptodate
def download(self, name):
with urllib.request.urlopen(self.linkfile.decode('utf8')) as f2:
xzfile = io.BytesIO(f2.read())
t = tarfile.open(fileobj=xzfile)
t.extractall(self.cache_root)
def location(self, name):
#Output path to files
#TODO: Path to individual files, or is dir enough?
return os.path.join(self.cache_root, 'share','symbiflow','arch',name+'_test')
class Sky130:
def __init__(self, cache_root):
self.cache_root = cache_root
def is_cached(name):
pass
#FIXME: There seems to be a nodeinfo.json we can parse to check versions of downloaded libs
def download(name):
pass
#Figure out how to use github's api for fetching artifacts or store them somewhere else
#If github, extract the zip to get the bz2 file. Extract that into cache_root/sky130a
def location(name):
return "No idea"
vendors = {
'symbiflow' : Symbiflow,
'sky130' : Sky130,
}
if __name__ == "__main__":
#TODO: Option to override cache dir
xdg_cache_home = os.environ.get("XDG_CACHE_HOME") or os.path.join(
os.path.expanduser("~"), ".cache"
)
pdk_config_root = os.path.join(xdg_cache_home, "pdk-config")
#TODO: Does this make sense or should we print help usage when we get
#called without args?
if len(sys.argv)<2:
print(os.path.join(pdk_config_root))
exit(0)
#TODO: Sanity check inputs
#Current format is e.g. symbiflow:xc7a100t or sky130:fd_sc_hd. Should we go for
#VLNV directly instead? e.g. symbiflow:xilinx:xc7a100t:0.1 or skywater:sky130:fd_sc_hd
parts = sys.argv[1].split(':')
if len(parts) == 1:
vendor = parts[0]
elif len(parts) == 2:
[vendor, name] = parts
else:
print("Syntax error")
exit(1)
if not vendor in vendors:
print("Unknown vendor. Valid vendors are "+", ".join(vendors))
exit(1)
cache_root = os.path.join(pdk_config_root, vendor)
#Print vendor's root dir
if len(parts) == 1:
print(cache_root)
exit(0)
backend = vendors[vendor](cache_root)
os.makedirs(cache_root, exist_ok=True)
if not backend.is_cached(name):
backend.download(name)
print(backend.location(name))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment