1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
###############################################################################
# Copyright (c) 2009-2024 by Altair Engineering, Inc.
# All rights reserved.
#
# Altair Engineering, Inc. makes this software available as part of the Vision
# tool platform.  As long as you are a licensee of the Vision tool platform
# you may make copies of the software and modify it to be used within the
# Vision tool platform, but you must include all of this notice on any copy.
# Redistribution without written permission to any third party, with or
# without modification, is not permitted.
# Altair Engineering, Inc. does not warrant that this software is error free
# or fit for any purpose.  Altair Engineering, Inc. disclaims any liability for
# all claims, expenses, losses, damages and costs any user may incur as a
# result of using, copying or modifying the software.
# =============================================================================
#   @userware
#       Highlight for RC
#   @section
#       Miscellaneous Userware Examples
#   @description
#       This example shows how to use the waveform parser to
#             - read a DC analysis result file
#             - traverse all curves defined in this file
#             - create value attributes for resistors and capacitors in
#               the schematic
#
#       - Load the spice netlist "demo/spice/Fig24_30/Fig24_30.sp".
#       - Load this userware file.
#       - Open the DC simulation result "demo/spice/Fig24_30/dcOpInfo.info"
#       - From the menu select "View->Select Attributes" and change
#         "Net Attributes -> Net" to "%volt"
#         The generated attributes are visible on the nets of the schematic.
#
#   @files
#       analogWave/create_attributes_for_rc.tcl
#   @example
#       demo/spice/Fig24_30/Fig24_30.sp
#       demo/spice/Fig24_30/dcOpInfo.info
#   @tag
#       gui analog
###############################################################################


# -----------------------------------------------------------------------------
# get_type_and_field_name_rc -
# -----------------------------------------------------------------------------
#
proc get_type_and_field_name_rc {type_index field_index} {
    set type_name [af_wp_find_type_property $type_index "prop_type_name"]
    if {$type_name == ""} {
        set type_name [af_wp_find_type_property $type_index "prop_type_unit"]
    }
    if {$field_index >= 0} {
        set sub_type_index [af_wp_get_sub_type_index $type_index $field_index]
        set sub_type_name  [af_wp_find_type_property $sub_type_index \
                                                     "prop_type_name"]
        if {$sub_type_name == ""} {
            set sub_type_name [af_wp_find_type_property $sub_type_index \
                                                        "prop_type_unit"]
        }
        set type_name "${type_name}.${sub_type_name}"
    }

    return $type_name
}


# -----------------------------------------------------------------------------
# create_attributes_for_section_and_type_rc -
# -----------------------------------------------------------------------------
#
proc create_attributes_for_section_and_type_rc {
    section_id selected_type_index
} {
    ##
    # The name of the current StarVision zdb is required to generate attributes.
    #
    set db [gui database get]

    ##
    # This function generates a mapping for the waveform section defined by
    # $section_id and the currently loaded schematic.
    # This mapping is required to map curve names to oids.
    #
    catch {af_sv_compute_mapping ${section_id}}

    ##
    # As we want to traverse all variables in the section we have to get the
    # number of variables defined in the section.
    # The first variables might be sweep variables holding the x-axis values.
    # They aren't interesting here.
    #
    set nb_sweep_variables [af_wp_find_section_property $section_id \
                                    "prop_section_number_of_sweep_variables"]
    set nb_all_variables [af_wp_find_section_property $section_id \
                                    "prop_section_total_number_of_variables"]

    set type_index -1
    set field_index -1
    set attribute_counter 0
    set field_name ""
    set len [llength $selected_type_index]
    if {[llength $selected_type_index] == 2} {
        set type_index [lindex $selected_type_index 0]
        set field_index [lindex $selected_type_index 1]
    }
    set    msg "creating attributes for section $section_id "
    append msg "and type $selected_type_index"
    puts $msg
    set type_name [get_type_and_field_name_rc $type_index $field_index]
    set    msg "type_index == $type_index, field_index == $field_index, "
    append msg "type_name == $type_name"
    puts $msg
    for {set curve_index $nb_sweep_variables} \
        {$curve_index<$nb_all_variables} \
        {incr curve_index} \
    {
        ##
        # Here we retrieve some information on the current variable.
        #
        set curve_name [af_wp_find_curve_property $section_id \
                                $curve_index "prop_variable_name"]
        set curve_type_index [af_wp_find_curve_property $section_id \
                                $curve_index "prop_variable_y_axis_type_index"]

        if {$curve_type_index == $type_index} {
            ##
            # Here we apply the mapping computed above. For a given curve name
            # it returns a matching oid.
            #
            set oid [af_sv_apply_mapping_waveform_to_oid $curve_name]

            puts "The curve $curve_name is mapped to the oid $oid"

            if {$oid != ""} {
                ##
                # Here we create an iterator for the specific curve.
                #
                set iterator [af_wp_curve_value_iterator_define $section_id \
                                                                $curve_index]
                if {$field_index > 0} {
                    af_wp_curve_value_iterator_go_to_position $iterator \
                                                              $field_index
                }

                ##
                # This iterator allows to iterate over all curve values.
                # However here we only use the first iterator value.
                #
                set value [af_wp_curve_value_iterator_read_next $iterator]

                ##
                # The string value "bad_index" is returned when the iterator
                # reaches the end.
                #
                if {![af_wp_check_is_return_code $value]} {
                    if {[string is double $value]} {
                        ##
                        # The iterator returns a single double value.
                        # We use it to generate an attribute for the
                        # net defined by $oid.
                        #
                        $db flatattr $oid set "${type_name}=${value}"
                        incr attribute_counter
                    } elseif {[string is list $value]} {
                        ##
                        # The iterator might define a list of two values
                        # with x- and y-axis data.
                        # In this case we create an annotation from
                        # the y-axis value.
                        #
                        set value [lindex $value 1]
                        if {[string is double $value]} {
                            $db flatattr $oid set "${type_name}=${value}"
                            incr attribute_counter
                        }
                    }
                }

                ##
                # destroy the iterator
                #
                af_wp_curve_value_iterator_release $iterator
            }
        }
    }

    ##
    # We inform the gui that attributes have changed.
    #
    gui attribute changed

    return "$attribute_counter attributes created for type \"$type_name\"."
}


