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
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
###############################################################################
# Copyright (c) 2013-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.
# =============================================================================
#   @script
#       Alternative 'Load Cone to Parasitic' implementation.
###############################################################################


# =============================================================================
# ParasiticCone - Alternative 'Load Cone to Parasitic' implementation that
#                 removes the paths from the parasitic view that are not
#                 connected in the Cone window.
# =============================================================================
#
proc ParasiticCone {} {
    ##
    # Return if the database is empty.
    #
    set db [gui database get]
    if {$db == {}} {
        return
    }

    ##
    # Make sure that the Parasitic window is visible.
    #
    gui parasitic showWindow

    ##
    # Get the contents of the Cone window.
    #
    set coneContents [gui cone contents -type "net"]

    ##
    # Clear used flags at all nets loaded to the Cone window.
    # Get rid of the contents of parasitic module, except interface nets,
    # because the DSPF parser does not reload them in fillContent mode.
    #
    foreach oid $coneContents {
        set parasitic [$db search parasitic [$db oid oname $oid]]
        if {[$db oid isnull $parasitic]} {
            continue
        }
        array unset _interfaceNets
        $db foreach port $parasitic port {
            $db flag $port clear hide
            if {[$db isConnected $port]} {
                set net [$db connectedNet $port]
                set _interfaceNets($net) 1
            }
        }
        $db foreach net  $parasitic net  {
            if {[info exists _interfaceNets($net)]} {
                continue
            }
            $db flag $net  set   zombie
        }
        $db foreach inst $parasitic inst {
            $db flag $inst set zombie
        }
    }

    ##
    # Remove zombie flagged objects.
    #
    $db deleteZombies

    ##
    # Load the contents of the Cone window to the Parasitic Window.
    # This is required to start the SPF parser and fill the contents of
    # the parasitic module with the RC-network.
    #
    gui parasitic show $coneContents

    ##
    # Get the 'Parasitic Top' module.
    #
    set pTop {}
    $db foreach parasitic p {
        if {[$db flag $p is parasiticTop]} {
            set pTop $p
            break
        }
    }
    if {$pTop == {}} {
        return
    }

    ##
    # Get the 'delimiter' used in the database.
    #
    set delimiter [string index [$db attr -db getValue "@DELIMITER"] end]

    ##
    # Get the connectivity of the contents loaded to the Cone window.
    # (This is an unofficial API call)!!
    #
    set nlv [gui cone nlv]
    foreach conn [$nlv search -conn net *] {
        set netName  [lindex $conn 1]
        set connInfo [lrange $conn 2 end]
        if {[llength $connInfo] == 0} {
            continue
        }

        ##
        # Search the parasitic module and the corresponding instance.
        #
        set parasitic [$db search parasitic $netName]
        set pInst     [$db search inst $pTop $netName]
        if {[$db oid isnull $parasitic] || [$db oid isnull $pInst]} {
            return
        }

        ##
        # Process the connectivity info of the contents loaded to the Cone
        # window and fill one list with the input ports and one list with all
        # output ports of the parasitic module.
        #
        set inputList  {}
        set outputList {}
        _getConnOids $db $connInfo $parasitic $delimiter inputList outputList

        ##
        # Calculate all possible paths between all input and all output ports.
        #
        set pathList [_calculatePaths $db $parasitic $inputList $outputList]
        if {[llength $pathList] == 0} {
            $db foreach inst $parasitic inst {
                $db flag $inst set zombie
            }
            continue
        }

        ##
        # Add the path to ground in all calculated result paths.
        #
        _addPathToGround $db $parasitic $pathList

        ##
        # Remove all instances not flagged with the 'green' flag.
        #
        $db foreach inst $parasitic inst {
            if {![$db flag $inst is green]} {
                $db flag $inst set zombie
            }
        }

        ##
        # Flag all connected input and output ports with the 'green' flag.
        #
        foreach port [concat $inputList $outputList] {
            $db flag $port set green
        }

        ##
        # Loop over all interface ports of the parasitic module.
        #
        $db foreach port $parasitic port {
            ##
            # Skip all ports flagged with the 'green' flag.
            #
            if {[$db flag $port is green]} {
                continue
            }

            ##
            # Remove the net connected to this port.
            #
            if {[$db isConnected $port]} {
                $db flag [$db connectedNet $port] set zombie
            }

            ##
            # Convert the port to the corresponding pin.
            #
            set pin [$db search pin $pInst [$db oid oname $port]]
            if {[$db oid isnull $pin]} {
                continue
            }

            ##
            # Set the hide flag at the port and pin.
            #
            $db flag $port set hide
            $db flag $pin  set hide

            ##
            # Remove the net connected to this pin.
            #
            if {[$db isConnected $pin]} {
                $db flag [$db connectedNet $pin] set zombie
            }
        }
    }

    ##
    # Mark all objects from the Cone window as 'green' in the Parasitic window.
    #
    foreach obj $coneContents {
        set pInst [$db search inst $pTop [$db oid oname $obj]]
        if {[$db oid isnull $pInst]} {
            continue
        }
        $db flag $pInst set green
    }

    ##
    # Remove all instances in the parasitic top module not flagged as 'green'.
    #
    $db foreach inst $pTop inst {
        if {![$db flag $inst is green]} {
            $db flag $inst set zombie
        }
    }

    ##
    # Actually remove the 'zombie' objects.
    #
    $db deleteZombies

    ##
    # Update the displayed RC-network after the database was modified.
    # (This is an unofficial API call, there may be a warning
    #  about 'duplicate symbol' because the interface of the hierbox
    #  may change)!!
    #
    set parasiticWindow [gui window defaultClassWindow Parasitic]
    set nlv [gui parasitic nlv]
    if {[$nlv ictrl isinit]} {
        $nlv increment
        $nlv ictrl update -connectivity
        $nlv show
    }

    ##
    # update list of displayed parasitic nets
    # (This is an unofficial code and will be replaced in one
    #  of the next releases)
    #
    set removeList {}
    foreach pInst [Parasitic:_getParasiticModInst $parasiticWindow] {
        if {[catch {$db oid create $pInst}]} {
            lappend removeList $pInst
        }
    }
    Parasitic:Remove $parasiticWindow $removeList

    ##
    # Regenerate the displayed RC-network.
    #
    gui parasitic regenerate

    ##
    # Call a 'zoom fullfit' command to show the whole contents.
    #
    gui parasitic zoom fullfit
}


