Spying on commands to get precious SKILL code

Discussion in 'Cadence' started by spectrallypure, Dec 7, 2007.

  1. 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.
     
    spectrallypure, Dec 7, 2007
    #1
  2. 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
     
    bernd.fischerkrellenberg, Dec 7, 2007
    #2
  3. spectrallypure

    Tim Guest

    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
     
    Tim, Dec 7, 2007
    #3
  4. spectrallypure

    Guest Guest

    That's correct.
    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.
    Documentation, classes, user guides, AEs, FEs, customer support, the
    user community, etc.
    Someone familiar with the ADE product will need to answer that.
    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
    ()

    "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
     
    Guest, Dec 7, 2007
    #4
  5. spectrallypure

    Guest Guest

    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
    ()

    "The Tree of Learning bears the noblest fruit, but noble fruit tastes bad."
     
    Guest, Dec 7, 2007
    #5
  6. 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.
     
    spectrallypure, Dec 8, 2007
    #6
  7. Any ideas? anybody?
    Sorry for the insistence... it really matters to me.
     
    spectrallypure, Dec 11, 2007
    #7
  8. spectrallypure

    andrewb Guest

    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.
     
    andrewb, Dec 11, 2007
    #8
  9. 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.
     
    spectrallypure, Dec 12, 2007
    #9
  10. spectrallypure

    S. Badel Guest

    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


    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.
     
    S. Badel, Dec 12, 2007
    #10
  11. 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:
    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
    (...)

    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.
     
    spectrallypure, Dec 12, 2007
    #11
  12. spectrallypure

    S. Badel Guest

    schPlotOptions->bBox = nil

    Yes, that's what I meant...
    I have no idea why. In fact, when I run your code over here, it works like a charm !
    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
     
    S. Badel, Dec 14, 2007
    #12
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.