# -----------------------------------------------------------------------------
# create_attribute_dialog_rc -
# -----------------------------------------------------------------------------
#
proc create_attribute_dialog_rc {section_id} {
    global dialog_variable selected_type_index

    set selected_type_index {-1 -1 }

    set w .af_dialog
    catch {destroy $w}
    toplevel $w
    wm title $w "Create Attributes From DC INFO file"
    wm protocol $w WM_DELETE_WINDOW {set dialog_variable 0}
    set dlg .af_dialog.main_frame
    ttk::frame $dlg
    set    txt "Select a type and if defined,\na sub-type to generate\n"
    append txt "attributes for all curves of this type."
    ttk::label $dlg.label -text $txt

    ttk::menubutton $dlg.mb_type -menu $dlg.mb_type.menu \
        -text "Select a type" -direction below
    menu $dlg.mb_type.menu -tearoff 0

    ttk::label $dlg.result -text "0 attributes created."

    ttk::menubutton $dlg.mb_sub_type -menu $dlg.mb_sub_type.menu \
        -text "Select a sub-type (if defined)" -direction below
    menu $dlg.mb_sub_type.menu -tearoff 0

    pack $dlg.label $dlg.mb_type $dlg.result -padx 20 -pady 20

    puts "result ttk label : $dlg.result"
    $dlg.result configure -text "sadasda"

    ttk::frame $dlg.f
    ttk::button $dlg.f.ok -width 10 -text "Create" -default active \
        -command {.af_dialog.main_frame.result configure \
                -text [create_attributes_for_section_and_type_rc \
                                        $section_id $selected_type_index]}
    ttk::button $dlg.f.cancel -width 10 -text "Close" \
        -command {catch {set dialog_variable 0}}
    pack $dlg.f.ok $dlg.f.cancel -padx 10 -pady 10 -side right
    pack $dlg.f -anchor s -side right

    pack $dlg -padx 20 -pady 20 -expand yes -fill both

    ##
    # we get the number of defined types
    #
    set nb_types [af_wp_find_global_property "prop_global_number_of_types"]

    ##
    # We traverse the types
    #
    for {set type_index 0} {$type_index<$nb_types} {incr type_index} {
        set number_of_sub_types [af_wp_find_type_property $type_index \
                                        "prop_type_number_of_sub_types"]
        set type_name [get_type_and_field_name_rc $type_index -1]
        if {$number_of_sub_types > 0} {
            set submenu_name $dlg.mb_type.menu.m_${type_index}
            menu $submenu_name -tearoff 0
            $dlg.mb_type.menu add cascade -menu $submenu_name \
                -label ${type_name}
            for {set field_index 0} \
                {$field_index<$number_of_sub_types} \
                {incr field_index} \
            {
                set sub_type_name [get_type_and_field_name_rc $type_index \
                                                                $field_index]
                $submenu_name add command -label ${sub_type_name} \
                    -command [list set selected_type_index \
                                    [list $type_index $field_index]]
            }
        } else {
            $dlg.mb_type.menu add command -label $type_name -command \
                        [list set selected_type_index [list $type_index -1]]
        }
    }

    tkwait variable dialog_variable

    destroy $w
}


##
#
#
set script_path [file dirname [file normalize [info script]]]

##
# This function loads the waveform parser
#       and makes the functions af_wp_... and af_sv_... available.
#
af_waveform_parser_create

##
# Define a file with dc voltages over the file dialog.
#
set file_name "${script_path}/../Fig24_30/dcOpInfo.info"
set file_name [tk_getOpenFile -title "Open DC INFO File" \
    -initialdir $script_path -initialfile ${file_name}]

##
# Clear all data in the waveform parser.
#
af_wp_release_all

##
# Parse the file
#
set rc [af_wp_read_file ${file_name}]
set nb_sections [af_wp_get_number_of_sections]

if {${nb_sections} > 0} {
    ##
    # Each file might define several data sections for example for several
    # runs with different parameters.
    #
    # At least one section has been parsed. We use the first one here.
    # We need to work with the section_id. This section_id doesn't change, even
    # if other files are parsed, reloaded or released.
    #
    set section_id [af_wp_get_section_identifier 0]

    ##
    # Create a dialog to create attributes.
    #
    create_attribute_dialog_rc $section_id
} else {
    zmessage print ERR "failed to load file ${file_name}"
}

##
# Everything is released.
#
af_wp_release_all

##
# unloads the waveform parser
#
af_waveform_parser_delete