Spying on commands to get precious SKILL code

S

spectrallypure

Guest
Hi all!

I would like to share an enquiry that has been twisting my mind for
some time now, and which I cannot put off any longer (for the sake of
my mental sanity!). It goes as follows...

I've heard many times that all the actions the Cadence tools receive
and process are performed internally by means of SKILL calls. This
appears mostly true to me, and for instance when one sets the log
filter with the more relaxed options, one can see all the commands in
the CIW going in and out, performing the actions required by the user.

However, I have noticed that most of the time what appears in the CIW
is not really the most low-level SKILL code of what the user does. For
instance. I know that in order to set the infix option one can use the
following code:

Code #1:
envSetVal( "ui" "infix" 'boolean t)

However, if one sets this option through the GUI, al what one gets in
the CIW (filtering relaxed to the most) is the following:

Code #2:
hiSetUserPreferences()
hiiSetCurrentForm('hiSysProps)
hiSysProps->hiSetMouseStyle->value = t
hiFormDone(hiSysProps)

Clearly, one cannot deduct from the Code #2 above what the user did,
nor reuse this code in any practical SKILL function in order to set,
like in this example, the infix mode. I suspect that in the end these
4 lines of code, along with the code regarding the GUI forms that
appear, result in the calling of other more low-level functions, like
the one in Code #1.

A second example. I know how to set bindkeys, but unfortunately the
templates and the documentation doesn't cover all the possible actions
a user can be interested in. For instance, I needed to define a
bindkey for selecting in Wavescan all the waveforms in the current
plot. I searched extensively all the template files I could possibly
find, all the documentation, and the internet, but I was unable to
determine what was the appropriate setting needed to be made. After
some guessing and by trial and error, I discovered that the following
entry worked fine:

hiSetBindKey("wavescan" "ctrl<key>a" "graph.trace.selectall")

Once again, the problem would have been resolved very easily if there
was some way of spying the SKILL code behind of what happens when one
does the GUI equivalent of this simple task (menu "Trace", option
"Select All").

Basically my question is then if it is possible to configure Cadence/
CIW/whatever in some way in order to see the code that is behind a
user action, but in a 'reusable' format. The main motivation for this
would be that then we could easily reuse the code and/or tailor it in
order to do lots of things such as defining more complex functions,
automating repetitive tasks or setting bindkey to actions for easy
access.

A) If the answer is yes, then... how can this be done?!!!

B) If the answer is no, then, how is a user supposed to determine what
is the right SKILL code/function/variable setting/etc needed to be
used in order to perform a task readily available in the GUI menus? I
mean, what is the 'official' way of learning what is the SKILL code
for a specific task (since the code for every single possible task
cannot be possibly documented, right?)?

Just two final examples to make my point (btw, I am in the need of
elucidating these two, sorry for the cheating!):

-How can I know what is the SKILL code/functions I need to call in
order to print the design variables and their values in the current
plot (i.e., to achieve the same effect of choosing in the ADE menu
"Results" the "Printing/Plotting Options" option and then setting the
"Annotations: Design Variables" checkbox)?

-How can I know what is the SKILL code that I need to put in
my .cdsinit / cdsenv in order to define a bindkey for sending the
active schematic to the plotter? OK, maybe this cannot be done
directly and one needs first to define a function and then associate a
bindkey for calling the function, but, how can I define the function
if I don't know the required code?

Well, thanks so much in advance for any help/ideas/comments/solutions;
and sorry once again for the long posts!

Regards,

Jorge Luis.
 
One essential thing of a software program is
that there might be variables to set which leads to
a special behaviour of the program and user actions
which leads also to a special behaviour.

Both setting a variable and performing an user action
can lead to the same result that's what you describe in
your first example.


