Merge pull request #1803 from KLayout/feature/issue-1790

Implemented a solution for issue #1790 (Support for recursive PCell i…
This commit is contained in:
Matthias Köfferlein
2024-07-30 18:57:34 +02:00
committed by GitHub
4 changed files with 263 additions and 30 deletions
@@ -272,6 +272,11 @@ module RBA
# of a PCell
class PCellDeclarationHelper < PCellDeclaration
# makes PCellDeclaration's "layout" method available
if ! self.method_defined?(:_layout_base)
alias_method :_layout_base, :layout
end
# import the Type... constants from PCellParameterDeclaration
PCellParameterDeclaration.constants.each do |c|
if !const_defined?(c)
@@ -290,18 +295,58 @@ module RBA
@cell = nil
@layer_param_index = []
@layers = nil
@state_stack = []
end
# provide accessors for the current layout and cell (for prod)
attr_reader :layout, :cell, :shape, :layer
attr_reader :cell, :shape, :layer
def layout
@layout || _layout_base()
end
# provide fallback accessors in case of a name clash with a
# parameter
def _layer; @layer; end
def _layout; @layout; end
def _layout; @layout || _layout_base(); end
def _cell; @cell; end
def _shape; @shape; end
# Starts an operation - pushes the state on the state stack
def start
@state_stack << [ @param_values, @param_states, @layers, @cell, @layout, @layer, @shape ]
self._reset_state
end
# Finishes an operation - pops the state from the state stack
def finish
if ! @state_stack.empty?
@param_values, @param_states, @layers, @cell, @layout, @layer, @shape = @state_stack.pop
else
self._reset_state
end
end
# Resets the state to default values
def _reset_state
@param_values = nil
@param_states = nil
@layers = nil
@layout = nil
# This should be here:
# @cell = nil
# @layer = nil
# @shape = nil
# but this would break backward compatibility of "display_text" (actually
# exploiting this bug) - fix this in the next major release.
end
# A helper method to access the nth parameter
def _get_param(nth, name)
@@ -410,11 +455,13 @@ module RBA
# implementation of display_text
def display_text(parameters)
self.start
@param_values = parameters
text = ""
begin
text = display_text_impl
ensure
@param_values = nil
self.finish
end
text
end
@@ -431,34 +478,33 @@ module RBA
# coerce parameters (make consistent)
def coerce_parameters(layout, parameters)
self.start
@param_values = parameters
@layout = layout
ret = parameters
begin
coerce_parameters_impl
ensure
@layout = nil
ret = @param_values
@param_values = nil
self.finish
end
ret
end
# parameter change callback
def callback(layout, name, states)
@param_values = nil
self.start
@param_states = states
@layout = layout
begin
callback_impl(name)
ensure
@param_states = nil
@layout = nil
self.finish
end
end
# produce the layout
def produce(layout, layers, parameters, cell)
self.start
@layers = layers
@cell = cell
@param_values = parameters
@@ -466,15 +512,13 @@ module RBA
begin
produce_impl
ensure
@layers = nil
@cell = nil
@param_values = nil
@layout = nil
self.finish
end
end
# produce a helper for can_create_from_shape
def can_create_from_shape(layout, shape, layer)
self.start
ret = false
@layout = layout
@shape = shape
@@ -482,24 +526,22 @@ module RBA
begin
ret = can_create_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
self.finish
end
ret
end
# produce a helper for parameters_from_shape
# produce a helper for transformation_from_shape
def transformation_from_shape(layout, shape, layer)
self.start
@layout = layout
@shape = shape
@layer = layer
t = nil
begin
t = transformation_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
self.finish
end
t
end
@@ -507,6 +549,7 @@ module RBA
# produce a helper for parameters_from_shape
# with this helper, the implementation can use the parameter setters
def parameters_from_shape(layout, shape, layer)
self.start
@param_values = @param_decls.map { |pd| pd.default }
@layout = layout
@shape = shape
@@ -514,11 +557,10 @@ module RBA
begin
parameters_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
ret = @param_values
self.finish
end
@param_values
ret
end
# default implementation
@@ -60,6 +60,7 @@ class _PCellDeclarationHelperMixin:
self._param_states = None
self._layer_param_index = []
self._layers = []
self._state_stack = []
# public attributes
self.layout = None
self.shape = None
@@ -129,6 +130,7 @@ class _PCellDeclarationHelperMixin:
This function delegates the implementation to self.display_text_impl
after configuring the PCellDeclaration object.
"""
self.start()
self._param_values = parameters
try:
text = self.display_text_impl()
@@ -165,6 +167,7 @@ class _PCellDeclarationHelperMixin:
"layers" are the layer indexes corresponding to the layer
parameters.
"""
self.start()
self._param_values = None
self._param_states = None
if states:
@@ -177,17 +180,39 @@ class _PCellDeclarationHelperMixin:
self._param_values = values
self._layers = layers
def start(self):
"""
Is called to prepare the environment for an operation
After the operation, "finish" must be called.
This method will push the state onto a stack, hence implementing
reentrant implementation methods.
"""
self._state_stack.append( (self._param_values, self._param_states, self._layers, self.cell, self.layout, self.layer, self.shape) )
self._reset_state()
def finish(self):
"""
Is called at the end of an implementation of a PCellDeclaration method
"""
if len(self._state_stack) > 0:
self._param_values, self._param_states, self._layers, self.cell, self.layout, self.layer, self.shape = self._state_stack.pop()
else:
self._reset_state()
def _reset_state(self):
"""
Resets the internal state
"""
self._param_values = None
self._param_states = None
self._layers = None
self._cell = None
self._layout = None
self._layer = None
self._shape = None
self.layout = super(_PCellDeclarationHelperMixin, self).layout()
# This should be here:
# self.cell = None
# self.layer = None
# self.shape = None
# but this would break backward compatibility of "display_text" (actually
# exploiting this bug) - fix this in the next major release.
def get_layers(self, parameters):
"""
@@ -255,6 +280,7 @@ class _PCellDeclarationHelperMixin:
The function delegates the implementation to can_create_from_shape_impl
after updating the state of this object with the current parameters.
"""
self.start()
self.layout = layout
self.shape = shape
self.layer = layer
@@ -271,6 +297,7 @@ class _PCellDeclarationHelperMixin:
The function delegates the implementation to transformation_from_shape_impl
after updating the state of this object with the current parameters.
"""
self.start()
self.layout = layout
self.shape = shape
self.layer = layer