• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. How to create two or three key strokes bindkeys

Stats

  • Locked Locked
  • Replies 21
  • Subscribers 146
  • Views 28525
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to create two or three key strokes bindkeys

SlimAnt
SlimAnt over 15 years ago

Hello,

How can I create two or three key strokes bindkeys without changing the existing bindkeys?

For example, addition of existing bindkeys such as: m -> to activate move

I would like to create new bindkeys such as: jmp -> SKILL code to jump to a certain coordinate


I tried using the following function getc to read the next character from keyboard and it doesn't work.

   procedure( call_2()

        TT = getc()

                if( TT = "p" then

                     ; function to jump

                )

     )


   procedure( call_1()

          TT = getc()

                 if( TT = "m" then

                        call_2()

                 )

      )


hiSetBindKey("Layout" "none<Key>j" "call_1()")


I am using version IC6.1.3

I Appreciate any help that I can get.

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 15 years ago

    I had originally planned to describe an outline of a way to do this - but realised that as I started writing the outline, I wasn't that far off having the code itself. So I put together the code below which is a way to implement what I've called "sequence" bindkeys.

    Rather than having to code each specific combination (as in the code in the original post) you register a SKILL action against particular sequences. 

    Anyway, the comments at the top of the code should explain things clearly enough.

    /* abSeqBindKey.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL++ (keep the .ils suffix on this file)
    Date       Oct 22, 2009 
    Modified   
    By         
    
    A package to support sequence bindkeys. This means you can define multi-key
    bindkeys. So for example, you can define a bindkey "chop" - you type the four
    characters c, h, o, and then p - and this then triggers the bindkey.
    The sequence is displayed as a banner label so you can see the current 
    sequence. Escape is normally used to reset the sequence.
    
    Note this is really a proof-of-concept - it is not fully formed, and may
    need some enhancement.
    
    ; Initialize the a-z, A-Z, and 0-9 bindkeys to be entry keys
    ; and escape to be a reset key for Layout application
    abSeqBindKey->initBindKeys("Layout")
    
    ; give warning if any key sequence defined which obscures another
    ; for example, "ed" obscures "edit"
    abSeqBindKey->option(?checkObscured t)
    
    ; Define some key sequences
    abSeqBindKey->set("Layout" "fit" "hiZoomAbsoluteScale(hiGetCurrentWindow() 0.9)")
    abSeqBindKey->set("Layout" 
      '(
        ("copy" "leHiCopy()")
        ("chop" "leHiChop()")
        ("del"  "leHiDelete()")
        ("undo" "hiUndo()")
       )
    )
    
    ; Retrieve bindkeys:
    abSeqBindKey->get("Layout") => returns all the keys
    abSeqBindKey->get("Layout" "chop") => "leHiChop()"
    
    ; If you want to define your own bindkeys (rather than using initBindKeys)
    ; then you'll need to use these:
    abSeqBindKey->enter("X") ; enters an X in the sequence
    abSeqBindKey->reset()    ; resets the sequence
    
    Limitations:
    
    Doesn't have the concept of "Enter Function" bindkeys which are
    different during enter functions. Could do, but needs some thought
    as to a sensible use model.
    
    ***************************************************
    
    SCCS Info: @(#) abSeqBindKey.ils 10/22/09.13:44:45 1.1
    
    */
    
    importSkillVar(abSeqBindKey)
    abSeqBindKey=let(
        ((bindkeys makeTable('bindkeys nil)) obscuredCheck)
    
        /*****************************************************************
        *                                                                *
        *                     initBindKeys(appType)                      *
        *                                                                *
        * EXPORTED function to initialize the bindkeys a-z, A-Z and 0-9, *
        *  as well as Escape, to work with the sequence bindkey system.  *
        *                                                                *
        *****************************************************************/
        defun(initBindKeys (appType)
            let((appRoot)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appRoot
                    ;--------------------------------------------------------
                    ; Define bindkeys for a-z, A-Z and 0-9
                    ;--------------------------------------------------------
                    for(ascii charToInt('a) charToInt('z)
                        hiSetBindKey(appRoot
                            strcat("<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                intToChar(ascii))
                        )
                        hiSetBindKey(appRoot
                            strcat("Shift<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                upperCase(intToChar(ascii)))
                        )
                    ) ; for
                    for(ascii charToInt('\0) charToInt('\9)
                        hiSetBindKey(appRoot
                            strcat("<Key>" intToChar(ascii))
                            sprintf(nil "abSeqBindKey->enter(\"%s\")" 
                                intToChar(ascii))
                        )
                    ) ; for
                    hiSetBindKey(appRoot "<Key>Escape" "abSeqBindKey->reset()")
                ) ; when appRoot
            ) ; let
        ) ; defun initBindKeys
    
        /************************************************************************
        *                                                                       *
        *                              enter(char)                              *
        *                                                                       *
        *   EXPORTED Function to enter a character in the sequence. If there    *
        *     is a sequence bindkey registered for that sequence, reset and     *
        *       then execute the bindkey definition - otherwise continue        *
        * collecting the characters in the sequence (and display in the banner) *
        *                                                                       *
        ************************************************************************/
        defun(enter (char)
            let((win appType appRoot bindkeyTab defn sequence)
                win=hiGetCurrentWindow()
                when(win
                    sequence=strcat(win~>abSequence || "" char)
                    win~>abSequence=sequence
                )
                appType=win && hiGetAppType(win)
                when(appType
                    appRoot=hiGetBindKeyInheritRoot(appType)
                )
                when(appRoot
                    ;--------------------------------------------------------
                    ; Look up the bindkey definition. If found, then
                    ; reset the sequence and evaluate it, otherwise just
                    ; append the current sequence.
                    ;--------------------------------------------------------
                    bindkeyTab=bindkeys[appRoot]
                    defn=bindkeyTab && bindkeyTab[sequence]
                    if(stringp(defn) then
                        reset()
                        errsetstring(defn t)
                    else
                        hiChangeBannerLabel(
                            hiGetCurrentWindow()
                            strcat("Seq: " sequence)
                            0
                        )
                    ) ; if bindkey found
                ) ; when appRoot
            ) ; let
        ) ; defun enter
    
        /***************************************************************
        *                                                              *
        *                           reset()                            *
        *                                                              *
        *       EXPORTED function to reset the current sequence        *
        *                                                              *
        ***************************************************************/
        defun(reset ()
            hiGetCurrentWindow()~>abSequence=""
            hiChangeBannerLabel(
                hiGetCurrentWindow()
                "Seq: "
                0
            )
        ) ; defun reset
    
        /***************************************************************
        *                                                              *
        *                    check(bindkeyTab key)                     *
        *                                                              *
        *  INTERNAL function to check that a new key sequence is not   *
        *    obscured by another, or does not obscure another. Only    *
        *      checked if option(?checkObscured t) has been used.      *
        *                                                              *
        ***************************************************************/
        defun(check (bindkeyTab key)
            let((len subKeyName)
                when(obscuredCheck && stringp(bindkeyTab[key])
                    len=strlen(key)
                    ;--------------------------------------------------------
                    ; Look for any existing key sequences which the new key is
                    ; the beginning part of
                    ;--------------------------------------------------------
                    foreach(keyName bindkeyTab
                        when(key!=keyName && zerop(strncmp(key keyName len)) &&
                            stringp(bindkeyTab[keyName])
                            warn("Definition for sequence %s will obscure sequence %s\n"
                                key keyName)
                        ) ; when
                    ) ; foreach
                    ;--------------------------------------------------------
                    ; Look for any key sequences which are shorter than the new key
                    ;--------------------------------------------------------
                    for(sub 1 sub1(len)
                        subKeyName=substring(key 1 sub)
                        when(stringp(bindkeyTab[subKeyName])
                            warn("Definition for sequence %s will obscure sequence %s\n"
                                subKeyName key)
                        ) ; when
                    ) ; for
                )
            ) ;let
        ) ; defun
    
        /***************************************************************
        *                                                              *
        *                   set(appType key [defn])                    *
        *                                                              *
        *  EXPORTED function to set one or more sequence bindkeys for  *
        *                        an application                        *
        *                                                              *
        ***************************************************************/
        defun(set (appType key @optional defn "tg")
            let((appRoot bindkeyTab)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appRoot
                    bindkeyTab=bindkeys[appRoot]
                    unless(bindkeyTab
                        bindkeyTab=makeTable('appBindkeys nil)
                        bindkeys[appRoot]=bindkeyTab
                    )
                    ;--------------------------------------------------------
                    ; Handle list of definitions, and individual definitions
                    ;--------------------------------------------------------
                    if(listp(key) then
                        foreach(keyDefn key
                            if(listp(keyDefn) && length(keyDefn==2) then
                                bindkeyTab[car(keyDefn)]=cadr(keyDefn)
                                check(bindkeyTab car(keyDefn))
                            else
                                warn("Key definition %L is invalid\n" keyDefn)
                            )
                        )
                    else
                        bindkeyTab[key]=defn
                        check(bindkeyTab key)
                    )
                    t
                ) ; when appRoot
            ) ; let
        ) ; defun set
    
        /*******************************************************************
        *                                                                  *
        *                        get(appType [key])                        *
        *                                                                  *
        * EXPORTED function to get one or all sequence bindkey definitions *
        *                                                                  *
        *******************************************************************/
        defun(get (appType @optional key "tg")
            let((appRoot bindkeyTab)
                appRoot=hiGetBindKeyInheritRoot(appType)
                when(appType 
                    bindkeyTab=bindkeys[appRoot]
                    ;--------------------------------------------------------
                    ; If the key argument provided, just return the definition
                    ; otherwise return an assoc list of the whole lot
                    ;--------------------------------------------------------
                    if(key then
                        bindkeyTab && bindkeyTab[key]
                    else
                        tableToList(bindkeyTab)
                    )
                ) ; when appType
            ) ; let
        ) ; defun get
    
        /***************************************************************
        *                                                              *
        *                  option(@key checkObscured)                  *
        *                                                              *
        *       EXPORTED function to set any options. Currently        *
        *                     just ?checkObscured.                     *
        *                                                              *
        ***************************************************************/
        defun(option (@key checkObscured)
            obscuredCheck=checkObscured
        )
    
        ;--------------------------------------------------------------------
        ; DPL containing all the package functions available from outside
        ;--------------------------------------------------------------------
        `(nil
            initBindKeys ,initBindKeys
            enter ,enter
            reset ,reset
            set ,set
            get ,get
            option ,option
        )
    ) ; let
    
    

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Varungr087
    Varungr087 over 6 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thanks for the code. It works great !

    But after I initialise the code, the default bindkeys of virtuoso like f(fit screen) are not working. Seems like I have to de-initialise the code. How do I do it

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 6 years ago in reply to Varungr087

    That's inevitable. The code works by redefining all the letter and number keys so that it can detect what keys you've pressed. If it left the original bind keys alone (e.g. the "f" key), then you wouldn't be able to have "f" in any key sequence!

    The examples in the comments show "fit" being defined for this. You could of course adapt that and use "f" instead, but then you wouldn't be able to have any other sequence which begins with 'f". So it's a compromise:

    abSeqBindKey->set("Layout" "f" "hiZoomAbsoluteScale(hiGetCurrentWindow() 0.9)")
    

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Varungr087
    Varungr087 over 6 years ago in reply to Andrew Beckett

    Understood ! So now to get it back to whatever it was before initialising the code, I have to re invoke virtuoso. Right ?  or Is there any other alternative other than re-invoking ?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 6 years ago in reply to Varungr087

    You can just re-load the standard bind keys file. Either:

    load(ddGetStartup("dfII/bindkeys/Layout.il"))

    or:

    load(prependInstallPath("samples/local/leBindKeys.il"))

    That's assuming you are using the "out of the box" bindkey definitions. The top function (with ddGetStartup) would work if you've put a dfII/bindkeys/Layout.il further up your "Cadence Search File" path, but if you've loaded some other custom bind keys from  your .cdsinit you'd need to locate that and re-load it.

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 6 years ago in reply to Varungr087

    You can just re-load the standard bind keys file. Either:

    load(ddGetStartup("dfII/bindkeys/Layout.il"))

    or:

    load(prependInstallPath("samples/local/leBindKeys.il"))

    That's assuming you are using the "out of the box" bindkey definitions. The top function (with ddGetStartup) would work if you've put a dfII/bindkeys/Layout.il further up your "Cadence Search File" path, but if you've loaded some other custom bind keys from  your .cdsinit you'd need to locate that and re-load it.

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • Varungr087
    Varungr087 over 6 years ago in reply to Andrew Beckett

    Ok Andrew. Thanks again

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information