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
###############################################################################
# Copyright (c) 2011-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
#       Do CDC Checks
#   @section
#       Miscellaneous Userware Examples
#   @description
#       Do additional CDC checks. The user can specify that input ports are in
#       sync with a specific clock.
#   @files
#       cust15/additionalCDC.tcl
#   @tag
#       zdb
###############################################################################


# -----------------------------------------------------------------------------
# _checkMoreCDC - This procedure do the additional CDC check.
# -----------------------------------------------------------------------------
#
proc _checkMoreCDC {w db topInputPorts} {
    ##
    # Show and clear the Cone window.
    #
    gui window show Cone
    gui cone clear

    ##
    # Loop over all top level ports and check all ports if a clock net name
    # was specified.
    #
    set i 1
    foreach port $topInputPorts {
        ##
        # Get the name of the 'sync' clock.
        #
        set syncClk [$w.cl$i get]
        incr i

        ##
        # Skip if the 'sync' clock is empty.
        #
        if {$syncClk == ""} {
            continue
        }

        ##
        # If the start port is a portBus then use the first sub port.
        #
        if {[$db oid type $port] == "portBus"} {
            set sub {}
            $db foreach port $port sub break
            if {$sub != {}} {
                set port $sub
            }
        }

        ##
        # Do a path extraction from the start port to all clocked cells.
        #
        set res [$db cone -paths -out -targetFlaggedCell clock $port]

        ##
        # Loop over the result list.
        #
        foreach path $res {
            set path   [lrange $path 1 end]
            set target [lindex $path end]
            set targetInst [$db oid convertTo inst $target]
            set hiCol ""

            ##
            # Loop over all pins of the target instance to find the clock port.
            #
            $db foreach pin $targetInst pin {
                if {[$db isBusMember $pin]} {
                    continue
                }
                set port [$db oid convertTo port $pin]
                if {![$db flag $port is clock]} {
                    continue
                }
                if {![$db isConnected $pin]} {
                    continue
                }
                set net [$db connectedNet $pin]
                set net [$db flat signalOf $net]

                ##
                # Set the color used to highlight the result.
                #
                set hiCol 0
                if {[$db oid oname $net] == $syncClk} {set hiCol 1}
                break
            }

            ##
            # The target instance should have a clock port.
            #
            if {$hiCol == ""} {
                zmessage print ERR "Target has no clock port."
                continue
            }

            ##
            # Highlight the target instance.
            #
            $db hilight $targetInst set $hiCol

            ##
            # Highlight the pins/ports of the path. Also create netSegments
            # between the pins/ports of the result.
            #
            set pair {}
            foreach p $path {
                $db hilight $p set $hiCol
                lappend pair $p
                if {[llength $pair] == 2} {
                    set netseg [$db oid createNetSeg \
                                [lindex $pair 0] [lindex $pair 1]]
                    $db flathilight $netseg set $hiCol
                    set pair {}
                }
            }
            gui cone append $path
        }
    }
    gui highlight changed
    gui cone zoom fullfit
}


# -----------------------------------------------------------------------------
# _createDlg - Create the dialog window to control the additional CDC check.
# -----------------------------------------------------------------------------
#
proc _createDlg {w db topInputPorts clockNetList} {
    ##
    # Create a new toplevel window.
    #
    destroy $w
    toplevel $w
    wm transient $w .
    wm title     $w "Additional CDC"

    ##
    # Create a list of all clock net names and store the length
    # of the longest clock net name.
    #
    set clockNetValues {}
    set maxLen 0
    foreach clkNet $clockNetList {
        set clkName [$db oid oname $clkNet]
        lappend clockNetValues $clkName
        set len [string length $clkName]
        if {$len > $maxLen} {
            set maxLen $len
        }
    }

    ##
    # Layout the components in the result dialog.
    #
    set row 1
    foreach port $topInputPorts {
        set ttype [$db oid type  $port]
        set tname [$db oid oname $port]
        ttk::label $w.tl$row -text "Check if '$ttype $tname' is in sync with:"
        ttk::combobox $w.cl$row -values $clockNetValues -state readonly \
                                -width $maxLen
        grid $w.tl$row -row $row -column 0 -sticky e
        grid $w.cl$row -row $row -column 1 -sticky w
        incr row
    }
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1

    ##
    # Add a 'Check' button to perform additional CDC checks and a 'Done'
    # button to close the dialog.
    #
    ttk::frame $w.bottom
    ttk::button $w.bottom.check -text "Check" \
                    -command [list _checkMoreCDC $w $db $topInputPorts]
    ttk::button $w.bottom.done  -text "Done"  -command "destroy $w"
    pack $w.bottom.check $w.bottom.done -side left -padx 2 -pady 1

    grid $w.bottom -row 0 -column 0 -columnspan 2
}


# -----------------------------------------------------------------------------
# _additionalCDC - Prepare all data needed to perform additional CDC checks.
# -----------------------------------------------------------------------------
#
proc _additionalCDC {} {
    ##
    # Get the corresponding database.
    #
    set db [gui database get]

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

    ##
    # Only one top module is allowed.
    #
    set topList {}
    $db foreach top top {lappend topList $top}
    set top [lindex $topList 0]
    if {[llength $topList] != 1} {
        gui console printWarning \
            "Multiple top modules: using [$db oid oname $top]"
    }

    ##
    # Create a new CDC (clock domain analyzer) object.
    #
    set cdc [$db cdc new $top]

    ##
    # Create a list with all clock nets.
    #
    set clockNetList {}
    array set _clkNet {}
    foreach domainIdx [$cdc getDomainList] {
        ##
        # Get all clock pins for this domain
        #
        foreach ffPin [$cdc getClkPinList $domainIdx] {
            if {![$db isConnected $ffPin]} {
                continue
            }
            set net [$db connectedNet $ffPin]
            set net [$db flat signalOf $net]
            if {![info exists _clkNet($net)]} {
                lappend clockNetList $net
                set _clkNet($net) 1
            }
        }
    }

    ##
    # Create a list with all top level input ports (without clock sources).
    #
    set topInputPorts {}
    $db foreach oPort input $top port {
        if {[$db oid type $port] == "port"} {
            if {![$db isConnected $port]} {
                continue
            }
            set net [$db connectedNet $port]
            set net [$db flat signalOf $net]
            if {[info exists _clkNet($net)]} {
                continue
            }
        }
        lappend topInputPorts $port
    }

    ##
    # Create the 'Additional CDC' dialog.
    #
    _createDlg .moreCDC $db $topInputPorts $clockNetList
}


##
# Extend the menu by an "Userware" entry and add the command
# "Additional CDC" below the "Userware" menu.
#
gui menu command {"Userware" "Additional CDC"} {_additionalCDC}