Code #1:
envSetVal( "ui" "infix" 'boolean t)

This example is setting the environment variable
switch the infix on, usually this is done during the
initialization of the tool.

Code #2:
hiSetUserPreferences()
hiiSetCurrentForm('hiSysProps)
hiSysProps->hiSetMouseStyle->value = t
hiFormDone(hiSysProps)

User action, tracked by the log file.


The answer to of all your questions is
that this is a mater of experience with SKILL.
Start using it.
There are tons of documentations with in the
installation directory or just call 'cdsdoc'.
Fro every application with the Cadence DFII there are
specific SKILL commands, which you would name as low level
SKILL.

Bernd
 
I know that bugs me to that not all commands are shown in the log.
When I used Mentor you could perform what you wanted by hand then cut
and paste the commands from the log file give it a function name and
some brackets and you had the code you needed to perform that action
when desired.

Tim
 
In article <31041148-cdb4-42c9-a6dc-f35fe857ae0d@d21g2000prf.googlegroups.com> spectrallypure <jorgelagos@gmail.com> writes:
Hi all!

I would like to share an enquiry that has been twisting my mind for
some time now, and which I cannot put off any longer (for the sake of
my mental sanity!). It goes as follows...

I've heard many times that all the actions the Cadence tools receive
and process are performed internally by means of SKILL calls. This
appears mostly true to me, and for instance when one sets the log
filter with the more relaxed options, one can see all the commands in
the CIW going in and out, performing the actions required by the user.

However, I have noticed that most of the time what appears in the CIW
is not really the most low-level SKILL code of what the user does. For
instance. I know that in order to set the infix option one can use the
following code:

Code #1:
envSetVal( "ui" "infix" 'boolean t)

However, if one sets this option through the GUI, al what one gets in
the CIW (filtering relaxed to the most) is the following:

Code #2:
hiSetUserPreferences()
hiiSetCurrentForm('hiSysProps)
hiSysProps->hiSetMouseStyle->value = t
hiFormDone(hiSysProps)

Clearly, one cannot deduct from the Code #2 above what the user did,
nor reuse this code in any practical SKILL function in order to set,
like in this example, the infix mode. I suspect that in the end these
4 lines of code, along with the code regarding the GUI forms that
appear, result in the calling of other more low-level functions, like
the one in Code #1.
That's correct.

A second example. I know how to set bindkeys, but unfortunately the
templates and the documentation doesn't cover all the possible actions
a user can be interested in. For instance, I needed to define a
bindkey for selecting in Wavescan all the waveforms in the current
plot. I searched extensively all the template files I could possibly
find, all the documentation, and the internet, but I was unable to
determine what was the appropriate setting needed to be made. After
some guessing and by trial and error, I discovered that the following
entry worked fine:

hiSetBindKey("wavescan" "ctrl<key>a" "graph.trace.selectall")

Once again, the problem would have been resolved very easily if there
was some way of spying the SKILL code behind of what happens when one
does the GUI equivalent of this simple task (menu "Trace", option
"Select All").

Basically my question is then if it is possible to configure Cadence/
CIW/whatever in some way in order to see the code that is behind a
user action, but in a 'reusable' format. The main motivation for this
would be that then we could easily reuse the code and/or tailor it in
order to do lots of things such as defining more complex functions,
automating repetitive tasks or setting bindkey to actions for easy
access.
No, you cannot. What is logged is what can be replayed. If you have a
SKILL Development license, I believe you can actually see the internals of
some Skill functions, but logging is specifically a record of what was done
in order to recreate what was done. So commands that are instigated by other
commands are not logged since on replay that would result in commands being
executed multiple times during replay, and that is undesirable.

Also, not all commands are implemented in SKILL. Many commands are
implemented in C/C++ (or possibly other languages), and all that can be seen
from SKILL is the function definition, not the internals.

A) If the answer is yes, then... how can this be done?!!!

B) If the answer is no, then, how is a user supposed to determine what
is the right SKILL code/function/variable setting/etc needed to be
used in order to perform a task readily available in the GUI menus? I
mean, what is the 'official' way of learning what is the SKILL code
for a specific task (since the code for every single possible task
cannot be possibly documented, right?)?
Documentation, classes, user guides, AEs, FEs, customer support, the
user community, etc.

Just two final examples to make my point (btw, I am in the need of
elucidating these two, sorry for the cheating!):

-How can I know what is the SKILL code/functions I need to call in
order to print the design variables and their values in the current
plot (i.e., to achieve the same effect of choosing in the ADE menu
"Results" the "Printing/Plotting Options" option and then setting the
"Annotations: Design Variables" checkbox)?
Someone familiar with the ADE product will need to answer that.

-How can I know what is the SKILL code that I need to put in
my .cdsinit / cdsenv in order to define a bindkey for sending the
active schematic to the plotter? OK, maybe this cannot be done
directly and one needs first to define a function and then associate a
bindkey for calling the function, but, how can I define the function
if I don't know the required code?
I believe that can be done, but it is not straightforward. The problem is
that there are many variables/options that need to be set to do this (I'm
assuming you want a bindkey that does all this without having to interact
with the plotting forms).

-Pete Zakel
(phz@seeheader.nospam)

"Natural selection won't matter soon, not anywhere as much as concious
selection. We will civilize and alter ourselves to suit our ideas of what
we can be. Within one more human lifespan, we will have changed ourselves
unrecognizably."
-Greg Bear
 
In article <31041148-cdb4-42c9-a6dc-f35fe857ae0d@d21g2000prf.googlegroups.com> spectrallypure <jorgelagos@gmail.com> writes:

However, I have noticed that most of the time what appears in the CIW
is not really the most low-level SKILL code of what the user does. For
instance. I know that in order to set the infix option one can use the
following code:

Code #1:
envSetVal( "ui" "infix" 'boolean t)

However, if one sets this option through the GUI, al what one gets in
the CIW (filtering relaxed to the most) is the following:

Code #2:
hiSetUserPreferences()
hiiSetCurrentForm('hiSysProps)
hiSysProps->hiSetMouseStyle->value = t
hiFormDone(hiSysProps)
One other thing. The two code snippets above are demonstrations of two
different ways to do the same thing.

Code snippet #1 will, as a side effect, change the value of the hiSysProps
hiSetMouseStyle field.

Code snippet #2 will, as a side effect, change the value of the ui.infix
envvar.

For better or for worse, when DFII was architected many years ago, this style
of logging and replay was selected, and it is difficult to change.

Logging is a reflection of what actions the user took, with GUI actions being
logged as GUI actions (Code #2) and code entry actions being logged as code
entry actions (Code #1). The idea was that for debugging purposes, the log
file could be replayed in order to achieve the same states and actions as
was performed by the user, and thus bugs in the software could more easily
be reproduced, and thus more easily fixed.

Also note that there may be more of what goes to the log file than appears in
the CIW, even with everything turned on in the log filter. The CIW output is
a filtered representation of what goes into the CDS.log file.

-Pete Zakel
(phz@seeheader.nospam)

"The Tree of Learning bears the noblest fruit, but noble fruit tastes bad."
 
Thanks so much for the valuable comments! I think I now understand
better the nature of the problem...

Since I am a fierce fan of the proverb that says 'it's better to teach
a man how to fish, than to give him fish", I would like then to change
my original enquiry and turn it into a survey, in order to benefit
this way from the advice of the more experienced people in the forum.
In other words, I would like you to tell me how would you find out the
required technical information (i.e. the SKILL code) needed to solve,
for instance, the two sample problems that I posted.

So, the question now would be as follows:

If you were to figure out the two following sample problems:

P1. Find out what is the SKILL code needed to run in order to print
the design variables and their values in the current plot (i.e., to
achieve the same effect of choosing in the ADE menu "Results" the
"Printing/Plotting Options" option and then setting the "Annotations:
Design Variables" checkbox).
P2. Find out what is the SKILL code needed to put in the .cdsinit /
cdsenv files in order to define a bindkey for sending the active
schematic to the plotter (i.e., to achieve the same effect of choosing
in the ADE menu "Design" the "Plot->Submit" option and then clicking
"OK").

...what would be your chosen course of action, given the following
restrictions:

R1. You are a third-world academic user: i.e. you have no technical
support whatsoever for your Cadence distribution.
R2. You don't have access to Sourcelink.
R3. There is no possible way to enroll yourself in any Cadence
training course: you have zero budget -besides the fact that you live
in Perú! :)
R4. You have managed to get the cdsdoc working and as a matter of fact
you regularly use it to try to find answers for problems like the ones
stated above, but irrespective of how hard you search for the required
SKILL code, you just don't seem to get any closer to the answer.
R5. You have repeatedly annoyed the people in your favorite Cadence
forum with your constant pleas for help, and even though they always
kindly help you, you start to feel that posting a new question every
time you cannot find the SKILL way to do something is by no means a
sustainable solution, and that there should be a better way to find
the information in a reasonable amount of time.

Well, jokes aside, thanks a lot to everyone for your ideas and for
your patience, time and willingness to help. I am really indebted to
all of you; what you do in forums like this is *invaluable* for people
like us, which otherwise would be totally lost on our own. Thanks
again!

Regards,

Jorge Luis.
 
Any ideas? anybody?
Sorry for the insistence... it really matters to me.
 
On Tue, 11 Dec 2007 04:43:12 -0800 (PST), spectrallypure
<jorgelagos@gmail.com> wrote:

Any ideas? anybody?
Sorry for the insistence... it really matters to me.
Well, strangely enough most of us are quite busy, and answer when we
can.

Anyway, here are my answers to your challenges:

1. Design Variable Printing

Use the function asiGetDesignVarList. I used "cdsFinder", and then
typed in DesignVar and picked what looked like a good function. I then
looked in the full documentation of this function to see that I need
an asi session id for this, so most likely asiGetCurrentSession()
would be the man for the job:

asiGetDesignVarList(asiGetCurrentSession())

Hey, now I want to make it print out more prettily. So:

foreach(var asiGetDesignVarList(asiGetCurrentSession())
printf("%-10s %10s\n" car(var) cadr(var))
)

2. Plotting from bindkey

Similar. I search for Plot in cdsFinder - see schPlot. Look at the
docs
for schPlot, and see that I can either give it a template file, or
just
have the schPlotOptions variable set.

So, I bring up the form, pick th settings I want, then save a template
file
from the form. I look in this file, and delete all the stuff which was
specific to the design I had, and then use this as the basis of my
SKILL code:

; Plot template generated by schSaveCurrentPlotOptions function - Dec
11 20:19:02 2007
;
abSchPlotOptions = '(nil
hierarchy nil
hierleveldown 0
multisheet nil
plot "cellview"
fullarea t
noteText ""
grid nil
indexsheet t
notes nil
header nil
; plotToFile t
vsheets 1
hsheets 1
display "display"
pagecount 1
nullpage nil
paperdim (8.0 10.5)
papersize "A"
resolution 300
plottertype "postscript1"
plotter "Generic 300 dpi Adobe PostScript Level 1 Plotter"
fit t
outputfile "local.ps"
time "now"
tmpdir "/usr/tmp"
copy 1
unit "inches"
center nil
mail nil
orientation "automatic"
offset (0.0 0.0)
)

procedure(abPlot(@optional (cv geGetEditCellView()))
schPlotOptions=copy(abSchPlotOptions)
schPlotOptions->library=cv~>libName
schPlotOptions->cell=cv~>cellName
schPlotOptions->view=cv~>viewName
schPlot()
)

hiSetBindKey("Schematics" "<Key>F8" "abPlot()")

Regards,

Andrew.
 
Thanks a lot for your reply, Andrew; that was indeed the type of
advice that I needed!
Now I do have a much clearer idea of the workflow to be followed when
developing SKILL code. Sorry if I was too insistent!

I worked hard on implementing your ideas, and I wanted to give some
feedback on the results. Here they are.

Chore 1. Design Variable Printing (result: 99.9999% success)
==========================================

Using your methodology for finding skill functions, I completed the
procedure in order to add the variables to the plot as a text label
(which was my final goal). I had to figure out how to get also the
temperature printed, since it is a simulator parameter rather than a
design variable. The final code is as follows:

/
*******************************************************************************
*File Name : AddLabelWithDesignVariablesToCurrentPlot.il
*Function(s) : AddLabelWithDesignVariablesToCurrentPlot
*Synopsis : AddLabelWithDesignVariablesToCurrentPlot()
*Call example : AddLabelWithDesignVariablesToCurrentPlot()
*Description : This function adds a text label to the current plot
window,
* with the contents of the design variables
*******************************************************************************/
procedure( AddLabelWithDesignVariablesToCurrentPlot(
)
; A list is created with all the design variables
list_with_vars = asiGetDesignVarList(asiGetCurrentSession())

; A string is created with the formated contents of the variable list
string_with_vars = ""
foreach(var list_with_vars
;sprintf( temp_string "%-20s = %10s\n" car(var)
cadr(var)) ;format 1
sprintf( temp_string "%s = %s\n" car(var) cadr(var)) ;format 2
string_with_vars = strcat( string_with_vars temp_string )
)

; Temperature for current simulator is obtained
current_simulator = asiGetAnalogSimulator(asiGetCurrentSession())
simulator(current_simulator)
temperature = temp()

; Temperature value is added as text to the variables string
sprintf( temp_string "temp = %s\n" temperature) ;format 2
string_with_vars = strcat( temp_string string_with_vars )

; The text label is added to the current plot
label = addWindowLabel( list( 0.75 0.75 ) string_with_vars )
)

Results:
The function itself works like a breeze, but for some reason...I
cannot bindkey it!!! I tried the following code without success:
hiSetBindKey("wavescan" "ctrl<key>v"
"AddLabelWithDesignVariablesToCurrentPlot()")
The function is on the Skill path, and when I load & call it either
from the CIW ot from my .cdsinit, I don't get any warnings/errors.
What could be going wrong here?


Chore 2. Plotting from bindkey (result: partial success)
==========================================

I tailored a little the code in order suit my printer. The function is
as follows:

/
*******************************************************************************
*File Name : SendSchematicToPrinter.il
*Function(s) : SendSchematicToPrinter
*Synopsis : SendSchematicToPrinter()
*Call example : SendSchematicToPrinter()
*Modification :
*Description : Sends the current schematic to the printer
*******************************************************************************/
procedure( SendSchematicToPrinter(
@optional ( cv geGetEditCellView() )
)
; Plotting template is created, using data previously dumped by using
; the command schSaveCurrentPlotOptions( "~/my_plotting_template" )
MySchPlotOptions = '(nil
hierarchy nil
hierleveldown 0
multisheet nil
plot "cellview"
fullarea t
noteText ""
grid nil
indexsheet t
notes nil
header t
vsheets 1
hsheets 1
display "display"
pagecount 1
nullpage nil
paperdim (7.85 11.27667)
papersize "A4_corrected"
resolution 600
plottertype "postscript1"
plotter "HP_LaserJet_1020 (B&W)"
fit t
outputfile ""
time "now"
tmpdir "/usr/tmp"
copy 1
unit "inches"
center t
mail nil
orientation "automatic"
offset (0.0 2.153115)
)

; 'schPlotOptions' variable is filled with data from previously
created template
schPlotOptions = copy(MySchPlotOptions)

; Missing entries on 'schPlotOptions' variable are filled with the
current cellview data
schPlotOptions->library = cv~>libName
schPlotOptions->cell = cv~>cellName
schPlotOptions->view = cv~>viewName

; *** STRANGE SETTING WITHOUT WHICH THE FUNCTION DOESN'T PLOT! ***
;schPlotOptions->bBox = list( list(-10 -10) list(10 10))

; Print job is sent to printer
schPlot()
)

Observations:
With the "bBox" definition uncommented, the function works fine
(altogether with the bindkeying), and I get the plots printed.
However, without this property set, I get the following on the CIW:

(...)
SendSchematicToPrinter()
Loading /programs/cadence/IC_5.1.41/tools/plot/.cdsplotinit
Loading /home/cdsmgr/.cdsplotinit
Loading layers.cxt
No cells plotted
nil

The big problem is that the values for "bBox" would be really
dependent on the particular size of the current schematic, and
therefore they shouldn't be hardcoded. But In principle there should
be not need to use this property at all!!: the documentation clearly
says that this property shoudn't be set when using the
"fullarea" (autoscale) option, which is the case here. We in fact want
to benefit from the autoscale feature of the plotting command in order
to be able to plot any (the current) schematic, irrespective of its
size. What could be happening here?


Well, these are my results after a whole day's work. I'll continue to
investigate on these; any further help/ideas are greatly welcomed, as
usual.

Thanks again for everything!

Regards,

Jorge Luis.
 
Hi Jorge,

I think you are doing pretty well, now. With some practice, you will know more and more where to
search to find the right function. cdsFinder is really a great help, and so are Sourcelink and this
very newsgroup :)


A few comments on your code - though it's working, there are some good habits that you might want to
learn from the start.

1/ You are not using any local variables.

As a rule, you should always use local variables. Use global variables only when absolutely
necessary, and in this case give them a name that's unlikely to be used by someone else (Cadence
recommends using names starting with a capital letter for both variables and functions).

When I write a procedure, I always start with writing a let() around the body, and as I need local
variables add them into the let() statement.

procedure(
myProc(

;; parameters
param1
....

;; named parameters
@key
(namedParam1 defaulValue)
...
)

let(
(
;; local variables
my_local_var
...
)

;;;
;;; code...
;;;

) ; let
) ; procedure

2/ There is no error checking in your code.

Though this is not a problem in this case, since you would just see an error message in your CIW and
no severe consequences, it might become one in more serious code.

As example in your code, temp() might well return nil in some cases. If that happens, sprintf() will
throw an error and exit your procedure. If this happens in the middle of some serious work, it can
be devastating.

3/ This is picky detail :), but lots of intermediate steps are not needed...

Based on this I would rewrite it as follows :

procedure(
AddLabelWithDesignVariablesToCurrentPlot(
@key
(session asiGetCurrentSession())
(coord '(0.75 0.75))
)

let(
(
)

when( session
simulator(asiGetAnalogSimulator(session))

addWindowLabel(
coord
buildString(
remd(nil foreach( mapcar var cons( list("temp" temp()) asiGetDesignVarList(session) )
when(car(var) sprintf(nil "%s = %s" car(var) or(cadr(var) "N/A"))) ))
"\n"
)
)

) ; when

) ; let

) ; procedure



; Print job is sent to printer
schPlot()
Observations:
With the "bBox" definition uncommented, the function works fine
(altogether with the bindkeying), and I get the plots printed.
However, without this property set, I get the following on the CIW:
It works if you set it to nil, instead of not having it set at all

i.e

schPlotOptions = list(nil ...... bBox nil)

alternatively, you can set it to cv~>bBox, for example.
 
Stéphane,

Thanks so much for your comments & observations! I will try to use
your template from now on when creating my functions (I'm still
crawling, so there are many construct that I still don't get, but I am
confident I will soon get through). Thanks also for the improved
version of the AddLabelWithDesignVariablesToCurrentPlot; it rocks :)

Just one enquiry with regard to the printing problem:

It works if you set it to nil, instead of not having it set at all
i.e
schPlotOptions = list(nil ...... bBox nil)
I guess I don't really get what you mean... wouldn't that piece of
code define a schPlotOptions with virtually all nil entries? how could
the schPlot() command plot without the remaining information? I
instead tried to define a nil bBox using the following:

schPlotOptions->bBox = nil

but I still get the same error:

(...)
SendSchematicToPrinter()
Loading /programs/cadence/IC_5.1.41/tools/plot/.cdsplotinit
Loading /home/cdsmgr/.cdsplotinit
No cells plotted
nil
(...)


alternatively, you can set it to cv~>bBox, for example.
I tried this other possibility, but unfortunately the schPlot() still
fails with the following output:

(...)
SendSchematicToPrinter()
Loading /programs/cadence/IC_5.1.41/tools/plot/.cdsplotinit
Loading /home/cdsmgr/.cdsplotinit
Start Plotting ...
plotServ 7.02, build a, 03.01, static
*WARNING* Computed number of 2 stripped pages exceeds maximum of 1.
*WARNING* PLOT: unable to initialize plot package.
*WARNING* Unable to generate plot
... End Plotting
No cells plotted
t
(...)

I guess this is related to the command trying to create a plot
spanning through several pages, but what I really wanted to do is to
create a one-page fit, autoscaled plot, making use of the 'fullarea'
and 'fit' properties of the 'schPlotOptions' list.

Thanks so much for any further ideas on this last issue (or on the
wavescan bindkey problem as well)!

Best regards,

Jorge Luis.
 
schPlotOptions->bBox = nil
Yes, that's what I meant...

but I still get the same error:

(...)
SendSchematicToPrinter()
Loading /programs/cadence/IC_5.1.41/tools/plot/.cdsplotinit
Loading /home/cdsmgr/.cdsplotinit
No cells plotted
nil
(...)
I have no idea why. In fact, when I run your code over here, it works like a charm !

Thanks so much for any further ideas on this last issue (or on the
wavescan bindkey problem as well)!
The wavescan bindkey also works here. Though, it displays some strange behavior... I sometimes have
to defocus the window and focus it back again to get the bindkey working. Sometimes, it won't work
if the mouse cursor is not over the window... but sometimes it will... You know, all these java
weirdnesses :)



Stéphane
 

Welcome to EDABoard.com

Sponsor

Back
Top