1 /*
2 * Copyright (c) 1998-2020 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 <iostream>
23
24 # include <typeinfo>
25 # include <cstdlib>
26 # include <climits>
27 # include <cstring>
28 # include "compiler.h"
29 # include "netlist.h"
30 # include "netmisc.h"
31 # include "netclass.h"
32 # include "netdarray.h"
33 # include "netenum.h"
34 # include "netparray.h"
35 # include "netqueue.h"
36 # include "netstruct.h"
37 # include "netvector.h"
38 # include "ivl_assert.h"
39
40
operator <<(ostream & o,NetNet::Type t)41 ostream& operator<< (ostream&o, NetNet::Type t)
42 {
43 switch (t) {
44 case NetNet::NONE:
45 o << "net_none";
46 break;
47 case NetNet::IMPLICIT:
48 o << "wire /*implicit*/";
49 break;
50 case NetNet::IMPLICIT_REG:
51 o << "reg /*implicit*/";
52 break;
53 case NetNet::INTEGER:
54 o << "integer";
55 break;
56 case NetNet::REG:
57 o << "reg";
58 break;
59 case NetNet::SUPPLY0:
60 o << "supply0";
61 break;
62 case NetNet::SUPPLY1:
63 o << "supply1";
64 break;
65 case NetNet::TRI:
66 o << "tri";
67 break;
68 case NetNet::TRI0:
69 o << "tri0";
70 break;
71 case NetNet::TRI1:
72 o << "tri1";
73 break;
74 case NetNet::TRIAND:
75 o << "triand";
76 break;
77 case NetNet::TRIOR:
78 o << "trior";
79 break;
80 case NetNet::WAND:
81 o << "wand";
82 break;
83 case NetNet::WOR:
84 o << "wor";
85 break;
86 case NetNet::WIRE:
87 o << "wire";
88 break;
89 case NetNet::UNRESOLVED_WIRE:
90 o << "uwire";
91 }
92 return o;
93 }
94
count_signals(const Link & pin)95 unsigned count_signals(const Link&pin)
96 {
97 unsigned count = 0;
98
99 const Nexus*nex = pin.nexus();
100 for (const Link*clnk = nex->first_nlink()
101 ; clnk ; clnk = clnk->next_nlink()) {
102 const NetPins*cur;
103 unsigned cpin;
104 clnk->cur_link(cur, cpin);
105 if (dynamic_cast<const NetNet*>(cur))
106 count += 1;
107 }
108
109 return count;
110 }
111
find_link_signal(const NetObj * net,unsigned pin,unsigned & bidx)112 const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
113 {
114 const Nexus*nex = net->pin(pin).nexus();
115
116 for (const Link*clnk = nex->first_nlink()
117 ; clnk ; clnk = clnk->next_nlink()) {
118
119 const NetPins*cur;
120 unsigned cpin;
121 clnk->cur_link(cur, cpin);
122
123 const NetNet*sig = dynamic_cast<const NetNet*>(cur);
124 if (sig) {
125 bidx = cpin;
126 return sig;
127 }
128 }
129
130 return 0;
131 }
132
find_next_output(Link * lnk)133 Link* find_next_output(Link*lnk)
134 {
135 Link*cur = lnk->next_nlink();
136 while (cur != lnk) {
137 if (cur->get_dir() == Link::OUTPUT)
138 return cur;
139
140 cur = cur->next_nlink();
141 if (cur == 0)
142 cur = lnk->nexus()->first_nlink();
143 }
144
145 return 0;
146 }
147
devirtualize_pins(void)148 void NetPins::devirtualize_pins(void)
149 {
150 if (pins_) return;
151 if (npins_ > array_size_limit) {
152 cerr << get_fileline() << ": error: pin count " << npins_ <<
153 " exceeds " << array_size_limit <<
154 " (set by -pARRAY_SIZE_LIMIT)" << endl;
155 assert(0);
156 }
157 if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
158
159 pins_ = new Link[npins_];
160 pins_[0].pin_zero_ = true;
161 pins_[0].node_ = this;
162 pins_[0].dir_ = default_dir_;
163
164 for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
165 pins_[idx].pin_zero_ = false;
166 pins_[idx].pin_ = idx;
167 pins_[idx].dir_ = default_dir_;
168 }
169 }
170
pins_are_virtual(void) const171 bool NetPins::pins_are_virtual(void) const
172 {
173 return pins_ == NULL;
174 }
175
NetPins(unsigned npins)176 NetPins::NetPins(unsigned npins)
177 : npins_(npins)
178 {
179 default_dir_ = Link::PASSIVE;
180 pins_ = NULL; // Wait until someone asks.
181 if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
182 }
183
~NetPins()184 NetPins::~NetPins()
185 {
186 if (pins_) {
187 assert(pins_[0].node_ == this);
188 assert(pins_[0].pin_zero_);
189 delete[] pins_;
190 }
191 }
192
pin(unsigned idx)193 Link& NetPins::pin(unsigned idx)
194 {
195 if (!pins_) devirtualize_pins();
196 if (idx >= npins_) {
197 cerr << get_fileline() << ": internal error: pin("<<idx<<")"
198 << " out of bounds("<<npins_<<")" << endl;
199 cerr << get_fileline() << ": : typeid="
200 << typeid(*this).name() << endl;
201 }
202
203 assert(idx < npins_);
204 assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx);
205
206 return pins_[idx];
207 }
208
pin(unsigned idx) const209 const Link& NetPins::pin(unsigned idx) const
210 {
211 if (!pins_ && !disable_virtual_pins) {
212 cerr << get_fileline() << ": internal error: pin is unexpectedly"
213 " virtual, try again with -pDISABLE_VIRTUAL_PINS=true" << endl;
214 assert(0);
215 }
216 assert(pins_);
217 assert(idx < npins_);
218 assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx);
219 return pins_[idx];
220 }
221
set_default_dir(Link::DIR d)222 void NetPins::set_default_dir(Link::DIR d)
223 {
224 default_dir_ = d;
225 }
226
is_linked(void)227 bool NetPins::is_linked(void)
228 {
229 bool linked_flag = false;
230 if (pins_ == NULL) return false;
231 for (unsigned u = 0; u < npins_; u++) {
232 if (pins_[u].is_linked()) {
233 linked_flag = true;
234 break;
235 }
236 }
237 return linked_flag;
238 }
239
NetObj(NetScope * s,perm_string n,unsigned np)240 NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
241 : NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
242 {
243 /* Don't
244 ivl_assert(*this, np > 0);
245 * because it would happen before we get to print a useful
246 * message in the NetNet constructor
247 */
248 }
249
~NetObj()250 NetObj::~NetObj()
251 {
252 }
253
scope()254 NetScope* NetObj::scope()
255 {
256 return scope_;
257 }
258
scope() const259 const NetScope* NetObj::scope() const
260 {
261 return scope_;
262 }
263
NetNode(NetScope * s,perm_string n,unsigned npins)264 NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
265 : NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
266 {
267 }
268
~NetNode()269 NetNode::~NetNode()
270 {
271 if (design_)
272 design_->del_node(this);
273 }
274
NetBranch(ivl_discipline_t dis)275 NetBranch::NetBranch(ivl_discipline_t dis)
276 : NetPins(2), IslandBranch(dis)
277 {
278 pin(0).set_dir(Link::PASSIVE);
279 pin(1).set_dir(Link::PASSIVE);
280 }
281
~NetBranch()282 NetBranch::~NetBranch()
283 {
284 }
285
NetBus(NetScope * s,unsigned pin_count__)286 NetBus::NetBus(NetScope*s, unsigned pin_count__)
287 : NetObj(s, perm_string::literal(""), pin_count__)
288 {
289 for (unsigned idx = 0 ; idx <pin_count__ ; idx += 1) {
290 pin(idx).set_dir(Link::PASSIVE);
291 }
292 }
293
~NetBus()294 NetBus::~NetBus()
295 {
296 }
297
find_link(const Link & that) const298 unsigned NetBus::find_link(const Link&that) const
299 {
300 unsigned ptr = 0;
301
302 while (ptr < pin_count()) {
303 if (pin(ptr).is_linked(that))
304 return ptr;
305
306 ptr += 1;
307 }
308 return ptr;
309 }
310
NetDelaySrc(NetScope * s,perm_string n,unsigned npins,bool condit_src,bool conditional,bool parallel)311 NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
312 bool condit_src, bool conditional, bool parallel)
313 : NetObj(s, n, npins + (condit_src?1:0))
314 {
315 condit_flag_ = false;
316 conditional_ = conditional;
317 parallel_ = parallel;
318 posedge_ = false;
319 negedge_ = false;
320 for (unsigned idx = 0 ; idx < npins ; idx += 1) {
321 pin(idx).set_dir(Link::INPUT);
322 }
323
324 if (condit_src) {
325 condit_flag_ = true;
326 pin(npins).set_dir(Link::INPUT);
327 }
328 }
329
~NetDelaySrc()330 NetDelaySrc::~NetDelaySrc()
331 {
332 }
333
set_delays(uint64_t del)334 void NetDelaySrc::set_delays(uint64_t del)
335 {
336 for (unsigned idx = 0 ; idx < 12 ; idx += 1)
337 transition_delays_[idx] = del;
338 }
339
set_delays(uint64_t trise,uint64_t tfall)340 void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall)
341 {
342 transition_delays_[IVL_PE_01] = trise;
343 transition_delays_[IVL_PE_10] = tfall;
344 transition_delays_[IVL_PE_0z] = trise;
345 transition_delays_[IVL_PE_z1] = trise;
346 transition_delays_[IVL_PE_1z] = tfall;
347 transition_delays_[IVL_PE_z0] = tfall;
348 transition_delays_[IVL_PE_0x] = trise;
349 transition_delays_[IVL_PE_x1] = trise;
350 transition_delays_[IVL_PE_1x] = tfall;
351 transition_delays_[IVL_PE_x0] = tfall;
352 transition_delays_[IVL_PE_xz] = max(trise,tfall);
353 transition_delays_[IVL_PE_zx] = min(trise,tfall);
354 }
355
set_delays(uint64_t trise,uint64_t tfall,uint64_t tz)356 void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall, uint64_t tz)
357 {
358 transition_delays_[IVL_PE_01] = trise;
359 transition_delays_[IVL_PE_10] = tfall;
360 transition_delays_[IVL_PE_0z] = tz;
361 transition_delays_[IVL_PE_z1] = trise;
362 transition_delays_[IVL_PE_1z] = tz;
363 transition_delays_[IVL_PE_z0] = tfall;
364 transition_delays_[IVL_PE_0x] = min(trise,tz);
365 transition_delays_[IVL_PE_x1] = trise;
366 transition_delays_[IVL_PE_1x] = min(tfall,tz);
367 transition_delays_[IVL_PE_x0] = tfall;
368 transition_delays_[IVL_PE_xz] = tz;
369 transition_delays_[IVL_PE_zx] = min(trise,tfall);
370 }
371
set_delays(uint64_t t01,uint64_t t10,uint64_t t0z,uint64_t tz1,uint64_t t1z,uint64_t tz0)372 void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
373 uint64_t tz1, uint64_t t1z, uint64_t tz0)
374 {
375 transition_delays_[IVL_PE_01] = t01;
376 transition_delays_[IVL_PE_10] = t10;
377 transition_delays_[IVL_PE_0z] = t0z;
378 transition_delays_[IVL_PE_z1] = tz1;
379 transition_delays_[IVL_PE_1z] = t1z;
380 transition_delays_[IVL_PE_z0] = tz0;
381 transition_delays_[IVL_PE_0x] = min(t01,t0z);
382 transition_delays_[IVL_PE_x1] = max(t01,tz1);
383 transition_delays_[IVL_PE_1x] = min(t10,t1z);
384 transition_delays_[IVL_PE_x0] = max(t10,tz0);
385 transition_delays_[IVL_PE_xz] = max(t1z,t0z);
386 transition_delays_[IVL_PE_zx] = min(tz1,tz0);
387 }
388
set_delays(uint64_t t01,uint64_t t10,uint64_t t0z,uint64_t tz1,uint64_t t1z,uint64_t tz0,uint64_t t0x,uint64_t tx1,uint64_t t1x,uint64_t tx0,uint64_t txz,uint64_t tzx)389 void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
390 uint64_t tz1, uint64_t t1z, uint64_t tz0,
391 uint64_t t0x, uint64_t tx1, uint64_t t1x,
392 uint64_t tx0, uint64_t txz, uint64_t tzx)
393 {
394 transition_delays_[IVL_PE_01] = t01;
395 transition_delays_[IVL_PE_10] = t10;
396 transition_delays_[IVL_PE_0z] = t0z;
397 transition_delays_[IVL_PE_z1] = tz1;
398 transition_delays_[IVL_PE_1z] = t1z;
399 transition_delays_[IVL_PE_z0] = tz0;
400 transition_delays_[IVL_PE_0x] = t0x;
401 transition_delays_[IVL_PE_x1] = tx1;
402 transition_delays_[IVL_PE_1x] = t1x;
403 transition_delays_[IVL_PE_x0] = tx0;
404 transition_delays_[IVL_PE_xz] = txz;
405 transition_delays_[IVL_PE_zx] = tzx;
406 }
407
get_delay(unsigned idx) const408 uint64_t NetDelaySrc::get_delay(unsigned idx) const
409 {
410 assert(idx < 12);
411 return transition_delays_[idx];
412 }
413
set_posedge()414 void NetDelaySrc::set_posedge()
415 {
416 posedge_ = true;
417 }
418
set_negedge()419 void NetDelaySrc::set_negedge()
420 {
421 negedge_ = true;
422 }
423
is_posedge() const424 bool NetDelaySrc::is_posedge() const
425 {
426 return posedge_;
427 }
428
is_negedge() const429 bool NetDelaySrc::is_negedge() const
430 {
431 return negedge_;
432 }
433
src_count() const434 unsigned NetDelaySrc::src_count() const
435 {
436 if (condit_flag_)
437 return pin_count() - 1;
438 else
439 return pin_count();
440 }
441
src_pin(unsigned idx)442 Link& NetDelaySrc::src_pin(unsigned idx)
443 {
444 ivl_assert(*this, idx < src_count());
445 return pin(idx);
446 }
447
src_pin(unsigned idx) const448 const Link& NetDelaySrc::src_pin(unsigned idx) const
449 {
450 ivl_assert(*this, idx < src_count());
451 return pin(idx);
452 }
453
is_condit() const454 bool NetDelaySrc::is_condit() const
455 {
456 return conditional_;
457 }
458
has_condit() const459 bool NetDelaySrc::has_condit() const
460 {
461 return condit_flag_;
462 }
463
condit_pin()464 Link& NetDelaySrc::condit_pin()
465 {
466 ivl_assert(*this, condit_flag_);
467 return pin(pin_count()-1);
468 }
469
condit_pin() const470 const Link& NetDelaySrc::condit_pin() const
471 {
472 ivl_assert(*this, condit_flag_);
473 return pin(pin_count()-1);
474 }
475
is_parallel() const476 bool NetDelaySrc::is_parallel() const
477 {
478 return parallel_;
479 }
480
merged(Enum lhs,Enum rhs)481 PortType::Enum PortType::merged( Enum lhs, Enum rhs )
482 {
483 if( lhs == NOT_A_PORT || rhs == NOT_A_PORT )
484 return NOT_A_PORT;
485 if( lhs == PIMPLICIT )
486 return rhs;
487 if( rhs == PIMPLICIT )
488 return lhs;
489 if( lhs == rhs ) {
490 return lhs;
491 }
492 return PINOUT;
493 }
494
initialize_dir_()495 void NetNet::initialize_dir_()
496 {
497 Link::DIR dir = Link::PASSIVE;
498
499 switch (type_) {
500 case REG:
501 case IMPLICIT_REG:
502 case SUPPLY0:
503 case SUPPLY1:
504 case TRI0:
505 case TRI1:
506 dir = Link::OUTPUT;
507 break;
508 default:
509 break;
510 }
511
512 if (pins_are_virtual()) {
513 if (0) cerr << "NetNet setting Link default dir" << endl;
514 set_default_dir(dir);
515 } else {
516 for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
517 pin(idx).set_dir(dir);
518 }
519 }
520 }
521
calculate_count(const list<netrange_t> & unpacked)522 static unsigned calculate_count(const list<netrange_t>&unpacked)
523 {
524 unsigned long sum = 1;
525 for (list<netrange_t>::const_iterator cur = unpacked.begin()
526 ; cur != unpacked.end() ; ++cur) {
527 // Special case: If there are any undefined dimensions,
528 // then give up on trying to create pins for the net.
529 if (! cur->defined())
530 return 0;
531
532 sum *= cur->width();
533 }
534
535 if (sum >= UINT_MAX)
536 return 0;
537
538 return sum;
539 }
540
calculate_count(T * type)541 template <class T> static unsigned calculate_count(T*type)
542 {
543 long wid = type->packed_width();
544 if (wid >= 0)
545 return wid;
546 else
547 return 1;
548 }
549
calculate_slice_widths_from_packed_dims_(void)550 void NetNet::calculate_slice_widths_from_packed_dims_(void)
551 {
552 ivl_assert(*this, net_type_);
553 slice_dims_ = net_type_->slice_dimensions();
554
555 // Special case: There are no actual packed dimensions, so
556 // build up a fake dimension of "1".
557 if (slice_dims_.empty()) {
558 slice_wids_.resize(1);
559 slice_wids_[0] = net_type_->packed_width();
560 return;
561 }
562
563 slice_wids_.resize(slice_dims_.size());
564
565 ivl_assert(*this, ! slice_wids_.empty());
566 slice_wids_[0] = netrange_width(slice_dims_);
567 vector<netrange_t>::const_iterator cur = slice_dims_.begin();
568 for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, ++cur) {
569 slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
570 }
571 }
572
573 const list<netrange_t> NetNet::not_an_array;
574
NetNet(NetScope * s,perm_string n,Type t,const list<netrange_t> & unpacked,ivl_type_t use_net_type)575 NetNet::NetNet(NetScope*s, perm_string n, Type t,
576 const list<netrange_t>&unpacked, ivl_type_t use_net_type)
577 : NetObj(s, n, calculate_count(unpacked)),
578 type_(t), port_type_(NOT_A_PORT),
579 local_flag_(false), net_type_(use_net_type),
580 discipline_(0), unpacked_dims_(unpacked.size()),
581 eref_count_(0), lref_count_(0)
582 {
583 calculate_slice_widths_from_packed_dims_();
584 size_t idx = 0;
585 for (list<netrange_t>::const_iterator cur = unpacked.begin()
586 ; cur != unpacked.end() ; ++cur, idx += 1) {
587 unpacked_dims_[idx] = *cur;
588 }
589 assert(idx == unpacked_dims_.size());
590
591 ivl_assert(*this, s);
592 if (pin_count() == 0) {
593 cerr << "Invalid array dimensions: " << unpacked << endl;
594 ivl_assert(*this, 0);
595 }
596
597 initialize_dir_();
598
599 s->add_signal(this);
600 }
601
602 /*
603 * When we create a netnet for a packed struct, create a single
604 * vector with the msb_/lsb_ chosen to name enough bits for the entire
605 * packed structure.
606 */
NetNet(NetScope * s,perm_string n,Type t,netstruct_t * ty)607 NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
608 : NetObj(s, n, 1),
609 type_(t), port_type_(NOT_A_PORT),
610 local_flag_(false), net_type_(ty),
611 discipline_(0),
612 eref_count_(0), lref_count_(0)
613 {
614 //XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
615 calculate_slice_widths_from_packed_dims_();
616
617 initialize_dir_();
618
619 s->add_signal(this);
620 }
621
NetNet(NetScope * s,perm_string n,Type t,netdarray_t * ty)622 NetNet::NetNet(NetScope*s, perm_string n, Type t, netdarray_t*ty)
623 : NetObj(s, n, 1),
624 type_(t), port_type_(NOT_A_PORT),
625 local_flag_(false), net_type_(ty),
626 discipline_(0),
627 eref_count_(0), lref_count_(0)
628 {
629 initialize_dir_();
630
631 s->add_signal(this);
632 }
633
NetNet(NetScope * s,perm_string n,Type t,netvector_t * ty)634 NetNet::NetNet(NetScope*s, perm_string n, Type t, netvector_t*ty)
635 : NetObj(s, n, 1),
636 type_(t), port_type_(NOT_A_PORT),
637 local_flag_(false), net_type_(ty),
638 discipline_(0),
639 eref_count_(0), lref_count_(0)
640 {
641 calculate_slice_widths_from_packed_dims_();
642
643 initialize_dir_();
644
645 s->add_signal(this);
646 }
647
~NetNet()648 NetNet::~NetNet()
649 {
650 if (eref_count_ > 0) {
651 cerr << get_fileline() << ": internal error: attempt to delete "
652 << "signal ``" << name() << "'' which has "
653 << "expression references." << endl;
654 dump_net(cerr, 4);
655 }
656 assert(eref_count_ == 0);
657 if (lref_count_ > 0) {
658 cerr << get_fileline() << ": internal error: attempt to delete "
659 << "signal ``" << name() << "'' which has "
660 << "assign references." << endl;
661 dump_net(cerr, 4);
662 }
663 assert(lref_count_ == 0);
664 if (scope())
665 scope()->rem_signal(this);
666
667 }
668
type() const669 NetNet::Type NetNet::type() const
670 {
671 return type_;
672 }
673
type(NetNet::Type t)674 void NetNet::type(NetNet::Type t)
675 {
676 if (type_ == t)
677 return;
678
679 type_ = t;
680
681 initialize_dir_();
682 }
683
684
port_type() const685 NetNet::PortType NetNet::port_type() const
686 {
687 return port_type_;
688 }
689
port_type(NetNet::PortType t)690 void NetNet::port_type(NetNet::PortType t)
691 {
692 port_type_ = t;
693 }
694
get_module_port_index() const695 int NetNet::get_module_port_index() const
696 {
697 return port_index_;
698 }
699
set_module_port_index(unsigned idx)700 void NetNet::set_module_port_index(unsigned idx)
701 {
702 port_index_ = idx;
703 assert( port_index_ >= 0 );
704 }
705
data_type() const706 ivl_variable_type_t NetNet::data_type() const
707 {
708 ivl_assert(*this, net_type_);
709 return net_type_->base_type();
710 }
711
get_signed() const712 bool NetNet::get_signed() const
713 {
714 ivl_assert(*this, net_type_);
715 return net_type_->get_signed();
716 }
717
get_isint() const718 bool NetNet::get_isint() const
719 {
720 if (const netvector_t*vec = dynamic_cast<const netvector_t*> (net_type_))
721 return vec->get_isint();
722 else
723 return false;
724 }
725
get_scalar() const726 bool NetNet::get_scalar() const
727 {
728 if (const netvector_t*vec = dynamic_cast<const netvector_t*> (net_type_))
729 return vec->get_scalar();
730 else
731 return false;
732 }
733
enumeration(void) const734 const netenum_t*NetNet::enumeration(void) const
735 {
736 return dynamic_cast<const netenum_t*> (net_type_);
737 }
738
struct_type(void) const739 const netstruct_t*NetNet::struct_type(void) const
740 {
741 ivl_type_t cur_type = net_type_;
742 while (cur_type) {
743 if (const netdarray_t*da = dynamic_cast<const netdarray_t*> (cur_type)) {
744 cur_type = da->element_type();
745 continue;
746 }
747 if (const netparray_t*da = dynamic_cast<const netparray_t*> (cur_type)) {
748 cur_type = da->element_type();
749 continue;
750 }
751 if (const netstruct_t*st = dynamic_cast<const netstruct_t*> (cur_type))
752 return st;
753 else
754 return 0;
755 }
756
757 assert(0);
758 return 0;
759 }
760
darray_type(void) const761 const netdarray_t* NetNet::darray_type(void) const
762 {
763 return dynamic_cast<const netdarray_t*> (net_type_);
764 }
765
queue_type(void) const766 const netqueue_t* NetNet::queue_type(void) const
767 {
768 return dynamic_cast<const netqueue_t*> (net_type_);
769 }
770
class_type(void) const771 const netclass_t* NetNet::class_type(void) const
772 {
773 return dynamic_cast<const netclass_t*> (net_type_);
774 }
775
776 /*
777 * "depth" is the number of index expressions that the user is using
778 * to index this identifier. So consider if Net was declared like so:
779 *
780 * reg [5:0][3:0] foo;
781 *
782 * In this case, slice_width(2) == 1 (slice_width(N) where N is the
783 * number of dimensions will always be 1.) and represents
784 * $bits(foo[a][b]). Then, slice_width(1)==4 ($bits(foo[a]) and slice_width(0)==24.
785 *
786 * NOTE: The caller should already have accounted for unpacked
787 * dimensions. The "depth" is only for the packed dimensions.
788 */
slice_width(size_t depth) const789 unsigned long NetNet::slice_width(size_t depth) const
790 {
791 if (depth > slice_wids_.size())
792 return 0;
793 if (depth == slice_wids_.size())
794 return 1;
795 return slice_wids_[depth];
796 }
797
get_discipline() const798 ivl_discipline_t NetNet::get_discipline() const
799 {
800 return discipline_;
801 }
802
set_discipline(ivl_discipline_t dis)803 void NetNet::set_discipline(ivl_discipline_t dis)
804 {
805 ivl_assert(*this, discipline_ == 0);
806 discipline_ = dis;
807 }
808
sb_is_valid(const list<long> & indices,long sb) const809 bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
810 {
811 ivl_assert(*this, indices.size()+1 == packed_dims().size());
812 assert(packed_dims().size() == 1);
813 const netrange_t&rng = packed_dims().back();
814 if (rng.get_msb() >= rng.get_lsb())
815 return (sb <= rng.get_msb()) && (sb >= rng.get_lsb());
816 else
817 return (sb <= rng.get_lsb()) && (sb >= rng.get_msb());
818 }
819
sb_to_idx(const list<long> & indices,long sb) const820 long NetNet::sb_to_idx(const list<long>&indices, long sb) const
821 {
822 ivl_assert(*this, indices.size()+1 == packed_dims().size());
823
824 vector<netrange_t>::const_iterator pcur = packed_dims().end();
825 -- pcur;
826
827 long acc_off;
828 long acc_wid = pcur->width();
829 if (pcur->get_msb() >= pcur->get_lsb())
830 acc_off = sb - pcur->get_lsb();
831 else
832 acc_off = pcur->get_lsb() - sb;
833
834 // The acc_off is the position within the innermost
835 // dimension. If this is a multi-dimension packed array then
836 // we need to add in the canonical address of the current slice.
837 if (! indices.empty()) {
838 list<long>::const_iterator icur = indices.end();
839 do {
840 -- icur;
841 -- pcur;
842
843 long tmp_off;
844 if (pcur->get_msb() >= pcur->get_lsb())
845 tmp_off = *icur - pcur->get_lsb();
846 else
847 tmp_off = pcur->get_lsb() - *icur;
848
849 acc_off += tmp_off * acc_wid;
850 acc_wid *= pcur->width();
851
852 } while (icur != indices.begin());
853 }
854
855 return acc_off;
856 }
857
sb_to_slice(const list<long> & indices,long sb,long & loff,unsigned long & lwid) const858 bool NetNet::sb_to_slice(const list<long>&indices, long sb, long&loff, unsigned long&lwid) const
859 {
860 ivl_assert(*this, indices.size() < packed_dims().size());
861 return prefix_to_slice(packed_dims(), indices, sb, loff, lwid);
862 }
863
unpacked_count() const864 unsigned NetNet::unpacked_count() const
865 {
866 unsigned c = 1;
867 for (size_t idx = 0 ; idx < unpacked_dims_.size() ; idx += 1) {
868 c *= unpacked_dims_[idx].width();
869 }
870
871 return c;
872 }
873
incr_eref()874 void NetNet::incr_eref()
875 {
876 eref_count_ += 1;
877 }
878
decr_eref()879 void NetNet::decr_eref()
880 {
881 assert(eref_count_ > 0);
882 eref_count_ -= 1;
883 }
884
peek_eref() const885 unsigned NetNet::peek_eref() const
886 {
887 return eref_count_;
888 }
889
890 /*
891 * Test each of the bits in the range, and set them. If any bits are
892 * already set then return true.
893 */
test_and_set_part_driver(unsigned pmsb,unsigned plsb,int widx)894 bool NetNet::test_and_set_part_driver(unsigned pmsb, unsigned plsb, int widx)
895 {
896 if (lref_mask_.empty())
897 lref_mask_.resize(vector_width() * pin_count());
898
899 // If indexing a word that doesn't exist, then pretend this is
900 // never driven.
901 if (widx < 0)
902 return false;
903 if (widx >= (int)pin_count())
904 return false;
905
906 bool rc = false;
907 unsigned word_base = vector_width() * widx;
908 for (unsigned idx = plsb ; idx <= pmsb ; idx += 1) {
909 if (lref_mask_[idx+word_base])
910 rc = true;
911 else
912 lref_mask_[idx+word_base] = true;
913 }
914
915 return rc;
916 }
917
incr_lref()918 void NetNet::incr_lref()
919 {
920 lref_count_ += 1;
921 }
922
decr_lref()923 void NetNet::decr_lref()
924 {
925 assert(lref_count_ > 0);
926 lref_count_ -= 1;
927 }
928
get_refs() const929 unsigned NetNet::get_refs() const
930 {
931 return lref_count_ + eref_count_;
932 }
933
add_delay_path(NetDelaySrc * path)934 void NetNet::add_delay_path(NetDelaySrc*path)
935 {
936 delay_paths_.push_back(path);
937 }
938
delay_paths(void) const939 unsigned NetNet::delay_paths(void)const
940 {
941 return delay_paths_.size();
942 }
943
delay_path(unsigned idx) const944 const NetDelaySrc* NetNet::delay_path(unsigned idx) const
945 {
946 assert(idx < delay_paths_.size());
947 return delay_paths_[idx];
948 }
949
NetPartSelect(NetNet * sig,unsigned off,unsigned wid,NetPartSelect::dir_t dir__,bool signed_flag__)950 NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
951 NetPartSelect::dir_t dir__,
952 bool signed_flag__)
953 : NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
954 off_(off), wid_(wid), dir_(dir__), signed_flag_(signed_flag__)
955 {
956 set_line(*sig);
957
958 switch (dir_) {
959 case NetPartSelect::VP:
960 pin(0).set_dir(Link::OUTPUT);
961 pin(1).set_dir(Link::INPUT);
962 break;
963 case NetPartSelect::PV:
964 pin(0).set_dir(Link::INPUT);
965 pin(1).set_dir(Link::OUTPUT);
966 break;
967 }
968
969 connect(pin(1), sig->pin(0));
970 }
971
NetPartSelect(NetNet * sig,NetNet * sel,unsigned wid,bool signed_flag__)972 NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
973 unsigned wid, bool signed_flag__)
974 : NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
975 off_(0), wid_(wid), dir_(VP), signed_flag_(signed_flag__)
976 {
977 switch (dir_) {
978 case NetPartSelect::VP:
979 pin(0).set_dir(Link::OUTPUT);
980 pin(1).set_dir(Link::INPUT);
981 break;
982 case NetPartSelect::PV:
983 /* Only a vector to part can be a variable select. */
984 assert(0);
985 }
986 pin(2).set_dir(Link::INPUT);
987
988 connect(pin(1), sig->pin(0));
989 connect(pin(2), sel->pin(0));
990 }
991
~NetPartSelect()992 NetPartSelect::~NetPartSelect()
993 {
994 }
995
width() const996 unsigned NetPartSelect::width() const
997 {
998 return wid_;
999 }
1000
base() const1001 unsigned NetPartSelect::base() const
1002 {
1003 return off_;
1004 }
1005
NetSubstitute(NetNet * sig,NetNet * sub,unsigned wid,unsigned off)1006 NetSubstitute::NetSubstitute(NetNet*sig, NetNet*sub, unsigned wid, unsigned off)
1007 : NetNode(sig->scope(), sig->scope()->local_symbol(), 3), wid_(wid), off_(off)
1008 {
1009 pin(0).set_dir(Link::OUTPUT);
1010 pin(1).set_dir(Link::INPUT);
1011 pin(2).set_dir(Link::INPUT);
1012 connect(pin(1), sig->pin(0));
1013 connect(pin(2), sub->pin(0));
1014 }
1015
~NetSubstitute()1016 NetSubstitute::~NetSubstitute()
1017 {
1018 }
1019
NetProc()1020 NetProc::NetProc()
1021 : next_(0)
1022 {
1023 }
1024
~NetProc()1025 NetProc::~NetProc()
1026 {
1027 }
1028
NetProcTop(NetScope * s,ivl_process_type_t t,NetProc * st)1029 NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
1030 : type_(t), statement_(st), scope_(s)
1031 {
1032 synthesized_design_ = 0;
1033 }
1034
~NetProcTop()1035 NetProcTop::~NetProcTop()
1036 {
1037 if (!synthesized_design_) {
1038 delete statement_;
1039 return;
1040 }
1041
1042 NexusSet nex_set;
1043 statement_->nex_output(nex_set);
1044
1045 delete statement_;
1046
1047 bool flag = false;
1048 for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
1049
1050 NetNet*net = nex_set[idx].lnk.nexus()->pick_any_net();
1051 if (net->peek_lref() > 0) {
1052 cerr << get_fileline() << ": warning: '" << net->name()
1053 << "' is driven by more than one process." << endl;
1054 flag = true;
1055 }
1056 }
1057 if (flag) {
1058 cerr << get_fileline() << ": sorry: Cannot synthesize signals "
1059 "that are driven by more than one process." << endl;
1060 synthesized_design_->errors += 1;
1061 }
1062 }
1063
statement()1064 NetProc* NetProcTop::statement()
1065 {
1066 return statement_;
1067 }
1068
statement() const1069 const NetProc* NetProcTop::statement() const
1070 {
1071 return statement_;
1072 }
1073
scope()1074 NetScope* NetProcTop::scope()
1075 {
1076 return scope_;
1077 }
1078
scope() const1079 const NetScope* NetProcTop::scope() const
1080 {
1081 return scope_;
1082 }
1083
NetAnalogTop(NetScope * scope__,ivl_process_type_t t,NetProc * st)1084 NetAnalogTop::NetAnalogTop(NetScope*scope__, ivl_process_type_t t, NetProc*st)
1085 : type_(t), statement_(st), scope_(scope__)
1086 {
1087 next_ = 0;
1088 }
1089
~NetAnalogTop()1090 NetAnalogTop::~NetAnalogTop()
1091 {
1092 }
1093
statement()1094 NetProc* NetAnalogTop::statement()
1095 {
1096 return statement_;
1097 }
1098
statement() const1099 const NetProc* NetAnalogTop::statement() const
1100 {
1101 return statement_;
1102 }
1103
scope()1104 NetScope* NetAnalogTop::scope()
1105 {
1106 return scope_;
1107 }
1108
scope() const1109 const NetScope* NetAnalogTop::scope() const
1110 {
1111 return scope_;
1112 }
1113
NetCastInt2(NetScope * scope__,perm_string n,unsigned width__)1114 NetCastInt2::NetCastInt2(NetScope*scope__, perm_string n, unsigned width__)
1115 : NetNode(scope__, n, 2), width_(width__)
1116 {
1117 pin(0).set_dir(Link::OUTPUT);
1118 pin(1).set_dir(Link::INPUT);
1119 }
1120
NetCastInt4(NetScope * scope__,perm_string n,unsigned width__)1121 NetCastInt4::NetCastInt4(NetScope*scope__, perm_string n, unsigned width__)
1122 : NetNode(scope__, n, 2), width_(width__)
1123 {
1124 pin(0).set_dir(Link::OUTPUT);
1125 pin(1).set_dir(Link::INPUT);
1126 }
1127
NetCastReal(NetScope * scope__,perm_string n,bool signed_flag__)1128 NetCastReal::NetCastReal(NetScope*scope__, perm_string n, bool signed_flag__)
1129 : NetNode(scope__, n, 2), signed_flag_(signed_flag__)
1130 {
1131 pin(0).set_dir(Link::OUTPUT);
1132 pin(1).set_dir(Link::INPUT);
1133 }
1134
NetConcat(NetScope * scope__,perm_string n,unsigned wid,unsigned cnt,bool trans_flag)1135 NetConcat::NetConcat(NetScope*scope__, perm_string n, unsigned wid, unsigned cnt, bool trans_flag)
1136 : NetNode(scope__, n, cnt+1), width_(wid), transparent_(trans_flag)
1137 {
1138 pin(0).set_dir(Link::OUTPUT);
1139 for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
1140 pin(idx).set_dir(Link::INPUT);
1141 }
1142 }
1143
~NetConcat()1144 NetConcat::~NetConcat()
1145 {
1146 }
1147
width() const1148 unsigned NetConcat::width() const
1149 {
1150 return width_;
1151 }
1152
NetReplicate(NetScope * scope__,perm_string n,unsigned wid,unsigned rpt)1153 NetReplicate::NetReplicate(NetScope*scope__, perm_string n,
1154 unsigned wid, unsigned rpt)
1155 : NetNode(scope__, n, 2), width_(wid), repeat_(rpt)
1156 {
1157 pin(0).set_dir(Link::OUTPUT);
1158 pin(1).set_dir(Link::INPUT);
1159 }
1160
~NetReplicate()1161 NetReplicate::~NetReplicate()
1162 {
1163 }
1164
width() const1165 unsigned NetReplicate::width() const
1166 {
1167 return width_;
1168 }
1169
repeat() const1170 unsigned NetReplicate::repeat() const
1171 {
1172 return repeat_;
1173 }
1174
1175 /*
1176 * The NetFF class represents an LPM_FF device. The pinout is assigned
1177 * like so:
1178 * 0 -- Clock
1179 * 1 -- Enable
1180 * 2 -- Aset
1181 * 3 -- Aclr
1182 * 4 -- Sset
1183 * 5 -- Sclr
1184 * 6 -- Data
1185 * 7 -- Q
1186 * ...
1187 */
1188
NetFF(NetScope * s,perm_string n,bool negedge__,unsigned width__)1189 NetFF::NetFF(NetScope*s, perm_string n, bool negedge__, unsigned width__)
1190 : NetNode(s, n, 8), negedge_(negedge__), width_(width__)
1191 {
1192 pin_Clock().set_dir(Link::INPUT);
1193 pin_Enable().set_dir(Link::INPUT);
1194 pin_Aset().set_dir(Link::INPUT);
1195 pin_Aclr().set_dir(Link::INPUT);
1196 pin_Sset().set_dir(Link::INPUT);
1197 pin_Sclr().set_dir(Link::INPUT);
1198 pin_Data().set_dir(Link::INPUT);
1199 pin_Q().set_dir(Link::OUTPUT);
1200 }
1201
~NetFF()1202 NetFF::~NetFF()
1203 {
1204 }
1205
is_negedge() const1206 bool NetFF::is_negedge() const
1207 {
1208 return negedge_;
1209 }
1210
width() const1211 unsigned NetFF::width() const
1212 {
1213 return width_;
1214 }
1215
pin_Clock()1216 Link& NetFF::pin_Clock()
1217 {
1218 return pin(0);
1219 }
1220
pin_Clock() const1221 const Link& NetFF::pin_Clock() const
1222 {
1223 return pin(0);
1224 }
1225
pin_Enable()1226 Link& NetFF::pin_Enable()
1227 {
1228 return pin(1);
1229 }
1230
pin_Enable() const1231 const Link& NetFF::pin_Enable() const
1232 {
1233 return pin(1);
1234 }
1235
pin_Aset()1236 Link& NetFF::pin_Aset()
1237 {
1238 return pin(2);
1239 }
1240
pin_Aset() const1241 const Link& NetFF::pin_Aset() const
1242 {
1243 return pin(2);
1244 }
1245
pin_Aclr()1246 Link& NetFF::pin_Aclr()
1247 {
1248 return pin(3);
1249 }
1250
pin_Aclr() const1251 const Link& NetFF::pin_Aclr() const
1252 {
1253 return pin(3);
1254 }
1255
pin_Sset()1256 Link& NetFF::pin_Sset()
1257 {
1258 return pin(4);
1259 }
1260
pin_Sset() const1261 const Link& NetFF::pin_Sset() const
1262 {
1263 return pin(4);
1264 }
1265
pin_Sclr()1266 Link& NetFF::pin_Sclr()
1267 {
1268 return pin(5);
1269 }
1270
pin_Sclr() const1271 const Link& NetFF::pin_Sclr() const
1272 {
1273 return pin(5);
1274 }
1275
pin_Data()1276 Link& NetFF::pin_Data()
1277 {
1278 return pin(6);
1279 }
1280
pin_Data() const1281 const Link& NetFF::pin_Data() const
1282 {
1283 return pin(6);
1284 }
1285
pin_Q()1286 Link& NetFF::pin_Q()
1287 {
1288 return pin(7);
1289 }
1290
pin_Q() const1291 const Link& NetFF::pin_Q() const
1292 {
1293 return pin(7);
1294 }
1295
aset_value(const verinum & val)1296 void NetFF::aset_value(const verinum&val)
1297 {
1298 aset_value_ = val;
1299 }
1300
aset_value() const1301 const verinum& NetFF::aset_value() const
1302 {
1303 return aset_value_;
1304 }
1305
sset_value(const verinum & val)1306 void NetFF::sset_value(const verinum&val)
1307 {
1308 sset_value_ = val;
1309 }
1310
sset_value() const1311 const verinum& NetFF::sset_value() const
1312 {
1313 return sset_value_;
1314 }
1315
1316 /*
1317 * The NetLatch class represents an LPM_LATCH device. The pinout is assigned
1318 * like so:
1319 * 0 -- Enable
1320 * 1 -- Data
1321 * 2 -- Q
1322 */
1323
NetLatch(NetScope * s,perm_string n,unsigned width__)1324 NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__)
1325 : NetNode(s, n, 3), width_(width__)
1326 {
1327 pin_Enable().set_dir(Link::INPUT);
1328 pin_Data().set_dir(Link::INPUT);
1329 pin_Q().set_dir(Link::OUTPUT);
1330 }
1331
~NetLatch()1332 NetLatch::~NetLatch()
1333 {
1334 }
1335
width() const1336 unsigned NetLatch::width() const
1337 {
1338 return width_;
1339 }
1340
pin_Enable()1341 Link& NetLatch::pin_Enable()
1342 {
1343 return pin(0);
1344 }
1345
pin_Enable() const1346 const Link& NetLatch::pin_Enable() const
1347 {
1348 return pin(0);
1349 }
1350
pin_Data()1351 Link& NetLatch::pin_Data()
1352 {
1353 return pin(1);
1354 }
1355
pin_Data() const1356 const Link& NetLatch::pin_Data() const
1357 {
1358 return pin(1);
1359 }
1360
pin_Q()1361 Link& NetLatch::pin_Q()
1362 {
1363 return pin(2);
1364 }
1365
pin_Q() const1366 const Link& NetLatch::pin_Q() const
1367 {
1368 return pin(2);
1369 }
1370
NetAbs(NetScope * s,perm_string n,unsigned w)1371 NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
1372 : NetNode(s, n, 2), width_(w)
1373 {
1374 pin(0).set_dir(Link::OUTPUT);
1375 pin(1).set_dir(Link::INPUT);
1376 }
1377
~NetAbs()1378 NetAbs::~NetAbs()
1379 {
1380 }
1381
width() const1382 unsigned NetAbs::width() const
1383 {
1384 return width_;
1385 }
1386
1387 /*
1388 * The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
1389 * assigned like so:
1390 * 0 -- Cout
1391 * 1 -- DataA (normally a vector)
1392 * 2 -- DataB (normally a vector)
1393 * 3 -- Result (normally a vector)
1394 */
NetAddSub(NetScope * s,perm_string n,unsigned w)1395 NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
1396 : NetNode(s, n, 4), width_(w)
1397 {
1398 pin(0).set_dir(Link::OUTPUT); // Cout
1399 pin(1).set_dir(Link::INPUT); // DataA
1400 pin(2).set_dir(Link::INPUT); // DataB
1401 pin(3).set_dir(Link::OUTPUT); // Result
1402 }
1403
~NetAddSub()1404 NetAddSub::~NetAddSub()
1405 {
1406 }
1407
width() const1408 unsigned NetAddSub::width()const
1409 {
1410 return width_;
1411 }
1412
pin_Cout()1413 Link& NetAddSub::pin_Cout()
1414 {
1415 return pin(0);
1416 }
1417
pin_Cout() const1418 const Link& NetAddSub::pin_Cout() const
1419 {
1420 return pin(0);
1421 }
1422
pin_DataA()1423 Link& NetAddSub::pin_DataA()
1424 {
1425 return pin(1);
1426 }
1427
pin_DataA() const1428 const Link& NetAddSub::pin_DataA() const
1429 {
1430 return pin(1);
1431 }
1432
pin_DataB()1433 Link& NetAddSub::pin_DataB()
1434 {
1435 return pin(2);
1436 }
1437
pin_DataB() const1438 const Link& NetAddSub::pin_DataB() const
1439 {
1440 return pin(2);
1441 }
1442
pin_Result()1443 Link& NetAddSub::pin_Result()
1444 {
1445 return pin(3);
1446 }
1447
pin_Result() const1448 const Link& NetAddSub::pin_Result() const
1449 {
1450 return pin(3);
1451 }
1452
NetArrayDq(NetScope * s,perm_string n,NetNet * mem__,unsigned awid)1453 NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem__, unsigned awid)
1454 : NetNode(s, n, 2),
1455 mem_(mem__), awidth_(awid)
1456 {
1457 pin(0).set_dir(Link::OUTPUT); // Result
1458 pin(1).set_dir(Link::INPUT); // Address
1459 // Increment the expression reference count for the target
1460 // memory so that it is not deleted underneath me.
1461 mem_->incr_eref();
1462 }
1463
~NetArrayDq()1464 NetArrayDq::~NetArrayDq()
1465 {
1466 }
1467
width() const1468 unsigned NetArrayDq::width() const
1469 {
1470 return mem_->vector_width();
1471 }
1472
awidth() const1473 unsigned NetArrayDq::awidth() const
1474 {
1475 return awidth_;
1476 }
1477
mem() const1478 const NetNet* NetArrayDq::mem() const
1479 {
1480 return mem_;
1481 }
1482
pin_Result()1483 Link& NetArrayDq::pin_Result()
1484 {
1485 return pin(0);
1486 }
1487
pin_Address()1488 Link& NetArrayDq::pin_Address()
1489 {
1490 return pin(1);
1491 }
1492
pin_Result() const1493 const Link& NetArrayDq::pin_Result() const
1494 {
1495 return pin(0);
1496 }
1497
pin_Address() const1498 const Link& NetArrayDq::pin_Address() const
1499 {
1500 return pin(1);
1501 }
1502
1503 /*
1504 * The pinout for the NetCLShift is:
1505 * 0 -- Result
1506 * 1 -- Data
1507 * 2 -- Distance
1508 */
NetCLShift(NetScope * s,perm_string n,unsigned width__,unsigned width_dist__,bool right_flag__,bool signed_flag__)1509 NetCLShift::NetCLShift(NetScope*s, perm_string n,
1510 unsigned width__, unsigned width_dist__,
1511 bool right_flag__, bool signed_flag__)
1512 : NetNode(s, n, 3),
1513 width_(width__), width_dist_(width_dist__),
1514 right_flag_(right_flag__), signed_flag_(signed_flag__)
1515 {
1516 pin(0).set_dir(Link::OUTPUT); // Result
1517 pin(1).set_dir(Link::INPUT); // Data
1518 pin(2).set_dir(Link::INPUT); // Distance
1519 }
1520
~NetCLShift()1521 NetCLShift::~NetCLShift()
1522 {
1523 }
1524
width() const1525 unsigned NetCLShift::width() const
1526 {
1527 return width_;
1528 }
1529
width_dist() const1530 unsigned NetCLShift::width_dist() const
1531 {
1532 return width_dist_;
1533 }
1534
right_flag() const1535 bool NetCLShift::right_flag() const
1536 {
1537 return right_flag_;
1538 }
1539
signed_flag() const1540 bool NetCLShift::signed_flag() const
1541 {
1542 return signed_flag_;
1543 }
1544
pin_Data()1545 Link& NetCLShift::pin_Data()
1546 {
1547 return pin(1);
1548 }
1549
pin_Data() const1550 const Link& NetCLShift::pin_Data() const
1551 {
1552 return pin(1);
1553 }
1554
pin_Result()1555 Link& NetCLShift::pin_Result()
1556 {
1557 return pin(0);
1558 }
1559
pin_Result() const1560 const Link& NetCLShift::pin_Result() const
1561 {
1562 return pin(0);
1563 }
1564
pin_Distance()1565 Link& NetCLShift::pin_Distance()
1566 {
1567 return pin(2);
1568 }
1569
pin_Distance() const1570 const Link& NetCLShift::pin_Distance() const
1571 {
1572 return pin(2);
1573 }
1574
NetCompare(NetScope * s,perm_string n,unsigned wi)1575 NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
1576 : NetNode(s, n, 8), width_(wi)
1577 {
1578 signed_flag_ = false;
1579 pin(0).set_dir(Link::OUTPUT); // AGB
1580 pin(1).set_dir(Link::OUTPUT); // AGEB
1581 pin(2).set_dir(Link::OUTPUT); // AEB
1582 pin(3).set_dir(Link::OUTPUT); // ANEB
1583 pin(4).set_dir(Link::OUTPUT); // ALB
1584 pin(5).set_dir(Link::OUTPUT); // ALEB
1585 pin(6).set_dir(Link::INPUT); // DataA
1586 pin(7).set_dir(Link::INPUT); // DataB
1587 }
1588
~NetCompare()1589 NetCompare::~NetCompare()
1590 {
1591 }
1592
width() const1593 unsigned NetCompare::width() const
1594 {
1595 return width_;
1596 }
1597
get_signed() const1598 bool NetCompare::get_signed() const
1599 {
1600 return signed_flag_;
1601 }
1602
set_signed(bool flag)1603 void NetCompare::set_signed(bool flag)
1604 {
1605 signed_flag_ = flag;
1606 }
1607
1608
pin_AGB()1609 Link& NetCompare::pin_AGB()
1610 {
1611 return pin(0);
1612 }
1613
pin_AGB() const1614 const Link& NetCompare::pin_AGB() const
1615 {
1616 return pin(0);
1617 }
1618
pin_AGEB()1619 Link& NetCompare::pin_AGEB()
1620 {
1621 return pin(1);
1622 }
1623
pin_AGEB() const1624 const Link& NetCompare::pin_AGEB() const
1625 {
1626 return pin(1);
1627 }
1628
pin_AEB()1629 Link& NetCompare::pin_AEB()
1630 {
1631 return pin(2);
1632 }
1633
pin_AEB() const1634 const Link& NetCompare::pin_AEB() const
1635 {
1636 return pin(2);
1637 }
1638
pin_ANEB()1639 Link& NetCompare::pin_ANEB()
1640 {
1641 return pin(3);
1642 }
1643
pin_ANEB() const1644 const Link& NetCompare::pin_ANEB() const
1645 {
1646 return pin(3);
1647 }
1648
pin_ALB()1649 Link& NetCompare::pin_ALB()
1650 {
1651 return pin(4);
1652 }
1653
pin_ALB() const1654 const Link& NetCompare::pin_ALB() const
1655 {
1656 return pin(4);
1657 }
1658
pin_ALEB()1659 Link& NetCompare::pin_ALEB()
1660 {
1661 return pin(5);
1662 }
1663
pin_ALEB() const1664 const Link& NetCompare::pin_ALEB() const
1665 {
1666 return pin(5);
1667 }
1668
pin_DataA()1669 Link& NetCompare::pin_DataA()
1670 {
1671 return pin(6);
1672 }
1673
pin_DataA() const1674 const Link& NetCompare::pin_DataA() const
1675 {
1676 return pin(6);
1677 }
1678
pin_DataB()1679 Link& NetCompare::pin_DataB()
1680 {
1681 return pin(7);
1682 }
1683
pin_DataB() const1684 const Link& NetCompare::pin_DataB() const
1685 {
1686 return pin(7);
1687 }
1688
NetDivide(NetScope * sc,perm_string n,unsigned wr,unsigned wa,unsigned wb)1689 NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
1690 unsigned wa, unsigned wb)
1691 : NetNode(sc, n, 3),
1692 width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
1693 {
1694 pin(0).set_dir(Link::OUTPUT); // Result
1695 pin(1).set_dir(Link::INPUT); // DataA
1696 pin(2).set_dir(Link::INPUT); // DataB
1697 }
1698
~NetDivide()1699 NetDivide::~NetDivide()
1700 {
1701 }
1702
width_r() const1703 unsigned NetDivide::width_r() const
1704 {
1705 return width_r_;
1706 }
1707
width_a() const1708 unsigned NetDivide::width_a() const
1709 {
1710 return width_a_;
1711 }
1712
width_b() const1713 unsigned NetDivide::width_b() const
1714 {
1715 return width_b_;
1716 }
1717
set_signed(bool flag)1718 void NetDivide::set_signed(bool flag)
1719 {
1720 signed_flag_ = flag;
1721 }
1722
get_signed() const1723 bool NetDivide::get_signed() const
1724 {
1725 return signed_flag_;
1726 }
1727
pin_Result()1728 Link& NetDivide::pin_Result()
1729 {
1730 return pin(0);
1731 }
1732
pin_Result() const1733 const Link& NetDivide::pin_Result() const
1734 {
1735 return pin(0);
1736 }
1737
pin_DataA()1738 Link& NetDivide::pin_DataA()
1739 {
1740 return pin(1);
1741 }
1742
pin_DataA() const1743 const Link& NetDivide::pin_DataA() const
1744 {
1745 return pin(1);
1746 }
1747
pin_DataB()1748 Link& NetDivide::pin_DataB()
1749 {
1750 return pin(2);
1751 }
1752
pin_DataB() const1753 const Link& NetDivide::pin_DataB() const
1754 {
1755 return pin(2);
1756 }
1757
NetLiteral(NetScope * sc,perm_string n,const verireal & val)1758 NetLiteral::NetLiteral(NetScope*sc, perm_string n, const verireal&val)
1759 : NetNode(sc, n, 1), real_(val)
1760 {
1761 pin(0).set_dir(Link::OUTPUT);
1762 }
1763
~NetLiteral()1764 NetLiteral::~NetLiteral()
1765 {
1766 }
1767
data_type() const1768 ivl_variable_type_t NetLiteral::data_type() const
1769 {
1770 return IVL_VT_REAL;
1771 }
1772
value_real() const1773 const verireal& NetLiteral::value_real() const
1774 {
1775 return real_;
1776 }
1777
NetMult(NetScope * sc,perm_string n,unsigned wr,unsigned wa,unsigned wb)1778 NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
1779 unsigned wa, unsigned wb)
1780 : NetNode(sc, n, 3),
1781 signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
1782 {
1783 pin(0).set_dir(Link::OUTPUT); // Result
1784 pin(1).set_dir(Link::INPUT); // DataA
1785 pin(2).set_dir(Link::INPUT); // DataB
1786 }
1787
~NetMult()1788 NetMult::~NetMult()
1789 {
1790 }
1791
set_signed(bool flag)1792 void NetMult::set_signed(bool flag)
1793 {
1794 signed_ = flag;
1795 }
1796
get_signed() const1797 bool NetMult::get_signed() const
1798 {
1799 return signed_;
1800 }
1801
width_r() const1802 unsigned NetMult::width_r() const
1803 {
1804 return width_r_;
1805 }
1806
width_a() const1807 unsigned NetMult::width_a() const
1808 {
1809 return width_a_;
1810 }
1811
width_b() const1812 unsigned NetMult::width_b() const
1813 {
1814 return width_b_;
1815 }
1816
pin_Result()1817 Link& NetMult::pin_Result()
1818 {
1819 return pin(0);
1820 }
1821
pin_Result() const1822 const Link& NetMult::pin_Result() const
1823 {
1824 return pin(0);
1825 }
1826
pin_DataA()1827 Link& NetMult::pin_DataA()
1828 {
1829 return pin(1);
1830 }
1831
pin_DataA() const1832 const Link& NetMult::pin_DataA() const
1833 {
1834 return pin(1);
1835 }
1836
pin_DataB()1837 Link& NetMult::pin_DataB()
1838 {
1839 return pin(2);
1840 }
1841
pin_DataB() const1842 const Link& NetMult::pin_DataB() const
1843 {
1844 return pin(2);
1845 }
1846
NetPow(NetScope * sc,perm_string n,unsigned wr,unsigned wa,unsigned wb)1847 NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
1848 unsigned wa, unsigned wb)
1849 : NetNode(sc, n, 3),
1850 signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
1851 {
1852 pin(0).set_dir(Link::OUTPUT); // Result
1853 pin(1).set_dir(Link::INPUT); // DataA
1854 pin(2).set_dir(Link::INPUT); // DataB
1855 }
1856
~NetPow()1857 NetPow::~NetPow()
1858 {
1859 }
1860
set_signed(bool flag)1861 void NetPow::set_signed(bool flag)
1862 {
1863 signed_ = flag;
1864 }
1865
get_signed() const1866 bool NetPow::get_signed() const
1867 {
1868 return signed_;
1869 }
1870
width_r() const1871 unsigned NetPow::width_r() const
1872 {
1873 return width_r_;
1874 }
1875
width_a() const1876 unsigned NetPow::width_a() const
1877 {
1878 return width_a_;
1879 }
1880
width_b() const1881 unsigned NetPow::width_b() const
1882 {
1883 return width_b_;
1884 }
1885
pin_Result()1886 Link& NetPow::pin_Result()
1887 {
1888 return pin(0);
1889 }
1890
pin_Result() const1891 const Link& NetPow::pin_Result() const
1892 {
1893 return pin(0);
1894 }
1895
pin_DataA()1896 Link& NetPow::pin_DataA()
1897 {
1898 return pin(1);
1899 }
1900
pin_DataA() const1901 const Link& NetPow::pin_DataA() const
1902 {
1903 return pin(1);
1904 }
1905
pin_DataB()1906 Link& NetPow::pin_DataB()
1907 {
1908 return pin(2);
1909 }
1910
pin_DataB() const1911 const Link& NetPow::pin_DataB() const
1912 {
1913 return pin(2);
1914 }
1915
1916 /*
1917 * The NetMux class represents an LPM_MUX device. The pinout is assigned
1918 * like so:
1919 * 0 -- Result
1920 * 1 -- Sel
1921 * 2+N -- Data[N] (N is the size of the mux)
1922 */
1923
NetMux(NetScope * s,perm_string n,unsigned wi,unsigned si,unsigned sw)1924 NetMux::NetMux(NetScope*s, perm_string n,
1925 unsigned wi, unsigned si, unsigned sw)
1926 : NetNode(s, n, 2+si),
1927 width_(wi), size_(si), swidth_(sw)
1928 {
1929 pin(0).set_dir(Link::OUTPUT); // Q
1930 pin(1).set_dir(Link::INPUT); // Sel
1931
1932 for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
1933 pin_Data(idx).set_dir(Link::INPUT); // Data[idx]
1934 }
1935 }
1936
~NetMux()1937 NetMux::~NetMux()
1938 {
1939 }
1940
width() const1941 unsigned NetMux::width()const
1942 {
1943 return width_;
1944 }
1945
size() const1946 unsigned NetMux::size() const
1947 {
1948 return size_;
1949 }
1950
sel_width() const1951 unsigned NetMux::sel_width() const
1952 {
1953 return swidth_;
1954 }
1955
pin_Result()1956 Link& NetMux::pin_Result()
1957 {
1958 return pin(0);
1959 }
1960
pin_Result() const1961 const Link& NetMux::pin_Result() const
1962 {
1963 return pin(0);
1964 }
1965
pin_Sel()1966 Link& NetMux::pin_Sel()
1967 {
1968 return pin(1);
1969 }
1970
pin_Sel() const1971 const Link& NetMux::pin_Sel() const
1972 {
1973 return pin(1);
1974 }
1975
pin_Data(unsigned s)1976 Link& NetMux::pin_Data(unsigned s)
1977 {
1978 assert(s < size_);
1979 return pin(2+s);
1980 }
1981
pin_Data(unsigned s) const1982 const Link& NetMux::pin_Data(unsigned s) const
1983 {
1984 assert(s < size_);
1985 return pin(2+s);
1986 }
1987
NetSignExtend(NetScope * s,perm_string n,unsigned w)1988 NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
1989 : NetNode(s, n, 2), width_(w)
1990 {
1991 pin(0).set_dir(Link::OUTPUT);
1992 pin(1).set_dir(Link::INPUT);
1993 }
1994
~NetSignExtend()1995 NetSignExtend::~NetSignExtend()
1996 {
1997 }
1998
width() const1999 unsigned NetSignExtend::width() const
2000 {
2001 return width_;
2002 }
2003
NetBUFZ(NetScope * s,perm_string n,unsigned w,bool trans)2004 NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w, bool trans)
2005 : NetNode(s, n, 2), width_(w), transparent_(trans)
2006 {
2007 pin(0).set_dir(Link::OUTPUT);
2008 pin(1).set_dir(Link::INPUT);
2009 }
2010
~NetBUFZ()2011 NetBUFZ::~NetBUFZ()
2012 {
2013 }
2014
width() const2015 unsigned NetBUFZ::width() const
2016 {
2017 return width_;
2018 }
2019
NetCaseCmp(NetScope * s,perm_string n,unsigned wid,kind_t k)2020 NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, kind_t k)
2021 : NetNode(s, n, 3), width_(wid), kind_(k)
2022 {
2023 pin(0).set_dir(Link::OUTPUT);
2024 pin(1).set_dir(Link::INPUT);
2025 pin(2).set_dir(Link::INPUT);
2026 }
2027
~NetCaseCmp()2028 NetCaseCmp::~NetCaseCmp()
2029 {
2030 }
2031
width() const2032 unsigned NetCaseCmp::width() const
2033 {
2034 return width_;
2035 }
2036
NetCondit(NetExpr * ex,NetProc * i,NetProc * e)2037 NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
2038 : expr_(ex), if_(i), else_(e)
2039 {
2040 }
2041
~NetCondit()2042 NetCondit::~NetCondit()
2043 {
2044 delete expr_;
2045 delete if_;
2046 delete else_;
2047 }
2048
expr() const2049 const NetExpr* NetCondit::expr() const
2050 {
2051 return expr_;
2052 }
2053
expr()2054 NetExpr* NetCondit::expr()
2055 {
2056 return expr_;
2057 }
2058
set_expr(NetExpr * ex)2059 void NetCondit::set_expr(NetExpr*ex)
2060 {
2061 delete expr_;
2062 expr_ = ex;
2063 }
2064
if_clause()2065 NetProc* NetCondit::if_clause()
2066 {
2067 return if_;
2068 }
2069
else_clause()2070 NetProc* NetCondit::else_clause()
2071 {
2072 return else_;
2073 }
2074
NetConst(NetScope * s,perm_string n,verinum::V v)2075 NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
2076 : NetNode(s, n, 1), value_(v, 1)
2077 {
2078 pin(0).set_dir(Link::OUTPUT);
2079 }
2080
NetConst(NetScope * s,perm_string n,const verinum & val)2081 NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
2082 : NetNode(s, n, 1), value_(val)
2083 {
2084 pin(0).set_dir(Link::OUTPUT);
2085 }
2086
~NetConst()2087 NetConst::~NetConst()
2088 {
2089 }
2090
value(unsigned idx) const2091 verinum::V NetConst::value(unsigned idx) const
2092 {
2093 assert(idx < width());
2094 return value_[idx];
2095 }
2096
NetBaseDef(NetScope * s,const vector<NetNet * > & po,const std::vector<NetExpr * > & pd)2097 NetBaseDef::NetBaseDef(NetScope*s, const vector<NetNet*>&po, const std::vector<NetExpr*>&pd)
2098 : scope_(s), ports_(po), pdefaults_(pd)
2099 {
2100 proc_ = 0;
2101 }
2102
~NetBaseDef()2103 NetBaseDef::~NetBaseDef()
2104 {
2105 }
2106
scope() const2107 const NetScope* NetBaseDef::scope() const
2108 {
2109 return scope_;
2110 }
2111
scope()2112 NetScope*NetBaseDef::scope()
2113 {
2114 return scope_;
2115 }
2116
port_count() const2117 unsigned NetBaseDef::port_count() const
2118 {
2119 return ports_.size();
2120 }
2121
port(unsigned idx) const2122 NetNet* NetBaseDef::port(unsigned idx) const
2123 {
2124 assert(idx < ports_.size());
2125 return ports_[idx];
2126 }
2127
port_defe(unsigned idx) const2128 NetExpr* NetBaseDef::port_defe(unsigned idx) const
2129 {
2130 assert(idx < pdefaults_.size());
2131 return pdefaults_[idx];
2132 }
2133
set_proc(NetProc * st)2134 void NetBaseDef::set_proc(NetProc*st)
2135 {
2136 assert(proc_ == 0);
2137 assert(st != 0);
2138 proc_ = st;
2139 }
2140
proc() const2141 const NetProc* NetBaseDef::proc() const
2142 {
2143 return proc_;
2144 }
2145
NetFuncDef(NetScope * s,NetNet * result,const vector<NetNet * > & po,const vector<NetExpr * > & pd)2146 NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po,
2147 const vector<NetExpr*>&pd)
2148 : NetBaseDef(s, po, pd), result_sig_(result)
2149 {
2150 }
2151
~NetFuncDef()2152 NetFuncDef::~NetFuncDef()
2153 {
2154 }
2155
return_sig() const2156 const NetNet* NetFuncDef::return_sig() const
2157 {
2158 return result_sig_;
2159 }
2160
NetSTask(const char * na,ivl_sfunc_as_task_t sfat,const vector<NetExpr * > & pa)2161 NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
2162 const vector<NetExpr*>&pa)
2163 : name_(0), sfunc_as_task_(sfat), parms_(pa)
2164 {
2165 name_ = lex_strings.add(na);
2166 assert(name_[0] == '$');
2167 }
2168
~NetSTask()2169 NetSTask::~NetSTask()
2170 {
2171 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
2172 delete parms_[idx];
2173
2174 /* The name_ string is perm-allocated in lex_strings. */
2175 }
2176
name() const2177 const char*NetSTask::name() const
2178 {
2179 return name_;
2180 }
2181
sfunc_as_task() const2182 ivl_sfunc_as_task_t NetSTask::sfunc_as_task() const
2183 {
2184 return sfunc_as_task_;
2185 }
2186
nparms() const2187 unsigned NetSTask::nparms() const
2188 {
2189 return parms_.size();
2190 }
2191
parm(unsigned idx) const2192 const NetExpr* NetSTask::parm(unsigned idx) const
2193 {
2194 return parms_[idx];
2195 }
2196
NetEUFunc(NetScope * scope,NetScope * def,NetESignal * res,vector<NetExpr * > & p,bool nc)2197 NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
2198 vector<NetExpr*>&p, bool nc)
2199 : scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
2200 {
2201 expr_width(result_sig_->expr_width());
2202 }
2203
~NetEUFunc()2204 NetEUFunc::~NetEUFunc()
2205 {
2206 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
2207 delete parms_[idx];
2208 }
2209 #if 0
2210 const string NetEUFunc::name() const
2211 {
2212 return func_->name();
2213 }
2214 #endif
result_sig() const2215 const NetESignal*NetEUFunc::result_sig() const
2216 {
2217 return result_sig_;
2218 }
2219
parm_count() const2220 unsigned NetEUFunc::parm_count() const
2221 {
2222 return parms_.size();
2223 }
2224
parm(unsigned idx) const2225 const NetExpr* NetEUFunc::parm(unsigned idx) const
2226 {
2227 assert(idx < parms_.size());
2228 return parms_[idx];
2229 }
2230
func() const2231 const NetScope* NetEUFunc::func() const
2232 {
2233 return func_;
2234 }
2235
expr_type() const2236 ivl_variable_type_t NetEUFunc::expr_type() const
2237 {
2238 if (result_sig_)
2239 return result_sig_->expr_type();
2240
2241 return IVL_VT_VOID;
2242 }
2243
enumeration() const2244 const netenum_t* NetEUFunc::enumeration() const
2245 {
2246 if (result_sig_)
2247 return result_sig_->enumeration();
2248
2249 return 0;
2250 }
2251
NetUTask(NetScope * def)2252 NetUTask::NetUTask(NetScope*def)
2253 : task_(def)
2254 {
2255 }
2256
~NetUTask()2257 NetUTask::~NetUTask()
2258 {
2259 }
2260
task() const2261 const NetScope* NetUTask::task() const
2262 {
2263 return task_;
2264 }
2265
NetAlloc(NetScope * scope__)2266 NetAlloc::NetAlloc(NetScope*scope__)
2267 : scope_(scope__)
2268 {
2269 }
2270
~NetAlloc()2271 NetAlloc::~NetAlloc()
2272 {
2273 }
2274 #if 0
2275 const string NetAlloc::name() const
2276 {
2277 return scope_->name();
2278 }
2279 #endif
scope() const2280 const NetScope* NetAlloc::scope() const
2281 {
2282 return scope_;
2283 }
2284
NetFree(NetScope * scope__)2285 NetFree::NetFree(NetScope*scope__)
2286 : scope_(scope__)
2287 {
2288 }
2289
~NetFree()2290 NetFree::~NetFree()
2291 {
2292 }
2293 #if 0
2294 const string NetFree::name() const
2295 {
2296 return scope_->name();
2297 }
2298 #endif
scope() const2299 const NetScope* NetFree::scope() const
2300 {
2301 return scope_;
2302 }
2303
2304 /*
2305 * Create a bitwise operator node from the opcode and the left and
2306 * right expressions.
2307 */
NetEBBits(char op__,NetExpr * l,NetExpr * r,unsigned wid,bool signed_flag)2308 NetEBBits::NetEBBits(char op__, NetExpr*l, NetExpr*r, unsigned wid, bool signed_flag)
2309 : NetEBinary(op__, l, r, wid, signed_flag)
2310 {
2311 }
2312
~NetEBBits()2313 NetEBBits::~NetEBBits()
2314 {
2315 }
2316
NetEBinary(char op__,NetExpr * l,NetExpr * r,unsigned wid,bool signed_flag)2317 NetEBinary::NetEBinary(char op__, NetExpr*l, NetExpr*r, unsigned wid, bool signed_flag)
2318 : op_(op__), left_(l), right_(r)
2319 {
2320 expr_width(wid);
2321 cast_signed_base_(signed_flag);
2322 }
2323
~NetEBinary()2324 NetEBinary::~NetEBinary()
2325 {
2326 delete left_;
2327 delete right_;
2328 }
2329
has_width() const2330 bool NetEBinary::has_width() const
2331 {
2332 return left_->has_width() && right_->has_width();
2333 }
2334
NetEBLogic(char op__,NetExpr * l,NetExpr * r)2335 NetEBLogic::NetEBLogic(char op__, NetExpr*l, NetExpr*r)
2336 : NetEBinary(op__, l, r, 1, false)
2337 {
2338 }
2339
~NetEBLogic()2340 NetEBLogic::~NetEBLogic()
2341 {
2342 }
2343
NetEConst(const verinum & val)2344 NetEConst::NetEConst(const verinum&val)
2345 : NetExpr(val.len()), value_(val)
2346 {
2347 cast_signed_base_(value_.has_sign());
2348 }
2349
~NetEConst()2350 NetEConst::~NetEConst()
2351 {
2352 }
2353
cast_signed(bool flag)2354 void NetEConst::cast_signed(bool flag)
2355 {
2356 cast_signed_base_(flag);
2357 value_.has_sign(flag);
2358 }
2359
value() const2360 const verinum& NetEConst::value() const
2361 {
2362 return value_;
2363 }
2364
has_width() const2365 bool NetEConst::has_width() const
2366 {
2367 return value_.has_len();
2368 }
2369
expr_type() const2370 ivl_variable_type_t NetEConst::expr_type() const
2371 {
2372 if (value_.len() == 0)
2373 return IVL_VT_LOGIC;
2374 if (value_.is_string())
2375 return IVL_VT_BOOL;
2376 if (value_.is_defined())
2377 return IVL_VT_BOOL;
2378
2379 return IVL_VT_LOGIC;
2380 }
2381
trim()2382 void NetEConst::trim()
2383
2384 {
2385 if (value_.is_string())
2386 return;
2387
2388 value_.has_len(false);
2389 value_ = trim_vnum(value_);
2390 expr_width(value_.len());
2391 }
2392
NetEConstParam(NetScope * s,perm_string n,const verinum & v)2393 NetEConstParam::NetEConstParam(NetScope*s, perm_string n, const verinum&v)
2394 : NetEConst(v), scope_(s), name_(n)
2395 {
2396 cast_signed_base_(v.has_sign());
2397 }
2398
~NetEConstParam()2399 NetEConstParam::~NetEConstParam()
2400 {
2401 }
2402
name() const2403 perm_string NetEConstParam::name() const
2404 {
2405 return name_;
2406 }
2407
scope() const2408 const NetScope* NetEConstParam::scope() const
2409 {
2410 return scope_;
2411 }
2412
NetEEvent(NetEvent * e)2413 NetEEvent::NetEEvent(NetEvent*e)
2414 : event_(e)
2415 {
2416 e->exprref_ += 1;
2417 }
2418
~NetEEvent()2419 NetEEvent::~NetEEvent()
2420 {
2421 }
2422
event() const2423 const NetEvent* NetEEvent::event() const
2424 {
2425 return event_;
2426 }
2427
NetEScope(NetScope * s)2428 NetEScope::NetEScope(NetScope*s)
2429 : scope_(s)
2430 {
2431 }
2432
~NetEScope()2433 NetEScope::~NetEScope()
2434 {
2435 }
2436
scope() const2437 const NetScope* NetEScope::scope() const
2438 {
2439 return scope_;
2440 }
2441
NetESignal(NetNet * n)2442 NetESignal::NetESignal(NetNet*n)
2443 : NetExpr(n->vector_width()), net_(n), enum_type_(n->enumeration()), word_(0)
2444 {
2445 net_->incr_eref();
2446 set_line(*n);
2447 cast_signed_base_(net_->get_signed());
2448 }
2449
NetESignal(NetNet * n,NetExpr * w)2450 NetESignal::NetESignal(NetNet*n, NetExpr*w)
2451 : NetExpr(n->vector_width()), net_(n), word_(w)
2452 {
2453 net_->incr_eref();
2454 set_line(*n);
2455 cast_signed_base_(net_->get_signed());
2456 }
2457
~NetESignal()2458 NetESignal::~NetESignal()
2459 {
2460 net_->decr_eref();
2461 }
2462
name() const2463 perm_string NetESignal::name() const
2464 {
2465 return net_->name();
2466 }
2467
enumeration() const2468 const netenum_t* NetESignal::enumeration() const
2469 {
2470 return enum_type_;
2471 }
2472
word_index() const2473 const NetExpr* NetESignal::word_index() const
2474 {
2475 return word_;
2476 }
2477
vector_width() const2478 unsigned NetESignal::vector_width() const
2479 {
2480 return net_->vector_width();
2481 }
2482
sig() const2483 const NetNet* NetESignal::sig() const
2484 {
2485 return net_;
2486 }
2487
sig()2488 NetNet* NetESignal::sig()
2489 {
2490 return net_;
2491 }
2492
2493 /*
2494 * The lsi() and msi() methods should be removed from the NetESignal
2495 * class, to be replaced with packed dimensions aware methods of
2496 * getting at dimensions.
2497 */
lsi() const2498 long NetESignal::lsi() const
2499 {
2500 const vector<netrange_t>&packed = net_->packed_dims();
2501 ivl_assert(*this, packed.size() == 1);
2502 return packed.back().get_lsb();
2503 }
2504
msi() const2505 long NetESignal::msi() const
2506 {
2507 const vector<netrange_t>&packed = net_->packed_dims();
2508 ivl_assert(*this, packed.size() == 1);
2509 return packed.back().get_msb();
2510 }
2511
expr_type() const2512 ivl_variable_type_t NetESignal::expr_type() const
2513 {
2514 if (net_->darray_type())
2515 return IVL_VT_DARRAY;
2516 else
2517 return net_->data_type();
2518 }
2519
2520 /*
2521 * Make a ternary operator from all the sub-expressions. The condition
2522 * expression is self-determined, but the true and false expressions
2523 * should have the same width. NOTE: This matching of the widths really
2524 * has to be done in elaboration.
2525 */
NetETernary(NetExpr * c,NetExpr * t,NetExpr * f,unsigned wid,bool signed_flag)2526 NetETernary::NetETernary(NetExpr*c, NetExpr*t, NetExpr*f,
2527 unsigned wid, bool signed_flag)
2528 : cond_(c), true_val_(t), false_val_(f)
2529 {
2530 expr_width(wid);
2531 cast_signed_base_(signed_flag);
2532 }
2533
~NetETernary()2534 NetETernary::~NetETernary()
2535 {
2536 delete cond_;
2537 delete true_val_;
2538 delete false_val_;
2539 }
2540
enumeration() const2541 const netenum_t* NetETernary::enumeration() const
2542 {
2543 // If the condition can evaluate to an ambiguous value,
2544 // the result may be blended, and so is not guaranteed
2545 // to be a valid enumeration value.
2546 if (cond_->expr_type() != IVL_VT_BOOL)
2547 return 0;
2548
2549 if (true_val_->enumeration() != false_val_->enumeration())
2550 return 0;
2551
2552 return true_val_->enumeration();
2553 }
2554
cond_expr() const2555 const NetExpr* NetETernary::cond_expr() const
2556 {
2557 return cond_;
2558 }
2559
true_expr() const2560 const NetExpr* NetETernary::true_expr() const
2561 {
2562 return true_val_;
2563 }
2564
false_expr() const2565 const NetExpr* NetETernary::false_expr() const
2566 {
2567 return false_val_;
2568 }
2569
expr_type() const2570 ivl_variable_type_t NetETernary::expr_type() const
2571 {
2572 ivl_assert(*this, true_val_);
2573 ivl_assert(*this, false_val_);
2574 ivl_variable_type_t tru = true_val_->expr_type();
2575 ivl_variable_type_t fal = false_val_->expr_type();
2576 ivl_variable_type_t sel = cond_->expr_type();
2577 if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
2578 return IVL_VT_LOGIC;
2579 if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
2580 return IVL_VT_LOGIC;
2581 if (sel == IVL_VT_LOGIC && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL) && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
2582 return IVL_VT_LOGIC;
2583 if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
2584 return IVL_VT_REAL;
2585 if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
2586 return IVL_VT_REAL;
2587
2588 if (tru != fal) {
2589 cerr << get_fileline() << ": internal error:"
2590 << " Unexpected ?: type clash:"
2591 << " tru=" << tru << ", fal=" << fal << endl;
2592 }
2593 ivl_assert(*this, tru == fal);
2594 return tru;
2595 }
2596
NetEUnary(char op__,NetExpr * ex,unsigned wid,bool signed_flag)2597 NetEUnary::NetEUnary(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
2598 : NetExpr(wid), op_(op__), expr_(ex)
2599 {
2600 cast_signed_base_(signed_flag);
2601 }
2602
~NetEUnary()2603 NetEUnary::~NetEUnary()
2604 {
2605 delete expr_;
2606 }
2607
expr_type() const2608 ivl_variable_type_t NetEUnary::expr_type() const
2609 {
2610 return expr_->expr_type();
2611 }
2612
NetEUBits(char op__,NetExpr * ex,unsigned wid,bool signed_flag)2613 NetEUBits::NetEUBits(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
2614 : NetEUnary(op__, ex, wid, signed_flag)
2615 {
2616 }
2617
~NetEUBits()2618 NetEUBits::~NetEUBits()
2619 {
2620 }
2621
expr_type() const2622 ivl_variable_type_t NetEUBits::expr_type() const
2623 {
2624 return expr_->expr_type();
2625 }
2626
NetEUReduce(char op__,NetExpr * ex)2627 NetEUReduce::NetEUReduce(char op__, NetExpr*ex)
2628 : NetEUnary(op__, ex, 1, false)
2629 {
2630 }
2631
~NetEUReduce()2632 NetEUReduce::~NetEUReduce()
2633 {
2634 }
2635
expr_type() const2636 ivl_variable_type_t NetEUReduce::expr_type() const
2637 {
2638 return expr_->expr_type();
2639 }
2640
NetECast(char op__,NetExpr * ex,unsigned wid,bool signed_flag)2641 NetECast::NetECast(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
2642 : NetEUnary(op__, ex, wid, signed_flag)
2643 {
2644 }
2645
~NetECast()2646 NetECast::~NetECast()
2647 {
2648 }
2649
expr_type() const2650 ivl_variable_type_t NetECast::expr_type() const
2651 {
2652 ivl_variable_type_t ret = IVL_VT_NO_TYPE;
2653 switch (op_) {
2654 case 'v':
2655 ret = IVL_VT_LOGIC;
2656 break;
2657 case 'r':
2658 ret = IVL_VT_REAL;
2659 break;
2660 case '2':
2661 ret = IVL_VT_BOOL;
2662 break;
2663 default:
2664 assert(0);
2665 }
2666
2667 return ret;
2668 }
2669
NetLogic(NetScope * s,perm_string n,unsigned pins,TYPE t,unsigned wid,bool is_cassign__)2670 NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
2671 TYPE t, unsigned wid, bool is_cassign__)
2672 : NetNode(s, n, pins), type_(t), width_(wid), is_cassign_(is_cassign__)
2673 {
2674 pin(0).set_dir(Link::OUTPUT);
2675 for (unsigned idx = 1 ; idx < pins ; idx += 1) {
2676 pin(idx).set_dir(Link::INPUT);
2677 }
2678 }
2679
type() const2680 NetLogic::TYPE NetLogic::type() const
2681 {
2682 return type_;
2683 }
2684
width() const2685 unsigned NetLogic::width() const
2686 {
2687 return width_;
2688 }
2689
is_cassign() const2690 bool NetLogic::is_cassign() const
2691 {
2692 return is_cassign_;
2693 }
2694
NetUReduce(NetScope * scope__,perm_string n,NetUReduce::TYPE t,unsigned wid)2695 NetUReduce::NetUReduce(NetScope*scope__, perm_string n,
2696 NetUReduce::TYPE t, unsigned wid)
2697 : NetNode(scope__, n, 2), type_(t), width_(wid)
2698 {
2699 pin(0).set_dir(Link::OUTPUT);
2700 pin(1).set_dir(Link::INPUT);
2701 }
2702
type() const2703 NetUReduce::TYPE NetUReduce::type() const
2704 {
2705 return type_;
2706 }
2707
width() const2708 unsigned NetUReduce::width() const
2709 {
2710 return width_;
2711 }
2712
NetTaskDef(NetScope * n,const vector<NetNet * > & po,const vector<NetExpr * > & pd)2713 NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
2714 : NetBaseDef(n, po, pd)
2715 {
2716 }
2717
~NetTaskDef()2718 NetTaskDef::~NetTaskDef()
2719 {
2720 delete proc_;
2721 }
2722
2723 /*
2724 * These are the delay_type() functions. They are used to determine
2725 * the type of delay for the given object.
2726 */
2727
2728 /*
2729 * This function implements the following table:
2730 *
2731 * in_A in_B out
2732 * NO NO NO
2733 * NO ZERO ZERO
2734 * NO POS POS
2735 * NO DEF POS
2736 * ZERO NO ZERO
2737 * ZERO ZERO ZERO
2738 * ZERO POS POS
2739 * ZERO DEF POS
2740 * POS NO POS
2741 * POS ZERO POS
2742 * POS POS POS
2743 * POS DEF POS
2744 * DEF NO POS
2745 * DEF ZERO POS
2746 * DEF POS POS
2747 * DEF DEF DEF
2748 *
2749 * It is used to combine two delay values.
2750 */
combine_delays(const DelayType a,const DelayType b)2751 static DelayType combine_delays(const DelayType a, const DelayType b)
2752 {
2753 /* The default is POSSIBLE_DELAY. */
2754 DelayType result = POSSIBLE_DELAY;
2755
2756 /* If both are no or zero delay then we return ZERO_DELAY. */
2757 if ((a == NO_DELAY || a == ZERO_DELAY) &&
2758 (b == NO_DELAY || b == ZERO_DELAY)) {
2759 result = ZERO_DELAY;
2760 }
2761
2762 /* Except if both are no delay then we return NO_DELAY. */
2763 if (a == NO_DELAY && b == NO_DELAY) {
2764 result = NO_DELAY;
2765 }
2766
2767 /* If both are definite delay then we return DEFINITE_DELAY. */
2768 if (a == DEFINITE_DELAY && b == DEFINITE_DELAY) {
2769 result = DEFINITE_DELAY;
2770 }
2771
2772 return result;
2773 }
2774
2775 /*
2776 * This is used to see what we can find out about the delay when it
2777 * is given as an expression. We also use this for loop expressions.
2778 */
delay_type_from_expr(const NetExpr * expr)2779 static DelayType delay_type_from_expr(const NetExpr*expr)
2780 {
2781 DelayType result = POSSIBLE_DELAY;
2782
2783 if (const NetEConst*e = dynamic_cast<const NetEConst*>(expr)) {
2784 if (e->value().is_zero()) result = ZERO_DELAY;
2785 else result = DEFINITE_DELAY;
2786 }
2787
2788 if (const NetECReal*e = dynamic_cast<const NetECReal*>(expr)) {
2789 if (e->value().as_double() == 0.0) result = ZERO_DELAY;
2790 else result = DEFINITE_DELAY;
2791 }
2792
2793 return result;
2794 }
2795
2796 /*
2797 * The looping structures can use the same basic code so put it here
2798 * instead of duplicating it for each one (repeat and while).
2799 */
get_loop_delay_type(const NetExpr * expr,const NetProc * proc,bool print_delay)2800 static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay)
2801 {
2802 DelayType result;
2803
2804 switch (delay_type_from_expr(expr)) {
2805 /* We have a constant false expression so the body never runs. */
2806 case ZERO_DELAY:
2807 result = NO_DELAY;
2808 break;
2809 /* We have a constant true expression so the body always runs. */
2810 case DEFINITE_DELAY:
2811 if (proc) {
2812 result = proc->delay_type(print_delay);
2813 } else {
2814 result = NO_DELAY;
2815 }
2816 break;
2817 /* We don't know if the body will run so reduce a DEFINITE_DELAY
2818 * to a POSSIBLE_DELAY. All other stay the same. */
2819 case POSSIBLE_DELAY:
2820 if (proc) {
2821 result = combine_delays(NO_DELAY, proc->delay_type(print_delay));
2822 } else {
2823 result = NO_DELAY;
2824 }
2825 break;
2826 /* This should never happen since delay_type_from_expr() only
2827 * returns three different values. */
2828 default:
2829 result = NO_DELAY;
2830 assert(0);
2831 }
2832
2833 return result;
2834 }
2835
2836 /* The default object does not have any delay. */
delay_type(bool) const2837 DelayType NetProc::delay_type(bool /* print_delay */ ) const
2838 {
2839 return NO_DELAY;
2840 }
2841
delay_type(bool print_delay) const2842 DelayType NetBlock::delay_type(bool print_delay) const
2843 {
2844 // A join_none has no delay.
2845 if (type() == PARA_JOIN_NONE) return NO_DELAY;
2846
2847 DelayType result;
2848 // A join_any has the minimum delay.
2849 if (type() == PARA_JOIN_ANY) {
2850 result = DEFINITE_DELAY;
2851 for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
2852 DelayType dt = cur->delay_type(print_delay);
2853 if (dt < result) result = dt;
2854 if ((dt == NO_DELAY) && !print_delay) break;
2855 }
2856
2857 // A begin or join has the maximum delay.
2858 } else {
2859 result = NO_DELAY;
2860 for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
2861 DelayType dt = cur->delay_type(print_delay);
2862 if (dt > result) result = dt;
2863 if ((dt == DEFINITE_DELAY) && !print_delay) break;
2864 }
2865 }
2866
2867 return result;
2868 }
2869
delay_type(bool print_delay) const2870 DelayType NetCase::delay_type(bool print_delay) const
2871 {
2872 DelayType result = NO_DELAY;
2873 bool def_stmt = false;
2874 unsigned nstmts = nitems();
2875
2876 for (unsigned idx = 0; idx < nstmts; idx += 1) {
2877 if (!expr(idx)) def_stmt = true;
2878 DelayType dt = stat(idx) ? stat(idx)->delay_type(print_delay) : NO_DELAY;
2879 if (idx == 0) {
2880 result = dt;
2881 } else {
2882 result = combine_delays(result, dt);
2883 }
2884 }
2885
2886 // FIXME: If all the cases are covered (e.g. an enum) then this is not true.
2887 /* If we don't have a default statement we don't know for sure
2888 * that we have a delay. */
2889 if (!def_stmt) result = combine_delays(NO_DELAY, result);
2890
2891 return result;
2892 }
2893
delay_type(bool print_delay) const2894 DelayType NetCondit::delay_type(bool print_delay) const
2895 {
2896 DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY;
2897 DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY;
2898 return combine_delays(if_type, el_type);
2899 }
2900
2901 /*
2902 * A do/while will execute the body at least once.
2903 */
delay_type(bool print_delay) const2904 DelayType NetDoWhile::delay_type(bool print_delay) const
2905 {
2906 if (proc_) return proc_->delay_type(print_delay);
2907
2908 return ZERO_DELAY;
2909 }
2910
delay_type(bool print_delay) const2911 DelayType NetEvWait::delay_type(bool print_delay) const
2912 {
2913 if (print_delay) {
2914 cerr << get_fileline() << ": error: an event control is not allowed "
2915 "in an always_comb, always_ff or always_latch process."
2916 << endl;
2917 }
2918
2919 return DEFINITE_DELAY;
2920 }
2921
delay_type(bool print_delay) const2922 DelayType NetForever::delay_type(bool print_delay) const
2923 {
2924 if (statement_) return statement_->delay_type(print_delay);
2925
2926 return ZERO_DELAY;
2927 }
2928
delay_type(bool print_delay) const2929 DelayType NetForLoop::delay_type(bool print_delay) const
2930 {
2931 return get_loop_delay_type(condition_, statement_, print_delay);
2932 }
2933
delay_type(bool print_delay) const2934 DelayType NetPDelay::delay_type(bool print_delay) const
2935 {
2936 if (print_delay) {
2937 cerr << get_fileline() << ": error: a blocking delay is not allowed "
2938 "in an always_comb, always_ff or always_latch process."
2939 << endl;
2940 }
2941
2942 if (expr_) {
2943 if (statement_) {
2944 return combine_delays(delay_type_from_expr(expr_),
2945 statement_->delay_type(print_delay));
2946 } else {
2947 return delay_type_from_expr(expr_);
2948 }
2949 }
2950
2951 if (delay() > 0) return DEFINITE_DELAY;
2952
2953 if (statement_) {
2954 return combine_delays(ZERO_DELAY,
2955 statement_->delay_type(print_delay));
2956 } else {
2957 return ZERO_DELAY;
2958 }
2959 }
2960
delay_type(bool print_delay) const2961 DelayType NetRepeat::delay_type(bool print_delay) const
2962 {
2963 return get_loop_delay_type(expr_, statement_, print_delay);
2964 }
2965
delay_type(bool print_delay) const2966 DelayType NetTaskDef::delay_type(bool print_delay) const
2967 {
2968 if (proc_) {
2969 return proc_->delay_type(print_delay);
2970 } else {
2971 return NO_DELAY;
2972 }
2973 }
2974
delay_type(bool print_delay) const2975 DelayType NetUTask::delay_type(bool print_delay) const
2976 {
2977 return task()->task_def()->delay_type(print_delay);
2978 }
2979
do_expr_event_match(const NetExpr * expr,const NetEvWait * evwt)2980 static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt)
2981 {
2982 // The event wait should only have a single event.
2983 if (evwt->nevents() != 1) return false;
2984 // The event should have a single probe.
2985 const NetEvent *evt = evwt->event(0);
2986 if (evt->nprobe() != 1) return false;
2987 // The probe should be for any edge.
2988 const NetEvProbe *prb = evt->probe(0);
2989 if (prb->edge() != NetEvProbe::ANYEDGE) return false;
2990 // Create a NexusSet from the event probe signals.
2991 NexusSet *ns_evwt = new NexusSet;
2992 for (unsigned idx =0; idx < prb->pin_count(); idx += 1) {
2993 if (! prb->pin(idx).is_linked()) {
2994 delete ns_evwt;
2995 return false;
2996 }
2997 // Casting away const is safe since this nexus set is only being read.
2998 ns_evwt->add(const_cast<Nexus*> (prb->pin(idx).nexus()),
2999 0, prb->pin(idx).nexus()->vector_width());
3000 }
3001 // Get the NexusSet for the expression.
3002 NexusSet *ns_expr = expr->nex_input();
3003 // Make sure the event and expression NexusSets match exactly.
3004 if (ns_evwt->size() != ns_expr->size()) {
3005 delete ns_evwt;
3006 delete ns_expr;
3007 return false;
3008 }
3009 ns_expr->rem(*ns_evwt);
3010 delete ns_evwt;
3011 if (ns_expr->size() != 0) {
3012 delete ns_expr;
3013 return false;
3014 }
3015 delete ns_expr;
3016
3017 return true;
3018 }
3019
while_is_wait(const NetExpr * expr,const NetProc * stmt)3020 static bool while_is_wait(const NetExpr*expr, const NetProc*stmt)
3021 {
3022 if (const NetEvWait*evwt = dynamic_cast<const NetEvWait*>(stmt)) {
3023 if (evwt->statement()) return false;
3024 const NetEBComp*cond = dynamic_cast<const NetEBComp*>(expr);
3025 if (! cond) return false;
3026 if (cond->op() != 'N') return false;
3027 const NetEConst*cval = dynamic_cast<const NetEConst*>(cond->right());
3028 if (! cval) return false;
3029 const verinum val = cval->value();
3030 if (val.len() != 1) return false;
3031 if (val.get(0) != verinum::V1) return false;
3032 if (! do_expr_event_match(cond->left(), evwt)) return false;
3033 if (evwt->get_lineno() != cond->get_lineno()) return false;
3034 if (evwt->get_file() != cond->get_file()) return false;
3035 return true;
3036 }
3037 return false;
3038 }
3039
delay_type(bool print_delay) const3040 DelayType NetWhile::delay_type(bool print_delay) const
3041 {
3042 // If the wait was a constant value the compiler already removed it
3043 // so we know we can only have a possible delay.
3044 if (while_is_wait(cond_, proc_)) {
3045 if (print_delay) {
3046 cerr << get_fileline() << ": error: a wait statement is "
3047 "not allowed in an "
3048 "always_comb, always_ff or always_latch process."
3049 << endl;
3050 }
3051 return POSSIBLE_DELAY;
3052 }
3053 return get_loop_delay_type(cond_, proc_, print_delay);
3054 }
3055
3056 /*
3057 * These are the check_synth() functions. They are used to print
3058 * a warning if the item is not synthesizable.
3059 */
get_process_type_as_string(ivl_process_type_t pr_type)3060 static const char * get_process_type_as_string(ivl_process_type_t pr_type)
3061 {
3062 switch (pr_type) {
3063 case IVL_PR_ALWAYS_COMB:
3064 return "in an always_comb process.";
3065 break;
3066 case IVL_PR_ALWAYS_FF:
3067 return "in an always_ff process.";
3068 break;
3069 case IVL_PR_ALWAYS_LATCH:
3070 return "in an always_latch process.";
3071 break;
3072 default:
3073 assert(0);
3074 return 0;
3075 }
3076 }
3077
print_synth_warning(const NetProc * net_proc,const char * name,ivl_process_type_t pr_type)3078 static void print_synth_warning(const NetProc *net_proc, const char *name,
3079 ivl_process_type_t pr_type)
3080 {
3081 cerr << net_proc->get_fileline() << ": warning: " << name
3082 << " statement cannot be synthesized "
3083 << get_process_type_as_string(pr_type) << endl;
3084 }
3085
check_if_logic_l_value(const NetAssignBase * base,ivl_process_type_t pr_type)3086 static void check_if_logic_l_value(const NetAssignBase *base,
3087 ivl_process_type_t pr_type)
3088 {
3089 if (base->l_val_count() != 1) return;
3090
3091 const NetAssign_*lval = base->l_val(0);
3092 if (! lval) return;
3093
3094 NetNet*sig = lval->sig();
3095 if (! sig) return;
3096
3097 if ((sig->data_type() != IVL_VT_BOOL) &&
3098 (sig->data_type() != IVL_VT_LOGIC)) {
3099 cerr << base->get_fileline() << ": warning: Assinging to a "
3100 "non-integral variable ("<< sig->name()
3101 << ") cannot be synthesized "
3102 << get_process_type_as_string(pr_type) << endl;
3103 }
3104 }
3105
3106 /* By default elements can be synthesized or ignored. */
check_synth(ivl_process_type_t,const NetScope *) const3107 bool NetProc::check_synth(ivl_process_type_t /* pr_type */,
3108 const NetScope* /* scope */ ) const
3109 {
3110 return false;
3111 }
3112
3113 // FIXME: User function calls still need to be checked (NetEUFunc).
3114 // : Non-constant system functions need a warning (NetESFunc).
3115 // : Constant functions should already be elaborated.
3116
3117 /* By default assign elements can be synthesized. */
check_synth(ivl_process_type_t,const NetScope *) const3118 bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */,
3119 const NetScope* /* scope */ ) const
3120 {
3121 return false;
3122 }
3123
check_synth(ivl_process_type_t pr_type,const NetScope *) const3124 bool NetAssign::check_synth(ivl_process_type_t pr_type,
3125 const NetScope* /* scope */ ) const
3126 {
3127 check_if_logic_l_value(this, pr_type);
3128
3129 // FIXME: Check that ff/latch only use this for internal signals.
3130 return false;
3131 }
3132
check_synth(ivl_process_type_t pr_type,const NetScope *) const3133 bool NetAssignNB::check_synth(ivl_process_type_t pr_type,
3134 const NetScope* /* scope */ ) const
3135 {
3136 bool result = false;
3137 if (pr_type == IVL_PR_ALWAYS_COMB) {
3138 cerr << get_fileline() << ": warning: A non-blocking assignment "
3139 "should not be used in an always_comb process." << endl;
3140 }
3141
3142 if (event_) {
3143 cerr << get_fileline() << ": error: A non-blocking assignment "
3144 "cannot be synthesized with an event control "
3145 << get_process_type_as_string(pr_type) << endl;
3146 result = true;
3147 }
3148
3149 check_if_logic_l_value(this, pr_type);
3150
3151 return result;
3152 }
3153
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3154 bool NetBlock::check_synth(ivl_process_type_t pr_type,
3155 const NetScope* scope) const
3156 {
3157 bool result = false;
3158 // Only a begin/end can be synthesized.
3159 if (type() != SEQU) {
3160 cerr << get_fileline() << ": error: A fork/";
3161 switch (type()) {
3162 case PARA:
3163 cerr << "join";
3164 break;
3165 case PARA_JOIN_ANY:
3166 cerr << "join_any";
3167 break;
3168 case PARA_JOIN_NONE:
3169 cerr << "join_none";
3170 break;
3171 default:
3172 assert(0);
3173 }
3174 cerr << " statement cannot be synthesized "
3175 << get_process_type_as_string(pr_type) << endl;
3176 result = true;
3177 }
3178
3179 const NetScope*save_scope = scope;
3180 if (subscope()) scope = subscope();
3181 if (scope != save_scope) {
3182 result |= scope->check_synth(pr_type, scope);
3183 }
3184 for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
3185 result |= cur->check_synth(pr_type, scope);
3186 }
3187 scope = save_scope;
3188 return result;
3189 }
3190
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3191 bool NetCase::check_synth(ivl_process_type_t pr_type,
3192 const NetScope* scope) const
3193 {
3194 bool result = false;
3195 for (unsigned idx = 0; idx < nitems(); idx += 1) {
3196 if (stat(idx)) result |= stat(idx)->check_synth(pr_type, scope);
3197 }
3198 // FIXME: Check for ff/latch/comb structures.
3199 return result;
3200 }
3201
check_synth(ivl_process_type_t pr_type,const NetScope *) const3202 bool NetCAssign::check_synth(ivl_process_type_t pr_type,
3203 const NetScope* /* scope */ ) const
3204 {
3205 print_synth_warning(this, "A procedural assign", pr_type);
3206 return false;
3207 }
3208
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3209 bool NetCondit::check_synth(ivl_process_type_t pr_type,
3210 const NetScope* scope) const
3211 {
3212 bool result = false;
3213 if (if_) result |= if_->check_synth(pr_type, scope);
3214 if (else_) result |= else_->check_synth(pr_type, scope);
3215 // FIXME: Check for ff/latch/comb structures.
3216 return result;
3217 }
3218
check_synth(ivl_process_type_t pr_type,const NetScope *) const3219 bool NetDeassign::check_synth(ivl_process_type_t pr_type,
3220 const NetScope* /* scope */ ) const
3221 {
3222 print_synth_warning(this, "A procedural deassign", pr_type);
3223 return false;
3224 }
3225
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3226 bool NetDisable::check_synth(ivl_process_type_t pr_type,
3227 const NetScope* scope) const
3228 {
3229 while (scope) {
3230 if (scope != target_) scope = scope->parent();
3231 else break;
3232 }
3233
3234
3235 if (! scope) {
3236 cerr << get_fileline() << ": warning: A disable statement can "
3237 "only be synthesized when disabling an enclosing block "
3238 << get_process_type_as_string(pr_type) << endl;
3239 }
3240 return false;
3241 }
3242
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3243 bool NetDoWhile::check_synth(ivl_process_type_t pr_type,
3244 const NetScope* scope) const
3245 {
3246 bool result = false;
3247 print_synth_warning(this, "A do/while", pr_type);
3248 if (proc_) result |= proc_->check_synth(pr_type, scope);
3249 return result;
3250 }
3251
check_synth(ivl_process_type_t pr_type,const NetScope *) const3252 bool NetEvTrig::check_synth(ivl_process_type_t pr_type,
3253 const NetScope* /* scope */ ) const
3254 {
3255 print_synth_warning(this, "An event trigger", pr_type);
3256 return false;
3257 }
3258
3259 // The delay check above has already marked this as an error.
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3260 bool NetEvWait::check_synth(ivl_process_type_t pr_type,
3261 const NetScope* scope) const
3262 {
3263 bool result = false;
3264 if (statement_) result |= statement_->check_synth(pr_type, scope);
3265 return result;
3266 }
3267
check_synth(ivl_process_type_t pr_type,const NetScope *) const3268 bool NetForce::check_synth(ivl_process_type_t pr_type,
3269 const NetScope* /* scope */ ) const
3270 {
3271 print_synth_warning(this, "A force", pr_type);
3272 return false;
3273 }
3274
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3275 bool NetForever::check_synth(ivl_process_type_t pr_type,
3276 const NetScope* scope) const
3277 {
3278 bool result = false;
3279 print_synth_warning(this, "A forever", pr_type);
3280 if (statement_) result |= statement_->check_synth(pr_type, scope);
3281 return result;
3282 }
3283
3284 /*
3285 * A bunch of private routines to verify that a for loop has the correct
3286 * structure for synthesis.
3287 */
print_for_idx_warning(const NetProc * proc,const char * check,ivl_process_type_t pr_type,NetNet * idx)3288 static void print_for_idx_warning(const NetProc*proc, const char*check,
3289 ivl_process_type_t pr_type, NetNet*idx)
3290 {
3291 cerr << proc->get_fileline() << ": warning: A for statement must use "
3292 "the index (" << idx->name() << ") in the " << check
3293 << " expression to be synthesized "
3294 << get_process_type_as_string(pr_type) << endl;
3295 }
3296
check_for_const_synth(const NetExpr * expr,const NetProc * proc,const char * str,ivl_process_type_t pr_type)3297 static void check_for_const_synth(const NetExpr*expr, const NetProc*proc,
3298 const char*str, ivl_process_type_t pr_type)
3299 {
3300 if (! dynamic_cast<const NetEConst*>(expr)) {
3301 cerr << proc-> get_fileline() << ": warning: A for "
3302 "statement must " << str
3303 << " value to be synthesized "
3304 << get_process_type_as_string(pr_type) << endl;
3305 }
3306 }
3307
check_for_bin_synth(const NetExpr * left,const NetExpr * right,const char * str,const char * check,const NetProc * proc,ivl_process_type_t pr_type,NetNet * index)3308 static void check_for_bin_synth(const NetExpr*left,const NetExpr*right,
3309 const char*str, const char*check,
3310 const NetProc*proc,
3311 ivl_process_type_t pr_type, NetNet*index)
3312 {
3313 const NetESignal*lsig = dynamic_cast<const NetESignal*>(left);
3314 const NetESignal*rsig = dynamic_cast<const NetESignal*>(right);
3315
3316 if (lsig && (lsig->sig() == index)) {
3317 check_for_const_synth(right, proc, str, pr_type);
3318 } else if (rsig && (rsig->sig() == index)) {
3319 check_for_const_synth(left, proc, str, pr_type);
3320 } else {
3321 print_for_idx_warning(proc, check, pr_type, index);
3322 }
3323 }
3324
print_for_step_warning(const NetProc * proc,ivl_process_type_t pr_type)3325 static void print_for_step_warning(const NetProc*proc,
3326 ivl_process_type_t pr_type)
3327 {
3328 cerr << proc->get_fileline() << ": warning: A for statement step must "
3329 "be a simple assignment statement to be synthesized "
3330 << get_process_type_as_string(pr_type) << endl;
3331 }
3332
print_for_step_warning(const NetProc * proc,ivl_process_type_t pr_type,NetNet * idx)3333 static void print_for_step_warning(const NetProc*proc,
3334 ivl_process_type_t pr_type, NetNet*idx)
3335 {
3336 cerr << proc->get_fileline() << ": warning: A for statement step must "
3337 "be an assignment to the index variable ("
3338 << idx->name() << ") to be synthesized "
3339 << get_process_type_as_string(pr_type) << endl;
3340 }
3341
check_for_bstep_synth(const NetExpr * expr,const NetProc * proc,ivl_process_type_t pr_type,NetNet * index)3342 static void check_for_bstep_synth(const NetExpr*expr, const NetProc*proc,
3343 ivl_process_type_t pr_type, NetNet*index)
3344 {
3345 if (const NetECast*tmp = dynamic_cast<const NetECast*>(expr)) {
3346 expr = tmp->expr();
3347 }
3348
3349 if (const NetEBAdd*tmp = dynamic_cast<const NetEBAdd*>(expr)) {
3350 check_for_bin_synth(tmp->left(), tmp->right(),
3351 "change by a constant", "step", proc, pr_type,
3352 index);
3353 } else {
3354 cerr << proc->get_fileline() << ": warning: A for statement "
3355 "step must be a simple binary +/- "
3356 "to be synthesized "
3357 << get_process_type_as_string(pr_type) << endl;
3358 }
3359 }
3360
check_for_step_synth(const NetAssign * assign,const NetProc * proc,ivl_process_type_t pr_type,NetNet * index)3361 static void check_for_step_synth(const NetAssign*assign, const NetProc*proc,
3362 ivl_process_type_t pr_type, NetNet*index)
3363 {
3364 if (assign->l_val_count() != 1) {
3365 print_for_step_warning(proc, pr_type);
3366 } else if (assign->l_val(0)->sig() != index) {
3367 print_for_step_warning(proc, pr_type, index);
3368 } else {
3369 switch (assign->assign_operator()) {
3370 case '+':
3371 case '-':
3372 check_for_const_synth(assign->rval(), proc,
3373 "have a constant step", pr_type);
3374 break;
3375 case 0:
3376 check_for_bstep_synth(assign->rval(), proc, pr_type, index);
3377 break;
3378 default:
3379 cerr << proc->get_fileline() << ": warning: A for statement "
3380 "step does not support operator '"
3381 << assign->assign_operator()
3382 << "' it must be +/- to be synthesized "
3383 << get_process_type_as_string(pr_type) << endl;
3384 break;
3385 }
3386 }
3387 }
3388
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3389 bool NetForLoop::check_synth(ivl_process_type_t pr_type,
3390 const NetScope* scope) const
3391 {
3392 bool result = false;
3393
3394 // FIXME: What about an enum (NetEConstEnum)?
3395 if (! dynamic_cast<const NetEConst*>(init_expr_)) {
3396 cerr << get_fileline() << ": warning: A for statement must "
3397 "have a constant initial value to be synthesized "
3398 << get_process_type_as_string(pr_type) << endl;
3399 }
3400
3401 // FIXME: Do the following also need to be supported in the condition?
3402 // It would seem like they are hard to use to find the bounds.
3403 // From NetEBinary
3404 // What about NetEBits sig & constant, etc.
3405 // From NetEUnary
3406 // What about NetEUBits ! sig or ! (sig == constat)
3407 // What about NetEUReduce &signal
3408 if (const NetESignal*tmp = dynamic_cast<const NetESignal*>(condition_)) {
3409 if (tmp->sig() != index_) {
3410 print_for_idx_warning(this, "condition", pr_type, index_);
3411 }
3412 } else if (const NetEBComp*cmp = dynamic_cast<const NetEBComp*>(condition_)) {
3413 check_for_bin_synth(cmp->left(), cmp->right(),
3414 "compare against a constant", "condition",
3415 this, pr_type, index_);
3416 } else {
3417 print_for_idx_warning(this, "condition", pr_type, index_);
3418 }
3419
3420 if (const NetAssign*tmp = dynamic_cast<const NetAssign*>(step_statement_)) {
3421 check_for_step_synth(tmp, this, pr_type, index_);
3422 } else {
3423 print_for_step_warning(this, pr_type);
3424 }
3425
3426 if (statement_) result |= statement_->check_synth(pr_type, scope);
3427 return result;
3428 }
3429
3430 // The delay check above has already marked this as an error.
check_synth(ivl_process_type_t,const NetScope *) const3431 bool NetPDelay::check_synth(ivl_process_type_t /* pr_type */,
3432 const NetScope* /* scope */ ) const
3433 {
3434 return false;
3435 }
3436
check_synth(ivl_process_type_t pr_type,const NetScope *) const3437 bool NetRelease::check_synth(ivl_process_type_t pr_type,
3438 const NetScope* /* scope */ ) const
3439 {
3440 print_synth_warning(this, "A release", pr_type);
3441 return false;
3442 }
3443
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3444 bool NetRepeat::check_synth(ivl_process_type_t pr_type,
3445 const NetScope* scope) const
3446 {
3447 bool result = false;
3448 print_synth_warning(this, "A repeat", pr_type);
3449 if (statement_) result |= statement_->check_synth(pr_type, scope);
3450 return result;
3451 }
3452
check_synth(ivl_process_type_t pr_type,const NetScope *) const3453 bool NetScope::check_synth(ivl_process_type_t pr_type,
3454 const NetScope* /* scope */) const
3455 {
3456 bool result = false;
3457 // Skip local events/signals
3458 for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
3459 if (cur->local_flag()) continue;
3460 cerr << cur->get_fileline() << ": warning: An event ("
3461 << cur->name() << ") cannot be synthesized "
3462 << get_process_type_as_string(pr_type) << endl;
3463 }
3464 for (signals_map_iter_t cur = signals_map_.begin();
3465 cur != signals_map_.end() ; ++ cur) {
3466 const NetNet*sig = cur->second;
3467 if ((sig->data_type() != IVL_VT_BOOL) &&
3468 (sig->data_type() != IVL_VT_LOGIC)) {
3469 cerr << sig->get_fileline() << ": warning: A non-integral "
3470 "variable (" << sig->name() << ") cannot be "
3471 "synthesized "
3472 << get_process_type_as_string(pr_type) << endl;
3473 }
3474 }
3475 return result;
3476 }
3477
check_synth(ivl_process_type_t pr_type,const NetScope *) const3478 bool NetSTask::check_synth(ivl_process_type_t pr_type,
3479 const NetScope* /* scope */) const
3480 {
3481 if (strcmp(name(), "$ivl_darray_method$delete") == 0) {
3482 cerr << get_fileline() << ": warning: Dynamic array "
3483 "delete method cannot be synthesized "
3484 << get_process_type_as_string(pr_type) << endl;
3485 } else {
3486 cerr << get_fileline() << ": warning: System task ("
3487 << name() << ") cannot be synthesized "
3488 << get_process_type_as_string(pr_type) << endl;
3489 }
3490 return false;
3491 }
3492
check_synth(ivl_process_type_t pr_type,const NetScope *) const3493 bool NetTaskDef::check_synth(ivl_process_type_t pr_type,
3494 const NetScope* /* scope */) const
3495 {
3496 bool result = false;
3497 const NetScope *tscope = this->scope();
3498 result |= tscope->check_synth(pr_type, tscope);
3499 if (! tscope->is_auto()) {
3500 cerr << tscope->get_def_file() << ":"
3501 << tscope->get_def_lineno()
3502 << ": warning: user task (" << tscope->basename()
3503 << ") must be automatic to be synthesized "
3504 << get_process_type_as_string(pr_type) << endl;
3505 }
3506 if (proc_) result |= proc_->check_synth(pr_type, tscope);
3507 return result;
3508 }
3509
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3510 bool NetUTask::check_synth(ivl_process_type_t pr_type,
3511 const NetScope* scope) const
3512 {
3513 return task()->task_def()->check_synth(pr_type, scope);
3514 }
3515
check_synth(ivl_process_type_t pr_type,const NetScope * scope) const3516 bool NetWhile::check_synth(ivl_process_type_t pr_type,
3517 const NetScope* scope) const
3518 {
3519 bool result = false;
3520 // A wait is already maked as an error in the delay check above.
3521 if (! while_is_wait(cond_, proc_)) {
3522 print_synth_warning(this, "A while", pr_type);
3523 if (proc_) result |= proc_->check_synth(pr_type, scope);
3524 }
3525 return result;
3526 }
3527