• 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. hiCreateLayoutForm local variables are undefined as soon...

Stats

  • Locked Locked
  • Replies 4
  • Subscribers 143
  • Views 6476
  • 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

hiCreateLayoutForm local variables are undefined as soon as the form is displayed

Dario T
Dario T over 2 years ago

Hello Everyone,

I'm Using ICAD 20.1-64b.

I've been trying to implement the hiCreateLayoutForm function to get Modular GUI and be able to reuse part of my GUIs in other scripts but I'm encountering a weird situation in which the local variables defined for the form are set to unbound as soon as you display the Layout Form, basically I've noticed that the execution of the hiDisplayForm with a r_layout item does not pause the execution of the script until the form is Closed from the user.

Which means that all the local variables are defined the moment you display the form but get immediately undefined soon after making the form unusable in most of my use cases.

This situation can easily be reproduced with little modification i did to the sample codes in the Cadence User Guide:

procedure(ExVerticalBox()
let((vbox layWinId)
layWinId = geGetWindowCellView()
vbox=hiCreateVerticalBoxLayout(
'vbox
?items
list(
hiCreateBooleanButton(
?name 'enable
?buttonText "Enable"
)
hiCreateStringField(
?name 'lib
?prompt "Lib"
)
hiCreateStringField(
?name 'cell
?prompt "Cell"
)
hiCreateStringField(
?name 'view
?prompt "View"
)
; swallow up any remaining space vertically
list('stretch_item 1)
)
)
hiCreateLayoutForm(
'ExVertBox
"Vertical Box"
vbox
?callback "printf(\"test\")"
)
hiDisplayForm(ExVertBox)
printf("\nDONE\n")
)
)

;****************************************
;Sample form and fields
;****************************************
; Create string entry for the form.
procedure( myformDefineFields()
let((strfld boolfld)
strfld = hiCreateStringField(
?name 'strfld
?prompt "sample string field" ;;; FIELD1, a string type
?defValue "initial string"
?callback "my_strfld_cb(hiGetCurrentForm())"
?editable t
)
; Create a Boolean button for the form.
boolfld = hiCreateBooleanButton(
?name 'boolfld
?buttonText "sample boolean field" ;;; FIELD2, a boolean type
?defValue t
?callback "my_boolfld_cb(hiGetCurrentForm())"
)
list( strfld boolfld )
)
)
; Generate the form
procedure( myformCreateForm()
if( !boundp(`myformglb) || (myformglb == nil)
then
myformglb = hiCreateAppForm(
?name `myformglb
?fields myformDefineFields()
?formTitle "My first Form"
?callback 'myformglb_cb
?buttonLayout `OKCancel
)
)
myformglb
)
procedure(myformglb_cb(form)
printf("Field values are: %s and %L\n" form->strfld->value form->boolfld->value)
)
procedure(my_strfld_cb(form)
printf("String field changed to %s\n" form->strfld->value)
)
procedure(my_boolfld_cb(form)
printf("Boolean field changed to %L\n" form->boolfld->value)
)
; Display the form
procedure( myformDisplayForm()
prog((formWinId)
formWinId = geGetWindowCellView()
myformCreateForm() ;;; Creation and Display are separate
hiDisplayForm(`myformglb)

printf("\nDONE\n")
return(t)
)

By tracing the formWinId and layWinId variables that should be the database object of a cell view you should be able to see that the classic hiCreateAppForm pauses the execution of the script until the form is closed therefore retaining the valiue of formWinId variable.

Form Open:                                                                                                         Form Closed:

While with the hiCreateLayoutForm this happens:

Form Open:                                                                                  Form Closed:

 

Is there any way to retain the local variables while the layout form is open? 

Thanks  in advance,

Dario Tonello

  • Cancel
  • mbracht
    mbracht over 2 years ago

    Hi Dario,

    There is in fact a difference between hiDisplayForm(hiCreateAppForm...)) and hiDisplayForm(hiCreateLayoutForm...) - in case of a "hiCreateAppForm form" hiDisplayForm() does in fact block unless the form has been created with the  dontBlock argument set to true. For "hiCreateLayoutForm forms" hiDisplayForm() is non blocking by default and I don't know whether there is a way to change that in the first place. I don't see any reason why you would want to retain a local variable other that in a callback...and that can be easily accomplished with a lexical scoping in SKILL++.  Modify the ExVerticalCox() function like this:

    procedure(ExVerticalBox()
    let((vbox layWinId)
    layWinId = geGetWindowCellView()
    vbox=hiCreateVerticalBoxLayout(
    'vbox
    ?items list(
    hiCreateBooleanButton(
    ?name 'enable
    ?buttonText "Enable")
    hiCreateStringField(
    ?name 'lib
    ?prompt "Lib")
    hiCreateStringField(
    ?name 'cell
    ?prompt "Cell")
    hiCreateStringField(
    ?name 'view
    ?prompt "View")
    ; swallow up any remaining space vertically
    list('stretch_item 1)
    )
    )
    ExVertBox = hiCreateLayoutForm(
    'ExVertBox
    "Vertical Box"
    vbox
    ?callback (list
    (lambda (@rest args) printf("layWinId: %L\n" layWinId))
    (lambda (@rest args) print("Cancel"))
    )
    )
    hiDisplayForm(ExVertBox)
    printf("\nDONE\n")
    )
    )

    ...and put the entire code in a *.ils file - that way it will get evaluated in SKILL++ context. If you now click the Apply or Ok button you will see that the layWinId variable is still visible

    Max

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Dario T
    Dario T over 2 years ago in reply to mbracht

    Hi Max,

    Thanks for your reply, 

    The reason for my request is because my GUIs tends to utilize some "service" variables, to pass for example the Cellview ID, in order to avoid  having errors due to using the geGetWindowCellView() function as input to the callbacks. Because i tend to work with both schematic and layout open . Misclicking on the wrong cellview before clicking the buttons on the GUI can result in some pretty annoying  situations.

    I'd prefere if there was a way to make the hiCreateLayoutForm() blocking via some options.

    I'll give it a shot with your suggestion SKILL++ Slight smile

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 2 years ago in reply to Dario T

    In general, it's not deemed good design to use blocking forms to access local variables - for a start, this prevents you being able to have "Apply" on your forms, because Apply will call the callback but the form will stay blocked. In the SKILL training class, it was stating for over 20 years that we might remove the blocking nature of forms at some point; in practice that was too risky so it was done when layout forms were introduced.

    There's no public mechanism to make layout forms blocking again.

    If you don't want to use the SKILL++ approach, another good idea is to store the relevant information on the form object itself - and then it can easily be retrieved in the callback. So in other words, having created the form you can do:

    form->cellViewID=cellViewID

    and then in the callback you retrieve it again using form->cellViewID

    So if moving to SKILL++ lexical scoping is a little scary, this might be a simpler way of achieving the storage of your service variables for easy recall later.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Dario T
    Dario T over 2 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thank you so much!

    This is exactly the kind of solution i was looking for. I wasn't aware of these kind of design things i mostly trained by myself with little help from a senior colleague and wasn't aware about these design guidelines.

    I'll try my best to put them in practice.

    Thanks again, have a nice day!

    Dario

    • 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