Fix for assertion error when expanding macro.
[iverilog.git] / pad_to_width.cc
blob784e98918f3fcb506971baf76f11a5fe2843512e
1 /*
2 * Copyright (c) 1999-2005 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: pad_to_width.cc,v 1.20 2005/12/22 15:43:47 steve Exp $"
21 #endif
23 # include "config.h"
25 # include "netlist.h"
26 # include "netmisc.h"
30 * This function transforms an expression by padding the high bits
31 * with V0 until the expression has the desired width. This may mean
32 * not transforming the expression at all, if it is already wide
33 * enough.
35 NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
37 if (wid <= expr->expr_width())
38 return expr;
40 /* If the expression is a const, then replace it with a wider
41 const. This is a more efficient result. */
42 if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
43 verinum oval = pad_to_width(tmp->value(), wid);
44 tmp = new NetEConst(oval);
45 delete expr;
46 return tmp;
49 NetESelect*tmp = new NetESelect(expr, 0, wid);
50 tmp->set_line(*expr);
51 tmp->cast_signed(expr->has_sign());
52 return tmp;
56 * Pad a NetNet to the desired vector width by concatenating a
57 * NetConst of constant zeros. Use a NetConcat node to do the
58 * concatenation.
60 NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
62 NetScope*scope = net->scope();
64 if (net->vector_width() >= wid)
65 return net;
67 // Make the NetConcat and connect the input net to the lsb input.
68 NetConcat*cc = new NetConcat(scope, scope->local_symbol(), wid, 2);
69 des->add_node(cc);
70 connect(cc->pin(1), net->pin(0));
72 // Make a NetConst of the desired width and connect in to the
73 // lsb input of the NetConcat.
74 verinum pad(verinum::V0, wid - net->vector_width());
75 NetConst*con = new NetConst(scope, scope->local_symbol(), pad);
76 des->add_node(con);
77 connect(cc->pin(2), con->pin(0));
79 // Make a NetNet for the NetConst to NetConcat link.
80 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
81 NetNet::WIRE, wid - net->vector_width());
82 tmp->data_type( net->data_type() );
83 tmp->local_flag(true);
84 connect(cc->pin(2), tmp->pin(0));
86 // Create a NetNet of the output width and connect it to the
87 // NetConcat node output pin.
88 tmp = new NetNet(scope, scope->local_symbol(),
89 NetNet::WIRE, wid);
90 tmp->data_type( net->data_type() );
91 tmp->local_flag(true);
92 connect(cc->pin(0), tmp->pin(0));
94 return tmp;
97 NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid)
99 NetScope*scope = net->scope();
101 if (net->vector_width() >= wid)
102 return net;
104 NetSignExtend*se
105 = new NetSignExtend(scope, scope->local_symbol(), wid);
106 se->set_line(*net);
107 des->add_node(se);
109 NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
110 tmp->set_line(*net);
111 tmp->local_flag(true);
112 tmp->data_type(net->data_type());
113 tmp->set_signed(true);
115 connect(tmp->pin(0), se->pin(0));
116 connect(se->pin(1), net->pin(0));
118 return tmp;
121 NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
123 NetScope*scope = net->scope();
125 if (net->vector_width() <= wid)
126 return net;
128 NetPartSelect*ps = new NetPartSelect(net, 0, wid, NetPartSelect::VP);
129 des->add_node(ps);
130 ps->set_line(*net);
132 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
133 NetNet::WIRE, wid);
134 tmp->data_type(net->data_type());
135 tmp->local_flag(true);
136 tmp->set_line(*tmp);
137 connect(ps->pin(0), tmp->pin(0));
139 return tmp;
143 * $Log: pad_to_width.cc,v $
144 * Revision 1.20 2005/12/22 15:43:47 steve
145 * pad_to_width handles signed expressions.
147 * Revision 1.19 2005/07/07 16:22:49 steve
148 * Generalize signals to carry types.
150 * Revision 1.18 2005/05/24 01:44:28 steve
151 * Do sign extension of structuran nets.
153 * Revision 1.17 2005/04/24 23:44:02 steve
154 * Update DFF support to new data flow.
156 * Revision 1.16 2005/01/12 03:17:37 steve
157 * Properly pad vector widths in pgassign.
159 * Revision 1.15 2004/02/18 17:11:57 steve
160 * Use perm_strings for named langiage items.
162 * Revision 1.14 2003/03/06 00:28:42 steve
163 * All NetObj objects have lex_string base names.
165 * Revision 1.13 2003/01/27 05:09:17 steve
166 * Spelling fixes.
168 * Revision 1.12 2003/01/26 21:15:59 steve
169 * Rework expression parsing and elaboration to
170 * accommodate real/realtime values and expressions.
172 * Revision 1.11 2002/08/12 01:35:00 steve
173 * conditional ident string using autoconfig.
175 * Revision 1.10 2002/05/25 16:43:22 steve
176 * Better padding of constants.
178 * Revision 1.9 2001/10/28 01:14:53 steve
179 * NetObj constructor finally requires a scope.
181 * Revision 1.8 2001/07/25 03:10:49 steve
182 * Create a config.h.in file to hold all the config
183 * junk, and support gcc 3.0. (Stephan Boettcher)