Remove restriction on size of constants
[iverilog.git] / pad_to_width.cc
blobefd10fc6e749f0cc33c8bde1c64be5d2716a754f
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"
29 * This function transforms an expression by padding the high bits
30 * with V0 until the expression has the desired width. This may mean
31 * not transforming the expression at all, if it is already wide
32 * enough.
34 NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
36 if (wid <= expr->expr_width())
37 return expr;
39 /* If the expression is a const, then replace it with a wider
40 const. This is a more efficient result. */
41 if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
42 verinum eval = tmp->value();
43 bool signed_flag = eval.has_sign();
45 verinum::V pad = verinum::V0;
46 if (signed_flag)
47 pad = eval.get(eval.len()-1);
48 verinum oval (pad, wid, eval.has_len());
50 for (unsigned idx = 0 ; idx < eval.len() ; idx += 1)
51 oval.set(idx, eval.get(idx));
53 oval.has_sign(signed_flag);
54 tmp = new NetEConst(oval);
55 delete expr;
56 return tmp;
59 NetESelect*tmp = new NetESelect(expr, 0, wid);
60 tmp->set_line(*expr);
61 tmp->cast_signed(expr->has_sign());
62 return tmp;
66 * Pad a NetNet to the desired vector width by concatenating a
67 * NetConst of constant zeros. Use a NetConcat node to do the
68 * concatenation.
70 NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
72 NetScope*scope = net->scope();
74 if (net->vector_width() >= wid)
75 return net;
77 // Make the NetConcat and connect the input net to the lsb input.
78 NetConcat*cc = new NetConcat(scope, scope->local_symbol(), wid, 2);
79 des->add_node(cc);
80 connect(cc->pin(1), net->pin(0));
82 // Make a NetConst of the desired width and connect in to the
83 // lsb input of the NetConcat.
84 verinum pad(verinum::V0, wid - net->vector_width());
85 NetConst*con = new NetConst(scope, scope->local_symbol(), pad);
86 des->add_node(con);
87 connect(cc->pin(2), con->pin(0));
89 // Make a NetNet for the NetConst to NetConcat link.
90 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
91 NetNet::WIRE, wid - net->vector_width());
92 tmp->data_type( net->data_type() );
93 tmp->local_flag(true);
94 connect(cc->pin(2), tmp->pin(0));
96 // Create a NetNet of the output width and connect it to the
97 // NetConcat node output pin.
98 tmp = new NetNet(scope, scope->local_symbol(),
99 NetNet::WIRE, wid);
100 tmp->data_type( net->data_type() );
101 tmp->local_flag(true);
102 connect(cc->pin(0), tmp->pin(0));
104 return tmp;
107 NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid)
109 NetScope*scope = net->scope();
111 if (net->vector_width() >= wid)
112 return net;
114 NetSignExtend*se
115 = new NetSignExtend(scope, scope->local_symbol(), wid);
116 se->set_line(*net);
117 des->add_node(se);
119 NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
120 tmp->set_line(*net);
121 tmp->local_flag(true);
122 tmp->data_type(net->data_type());
123 tmp->set_signed(true);
125 connect(tmp->pin(0), se->pin(0));
126 connect(se->pin(1), net->pin(0));
128 return tmp;
131 NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
133 NetScope*scope = net->scope();
135 if (net->vector_width() <= wid)
136 return net;
138 NetPartSelect*ps = new NetPartSelect(net, 0, wid, NetPartSelect::VP);
139 des->add_node(ps);
140 ps->set_line(*net);
142 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
143 NetNet::WIRE, wid);
144 tmp->data_type(net->data_type());
145 tmp->local_flag(true);
146 tmp->set_line(*tmp);
147 connect(ps->pin(0), tmp->pin(0));
149 return tmp;
153 * $Log: pad_to_width.cc,v $
154 * Revision 1.20 2005/12/22 15:43:47 steve
155 * pad_to_width handles signed expressions.
157 * Revision 1.19 2005/07/07 16:22:49 steve
158 * Generalize signals to carry types.
160 * Revision 1.18 2005/05/24 01:44:28 steve
161 * Do sign extension of structuran nets.
163 * Revision 1.17 2005/04/24 23:44:02 steve
164 * Update DFF support to new data flow.
166 * Revision 1.16 2005/01/12 03:17:37 steve
167 * Properly pad vector widths in pgassign.
169 * Revision 1.15 2004/02/18 17:11:57 steve
170 * Use perm_strings for named langiage items.
172 * Revision 1.14 2003/03/06 00:28:42 steve
173 * All NetObj objects have lex_string base names.
175 * Revision 1.13 2003/01/27 05:09:17 steve
176 * Spelling fixes.
178 * Revision 1.12 2003/01/26 21:15:59 steve
179 * Rework expression parsing and elaboration to
180 * accommodate real/realtime values and expressions.
182 * Revision 1.11 2002/08/12 01:35:00 steve
183 * conditional ident string using autoconfig.
185 * Revision 1.10 2002/05/25 16:43:22 steve
186 * Better padding of constants.
188 * Revision 1.9 2001/10/28 01:14:53 steve
189 * NetObj constructor finally requires a scope.
191 * Revision 1.8 2001/07/25 03:10:49 steve
192 * Create a config.h.in file to hold all the config
193 * junk, and support gcc 3.0. (Stephan Boettcher)