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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400 | ###############################################################################
# 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
# Create Attributes for DC
# @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 in the schematic from this data
#
# - Load the spice netlist "demo/spice/Fig24_30/Fig24_30.sp".
# - Load this userware file. A small GUI will open
# - Open the DC simulation result
# (1) "demo/spice/Fig24_30/dcOpInfo.info"
# - Select a subtype such as "bsim3v3.region".
# - Click "Create"
# - Check the attributes for the transistors in the schematic.
# Attributes such as "bsim3v3.region=1" have been added.
# (2) "demo/spice/Fig24_30/dcOp.dc"
# - Select a type such as "volt".
# - Click "Create"
# - 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_dc.tcl
# @example
# demo/spice/Fig24_30/Fig24_30.sp
# demo/spice/Fig24_30/dcOpInfo.info
# demo/spice/Fig24_30/dcOp.dc
# @tag
# gui analog
###############################################################################
# -----------------------------------------------------------------------------
# getTypeAndFieldName - Returns a type name for a given type_index and
# field_index (if it is a struct type).
# -----------------------------------------------------------------------------
#
proc getTypeAndFieldName {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
}
# -----------------------------------------------------------------------------
# createAttributesForSectionAndType - This function is called when
# clicking the "Create" button.
#
# It traverses all curves. If the curve makes use of the type "type_index", an
# attribute is created.
# If the type is a struct type, the attribute is created for the field
# "field_index".
# -----------------------------------------------------------------------------
#
proc createAttributesForSectionAndType {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 the oid names of the
# schematic.
#
set rc [af_sv_compute_mapping ${section_id}]
if {$rc != "ok"} {
zmessage print ERR "failed to create mapping !"
}
##
# 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 type_name [getTypeAndFieldName $type_index $field_index]
##
# We traverse all curves of the section "section_id"
#
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"]
##
# Check if the type_index is the required one.
#
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]
##
# Check if the curve was mapped correctly.
#
if {$oid != ""} {
##
# Here we create an iterator for the specific curve.
# This iterator allows to iterate through the values.
#
set iterator [af_wp_curve_value_iterator_define $section_id \
$curve_index]
##
# If no field_index is used we simply take the first value.
#
if {$field_index > 0} {
##
# A field index is specified => go to the corresponding
# position.
#
af_wp_curve_value_iterator_go_to_position $iterator \
$field_index
}
##
# Get the iterator's value.
#
set value [af_wp_curve_value_iterator_read_next $iterator]
##
# The string value "bad_index" is returned when the iterator
# reaches the end.
# Check if "value" holds valid data.
#
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.
# This should not occur for dc data.
#
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 a string that will be shown in the GUI.
#
return "$attribute_counter attributes created for type \"$type_name\"."
}
# -----------------------------------------------------------------------------
# createAttributeDialog - This function creates a simple Tk dialog.
# This dialog allows to select a type and create
# attributes.
# -----------------------------------------------------------------------------
#
proc createAttributeDialog {section_id} {
variable dialog_variable
variable selected_type_index
##
# variable set when selection changes
#
set selected_type_index {-1 -1 }
##
# Create toplevel dialog
#
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
set txt "Select a type and if defined,\na sub-type to generate\n"
append txt "attributes for all curves of this type."
ttk::frame $dlg
ttk::label $dlg.label \
-text $txt
##
# menu button allowing to select the type.
#
ttk::menubutton $dlg.mb_type -menu $dlg.mb_type.menu \
-text "Select a type" -direction below
menu $dlg.mb_type.menu -tearoff 0
##
# a label for feedback
#
ttk::label $dlg.result -text "0 attributes created."
pack $dlg.label $dlg.mb_type $dlg.result -padx 20 -pady 20
##
# BUTTON BAR
#
ttk::frame $dlg.f
ttk::button $dlg.f.ok -width 10 -text "Create" \
-default active \
-command {.af_dialog.main_frame.result configure \
-text [createAttributesForSectionAndType $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 -expand yes -fill both
##
# Here we create the menu holding the types and sub-types (or type fields).
# 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 [getTypeAndFieldName $type_index -1]
##
# Is this a struct type with fields ?
#
if {$number_of_sub_types > 0} {
##
# Create a sub-menu with the corresponding fields.
#
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 [getTypeAndFieldName $type_index \
$field_index]
$submenu_name add command -label ${sub_type_name} \
-command [list set selected_type_index \
[list $type_index $field_index]]
}
} else {
##
# Simple type (field_index = -1)
#
$dlg.mb_type.menu add command -label $type_name \
-command [list set selected_type_index [list $type_index -1]]
}
}
##
# Wait for the dialogto close
#
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 data over the file dialog.
#
set file_name "${script_path}/../../spice/Fig24_30/dcOpInfo.info"
set file_name [tk_getOpenFile -title "Open DC 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}]
##
# if cucessful at least 1 section is created
#
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.
#
createAttributeDialog $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
|