• 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. Help me! How to SKILL activation in the background??

Stats

  • Locked Locked
  • Replies 5
  • Subscribers 143
  • Views 9318
  • 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

Help me! How to SKILL activation in the background??

dohyun
dohyun over 3 years ago

Hi. first, i'm sorry for my english is poor.

i want a window view bbox to be synchronize between window A and window B

1. Skill execute

2. Change the window-A bbox such as Zoom-in, Zoom-out, full fit... etc 

3. Window-B synchronized to the same bbox as window-A (Real time synchronization when view bbox change command is input in window-A)

Here, i think maybe SKILL should always activation for real time synchronization.

but, i don't know that SKILL activation in the background.

How to SKLL activation in the background?

Or, if you can tell me another way, thanks.

best regards.

  • Cancel
Parents
  • AurelBuche
    AurelBuche over 3 years ago

    Hi dohyun,

    Here you go.
    You can load below script and use it like this:
    1. Click on source window
    2. In CIW: win0 = hiGetCurrentWindow()
    3. Click on target window
    4. In CIW: win1 = hiGetCurrentWindow()
    5. In CIW: sync_windows win0 win1

    Hope it does what you expect
    I might come up with a GUI soon

    Cheers,
    Aurelien





    (inScheme

      ;; =======================================================
      ;; Core
      ;; =======================================================

      (let ((sync_windows_table (makeTable 'sync_windows nil)))

        (defglobalfun move_sync_window (src_win bbox)
          "Pan all windows synchronized on SRC_WIN"
          (foreach win sync_windows_table[src_win] (hiZoomIn win bbox))
          )

        (defglobalfun sync_windows (src_win win)
          "Synchronize WIN so it mimic SRC_WIN moves"
          ;; Make sure provided arguments are valid windows
          (foreach win (list src_win win) (assert (windowp win) "%A is no window object" win))
          (pushf win sync_windows_table[src_win])
          (hiRegZoomPanProc "move_sync_window" src_win)
          )

        (defglobalfun unsync_windows (src_win @optional win)
          "Unsynchronize WIN from SRC_WIN, if WIN is not provided all windows synchronized with SRC_WIN are unsynchronized"
          ;; Win is not provided, remove src_win from table
          (if (not win) (remove src_win sync_windows_table)
            ;; Win is provided, remove it from src_win synchronized windows
            (let ((wins sync_windows_table[src_win]))
              (setq wins (remove win wins))
              ;; Remove table entry when list is empty
              (if wins (setf sync_windows_table[src_win] wins)
                (remove src_win sync_windows_table)
                ))
            ))

        (defglobalfun unsync_all_windows nil
          "Unsynchronize all windows"
          (hiUnregZoomPanProc "move_sync_window")
          (foreach src_win sync_windows_table[?] (remove src_win sync_windows_table))
          )

      );closure
    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • AurelBuche
    AurelBuche over 3 years ago in reply to AurelBuche

    Here is the updated code with an associated GUI

    It became more complicated than I expected but does the job nicely

    Cheers,

    Aurélien

    ;; ===============================================================================================================
    ;; Synchronize zoom between windows
    ;;
    ;; A. Buchet - September 2022
    ;; ===============================================================================================================

    (inScheme

      ;; =======================================================
      ;; Core
      ;; =======================================================

      (let ((sync_windows_table (makeTable 'sync_windows nil)))

        (defglobalfun move_sync_window (src_win bbox)
          "Pan all windows synchronized on SRC_WIN"
          ;; Inhibit current function to avoid infinite calls
          (let ((current_fun (getd 'move_sync_window)))
            (putd 'move_sync_window (lambda (@rest _args) nil))
            (unwindProtect
              (foreach win sync_windows_table[src_win] (hiZoomIn win bbox))
              (putd 'move_sync_window current_fun)
              ))
          ;; Always return t
          t)

        (defglobalfun sync_windows (src_win win)
          "Synchronize WIN so it mimic SRC_WIN moves"
          ;; Make sure provided arguments are valid windows
          (foreach win (list src_win win) (assert (windowp win) "%A is no window object" win))
          (unless (memq win sync_windows_table[src_win]) (pushf win sync_windows_table[src_win]))
          ;; Register callback to all windows as it seems impossible to register it for several different windows
          (hiRegZoomPanProc "move_sync_window")
          )

        (defglobalfun unsync_windows (src_win @optional win)
          "Unsynchronize WIN from SRC_WIN, if WIN is not provided all windows synchronized with SRC_WIN are unsynchronized"
          ;; Win is not provided, remove src_win from table
          (if (not win) (remove src_win sync_windows_table)
            ;; Win is provided, remove it from src_win synchronized windows
            (let ((wins sync_windows_table[src_win]))
              (setq wins (remove win wins))
              ;; Remove table entry when list is empty
              (if wins (setf sync_windows_table[src_win] wins)
                (remove src_win sync_windows_table)
                ))
            ))

        (defglobalfun unsync_all_windows nil
          "Unsynchronize all windows"
          (hiUnregZoomPanProc "move_sync_window")
          (foreach src_win sync_windows_table[?] (remove src_win sync_windows_table))
          )

        (defglobalfun get_sync_windows nil
          "Return the list of synchronized windows"
          (tableToList sync_windows_table))

      );closure

      ;; =======================================================
      ;; GUI
      ;; =======================================================

      (let ( (empty_list '("*Empty*"))
             form
             )

        (defun win_to_str (win)
          "Return string describing WIN"
          (lsprintf "%N - %s" win (or (pcreReplace (pcreCompile "\\256") (hiGetWindowName win) "" 0) "*Unknown*")))

        (defun str_to_win (str)
          "Return window described by STR"
          (car (errset (window (let (win_id) (sscanf str "window:%d" win_id) win_id)))))

        (defun update_sync_windows (@rest _args)
          "Updated synchronized windows according to currently selected source windows"
          (let ((win_assoc (get_sync_windows))
                (src_win   (str_to_win form->source_window->value))
                )
            (setf form->sync_windows->choices (when src_win (mapcar win_to_str (cadr (assoc src_win win_assoc)))))
            ;; Always return t
            t))

        (defun refresh (@rest _args)
          "Update GUI according to currently synchronized windows"
          (let ((win_assoc  (get_sync_windows))
                (graph_wins (mapcar win_to_str (setof win (hiGetWindowList) (geIsGraphicalWindow win))))
                )
            ;; Update new source and target window choices
            (setf form->new_source_window->choices graph_wins)
            (setf form->new_target_window->choices graph_wins)
            ;; Update source window choices
            (setf form->source_window->choices (or (foreach mapcar l_win win_assoc (win_to_str (car l_win))) '("*Empty*")))
            ;; Update associated synchronized windows
            (update_sync_windows)
            ))

        (defun create_form nil
          "Create the graphical interface"
          (hiCreateLayoutForm 'sync_windows_form "Manage Sync Windows"
            (hiCreateFormLayout 'main_layout ?items (list
                ;; Fields to select source and target windows with button to synchronize them
                (hiCreateFormLayout 'new_sync_layout ?frame "Synchronize" ?items (list
                    (hiCreateCyclicField ?name 'new_source_window ?prompt "Source" ?choices empty_list)
                    (hiCreateCyclicField ?name 'new_target_window ?prompt "Target" ?choices empty_list)
                    ;; Synchronize button
                    (hiCreateHorizontalBoxLayout 'new_sync_hlayout ?items (list
                        '(stretch_item 1)
                        (hiCreateButton ?name 'sync_button ?buttonText "Synchronize" ?callback
                          (lambda (@rest _args)
                            (let ((win0 (str_to_win form->new_source_window->value))
                                  (win1 (str_to_win form->new_target_window->value))
                                  )
                              (if (eq win0 win1) (warn "Unable to synchronize a window to itself")
                                (when (and (windowp win0) (windowp win1)) (sync_windows win0 win1)))
                              (refresh)
                              )))
                        ));hlayout
                    ));new_sync_layout
                ;; Fields to show currently synchronized windows with button to unsynchronize them
                (hiCreateFormLayout 'unsync_layout ?frame "Unsynchronize" ?items (list
                    (hiCreateCyclicField ?name 'source_window ?prompt "Source" ?choices empty_list ?callback update_sync_windows)
                    (hiCreateListBoxField ?name 'sync_windows ?choices nil ?prompt "Targets" ?multipleSelect t)
                    (hiCreateHorizontalBoxLayout 'unsync_hlayout ?items (list
                        '(stretch_item 1)
                        ;; Unsynchronize button
                        (hiCreateButton ?name 'unsync_button ?buttonText "Unsynchronize" ?callback
                          (lambda (@rest _args)
                            (let ((src_win (str_to_win form->source_window->value))
                                  (wins    (mapcar str_to_win form->sync_windows->value))
                                  )
                              (foreach win wins (unsync_windows src_win win))
                              (refresh)
                              )))
                        ));hlayout
                    ));unsync_layout
                ));main_layout
            ?mapCB refresh
            ?buttonLayout `(Empty
                             (Close              hiFormClose)
                             (Refresh            ,refresh)
                             (Unsynchronize\ All ,(lambda (@rest _args) (unsync_all_windows) (refresh)))
                             )
            ?buttonDisabled '(Help)
            ));hiCreateLayoutForm ;def

        (defglobalfun sync_windows_gui (@rest _args)
          "Show GUI to manage Synchronized windows"
          (unless form (setq form (create_form)))
          (hiDisplayForm form)
          )

        );nil

      );SKILL++

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Reply
  • AurelBuche
    AurelBuche over 3 years ago in reply to AurelBuche

    Here is the updated code with an associated GUI

    It became more complicated than I expected but does the job nicely

    Cheers,

    Aurélien

    ;; ===============================================================================================================
    ;; Synchronize zoom between windows
    ;;
    ;; A. Buchet - September 2022
    ;; ===============================================================================================================

    (inScheme

      ;; =======================================================
      ;; Core
      ;; =======================================================

      (let ((sync_windows_table (makeTable 'sync_windows nil)))

        (defglobalfun move_sync_window (src_win bbox)
          "Pan all windows synchronized on SRC_WIN"
          ;; Inhibit current function to avoid infinite calls
          (let ((current_fun (getd 'move_sync_window)))
            (putd 'move_sync_window (lambda (@rest _args) nil))
            (unwindProtect
              (foreach win sync_windows_table[src_win] (hiZoomIn win bbox))
              (putd 'move_sync_window current_fun)
              ))
          ;; Always return t
          t)

        (defglobalfun sync_windows (src_win win)
          "Synchronize WIN so it mimic SRC_WIN moves"
          ;; Make sure provided arguments are valid windows
          (foreach win (list src_win win) (assert (windowp win) "%A is no window object" win))
          (unless (memq win sync_windows_table[src_win]) (pushf win sync_windows_table[src_win]))
          ;; Register callback to all windows as it seems impossible to register it for several different windows
          (hiRegZoomPanProc "move_sync_window")
          )

        (defglobalfun unsync_windows (src_win @optional win)
          "Unsynchronize WIN from SRC_WIN, if WIN is not provided all windows synchronized with SRC_WIN are unsynchronized"
          ;; Win is not provided, remove src_win from table
          (if (not win) (remove src_win sync_windows_table)
            ;; Win is provided, remove it from src_win synchronized windows
            (let ((wins sync_windows_table[src_win]))
              (setq wins (remove win wins))
              ;; Remove table entry when list is empty
              (if wins (setf sync_windows_table[src_win] wins)
                (remove src_win sync_windows_table)
                ))
            ))

        (defglobalfun unsync_all_windows nil
          "Unsynchronize all windows"
          (hiUnregZoomPanProc "move_sync_window")
          (foreach src_win sync_windows_table[?] (remove src_win sync_windows_table))
          )

        (defglobalfun get_sync_windows nil
          "Return the list of synchronized windows"
          (tableToList sync_windows_table))

      );closure

      ;; =======================================================
      ;; GUI
      ;; =======================================================

      (let ( (empty_list '("*Empty*"))
             form
             )

        (defun win_to_str (win)
          "Return string describing WIN"
          (lsprintf "%N - %s" win (or (pcreReplace (pcreCompile "\\256") (hiGetWindowName win) "" 0) "*Unknown*")))

        (defun str_to_win (str)
          "Return window described by STR"
          (car (errset (window (let (win_id) (sscanf str "window:%d" win_id) win_id)))))

        (defun update_sync_windows (@rest _args)
          "Updated synchronized windows according to currently selected source windows"
          (let ((win_assoc (get_sync_windows))
                (src_win   (str_to_win form->source_window->value))
                )
            (setf form->sync_windows->choices (when src_win (mapcar win_to_str (cadr (assoc src_win win_assoc)))))
            ;; Always return t
            t))

        (defun refresh (@rest _args)
          "Update GUI according to currently synchronized windows"
          (let ((win_assoc  (get_sync_windows))
                (graph_wins (mapcar win_to_str (setof win (hiGetWindowList) (geIsGraphicalWindow win))))
                )
            ;; Update new source and target window choices
            (setf form->new_source_window->choices graph_wins)
            (setf form->new_target_window->choices graph_wins)
            ;; Update source window choices
            (setf form->source_window->choices (or (foreach mapcar l_win win_assoc (win_to_str (car l_win))) '("*Empty*")))
            ;; Update associated synchronized windows
            (update_sync_windows)
            ))

        (defun create_form nil
          "Create the graphical interface"
          (hiCreateLayoutForm 'sync_windows_form "Manage Sync Windows"
            (hiCreateFormLayout 'main_layout ?items (list
                ;; Fields to select source and target windows with button to synchronize them
                (hiCreateFormLayout 'new_sync_layout ?frame "Synchronize" ?items (list
                    (hiCreateCyclicField ?name 'new_source_window ?prompt "Source" ?choices empty_list)
                    (hiCreateCyclicField ?name 'new_target_window ?prompt "Target" ?choices empty_list)
                    ;; Synchronize button
                    (hiCreateHorizontalBoxLayout 'new_sync_hlayout ?items (list
                        '(stretch_item 1)
                        (hiCreateButton ?name 'sync_button ?buttonText "Synchronize" ?callback
                          (lambda (@rest _args)
                            (let ((win0 (str_to_win form->new_source_window->value))
                                  (win1 (str_to_win form->new_target_window->value))
                                  )
                              (if (eq win0 win1) (warn "Unable to synchronize a window to itself")
                                (when (and (windowp win0) (windowp win1)) (sync_windows win0 win1)))
                              (refresh)
                              )))
                        ));hlayout
                    ));new_sync_layout
                ;; Fields to show currently synchronized windows with button to unsynchronize them
                (hiCreateFormLayout 'unsync_layout ?frame "Unsynchronize" ?items (list
                    (hiCreateCyclicField ?name 'source_window ?prompt "Source" ?choices empty_list ?callback update_sync_windows)
                    (hiCreateListBoxField ?name 'sync_windows ?choices nil ?prompt "Targets" ?multipleSelect t)
                    (hiCreateHorizontalBoxLayout 'unsync_hlayout ?items (list
                        '(stretch_item 1)
                        ;; Unsynchronize button
                        (hiCreateButton ?name 'unsync_button ?buttonText "Unsynchronize" ?callback
                          (lambda (@rest _args)
                            (let ((src_win (str_to_win form->source_window->value))
                                  (wins    (mapcar str_to_win form->sync_windows->value))
                                  )
                              (foreach win wins (unsync_windows src_win win))
                              (refresh)
                              )))
                        ));hlayout
                    ));unsync_layout
                ));main_layout
            ?mapCB refresh
            ?buttonLayout `(Empty
                             (Close              hiFormClose)
                             (Refresh            ,refresh)
                             (Unsynchronize\ All ,(lambda (@rest _args) (unsync_all_windows) (refresh)))
                             )
            ?buttonDisabled '(Help)
            ));hiCreateLayoutForm ;def

        (defglobalfun sync_windows_gui (@rest _args)
          "Show GUI to manage Synchronized windows"
          (unless form (setq form (create_form)))
          (hiDisplayForm form)
          )

        );nil

      );SKILL++

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Children
  • dohyun
    dohyun over 3 years ago in reply to AurelBuche

    Hi AurelBuche,

    Thank you for your kindness.

    This is the perfect code! It works powerful as i want.

    I think the "hiRegZoomPanProc" is key point, right?

    I don't understand code yet, but i will study hard.

    Thank you very so much!!

    Best regards.

    • Cancel
    • Vote Up +2 Vote Down
    • Cancel
  • AurelBuche
    AurelBuche over 3 years ago in reply to dohyun

    Hi dohyun,

    Yes hiRegZoomPanProc is the key function which fit your needs!

    Effectively my code is in SKILL++ with an almost pure LISP syntax which might be hard to understand at first

    If you have to learn SKILL, consider learning SKILL++ instead as its behavior might be more intuitive

    If you don't rely much on global variables, you have 99% chances your SKILL code can give the same result if evaluated in SKILL++ (It might not be the case in the other way around though)

    Key points in my code (mainly related to SKIL++) :

    1. The inScheme call at the beginning of the script is to force the use of SKILL++, you don't have to make this call if you rename your file with .ils suffix and load it normally

    2. In SKILL++ a let call creates an environment which is shared and can be accessed at any time by the functions defined in it.
       Those functions are local by default except if you make them global by explicitely calling putd, defglobalfun or globalProc (note that the two last ones are only macros calling putd)#

    Example:

    (inScheme 
    (let ((a 12)
    (b 27)
    )
    (defun get_a nil a)

    (defglobalfun get_b nil b)

    (defglobalfun incr_b nil (setq b (add1 b)))
    ));closure
    > get_a
    *Error* toplevel: undefined variable - get_a
    > get_b
    27
    > incr_b
    28
    > get_b
    28

    What happened here is the expected behavior, get_a is local so we cannot access it outside the let

    get_b and incr_b on the other hand are available. They both access the same variable b, if incr_b modifies it, get_b sees the updated variable as well

    3. This behavior allows me to create semi-global variables, they do not pollute the top-level namespace but are still available for all my functions. This is what I use to store and update the list of synchronized windows. I also do the same so that my GUI form can be accessed easily (in my callbacks for instance):

    In sync_windows_gui I make sure the variable form contains my GUI before I display it, which means I can use the form variable in all my callbacks. So I can pass (lambda (@rest args) ... ) as callback of all my fields as I do not need their arguments anymore

    Hope I made my code a little bit clearer

    Cheers

    Aurélien

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • dohyun
    dohyun over 3 years ago in reply to AurelBuche

    Hi AurelBuche.

    Thank you so much for explaining this.

    I was really impressed.

    Thanks again for helping me study SKILL.

    I think i'm lucky to have met you here.

    Have a nice day!

    Best regards.

    • Cancel
    • Vote Up +1 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