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 | ###############################################################################
# Copyright (c) 2006-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
# Replace AND-Gates
# @section
# Modify the Loaded Database
# @description
# Replace any two connected and2 gates by one module.
# @files
# replaceAnd.tcl
# @example
# demo/verilog/bus85.f
# @cmdline
# -verilog
# -F @example[0]
# -userware @files[0]
# @tag
# gui zdb
###############################################################################
# -----------------------------------------------------------------------------
# run_replace - This is the main function which processes the database and
# replaces any two connected and2 gates by one module.
# -----------------------------------------------------------------------------
#
proc run_replace {db} {
##
# Return if the database is empty.
#
if {$db == {}} {
return
}
##
# Loop over all modules in the database.
#
array set _hash {}
$db foreach module module {
##
# Loop over all instances in this module and flag all instances
# of "and2" with the 'red' flag.
#
$db foreach inst $module inst {
if {[$db oid cname $inst] == "and2"} {$db flag $inst set red}
}
##
# Again loop over all instances in this module, skip all instances
# without the red flag.
#
$db foreach inst $module inst {
if {![$db flag $inst is red]} continue
##
# Loop over all pins of a red flagged instance,
# only examine the outputpin.
#
$db foreach pin $inst pin {
if {[$db directionOf $pin] != "output"} continue
##
# If the output pin is connected, then get the
# connected net
#
if {![$db isConnected $pin]} {
break
}
set net [$db connectedNet $pin]
##
# Count the number of connections. Only a net with two
# connections can be a candidate.
#
set count 0
$db foreach pin $net next {incr count}
if {$count > 2} {
break
}
##
# Loop over all pins of this net and skip the one we're
# coming from.
#
$db foreach pin $net next {
if {$next == $pin} continue
if {[$db oid type $next] == "port"} continue
##
# Create an instance OID out of this pin OID.
#
set nextInst [lreplace [lrange $next 0 end-1] 0 0 inst]
##
# If this instance is flagged red, then we've got a hit.
#
if {[$db flag $nextInst is red]} {
##
# Clear the red flag to avoid duplicate processing.
#
$db flag $nextInst clear red
$db flag $inst clear red
##
# Remember the two instances (in a hash table) to be
# processed later.
#
set _hash($inst) $nextInst
}
}
}
}
}
##
# Create a new module including two and gates.
#
set and2_notFound 1
$db foreach module module {
if {[$db oid oname $module] == "and2"} {
set and2_notFound 0
break
}
}
if {$and2_notFound} {
$db load module and2
$db load port Y output
$db load port A input
$db load port B input
}
$db load module encapsulate_2_gates
$db load port Y output
$db load port A input
$db load port B input
$db load port C input
$db load inst U1 and2
$db load inst U2 and2
$db load net A -port A -pin U1 A
$db load net B -port B -pin U1 B
$db load net C -port C -pin U2 A
$db load net Y -port Y -pin U2 Y
$db load net n -pin U1 Y -pin U2 B
##
# Process all instance pairs in the hash table _hash.
#
foreach {i1 i2} [array get _hash] {
##
# Get the parent module and reload this module.
#
set parent [$db parentModule $i1]
$db reloadModule [$db oid oname $parent]
##
# Place a new instance of encapsulate_2_gates in this module.
#
set iName "[$db oid oname $i1]&[$db oid oname $i2]"
$db load inst $iName encapsulate_2_gates
set iPins {A B C}
set idx 0
$db foreach pin $i1 p {
##
# Skip all unconnected pins.
# Get the net connected to this pin.
#
if {![$db isConnected $p]} {
continue
}
set net [$db connectedNet $p]
##
# Remember the interconnection to i2.
#
if {[$db directionOf $p] == "output"} {
$db foreach pin $net np {
if {[$db directionOf $np] == "output"} {
continue
}
set skipPin $np
}
continue
}
##
# Connect the next input pin.
#
set pName [lindex $iPins $idx]
incr idx
$db load net [$db oid oname $net] -pin $iName $pName
}
$db foreach pin $i2 p {
##
# Skip all unconnected pins.
# Get the net connected to this pin.
#
if {![$db isConnected $p]} {
continue
}
set net [$db connectedNet $p]
##
# Connect the output pin
#
if {[$db directionOf $p] == "output"} {
$db load net [$db oid oname $net] -pin $iName Y
continue
}
##
# Skip interconnection to i1.
#
if {[$db oid pname $p] == [$db oid pname $skipPin]} {
continue
}
##
# Connect the next input pin.
#
set pName [lindex $iPins $idx]
incr idx
$db load net [$db oid oname $net] -pin $iName $pName
}
##
# Flag i1 and i2 as zombies to be deleted later.
#
$db flag $i1 set zombie
$db flag $i2 set zombie
}
##
# Delete all zombies.
#
$db deleteZombies
##
# Remove registration to avoid endless loop when calling
# gui database changed below.
#
gui database removeChangedCallback run_replace
##
# Inform the GUI that the database has changed.
#
gui database changed $db
}
##
# Use gui database runOrRegisterChangedCallback to immediately run
# run_replace
# if we have a database, or otherwise register the proc to be executed after
# the database is available.
#
gui database runOrRegisterChangedCallback run_replace
|