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)
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
20 #ident "$Id: netmisc.cc,v 1.14 2007/06/02 03:42:13 steve Exp $"
28 # include "pform_types.h"
29 # include "ivl_assert.h"
31 NetNet
* add_to_net(Design
*des
, NetNet
*sig
, long val
)
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
));
67 add
->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
69 add
->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
76 cerr
<< sig
->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl
;
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
)
91 // If the value to be added is <0, then instead generate a
92 // SUBTRACT node and turn the value positive.
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
);
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
);
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);
135 if (NetExpr
*tmp2
= tmp
->eval_tree(prune_width
)) {
143 bool eval_as_long(long&value
, NetExpr
*expr
)
145 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(expr
) ) {
146 value
= tmp
->value().as_long();
150 if (NetECReal
*rtmp
= dynamic_cast<NetECReal
*>(expr
)) {
151 value
= rtmp
->value().as_long();
158 std::list
<hname_t
> eval_scope_path(Design
*des
, NetScope
*scope
,
159 const pform_name_t
&path
)
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
));
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()));
184 cerr
<< index
.msb
->get_line() << ": error: "
185 << "Scope index expression is not constant: "
186 << *index
.msb
<< endl
;