Skip to content

Commit

Permalink
fixing autolibrary in environments where klayout (i.e. pya) is not in…
Browse files Browse the repository at this point in the history
…stalled
  • Loading branch information
atait committed Jun 15, 2019
1 parent f874598 commit 533e7f5
Showing 1 changed file with 98 additions and 89 deletions.
187 changes: 98 additions & 89 deletions lygadgets/autolibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,100 +62,109 @@ def my_argspec(function):
return args, kwargs


class WrappedPCell(pya.PCellDeclarationHelper):
''' Wraps a non-klayout PCell as a klayout PCell.
The pcell is here defined as a function with arguments.
When produce_impl is called, the cell geometry is compiled and added to this instance's cell.
The transfer of external pcell geometry is done through a temporary gds file.
I think this is not specific to phidl implementation. It just needs some function.
Oh wait, yes it is (barely) because of write_gds.
'''
generating_function = None

def kwargs_to_params(self):
''' Extracts the arguments of the generating_function and registers them as params of this object
If it is a keyword argument, the default type is detected and value added as default
'''
def kwarg_to_param(key, default=None):
self.param(key, pytype_to_PCelltype(type(default)), key, default=default)
args, kwargs = my_argspec(self.generating_function)
for arg in args:
kwarg_to_param(arg)
for key, default in kwargs.items():
kwarg_to_param(key, default)

def params_to_kwargs(self):
''' Inverse of kwargs_to_params. Converts the parameters of this instance and their chosen values
back into arguments that can be sent to the generating_function.
'''
# todo: handle non-keyword args
all_args = list()
all_kwargs = dict()
for pdecl, pval in zip(self.get_parameters(), self.get_values()):
all_kwargs[pdecl.name] = pval
return all_args, all_kwargs

def __init__(self, generating_function):
self.generating_function = generating_function
super().__init__()
self.kwargs_to_params()

def display_text_impl(self):
''' Produces a string that includes all of the parameters. This means it is unique for identical cells.
We assume that the pcells are functional in the sense that identical parameters yield identical geometry.
In this way, different pcell instances with the same arguments are correctly identified as the same cell.
# protect against missing pya
if pya is None:
class WrappedPCell(object):
def __init__(self, *args, **kwargs):
raise AttributeError('WrappedPCell requires a working installation of klayout python package')
class WrappedLibrary(object):
def __init__(self, *args, **kwargs):
raise AttributeError('WrappedLibrary requires a working installation of klayout python package')
else:
class WrappedPCell(pya.PCellDeclarationHelper):
''' Wraps a non-klayout PCell as a klayout PCell.
The pcell is here defined as a function with arguments.
When produce_impl is called, the cell geometry is compiled and added to this instance's cell.
The transfer of external pcell geometry is done through a temporary gds file.
I think this is not specific to phidl implementation. It just needs some function.
Oh wait, yes it is (barely) because of write_gds.
'''
text = self.generating_function.__name__ + '_'
for pdecl, pval in zip(self.get_parameters(), self.get_values()):
# sanitize _'s and ='s
if isinstance(pval, str):
pval.replace('_', '[_]')
pval.replace('=', '[=]')
text += '_{}={}'.format(pdecl.name, pval)
return text

def produce_impl(self):
''' Creates a fixed cell instance based on the previously specified parameters
generating_function = None

def kwargs_to_params(self):
''' Extracts the arguments of the generating_function and registers them as params of this object
If it is a keyword argument, the default type is detected and value added as default
'''
def kwarg_to_param(key, default=None):
self.param(key, pytype_to_PCelltype(type(default)), key, default=default)
args, kwargs = my_argspec(self.generating_function)
for arg in args:
kwarg_to_param(arg)
for key, default in kwargs.items():
kwarg_to_param(key, default)

def params_to_kwargs(self):
''' Inverse of kwargs_to_params. Converts the parameters of this instance and their chosen values
back into arguments that can be sent to the generating_function.
'''
# todo: handle non-keyword args
all_args = list()
all_kwargs = dict()
for pdecl, pval in zip(self.get_parameters(), self.get_values()):
all_kwargs[pdecl.name] = pval
return all_args, all_kwargs

def __init__(self, generating_function):
self.generating_function = generating_function
super().__init__()
self.kwargs_to_params()

def display_text_impl(self):
''' Produces a string that includes all of the parameters. This means it is unique for identical cells.
We assume that the pcells are functional in the sense that identical parameters yield identical geometry.
In this way, different pcell instances with the same arguments are correctly identified as the same cell.
'''
text = self.generating_function.__name__ + '_'
for pdecl, pval in zip(self.get_parameters(), self.get_values()):
# sanitize _'s and ='s
if isinstance(pval, str):
pval.replace('_', '[_]')
pval.replace('=', '[=]')
text += '_{}={}'.format(pdecl.name, pval)
return text

def produce_impl(self):
''' Creates a fixed cell instance based on the previously specified parameters
'''
# Produce the geometry
args, kwargs = self.params_to_kwargs()
phidl_Device = self.generating_function(*args, **kwargs)
# Convert phidl.Device to pya.Cell - just geometry
anyCell_to_anyCell(phidl_Device, self.cell)
# Transfer other data (ports, metadata, CML files, etc.)
pass # TODO


class WrappedLibrary(pya.Library):
''' An abstract library consisting of pya PCells that are
based on function calls that possibly involve other languages (specified in all_funcs_to_wrap)
The names of the PCells will end up being the same as the names of the functions.
Initializing the library registers it in klayout's repository of libraries.
To subclass this class, no extra methods are needed.
Just override the class attributes.
'''
# Produce the geometry
args, kwargs = self.params_to_kwargs()
phidl_Device = self.generating_function(*args, **kwargs)
# Convert phidl.Device to pya.Cell - just geometry
anyCell_to_anyCell(phidl_Device, self.cell)
# Transfer other data (ports, metadata, CML files, etc.)
pass # TODO


class WrappedLibrary(pya.Library):
''' An abstract library consisting of pya PCells that are
based on function calls that possibly involve other languages (specified in all_funcs_to_wrap)
The names of the PCells will end up being the same as the names of the functions.
Initializing the library registers it in klayout's repository of libraries.
To subclass this class, no extra methods are needed.
Just override the class attributes.
'''
tech_name = None
all_funcs_to_wrap = None
description = None
tech_name = None
all_funcs_to_wrap = None
description = None

def __init__(self):
if self.tech_name is None or self.all_funcs_to_wrap is None:
raise NotImplementedError('WrappedLibrary must be subclassed.')
def __init__(self):
if self.tech_name is None or self.all_funcs_to_wrap is None:
raise NotImplementedError('WrappedLibrary must be subclassed.')

print("Initializing '%s' Library." % self.tech_name)
print("Initializing '%s' Library." % self.tech_name)

# Not doing fixed GDS in this Library
# Not doing fixed GDS in this Library

# Create all the new klayout-format PCells
for func in self.all_funcs_to_wrap:
self.layout().register_pcell(func.__name__, WrappedPCell(func)) # generic version
# Create all the new klayout-format PCells
for func in self.all_funcs_to_wrap:
self.layout().register_pcell(func.__name__, WrappedPCell(func)) # generic version

self.register(self.tech_name)
self.register(self.tech_name)

if int(pya.Application.instance().version().split('.')[1]) > 24:
# KLayout v0.25 introduced technology variable:
self.technology = self.tech_name
if int(pya.Application.instance().version().split('.')[1]) > 24:
# KLayout v0.25 introduced technology variable:
self.technology = self.tech_name

0 comments on commit 533e7f5

Please sign in to comment.