1 /*
2 * Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
3 *
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.
9 *
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.
14 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "config.h"
21
22 # include "netlist.h"
23 # include "netclass.h"
24 # include "netdarray.h"
25 # include "netenum.h"
26 # include "ivl_assert.h"
27
28 /*
29 * NetAssign
30 */
31
count_lval_width(const NetAssign_ * idx)32 unsigned count_lval_width(const NetAssign_*idx)
33 {
34 unsigned wid = 0;
35 while (idx) {
36 wid += idx->lwidth();
37 idx = idx->more;
38 }
39 return wid;
40 }
41
NetAssign_(NetAssign_ * n)42 NetAssign_::NetAssign_(NetAssign_*n)
43 : nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
44 {
45 lwid_ = 0;
46 more = 0;
47 signed_ = false;
48 turn_sig_to_wire_on_release_ = false;
49 }
50
NetAssign_(NetNet * s)51 NetAssign_::NetAssign_(NetNet*s)
52 : nest_(0), sig_(s), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
53 {
54 lwid_ = sig_->vector_width();
55 sig_->incr_lref();
56 more = 0;
57 signed_ = false;
58 turn_sig_to_wire_on_release_ = false;
59 }
60
~NetAssign_()61 NetAssign_::~NetAssign_()
62 {
63 if (sig_) {
64 sig_->decr_lref();
65 if (turn_sig_to_wire_on_release_ && sig_->peek_lref() == 0)
66 sig_->type(NetNet::WIRE);
67 }
68
69 assert( more == 0 );
70 delete word_;
71 }
72
get_fileline() const73 string NetAssign_::get_fileline() const
74 {
75 if (sig_) return sig_->get_fileline();
76 else return nest_->get_fileline();
77 }
78
scope() const79 NetScope*NetAssign_::scope() const
80 {
81 if (sig_) return sig_->scope();
82 else return nest_->scope();
83 }
84
set_word(NetExpr * r)85 void NetAssign_::set_word(NetExpr*r)
86 {
87 assert(word_ == 0);
88 word_ = r;
89 }
90
word()91 NetExpr* NetAssign_::word()
92 {
93 return word_;
94 }
95
word() const96 const NetExpr* NetAssign_::word() const
97 {
98 return word_;
99 }
100
get_base() const101 const NetExpr* NetAssign_::get_base() const
102 {
103 return base_;
104 }
105
select_type() const106 ivl_select_type_t NetAssign_::select_type() const
107 {
108 return sel_type_;
109 }
110
lwidth() const111 unsigned NetAssign_::lwidth() const
112 {
113 // This gets me the type of the l-value expression, down to
114 // the type of the member. If this returns nil, then resort to
115 // the lwid_ value.
116 ivl_type_t ntype = net_type();
117 if (ntype == 0)
118 return lwid_;
119
120 // If the type is a darray, and there is a word index, then we
121 // actually want the width of the elements.
122 if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
123 if (word_ == 0)
124 return 1;
125 else
126 return darray->element_width();
127 }
128
129 return ntype->packed_width();
130 }
131
expr_type() const132 ivl_variable_type_t NetAssign_::expr_type() const
133 {
134 ivl_type_t ntype = net_type();
135 if (const netdarray_t*darray = dynamic_cast<const netdarray_t*>(ntype)) {
136 if (word_ == 0)
137 return IVL_VT_DARRAY;
138 else
139 return darray->element_base_type();
140 }
141
142 if (sig_ && sig_->data_type()==IVL_VT_STRING && base_!=0)
143 return IVL_VT_BOOL;
144
145 if (ntype) return ntype->base_type();
146
147 ivl_assert(*this, sig_);
148 return sig_->data_type();
149 }
150
net_type() const151 const ivl_type_s* NetAssign_::net_type() const
152 {
153 if (nest_) {
154 const ivl_type_s*ntype = nest_->net_type();
155 if (member_.nil())
156 return ntype;
157
158 if (const netclass_t*class_type = dynamic_cast<const netclass_t*>(ntype)) {
159 int pidx = class_type->property_idx_from_name(member_);
160 ivl_assert(*this, pidx >= 0);
161 ivl_type_t tmp = class_type->get_prop_type(pidx);
162 return tmp;
163 }
164
165 if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
166 if (word_ == 0)
167 return ntype;
168 else
169 return darray->element_type();
170 }
171
172 return 0;
173 }
174
175 if (const netclass_t*class_type = sig_->class_type()) {
176 if (member_.nil())
177 return sig_->net_type();
178
179 int pidx = class_type->property_idx_from_name(member_);
180 ivl_assert(*sig_, pidx >= 0);
181 ivl_type_t tmp = class_type->get_prop_type(pidx);
182 return tmp;
183 }
184
185 if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (sig_->net_type())) {
186 if (word_ == 0)
187 return sig_->net_type();
188 else
189 return darray->element_type();
190 }
191
192 return 0;
193 }
194
enumeration() const195 const netenum_t*NetAssign_::enumeration() const
196 {
197 const netenum_t*tmp = 0;
198 ivl_type_t ntype = net_type();
199 if (ntype == 0) {
200
201 ivl_assert(*this, sig_);
202
203 // If the base signal is not an enumeration, return nil.
204 if ( (tmp = sig_->enumeration()) == 0 )
205 return 0;
206
207 } else {
208 tmp = dynamic_cast<const netenum_t*>(ntype);
209 if (tmp == 0)
210 return 0;
211 }
212
213 // Part select of an enumeration is not an enumeration.
214 if (base_ != 0)
215 return 0;
216
217 // Concatenation of enumerations is not an enumeration.
218 if (more != 0)
219 return 0;
220
221 return tmp;
222 }
223
name() const224 perm_string NetAssign_::name() const
225 {
226 if (sig_) {
227 return sig_->name();
228 } else {
229 return perm_string::literal("");
230 }
231 }
232
sig() const233 NetNet* NetAssign_::sig() const
234 {
235 assert(sig_? nest_==0 : nest_!=0);
236 return sig_;
237 }
238
set_part(NetExpr * base,unsigned wid,ivl_select_type_t sel_type)239 void NetAssign_::set_part(NetExpr*base, unsigned wid,
240 ivl_select_type_t sel_type)
241 {
242 base_ = base;
243 lwid_ = wid;
244 sel_type_ = sel_type;
245 }
246
set_property(const perm_string & mname)247 void NetAssign_::set_property(const perm_string&mname)
248 {
249 //ivl_assert(*sig_, sig_->class_type());
250 member_ = mname;
251 }
252
253 /*
254 */
turn_sig_to_wire_on_release()255 void NetAssign_::turn_sig_to_wire_on_release()
256 {
257 turn_sig_to_wire_on_release_ = true;
258 }
259
NetAssignBase(NetAssign_ * lv,NetExpr * rv)260 NetAssignBase::NetAssignBase(NetAssign_*lv, NetExpr*rv)
261 : lval_(lv), rval_(rv), delay_(0)
262 {
263 }
264
~NetAssignBase()265 NetAssignBase::~NetAssignBase()
266 {
267 delete rval_;
268 while (lval_) {
269 NetAssign_*tmp = lval_;
270 lval_ = tmp->more;
271 tmp->more = 0;
272 delete tmp;
273 }
274 }
275
rval()276 NetExpr* NetAssignBase::rval()
277 {
278 return rval_;
279 }
280
rval() const281 const NetExpr* NetAssignBase::rval() const
282 {
283 return rval_;
284 }
285
set_rval(NetExpr * r)286 void NetAssignBase::set_rval(NetExpr*r)
287 {
288 delete rval_;
289 rval_ = r;
290 }
291
l_val(unsigned idx)292 NetAssign_* NetAssignBase::l_val(unsigned idx)
293 {
294 NetAssign_*cur = lval_;
295 while (idx > 0) {
296 if (cur == 0)
297 return cur;
298
299 cur = cur->more;
300 idx -= 1;
301 }
302
303 assert(idx == 0);
304 return cur;
305 }
306
l_val(unsigned idx) const307 const NetAssign_* NetAssignBase::l_val(unsigned idx) const
308 {
309 const NetAssign_*cur = lval_;
310 while (idx > 0) {
311 if (cur == 0)
312 return cur;
313
314 cur = cur->more;
315 idx -= 1;
316 }
317
318 assert(idx == 0);
319 return cur;
320 }
321
l_val_count() const322 unsigned NetAssignBase::l_val_count() const
323 {
324 const NetAssign_*cur = lval_;
325 unsigned cnt = 0;
326 while (cur) {
327 cnt += 1;
328 cur = cur->more;
329 }
330
331 return cnt;
332 }
333
lwidth() const334 unsigned NetAssignBase::lwidth() const
335 {
336 unsigned sum = 0;
337 for (NetAssign_*cur = lval_ ; cur ; cur = cur->more)
338 sum += cur->lwidth();
339 return sum;
340 }
341
set_delay(NetExpr * expr)342 void NetAssignBase::set_delay(NetExpr*expr)
343 {
344 delay_ = expr;
345 }
346
get_delay() const347 const NetExpr* NetAssignBase::get_delay() const
348 {
349 return delay_;
350 }
351
NetAssign(NetAssign_ * lv,NetExpr * rv)352 NetAssign::NetAssign(NetAssign_*lv, NetExpr*rv)
353 : NetAssignBase(lv, rv), op_(0)
354 {
355 }
356
NetAssign(NetAssign_ * lv,char op,NetExpr * rv)357 NetAssign::NetAssign(NetAssign_*lv, char op, NetExpr*rv)
358 : NetAssignBase(lv, rv), op_(op)
359 {
360 }
361
~NetAssign()362 NetAssign::~NetAssign()
363 {
364 }
365
NetAssignNB(NetAssign_ * lv,NetExpr * rv,NetEvWait * ev,NetExpr * cnt)366 NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
367 : NetAssignBase(lv, rv)
368 {
369 event_ = ev;
370 count_ = cnt;
371 }
372
~NetAssignNB()373 NetAssignNB::~NetAssignNB()
374 {
375 }
376
nevents() const377 unsigned NetAssignNB::nevents() const
378 {
379 if (event_) return event_->nevents();
380 return 0;
381 }
382
event(unsigned idx) const383 const NetEvent*NetAssignNB::event(unsigned idx) const
384 {
385 if (event_) return event_->event(idx);
386 return 0;
387 }
388
get_count() const389 const NetExpr*NetAssignNB::get_count() const
390 {
391 return count_;
392 }
393
NetCAssign(NetAssign_ * lv,NetExpr * rv)394 NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
395 : NetAssignBase(lv, rv)
396 {
397 }
398
~NetCAssign()399 NetCAssign::~NetCAssign()
400 {
401 }
402
NetDeassign(NetAssign_ * l)403 NetDeassign::NetDeassign(NetAssign_*l)
404 : NetAssignBase(l, 0)
405 {
406 }
407
~NetDeassign()408 NetDeassign::~NetDeassign()
409 {
410 }
411
NetForce(NetAssign_ * lv,NetExpr * rv)412 NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
413 : NetAssignBase(lv, rv)
414 {
415 }
416
~NetForce()417 NetForce::~NetForce()
418 {
419 }
420
NetRelease(NetAssign_ * l)421 NetRelease::NetRelease(NetAssign_*l)
422 : NetAssignBase(l, 0)
423 {
424 }
425
~NetRelease()426 NetRelease::~NetRelease()
427 {
428 }
429