# -----------------------------------------------------------------------------
# _getConnOids - Process the connectivity info of the contents loaded to the
#                Cone window and fill one list with the input ports and one
#                list with all output ports of the parasitic module.
# -----------------------------------------------------------------------------
#
proc _getConnOids {db connList parasitic delim inputListName outputListName} {
    upvar 1 $inputListName  inputList
    upvar 1 $outputListName outputList

    for {set i 0} {$i < [llength $connList]} {incr i} {
        switch -- [lindex $connList $i] {
            "-pin"  {
                set instName [lindex $connList [incr i]]
                set portName [lindex $connList [incr i]]
                set paraName "${instName}${delim}${portName}"
            }
            "-port" {
                set paraName [lindex $connList [incr i]]
            }
            default {}
        }

        set oid [$db search port $parasitic $paraName]
        if {[$db oid isnull $oid]} {
            continue
        }

        switch -- [$db directionOf $oid] {
            "input"  {
                lappend inputList  $oid
            }
            "output" {
                lappend outputList $oid
            }
            default {
                zmessage print ERR "Unsupported port direction of '$oid'."
            }
        }
    }
}


# -----------------------------------------------------------------------------
# _calculatePaths - Calculate all possible paths between all input and all
#                   output ports.
# -----------------------------------------------------------------------------
#
proc _calculatePaths {db parasitic inputList outputList} {
    array set _instList {}
    foreach input $inputList {
        foreach output $outputList {
            ##
            # Use the cone extraction API to find all path from the input port
            # to the output port.
            #
            set res [$db cone -paths -out -addStartPin  \
                -excludeFlaggedNet ground \
                -excludeFlaggedNet power  \
                -targetObj $output $input]

            ##
            # Convert all pins in the calculated path to the corresponding
            # instance and add it to the result table.
            #
            foreach path $res {
                foreach oid [lrange $path 1 end] {
                    if {[$db oid type $oid] == "pin"} {
                        set inst [$db oid convertTo inst $oid]
                        set _instList($inst) 1
                    }
                }
            }
        }
    }

    ##
    # Return the result list by converting the result table to a list.
    #
    return [array names _instList]
}


# -----------------------------------------------------------------------------
# _addPathToGround - Add the path to ground in all calculated result paths.
# -----------------------------------------------------------------------------
#
proc _addPathToGround {db parasitic instList} {
    foreach inst $instList {
        $db flag $inst set green
    }

    ##
    # Mark all resistors not flagged with the 'green' flag as 'red'.
    #
    $db foreach inst $parasitic inst {
        if {[$db primFuncOf $inst] == "RES" && ![$db flag $inst is green]} {
            $db flag $inst set red  ;# mark resistors
        } else {
            $db flag $inst clear red ;# may be set by other code
        }
    }

    ##
    # Temporarily remove the ground flag from the ground net and flag all pins
    # connected to the ground net as target.
    #
    set groundNetList {}
    $db foreach net $parasitic net {
        if {![$db flag $net is ground]} {
            continue
        }

        $db foreach pin $net pin {$db flag $pin set target}
        lappend groundNetList $net
        $db flag $net clear ground
    }

    ##
    # Use the cone extraction API to find all paths from the start list
    # to the target pins (connections to a ground net).
    #
    set res [$db cone -out \
        -targetFlaggedPin   target \
        -excludeFlaggedInst red \
        -startList $instList]

    ##
    # Flag all instances in the cone result list with the 'green' flag.
    #
    foreach oid $res {
        $db flag [$db oid convertTo inst $oid] set green
    }

    ##
    # Restore the ground flag.
    #
    foreach net $groundNetList {
        $db flag $net set ground
    }
}


# =============================================================================
# Add "Load Cone to Parasitic" command to a new Userware main menu.
# =============================================================================
#
gui menu command {"Userware" "Load Cone to Parasitic"} {ParasiticCone}