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
###############################################################################
# Copyright (c) 2012-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
#       Generate Placement Information
###############################################################################


# -----------------------------------------------------------------------------
# _getLevel - Return the integer value after the last underscore character
#             in the given instance name.
# -----------------------------------------------------------------------------
#
proc _getLevel {instName} {
    ##
    # Initialize the level with an invalid number.
    #
    set level -1

    ##
    # Find the last underscore character in the instance name.
    #
    set pos [string last "_" $instName]

    ##
    # Check if the instance name contains an underscore character.
    #
    if {$pos > 0} {
        ##
        # Get all characters after the underscore until the end of
        # the instance name.
        #
        set value [string range $instName [expr {$pos + 1}] end]

        ##
        # If this value is an integer then assign the value to
        # the level variable.
        #
        if {[string is integer $value]} {
            set level $value
        }
    }

    ##
    # Return a value for the level.
    #
    return $level
}


# -----------------------------------------------------------------------------
# _getMaxNodes - Count the number (levels) of 'MT_Nodes'.
# -----------------------------------------------------------------------------
#
proc _getMaxNodes {db module} {
    ##
    # Initialize the node count variable.
    #
    set maxNodes 0

    ##
    # Loop over all instances in the given module.
    #
    $db foreach inst $module inst {
        ##
        # Skip all instances that are not of the type MT_Node.
        #
        if {[$db oid cname $inst] != "MT_Node"} {
            continue
        }

        ##
        # Get the level value for this instance.
        #
        set level [_getLevel [$db oid oname $inst]]

        ##
        # If this level is greater than the maxNodes value then set it
        # as the new maxNodes value.
        #
        if {$level > $maxNodes} {set maxNodes $level}
    }

    ##
    # Return the calculated number.
    #
    return $maxNodes
}


# -----------------------------------------------------------------------------
# _getOutFileName - Return a filename with the same basename as the read Spice
#                   file but add the given extension.
# -----------------------------------------------------------------------------
#
proc _getOutFileName {ext} {
    return [file rootname [gui settings get "Spice:fname:F"]].$ext
}


# =============================================================================
# GeneratePlacement - Loop over the loaded design and generate placement
#                     information based on the instance names.
# =============================================================================
#
proc GeneratePlacement {db} {
    ##
    # Return if the database is empty.
    #
    if {$db == {}} {
        return
    }

    ##
    # Only process the top module automatically generated by PSpice parser
    # of SpiceVision PRO. This module is always named 'TOP'.
    #
    set module [$db search top "TOP"]

    ##
    # Show an error if this module could not be found.
    #
    if {[$db oid isnull $module]} {
        error "Could not find top module 'TOP'."
    }

    ##
    # Open an output file to store the preplace information.
    #
    set out [open [_getOutFileName "plc"] w]

    ##
    # Get the maximum number of 'X_NODE_' instances.
    #
    set max [_getMaxNodes $db $module]

    ##
    # Inside the top module loop over all instances.
    #
    $db foreach inst $module inst {
        ##
        # Set the instance name.
        #
        set instName [$db oid oname $inst]

        ##
        # Initialize the preplace information.
        #
        set preplace "preplace inst $instName -pg 1 "

        ##
        # Generate preplace information depending on the cell name.
        #
        switch [$db oid cname $inst] {
            "MT_Branch"    -
            "MT_Branchoil" {
                ##
                # Define the tmid pin as hidden (no net connected).
                #
                set pin [$db search pin $inst "tmid"]
                if {![$db oid isnull $pin]} {
                    puts $out "hide $instName [$db oid pname $pin]"
                }

                ##
                # Define the m_min pin as hidden (no net connected).
                #
                set pin [$db search pin $inst "m_min"]
                if {![$db oid isnull $pin]} {
                    puts $out "hide $instName [$db oid pname $pin]"
                }

                ##
                # Depending on the instance name write preplace and rotate info.
                #
                switch -glob -nocase $instName {
                    "*_BYPASS" {
                        append preplace "-lvl [expr {$max + 1}] -y 300 "
                    }
                    "*_TOP_YOKE"   {
                        append preplace "-lvl [expr {$max + 2}] -y 200 "
                    }
                    "*_BOTTOM_YOKE" {
                        append preplace "-lvl [expr {$max + 2}] -y 500 "
                    }
                    "*_COVER" {
                        append preplace "-lvl [expr {$max + 3}] -y 100 "
                        puts $out "orient $instName R270"
                    }
                    "*_RADIATOR_SLICE_1" {
                        append preplace "-lvl [expr {$max + 4}] -y 200 "
                    }
                    "*_RADIATOR_SLICE_2" {
                        append preplace "-lvl [expr {$max + 4}] -y 300 "
                    }
                    "*_RADIATOR_SLICE_3" {
                        append preplace "-lvl [expr {$max + 4}] -y 400 "
                    }
                    default    {
                        set level [_getLevel $instName]
                        if {$level > 0} {append preplace "-lvl $level "}

                        append preplace "-y 300 "
                    }
                }
            }
            "MT_Node" {
                ##
                # Depending on the instance name write out the orientation
                # and set a Y position.
                #
                switch -glob -nocase $instName {
                    "*TOP*" {
                        append preplace "-y 100 "
                        puts $out "rotate $instName R270"
                    }
                    "*BOTTOM*" {
                        append preplace "-y 500 "
                        puts $out "rotate $instName R90"

                        ##
                        # Define the m_sid pin as hidden (no net connected).
                        #
                        set pin [$db search pin $inst "m_sid"]
                        if {![$db oid isnull $pin]} {
                            puts $out "hide $instName [$db oid pname $pin]"
                        }
                    }
                }

                ##
                # Get the desired level for this instance.
                #
                set level [_getLevel $instName]

                ##
                # If the level is '0' then move the instance to one level
                # after the max node count.
                #
                if {$level == 0} {set level [expr {$max + 1}]}

                ##
                # If a level is set then add it to the preplace info.
                #
                if {$level > 0} {append preplace "-lvl $level "}
            }
        }

        ##
        # Write out the preplace info.
        #
        puts $out $preplace
    }

    close $out

    ##
    # Quit the GUI.
    #
    gui quit
}


##
# Use gui database runOrRegisterChangedCallback to immediately run
# GeneratePlacement if we have a database, or otherwise register the proc to be
# executed after the database is available.
#
gui database runOrRegisterChangedCallback GeneratePlacement