The way SKILL++ deals with functions is a bit different than the
way traditional SKILL deals with them. In this posting I'd
like to show how to implement a design hierarchy traversal engine in
SKILL++ and use it as an introduction to SKILL++.
What is SKILL++?
SKILL++ is a subset of the SKILL language, not a separate language as
one might suppose. The term SKILL++ refers to a small but powerful
set of extensions that were made to the core SKILL language in the
mid 1990s and are now available for use in many Cadence tools. In
fact, any Cadence tool that is extensible by loading and executing
SKILL programs is a candidate for using SKILL++, including: Virtuoso,
VirtuosoXL, pipo, Assura, Dracula, PVS, Allegro-PCB, cdnsip and
probably a few more that I'm forgetting.
Basically the language features are:
By contrast, traditional SKILL offers
variables and separate names spaces (sometimes called Lisp-2) for
functions and variables. Dynamic and lexical variables are both
useful for different purposes.
What are dynamic and lexical variables?
These two kinds of variables differ semantically but not
syntactically. All variables appearing in SKILL++ code are considered
lexical while all variables appearing in traditional SKILL code are
If you are wondering what the semantic difference is:
- Dynamic variables allow SKILL expressions to control particular
values during a dynamic extent; i.e., while a function and its
children functions are pending evaluation. During this time of
pending evaluation, dynamic variables are visible globally unless
explicitly shadowed by another enclosed binding of the same name.
- Lexical variables allow functions to isolate visibility of
objects so that only a fixed set of expressions have access to the
value by name, but extend that access indefinitely -- even after the
dynamic extent of pending evaluation.
Perceptions of SKILL++
In this article, we'll ignore the SKILL++ object system and
concentrate on the first two of these capabilities -- sometimes referred
to jointly as the SKILL++
Dialect. Unfortunately, the other dialect which lives alongside
Scheme has no official marketing name. For lack of a better name,
we'll call it traditional SKILL. Hereafter, I'll just use the
term SKILL++ rather than the SKILL++ Scheme Dialect.
If you haven't started using SKILL++ yet, the basics are simpler than
you might think. If you are completely new to SKILL, you'll find
SKILL++ easy and intuitive. If you're a long time SKILL programmer,
you'll do things in SKILL++ pretty much the way you would have wanted
to 25 years ago when you started learning SKILL. That is, you've already
learned the hard way; now you can take a look at the easy way.
How to create SKILL++ code
There are several ways to indicate to the SKILL interpreter that you
want to use SKILL++ rather than traditional SKILL. One way is to end
your file names with the .ils extension for SKILL++
and .il for traditional SKILL; file.ils is
SKILL++; file.il is traditional SKILL.
Please assume all the functions in the remainder of this article are
SKILL++ by example
The first example function,
walkCvHier, is an ultra-simple
design hierarchy traversal engine. It won't work for all purposes you
might need but is good for the purpose of the examples below.
1.1: (defun walkCvHier (cv consume)
1.2: (foreach inst cv~>instances
1.3: (walkCvHier inst~>master consume))
1.4: (consume cv))
This function is a type of
function, because it takes a function as one of its arguments. It
is also possible with SKILL++ for functions to compute and create
other functions at run time according to their given arguments -- more
about this in a future article. Although it is sometimes possible to
use traditional SKILL to create higher-order functions with limited
capability, my advice is that you always use SKILL++ if you need this
How does it work? The function,
walkCvHier, steps through
the explicit cellView hierarchy such as a layout, assuming you always
want to descend into the instance master. At each step of the
hierarchy, a given function is applied. You can pass in any function
as long as that function can take a cellView as its only argument.
walkCvHier, will happily call that function
for you at each cellView found of the hierarchy, every time that
Saving the hierarchy?
Here's an example of how to use
dbSave on each cellView in the hierarchy.
2.1: (defun saveCvHier (cv)
2.2: (walkCvHier cv dbSave))
walkCvHier has a local
consume, declared on line 1.1, which it uses on
line 1.4 in the function call position
Because this is SKILL++,
consume does not refer to the
global function of that name, but since there is a local variable of
that name, that variable is used instead. The value of that variable
better be a function, else an error will occur at run-time. On line
saveCvHier function calls
this second argument. There are several important things to note here:
Reporting the hierarchy
- The reference to
dbSave on line 2.2 is NOT QUOTED.
Why? Because in SKILL++ names of global functions can be referenced
exactly as variables.
consume function is called on line 1.4 with
normal function calling syntax. Why? Because in SKILL++ you are
allowed to call global functions and local functions with the exact
- The name
consume does not need to start with a
capital letter or an underscore. It need only obey the naming rules
for local variables.
Suppose that rather than
dbSave on the hierarchy, you'd like to do
something for which there is no built-in function. For example,
suppose you want to descend a design hierarchy and report which cellViews
are found. You'll need to provide a function which will do the
reporting for one cellView. One alternative is to define a function
for this purpose, such as
3.1: (defun _reportCv (cv)
3.2: (println (list cv~>libName
3.6: (defun reportCvHier (cv)
3.7: (walkCvHier cv _reportCv))
The intent here is that
_reportCv be private and
only be used in this one place. However, because it is defined
defun (the same would be true if it were defined
procedure) it is actually available globally. Its
private status cannot be enforced. In the past, privacy has been
implemented in traditional SKILL using naming conventions and
documentation. SKILL++ provides better fixes this problem by
providing ways systematic ways for
...to be continued...
In the next posting we'll look at local functions, closures (functions
with state), and a few slightly more advanced examples using