Make %t with real values use specified width if given.
[iverilog.git] / nodangle.cc
blobb90eee00022a2927313e75da51327486858401ea
1 /*
2 * Copyright (c) 1999 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $"
21 #endif
23 # include "config.h"
26 * This functor scans the design looking for dangling objects and
27 * excess local signals. These deletions are not necessarily required
28 * for proper functioning of anything, but they can clean up the
29 * appearance of design files that are generated.
31 # include "functor.h"
32 # include "netlist.h"
33 # include "compiler.h"
35 class nodangle_f : public functor_t {
36 public:
37 void event(Design*des, NetEvent*ev);
38 void signal(Design*des, NetNet*sig);
40 unsigned count_;
41 unsigned stotal, etotal;
44 void nodangle_f::event(Design*des, NetEvent*ev)
46 /* If there are no references to this event, then go right
47 ahead and delete in. There is no use looking further at
48 it. */
49 if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
50 delete ev;
51 etotal += 1;
52 return;
55 /* Try to remove duplicate probes from the event. */
56 for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
57 unsigned jdx = idx + 1;
58 while (jdx < ev->nprobe()) {
59 NetEvProbe*ip = ev->probe(idx);
60 NetEvProbe*jp = ev->probe(jdx);
62 if (ip->edge() != jp->edge()) {
63 jdx += 1;
64 continue;
67 bool fully_connected = true;
68 for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
69 unsigned ipin = 0;
70 bool connected_flag = false;
71 for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
72 if (connected(ip->pin(ipin), jp->pin(jpin))) {
73 connected_flag = true;
74 break;
77 if (!connected_flag) {
78 fully_connected = false;
79 break;
83 if (fully_connected) {
84 delete jp;
85 } else {
86 jdx += 1;
91 /* Try to find all the events that are similar to me, and
92 replace their references with references to me. */
93 list<NetEvent*> match;
94 ev->find_similar_event(match);
95 for (list<NetEvent*>::iterator idx = match.begin()
96 ; idx != match.end() ; idx ++) {
98 NetEvent*tmp = *idx;
99 assert(tmp != ev);
100 tmp ->replace_event(ev);
105 void nodangle_f::signal(Design*des, NetNet*sig)
107 /* Cannot delete signals referenced in an expression
108 or an l-value. */
109 if (sig->get_refs() > 0)
110 return;
112 /* Cannot delete the ports of tasks or functions. There are
113 too many places where they are referenced. */
114 if ((sig->port_type() != NetNet::NOT_A_PORT)
115 && (sig->scope()->type() == NetScope::TASK))
116 return;
118 if ((sig->port_type() != NetNet::NOT_A_PORT)
119 && (sig->scope()->type() == NetScope::FUNC))
120 return;
122 /* Can't delete ports of cells. */
123 if ((sig->port_type() != NetNet::NOT_A_PORT)
124 && (sig->scope()->attribute(perm_string::literal("ivl_synthesis_cell")) != verinum()))
125 return;
127 /* Check to see if the signal is completely unconnected. If
128 all the bits are unlinked, then delete it. */
129 bool linked_flag = false;
130 for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1)
131 if (sig->pin(idx).is_linked()) {
132 linked_flag = true;
133 break;
136 if (! linked_flag) {
137 delete sig;
138 stotal += 1;
139 return;
142 /* The remaining things can only be done to synthesized
143 signals, not ones that appear in the original Verilog. */
144 if (! sig->local_flag())
145 return;
147 /* Check to see if there is some significant signal connected
148 to every pin of this signal. */
149 unsigned significant_flags = 0;
150 for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) {
151 Nexus*nex = sig->pin(idx).nexus();
153 for (Link*cur = nex->first_nlink()
154 ; cur ; cur = cur->next_nlink()) {
156 if (cur == &sig->pin(idx))
157 continue;
159 NetNet*cursig = dynamic_cast<NetNet*>(cur->get_obj());
160 if (cursig == 0)
161 continue;
163 if (cursig->local_flag())
164 continue;
166 significant_flags += 1;
167 break;
170 if (significant_flags <= idx)
171 break;
174 /* If every pin is connected to another significant signal,
175 then I can delete this one. */
176 if (significant_flags == sig->pin_count()) {
177 count_ += 1;
178 delete sig;
179 stotal += 1;
183 void nodangle(Design*des)
185 nodangle_f fun;
186 unsigned count_iterations = 0;
187 fun.stotal = 0;
188 fun.etotal = 0;
190 do {
191 fun.count_ = 0;
192 des->functor(&fun);
193 count_iterations += 1;
195 if (verbose_flag) {
196 cout << " ... " << count_iterations << " iterations"
197 << " deleted " << fun.stotal << " dangling signals"
198 << " and " << fun.etotal << " events."
199 << " (count=" << fun.count_ << ")" << endl;
202 } while (fun.count_ > 0);
207 * $Log: nodangle.cc,v $
208 * Revision 1.21 2004/02/20 18:53:35 steve
209 * Addtrbute keys are perm_strings.
211 * Revision 1.20 2004/01/15 06:04:19 steve
212 * Remove duplicate NetEvProbe objects in nodangle.
214 * Revision 1.19 2003/06/25 04:46:03 steve
215 * Do not elide ports of cells.
217 * Revision 1.18 2003/04/22 04:48:30 steve
218 * Support event names as expressions elements.
220 * Revision 1.17 2002/08/12 01:35:00 steve
221 * conditional ident string using autoconfig.
223 * Revision 1.16 2002/07/24 16:24:45 steve
224 * Rewrite find_similar_event to support doing
225 * all event matching and replacement in one
226 * shot, saving time in the scans.
228 * Revision 1.15 2002/05/26 01:39:02 steve
229 * Carry Verilog 2001 attributes with processes,
230 * all the way through to the ivl_target API.
232 * Divide signal reference counts between rval
233 * and lval references.
235 * Revision 1.14 2002/02/02 06:13:38 steve
236 * event find_similar should not find self.
238 * Revision 1.13 2001/07/27 02:41:55 steve
239 * Fix binding of dangling function ports. do not elide them.
241 * Revision 1.12 2001/07/25 03:10:49 steve
242 * Create a config.h.in file to hold all the config
243 * junk, and support gcc 3.0. (Stephan Boettcher)
245 * Revision 1.11 2001/02/17 05:14:35 steve
246 * Cannot elide task ports.
248 * Revision 1.10 2000/11/19 20:48:53 steve
249 * Killing some signals might make others killable.
251 * Revision 1.9 2000/11/18 05:12:45 steve
252 * Delete unreferenced signals no matter what.
254 * Revision 1.8 2000/06/25 19:59:42 steve
255 * Redesign Links to include the Nexus class that
256 * carries properties of the connected set of links.
258 * Revision 1.7 2000/05/31 02:26:49 steve
259 * Globally merge redundant event objects.
261 * Revision 1.6 2000/05/07 04:37:56 steve
262 * Carry strength values from Verilog source to the
263 * pform and netlist for gates.
265 * Change vvm constants to use the driver_t to drive
266 * a constant value. This works better if there are
267 * multiple drivers on a signal.
269 * Revision 1.5 2000/04/28 21:00:29 steve
270 * Over agressive signal elimination in constant probadation.
272 * Revision 1.4 2000/04/18 04:50:20 steve
273 * Clean up unneeded NetEvent objects.
275 * Revision 1.3 2000/02/23 02:56:55 steve
276 * Macintosh compilers do not support ident.
278 * Revision 1.2 1999/11/28 23:42:02 steve
279 * NetESignal object no longer need to be NetNode
280 * objects. Let them keep a pointer to NetNet objects.
282 * Revision 1.1 1999/11/18 03:52:20 steve
283 * Turn NetTmp objects into normal local NetNet objects,
284 * and add the nodangle functor to clean up the local
285 * symbols generated by elaboration and other steps.