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