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
###############################################################################
# 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.
# =============================================================================
#   @userware
#       Detect Cells Directly Connected to Input
#   @section
#       Analyze the Loaded Database
#   @description
#       Detect and highlight any FF/latches (with specific std cell name
#       pattern) that is directly connected to the input ports (directly driven
#       by input ports without any buffers/inverters).
#   @files
#       cust22/directlyConnectedFlops.tcl
#   @tag
#       zdb
###############################################################################


##
# Initialize the list with the std cell name patterns matching FF/latches.
#
set stdCellFF {
    "*FF*"
    "*latch*"
}


##
# Define color number to highlight the FF.
#
set ffInstColor  0
set ffPinColor   1
set modPortColor 2


##
# Configure if net segment IDs and highlights should be calculated. Use this
# option with care (long runtime).
#
set createNetSeg 0
set netSegColor  3


# -----------------------------------------------------------------------------
# _identifyFFs - Mark all cells that match one of the 'stdCellFF' patterns.
# -----------------------------------------------------------------------------
#
proc _identifyFFs {db} {
    global stdCellFF

    ##
    # Create a list of all cells in the loaded database.
    #
    set cellList {}
    $db foreach cell cell {lappend cellList $cell}

    ##
    # Count the number of cells.
    #
    set cellCount [llength $cellList]
    set i 0

    ##
    # Loop over all cells in the cellList.
    #
    foreach cell $cellList {
        zprogress update "" [incr i] $cellCount

        ##
        # Clear the red flag at this cell.
        #
        $db flag $cell clear red

        ##
        # Get the name of this cell.
        #
        set cellName [$db oid oname $cell]

        ##
        # Match the cell name against each defined pattern.
        #
        foreach pattern $stdCellFF {
            ##
            # Mark matching cells with the red flag.
            #
            if {[string match $pattern $cellName]} {
                $db flag $cell set red
                continue
            }
        }
    }
}


# -----------------------------------------------------------------------------
# _getInputPorts - Return a list of all input ports for the given module.
# -----------------------------------------------------------------------------
#
proc _getInputPorts {db module} {
    ##
    # Loop over all ports of the given module.
    #
    set inputPortList {}
    $db foreach port $module port {
        ##
        # If the direction is input then add the port to the result list.
        #
        if {[$db directionOf $port] == "input"} {lappend inputPortList $port}
    }
    return $inputPortList
}


# -----------------------------------------------------------------------------
# _findDirectlyConnectedFFs - Detect and highlight any FF/latch that is
#                             directly connected to an input port.
# -----------------------------------------------------------------------------
#
proc _findDirectlyConnectedFFs {db} {
    global ffInstColor ffPinColor modPortColor createNetSeg netSegColor

    ##
    # Return if the database is empty.
    #
    if {$db == {}} {
        return
    }

    ##
    # Start the progress bar.
    #
    zprogress begin

    ##
    # Call a procedure to identify FFs/Latches
    #
    zprogress push "Identify FSs" 0.1
    _identifyFFs $db
    if {[zprogress pop]} {
        return
    }

    ##
    # Create a list of all top modules in the loaded database.
    #
    set topList {}
    $db foreach top top {lappend topList $top}

    ##
    # Count the number of top modules.
    #
    set topCount [llength $topList]
    set i 0

    ##
    # Loop over all top modules in the topList.
    #
    set resultList {}
    foreach top $topList {
        set topName [$db oid oname $top]
        zprogress push $topName [expr {[incr i] / double($topCount)}]

        ##
        # Get the list of all input ports.
        #
        set inputPortList [_getInputPorts $db $top]

        ##
        # Count the number of input ports.
        #
        set inputCount [llength $inputPortList]
        set p 0

        ##
        # Loop over all input ports of this top module.
        #
        foreach port $inputPortList {
            zprogress push "" [expr {[incr p] / double($inputCount)}]

            ##
            # Skip unconnected ports.
            #
            if {![$db isConnected $port]} {
                continue
            }

            ##
            # Create a list with all connections of this net.
            #
            set pinList {}
            set connectedNet  [$db connectedNet $port]
            $db flat foreach pin $connectedNet pin {
                lappend pinList $pin
            }

            ##
            # Loop over all connections of this net.
            #
            foreach pin $pinList {
                ##
                # Skip connections to ports.
                #
                if {[$db oid type $pin] == "port"} {
                    continue
                }

                ##
                # Convert the connected pin to an instance object and
                # get the referenced cell of the instance.
                #
                set inst [$db oid convertTo inst $pin]
                set cell [$db down $inst]

                ##
                # If the cell is flagged with the red flag then it is a result.
                #
                if {[$db flag $cell is red]} {
                    ##
                    # Add this instance to the result list.
                    #
                    if {[llength $resultList] > 0} {
                        lappend resultList "------"
                    }
                    lappend resultList $port $inst

                    ##
                    # Highlight the instance as well as the pin and port of the
                    # connection.
                    #
                    $db hilight $inst   set $ffInstColor
                    $db hilight $pin    set $ffPinColor
                    $db hilight $port   set $modPortColor

                    ##
                    # Only if 'createNetSeg' is true run the code to calculate
                    # and highlight net segment OIDs.
                    #
                    if {$createNetSeg} {
                        set flatPort [$db oid searchTreeBased $port]
                        set flatPin  [$db oid searchTreeBased $pin]
                        set netSeg   [$db oid createNetSeg $flatPort $flatPin]
                        $db flathilight $netSeg set $netSegColor
                    }
                }
            }
        }
        if {[zprogress pop]} {
            break
        }
    }

    ##
    # Show the result in the 'Mem' tab.
    #
    gui window show Mem
    gui mem append $resultList

    ##
    # End the progress bar.
    #
    zprogress end
}


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