Dear Alex,
The template functions are based so-called “closures”, where a closure is a function that returns a function while storing the variable status at time of function creation.
In Nazca we try to identify these closures with the Tp_ prefix in the function name. Initially, the idea was to create these Tp_ functions for building blocks and reuse the Tp_ functions across foundries. When dealing with 10s of PDKs, however, it becomes a less ideal to reuse these building block templates, because updating a function template for one PDK would not be disconnected from other PDKs. In Nazca we prefer, in contrast, a workflow where PDKs are updated independently from each other. The specific PDK building block template functions should be considered as examples that you hardcopy and adapt for your specific use case.
def Tp_test(a='hello'):
b = "Monday"
def say_stuff(a=a, b=b, c=3):
message = f"I say {a} to {b} {c} times"
return message
return say_stuff
# Create and initialize a function using the template:
F1 = Tp_test()
F2 = Tp_test(a='good day')
# Use the function like any other normal function:
print( F1() )
print( F1(b='Tuesday') )
print( F1(b='Tuesday', c=5) )
print( F2() )
print( F2(b='Wednesday') )
# output:
I say hello to Monday 3 times
I say hello to Tuesday 3 times
I say hello to Tuesday 5 times
I say good day to Monday 3 times
I say good day to Wednesday 3 times
For creating GDS cells, PDK template functions all return a function (like F1 and F2 above) which on its turn returns a Cell object. In the example above the closures F1 and F2 return a string object that can be printed. If F1 and F2 return a Cell, you can put it. Parameter a and b can be used to initialize your closure, in the case of a design with e.g. geometry or xsection settings.
Ronald