Fix for assertion error when expanding macro.
[iverilog.git] / netmisc.cc
blobcbe8983a4f5a51d14b2d3a2a976c348427c3a885
1 /*
2 * Copyright (c) 2001-2003 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: netmisc.cc,v 1.14 2007/06/02 03:42:13 steve Exp $"
21 #endif
23 # include "config.h"
25 # include "netlist.h"
26 # include "netmisc.h"
27 # include "PExpr.h"
28 # include "pform_types.h"
29 # include "ivl_assert.h"
31 NetNet* add_to_net(Design*des, NetNet*sig, long val)
33 if (val == 0)
34 return sig;
35 #if 0
36 NetScope*scope = sig->scope();
37 unsigned long abs_val = (val >= 0)? val : (-val);
38 unsigned width = sig->pin_count();
40 verinum val_v (abs_val, width);
42 NetConst*val_c = new NetConst(scope, scope->local_symbol(), val_v);
44 NetNet*val_s = new NetNet(scope, scope->local_symbol(),
45 NetNet::IMPLICIT, width);
46 val_s->local_flag(true);
48 NetNet*res = new NetNet(scope, scope->local_symbol(),
49 NetNet::IMPLICIT, width);
50 res->local_flag(true);
52 NetAddSub*add = new NetAddSub(scope, scope->local_symbol(), width);
54 for (unsigned idx = 0 ; idx < width ; idx += 1)
55 connect(sig->pin(idx), add->pin_DataA(idx));
57 for (unsigned idx = 0 ; idx < width ; idx += 1)
58 connect(val_c->pin(idx), add->pin_DataB(idx));
60 for (unsigned idx = 0 ; idx < width ; idx += 1)
61 connect(val_s->pin(idx), add->pin_DataB(idx));
63 for (unsigned idx = 0 ; idx < width ; idx += 1)
64 connect(res->pin(idx), add->pin_Result(idx));
66 if (val < 0)
67 add->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
68 else
69 add->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
71 des->add_node(add);
72 des->add_node(val_c);
74 return res;
75 #else
76 cerr << sig->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl;
77 return 0;
78 #endif
82 * Add a signed constant to an existing expression. Generate a new
83 * NetEBAdd node that has the input expression and an expression made
84 * from the constant value.
86 NetExpr* make_add_expr(NetExpr*expr, long val)
88 if (val == 0)
89 return expr;
91 // If the value to be added is <0, then instead generate a
92 // SUBTRACT node and turn the value positive.
93 char add_op = '+';
94 if (val < 0) {
95 add_op = '-';
96 val = -val;
99 verinum val_v (val);
100 val_v.has_sign(true);
102 if (expr->has_width()) {
103 val_v = verinum(val_v, expr->expr_width());
106 NetEConst*val_c = new NetEConst(val_v);
107 val_c->set_line(*expr);
109 NetEBAdd*res = new NetEBAdd(add_op, expr, val_c);
110 res->set_line(*expr);
112 return res;
115 NetExpr* make_sub_expr(long val, NetExpr*expr)
117 verinum val_v (val, expr->expr_width());
118 val_v.has_sign(true);
119 NetEConst*val_c = new NetEConst(val_v);
120 val_c->set_line(*expr);
122 NetEBAdd*res = new NetEBAdd('-', val_c, expr);
123 res->set_line(*expr);
125 return res;
128 NetExpr* elab_and_eval(Design*des, NetScope*scope,
129 const PExpr*pe, int expr_wid, int prune_width)
131 NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
132 if (tmp == 0)
133 return 0;
135 if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) {
136 delete tmp;
137 tmp = tmp2;
140 return tmp;
143 bool eval_as_long(long&value, NetExpr*expr)
145 if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
146 value = tmp->value().as_long();
147 return true;
150 if (NetECReal*rtmp = dynamic_cast<NetECReal*>(expr)) {
151 value = rtmp->value().as_long();
152 return true;
155 return false;
158 std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
159 const pform_name_t&path)
161 list<hname_t> res;
163 typedef pform_name_t::const_iterator pform_path_it;
165 for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
166 const name_component_t&comp = *cur;
167 if (comp.index.empty()) {
168 res.push_back(hname_t(comp.name));
169 continue;
172 assert(comp.index.size() == 1);
173 const index_component_t&index = comp.index.front();
174 assert(index.sel == index_component_t::SEL_BIT);
176 NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
177 ivl_assert(*index.msb, tmp);
179 if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
180 res.push_back(hname_t(comp.name, ctmp->value().as_long()));
181 delete ctmp;
182 continue;
183 } else {
184 cerr << index.msb->get_line() << ": error: "
185 << "Scope index expression is not constant: "
186 << *index.msb << endl;
187 des->errors += 1;
190 return res;
193 return res;