Merge similar probes within a module.
[iverilog.git] / netlist.cc
blob8b1edfe90af6b1ea870ba021ddd9a5a00c07b77c
1 /*
2 * Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #if !defined(WINNT) && !defined(macintosh)
20 #ident "$Id: netlist.cc,v 1.127 2000/05/27 19:33:23 steve Exp $"
21 #endif
23 # include <cassert>
24 # include <typeinfo>
25 # include "netlist.h"
26 # include "netmisc.h"
28 ostream& operator<< (ostream&o, NetNet::Type t)
30 switch (t) {
31 case NetNet::IMPLICIT:
32 o << "wire /*implicit*/";
33 break;
34 case NetNet::IMPLICIT_REG:
35 o << "reg /*implicit*/";
36 break;
37 case NetNet::INTEGER:
38 o << "integer";
39 break;
40 case NetNet::REG:
41 o << "reg";
42 break;
43 case NetNet::SUPPLY0:
44 o << "supply0";
45 break;
46 case NetNet::SUPPLY1:
47 o << "supply1";
48 break;
49 case NetNet::TRI:
50 o << "tri";
51 break;
52 case NetNet::TRI0:
53 o << "tri0";
54 break;
55 case NetNet::TRI1:
56 o << "tri1";
57 break;
58 case NetNet::TRIAND:
59 o << "triand";
60 break;
61 case NetNet::TRIOR:
62 o << "trior";
63 break;
64 case NetNet::WAND:
65 o << "wand";
66 break;
67 case NetNet::WOR:
68 o << "wor";
69 break;
70 case NetNet::WIRE:
71 o << "wire";
72 break;
74 return o;
78 void connect(Link&l, Link&r)
80 assert(&l != &r);
81 assert(l.next_->prev_ == &l);
82 assert(l.prev_->next_ == &l);
83 assert(r.next_->prev_ == &r);
84 assert(r.prev_->next_ == &r);
86 Link* cur = &l;
87 do {
88 Link*tmp = cur->next_;
90 // If I stumble on r in the nexus, then stop now because
91 // we are already connected.
92 if (tmp == &r) break;
94 // Pull cur out of left list...
95 cur->prev_->next_ = cur->next_;
96 cur->next_->prev_ = cur->prev_;
98 // Put cur in right list
99 cur->next_ = r.next_;
100 cur->prev_ = &r;
101 cur->next_->prev_ = cur;
102 cur->prev_->next_ = cur;
104 // Go to the next item in the left list.
105 cur = tmp;
106 } while (cur != &l);
108 assert(l.next_->prev_ == &l);
109 assert(l.prev_->next_ == &l);
110 assert(r.next_->prev_ == &r);
111 assert(r.prev_->next_ == &r);
114 Link::Link()
115 : dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG),
116 inst_(0), next_(this), prev_(this)
120 Link::~Link()
122 unlink();
125 void Link::set_dir(DIR d)
127 dir_ = d;
130 Link::DIR Link::get_dir() const
132 return dir_;
135 void Link::drive0(Link::strength_t str)
137 drive0_ = str;
140 void Link::drive1(Link::strength_t str)
142 drive1_ = str;
145 Link::strength_t Link::drive0() const
147 return drive0_;
150 Link::strength_t Link::drive1() const
152 return drive1_;
155 void Link::cur_link(NetObj*&net, unsigned &pin)
157 net = node_;
158 pin = pin_;
161 void Link::unlink()
163 next_->prev_ = prev_;
164 prev_->next_ = next_;
165 next_ = prev_ = this;
168 bool Link::is_equal(const Link&that) const
170 return (node_ == that.node_) && (pin_ == that.pin_);
173 bool Link::is_linked() const
175 return next_ != this;
178 bool Link::is_linked(const NetObj&that) const
180 for (const Link*idx = next_ ; this != idx ; idx = idx->next_)
181 if (idx->node_ == &that)
182 return true;
184 return false;
187 bool Link::is_linked(const Link&that) const
189 for (const Link*idx = next_ ; this != idx ; idx = idx->next_)
190 if (idx->is_equal(that))
191 return true;
193 return false;
196 void Link::next_link(NetObj*&net, unsigned&pin)
198 assert(next_->prev_ == this);
199 assert(prev_->next_ == this);
200 net = next_->node_;
201 pin = next_->pin_;
204 void Link::next_link(const NetObj*&net, unsigned&pin) const
206 assert(next_->prev_ == this);
207 assert(prev_->next_ == this);
208 net = next_->node_;
209 pin = next_->pin_;
212 Link* Link::next_link()
214 assert(next_->prev_ == this);
215 assert(prev_->next_ == this);
216 return next_;
219 const Link* Link::next_link() const
221 assert(next_->prev_ == this);
222 assert(prev_->next_ == this);
223 return next_;
226 const NetObj*Link::get_obj() const
228 return node_;
231 NetObj*Link::get_obj()
233 return node_;
236 unsigned Link::get_pin() const
238 return pin_;
241 void Link::set_name(const string&n, unsigned i)
243 name_ = n;
244 inst_ = i;
247 const string& Link::get_name() const
249 return name_;
252 unsigned Link::get_inst() const
254 return inst_;
257 bool connected(const NetObj&l, const NetObj&r)
259 for (unsigned idx = 0 ; idx < l.pin_count() ; idx += 1)
260 if (! l.pin(idx).is_linked(r))
261 return false;
263 return true;
266 unsigned count_inputs(const Link&pin)
268 unsigned count = (pin.get_dir() == Link::INPUT)? 1 : 0;
269 const NetObj*cur;
270 unsigned cpin;
271 pin.next_link(cur, cpin);
272 while (cur->pin(cpin) != pin) {
273 if (cur->pin(cpin).get_dir() == Link::INPUT)
274 count += 1;
275 cur->pin(cpin).next_link(cur, cpin);
278 return count;
281 unsigned count_outputs(const Link&pin)
283 unsigned count = (pin.get_dir() == Link::OUTPUT)? 1 : 0;
284 const NetObj*cur;
285 unsigned cpin;
286 pin.next_link(cur, cpin);
287 while (cur->pin(cpin) != pin) {
288 if (cur->pin(cpin).get_dir() == Link::OUTPUT)
289 count += 1;
290 cur->pin(cpin).next_link(cur, cpin);
293 return count;
296 unsigned count_signals(const Link&pin)
298 unsigned count = 0;
299 if (dynamic_cast<const NetNet*>(pin.get_obj()))
300 count += 1;
302 const NetObj*cur;
303 unsigned cpin;
304 pin.next_link(cur, cpin);
305 while (cur->pin(cpin) != pin) {
306 if (dynamic_cast<const NetNet*>(cur))
307 count += 1;
309 cur->pin(cpin).next_link(cur, cpin);
312 return count;
315 const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
317 const NetObj*cur;
318 unsigned cpin;
319 net->pin(pin).next_link(cur, cpin);
321 while (cur != net) {
322 const NetNet*sig = dynamic_cast<const NetNet*>(cur);
323 if (sig) {
324 bidx = cpin;
325 return sig;
327 cur->pin(cpin).next_link(cur, cpin);
330 return 0;
333 Link* find_next_output(Link*lnk)
335 for (Link*cur = lnk->next_link()
336 ; cur != lnk ; cur = cur->next_link())
337 if (cur->get_dir() == Link::OUTPUT)
338 return cur;
340 return 0;
343 NetObj::NetObj(const string&n, unsigned np)
344 : name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0), mark_(false)
346 pins_ = new Link[npins_];
347 for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
348 pins_[idx].node_ = this;
349 pins_[idx].pin_ = idx;
353 NetObj::~NetObj()
355 delete[]pins_;
358 void NetObj::set_attributes(const map<string,string>&attr)
360 assert(attributes_.size() == 0);
361 attributes_ = attr;
364 string NetObj::attribute(const string&key) const
366 map<string,string>::const_iterator idx = attributes_.find(key);
367 if (idx == attributes_.end())
368 return "";
370 return (*idx).second;
373 void NetObj::attribute(const string&key, const string&value)
375 attributes_[key] = value;
378 bool NetObj::has_compat_attributes(const NetObj&that) const
380 map<string,string>::const_iterator idx;
381 for (idx = that.attributes_.begin()
382 ; idx != that.attributes_.end() ; idx ++) {
383 map<string,string>::const_iterator cur;
384 cur = attributes_.find((*idx).first);
386 if (cur == attributes_.end())
387 return false;
388 if ((*cur).second != (*idx).second)
389 return false;
392 return true;
395 Link& NetObj::pin(unsigned idx)
397 assert(idx < npins_);
398 return pins_[idx];
401 const Link& NetObj::pin(unsigned idx) const
403 assert(idx < npins_);
404 return pins_[idx];
407 NetNode::NetNode(const string&n, unsigned npins)
408 : NetObj(n, npins), node_next_(0), node_prev_(0), design_(0)
412 NetNode::~NetNode()
414 if (design_)
415 design_->del_node(this);
418 NetNode* NetNode::next_node()
420 for (Link*pin0 = pin(0).next_link()
421 ; *pin0 != pin(0) ; pin0 = pin0->next_link()) {
422 NetNode*cur = dynamic_cast<NetNode*>(pin0->get_obj());
423 if (cur == 0)
424 continue;
425 if (cur->pin_count() != pin_count())
426 continue;
429 bool flag = true;
430 for (unsigned idx = 0 ; idx < pin_count() ; idx += 1)
431 flag = flag && pin(idx).is_linked(cur->pin(idx));
433 if (flag == true)
434 return cur;
437 return 0;
440 NetNet::NetNet(NetScope*s, const string&n, Type t, unsigned npins)
441 : NetObj(n, npins), sig_next_(0), sig_prev_(0), scope_(s),
442 type_(t), port_type_(NOT_A_PORT), msb_(npins-1), lsb_(0),
443 local_flag_(false), eref_count_(0)
445 assert(scope_);
447 ivalue_ = new verinum::V[npins];
448 for (unsigned idx = 0 ; idx < npins ; idx += 1) {
449 pin(idx).set_name("P", idx);
450 ivalue_[idx] = verinum::Vz;
453 scope_->add_signal(this);
456 NetNet::NetNet(NetScope*s, const string&n, Type t, long ms, long ls)
457 : NetObj(n, ((ms>ls)?ms-ls:ls-ms) + 1), sig_next_(0),
458 sig_prev_(0), scope_(s), type_(t),
459 port_type_(NOT_A_PORT), msb_(ms), lsb_(ls), local_flag_(false),
460 eref_count_(0)
462 assert(scope_);
464 ivalue_ = new verinum::V[pin_count()];
465 for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
466 pin(idx).set_name("P", idx);
467 ivalue_[idx] = verinum::Vz;
470 scope_->add_signal(this);
473 NetNet::~NetNet()
475 assert(eref_count_ == 0);
476 if (scope_)
477 scope_->rem_signal(this);
480 NetScope* NetNet::scope()
482 return scope_;
485 const NetScope* NetNet::scope() const
487 return scope_;
490 unsigned NetNet::sb_to_idx(long sb) const
492 if (msb_ >= lsb_)
493 return sb - lsb_;
494 else
495 return lsb_ - sb;
498 void NetNet::incr_eref()
500 eref_count_ += 1;
503 void NetNet::decr_eref()
505 assert(eref_count_ > 0);
506 eref_count_ -= 1;
509 unsigned NetNet::get_eref() const
511 return eref_count_;
514 NetTmp::NetTmp(NetScope*s, const string&name, unsigned npins)
515 : NetNet(s, name, IMPLICIT, npins)
517 local_flag(true);
520 NetProc::NetProc()
521 : next_(0)
525 NetProc::~NetProc()
529 NetProcTop::NetProcTop(Type t, NetProc*st)
530 : type_(t), statement_(st)
534 NetProcTop::~NetProcTop()
536 delete statement_;
539 NetProc* NetProcTop::statement()
541 return statement_;
544 const NetProc* NetProcTop::statement() const
546 return statement_;
550 * The NetFF class represents an LPM_FF device. The pinout is assigned
551 * like so:
552 * 0 -- Clock
553 * 1 -- Enable
554 * 2 -- Aload
555 * 3 -- Aset
556 * 4 -- Aclr
557 * 5 -- Sload
558 * 6 -- Sset
559 * 7 -- Sclr
561 * 8 -- Data[0]
562 * 9 -- Q[0]
563 * ...
566 NetFF::NetFF(const string&n, unsigned wid)
567 : NetNode(n, 8 + 2*wid)
569 pin_Clock().set_dir(Link::INPUT);
570 pin_Clock().set_name("Clock", 0);
571 pin_Enable().set_dir(Link::INPUT);
572 pin_Enable().set_name("Enable", 0);
573 pin_Aload().set_dir(Link::INPUT);
574 pin_Aload().set_name("Aload", 0);
575 pin_Aset().set_dir(Link::INPUT);
576 pin_Aset().set_name("Aset", 0);
577 pin_Aclr().set_dir(Link::INPUT);
578 pin_Aclr().set_name("Aclr", 0);
579 pin_Sload().set_dir(Link::INPUT);
580 pin_Sload().set_name("Sload", 0);
581 pin_Sset().set_dir(Link::INPUT);
582 pin_Sset().set_name("Sset", 0);
583 pin_Sclr().set_dir(Link::INPUT);
584 pin_Sclr().set_name("Sclr", 0);
585 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
586 pin_Data(idx).set_dir(Link::INPUT);
587 pin_Data(idx).set_name("Data", idx);
588 pin_Q(idx).set_dir(Link::OUTPUT);
589 pin_Q(idx).set_name("Q", idx);
593 NetFF::~NetFF()
597 unsigned NetFF::width() const
599 return (pin_count() - 8) / 2;
602 Link& NetFF::pin_Clock()
604 return pin(0);
607 const Link& NetFF::pin_Clock() const
609 return pin(0);
612 Link& NetFF::pin_Enable()
614 return pin(1);
617 const Link& NetFF::pin_Enable() const
619 return pin(1);
622 Link& NetFF::pin_Aload()
624 return pin(2);
627 Link& NetFF::pin_Aset()
629 return pin(3);
632 Link& NetFF::pin_Aclr()
634 return pin(4);
637 Link& NetFF::pin_Sload()
639 return pin(5);
642 Link& NetFF::pin_Sset()
644 return pin(6);
647 Link& NetFF::pin_Sclr()
649 return pin(7);
652 Link& NetFF::pin_Data(unsigned w)
654 unsigned pn = 8 + 2*w;
655 assert(pn < pin_count());
656 return pin(pn);
659 const Link& NetFF::pin_Data(unsigned w) const
661 unsigned pn = 8 + 2*w;
662 assert(pn < pin_count());
663 return pin(pn);
666 Link& NetFF::pin_Q(unsigned w)
668 unsigned pn = 9 + w*2;
669 assert(pn < pin_count());
670 return pin(pn);
673 const Link& NetFF::pin_Q(unsigned w) const
675 unsigned pn = 9 + w*2;
676 assert(pn < pin_count());
677 return pin(pn);
682 * The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
683 * assigned like so:
684 * 0 -- Add_Sub
685 * 1 -- Aclr
686 * 2 -- Clock
687 * 3 -- Cin
688 * 4 -- Cout
689 * 5 -- Overflow
690 * 6 -- DataA[0]
691 * 7 -- DataB[0]
692 * 8 -- Result[0]
694 NetAddSub::NetAddSub(const string&n, unsigned w)
695 : NetNode(n, w*3+6)
697 pin(0).set_dir(Link::INPUT); pin(0).set_name("Add_Sub", 0);
698 pin(1).set_dir(Link::INPUT); pin(1).set_name("Aclr", 0);
699 pin(2).set_dir(Link::INPUT); pin(2).set_name("Clock", 0);
700 pin(3).set_dir(Link::INPUT); pin(3).set_name("Cin", 0);
701 pin(4).set_dir(Link::OUTPUT); pin(4).set_name("Cout", 0);
702 pin(5).set_dir(Link::OUTPUT); pin(5).set_name("Overflow", 0);
703 for (unsigned idx = 0 ; idx < w ; idx += 1) {
704 pin_DataA(idx).set_dir(Link::INPUT);
705 pin_DataB(idx).set_dir(Link::INPUT);
706 pin_Result(idx).set_dir(Link::OUTPUT);
707 pin_DataA(idx).set_name("DataA", idx);
708 pin_DataB(idx).set_name("DataB", idx);
709 pin_Result(idx).set_name("Result", idx);
713 NetAddSub::~NetAddSub()
717 unsigned NetAddSub::width()const
719 return (pin_count() - 6) / 3;
722 Link& NetAddSub::pin_Cout()
724 return pin(4);
727 const Link& NetAddSub::pin_Cout() const
729 return pin(4);
732 Link& NetAddSub::pin_DataA(unsigned idx)
734 idx = 6 + idx*3;
735 assert(idx < pin_count());
736 return pin(idx);
739 const Link& NetAddSub::pin_DataA(unsigned idx) const
741 idx = 6 + idx*3;
742 assert(idx < pin_count());
743 return pin(idx);
746 Link& NetAddSub::pin_DataB(unsigned idx)
748 idx = 7 + idx*3;
749 assert(idx < pin_count());
750 return pin(idx);
753 const Link& NetAddSub::pin_DataB(unsigned idx) const
755 idx = 7 + idx*3;
756 assert(idx < pin_count());
757 return pin(idx);
760 Link& NetAddSub::pin_Result(unsigned idx)
762 idx = 8 + idx*3;
763 assert(idx < pin_count());
764 return pin(idx);
767 const Link& NetAddSub::pin_Result(unsigned idx) const
769 idx = 8 + idx*3;
770 assert(idx < pin_count());
771 return pin(idx);
775 * The pinout for the NetCLShift is:
776 * 0 -- Direction
777 * 1 -- Underflow
778 * 2 -- Overflow
779 * 3 -- Data(0)
780 * 3+W -- Result(0)
781 * 3+2W -- Distance(0)
783 NetCLShift::NetCLShift(const string&n, unsigned width, unsigned width_dist)
784 : NetNode(n, 3+2*width+width_dist), width_(width), width_dist_(width_dist)
786 pin(0).set_dir(Link::INPUT); pin(0).set_name("Direction", 0);
787 pin(1).set_dir(Link::OUTPUT); pin(1).set_name("Underflow", 0);
788 pin(2).set_dir(Link::OUTPUT); pin(2).set_name("Overflow", 0);
790 for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
791 pin(3+idx).set_dir(Link::INPUT);
792 pin(3+idx).set_name("Data", idx);
794 pin(3+width_+idx).set_dir(Link::OUTPUT);
795 pin(3+width_+idx).set_name("Result", idx);
798 for (unsigned idx = 0 ; idx < width_dist_ ; idx += 1) {
799 pin(3+2*width_+idx).set_dir(Link::INPUT);
800 pin(3+2*width_+idx).set_name("Distance", idx);
804 NetCLShift::~NetCLShift()
808 unsigned NetCLShift::width() const
810 return width_;
813 unsigned NetCLShift::width_dist() const
815 return width_dist_;
818 Link& NetCLShift::pin_Direction()
820 return pin(0);
823 const Link& NetCLShift::pin_Direction() const
825 return pin(0);
828 Link& NetCLShift::pin_Underflow()
830 return pin(1);
833 const Link& NetCLShift::pin_Underflow() const
835 return pin(1);
838 Link& NetCLShift::pin_Overflow()
840 return pin(2);
843 const Link& NetCLShift::pin_Overflow() const
845 return pin(2);
848 Link& NetCLShift::pin_Data(unsigned idx)
850 assert(idx < width_);
851 return pin(3+idx);
854 const Link& NetCLShift::pin_Data(unsigned idx) const
856 assert(idx < width_);
857 return pin(3+idx);
860 Link& NetCLShift::pin_Result(unsigned idx)
862 assert(idx < width_);
863 return pin(3+width_+idx);
866 const Link& NetCLShift::pin_Result(unsigned idx) const
868 assert(idx < width_);
869 return pin(3+width_+idx);
872 Link& NetCLShift::pin_Distance(unsigned idx)
874 assert(idx < width_dist_);
875 return pin(3+2*width_+idx);
878 const Link& NetCLShift::pin_Distance(unsigned idx) const
880 assert(idx < width_dist_);
881 return pin(3+2*width_+idx);
884 NetCompare::NetCompare(const string&n, unsigned wi)
885 : NetNode(n, 8+2*wi), width_(wi)
887 pin(0).set_dir(Link::INPUT); pin(0).set_name("Aclr");
888 pin(1).set_dir(Link::INPUT); pin(1).set_name("Clock");
889 pin(2).set_dir(Link::OUTPUT); pin(2).set_name("AGB");
890 pin(3).set_dir(Link::OUTPUT); pin(3).set_name("AGEB");
891 pin(4).set_dir(Link::OUTPUT); pin(4).set_name("AEB");
892 pin(5).set_dir(Link::OUTPUT); pin(5).set_name("ANEB");
893 pin(6).set_dir(Link::OUTPUT); pin(6).set_name("ALB");
894 pin(7).set_dir(Link::OUTPUT); pin(7).set_name("ALEB");
895 for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
896 pin(8+idx).set_dir(Link::INPUT);
897 pin(8+idx).set_name("DataA", idx);
898 pin(8+width_+idx).set_dir(Link::INPUT);
899 pin(8+width_+idx).set_name("DataB", idx);
903 NetCompare::~NetCompare()
907 unsigned NetCompare::width() const
909 return width_;
912 Link& NetCompare::pin_Aclr()
914 return pin(0);
917 const Link& NetCompare::pin_Aclr() const
919 return pin(0);
922 Link& NetCompare::pin_Clock()
924 return pin(1);
927 const Link& NetCompare::pin_Clock() const
929 return pin(1);
932 Link& NetCompare::pin_AGB()
934 return pin(2);
937 const Link& NetCompare::pin_AGB() const
939 return pin(2);
942 Link& NetCompare::pin_AGEB()
944 return pin(3);
947 const Link& NetCompare::pin_AGEB() const
949 return pin(3);
952 Link& NetCompare::pin_AEB()
954 return pin(4);
957 const Link& NetCompare::pin_AEB() const
959 return pin(4);
962 Link& NetCompare::pin_ANEB()
964 return pin(5);
967 const Link& NetCompare::pin_ANEB() const
969 return pin(5);
972 Link& NetCompare::pin_ALB()
974 return pin(6);
977 const Link& NetCompare::pin_ALB() const
979 return pin(6);
982 Link& NetCompare::pin_ALEB()
984 return pin(7);
987 const Link& NetCompare::pin_ALEB() const
989 return pin(7);
992 Link& NetCompare::pin_DataA(unsigned idx)
994 return pin(8+idx);
997 const Link& NetCompare::pin_DataA(unsigned idx) const
999 return pin(8+idx);
1002 Link& NetCompare::pin_DataB(unsigned idx)
1004 return pin(8+width_+idx);
1007 const Link& NetCompare::pin_DataB(unsigned idx) const
1009 return pin(8+width_+idx);
1012 NetDivide::NetDivide(const string&n, unsigned wr,
1013 unsigned wa, unsigned wb)
1014 : NetNode(n, wr+wa+wb), width_r_(wr), width_a_(wa), width_b_(wb)
1016 unsigned p = 0;
1017 for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
1018 pin(p).set_dir(Link::OUTPUT);
1019 pin(p).set_name("Result", idx);
1021 for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
1022 pin(p).set_dir(Link::INPUT);
1023 pin(p).set_name("DataA", idx);
1025 for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
1026 pin(p).set_dir(Link::INPUT);
1027 pin(p).set_name("DataB", idx);
1031 NetDivide::~NetDivide()
1035 unsigned NetDivide::width_r() const
1037 return width_r_;
1040 unsigned NetDivide::width_a() const
1042 return width_a_;
1045 unsigned NetDivide::width_b() const
1047 return width_b_;
1050 Link& NetDivide::pin_Result(unsigned idx)
1052 assert(idx < width_r_);
1053 return pin(idx);
1056 const Link& NetDivide::pin_Result(unsigned idx) const
1058 assert(idx < width_r_);
1059 return pin(idx);
1062 Link& NetDivide::pin_DataA(unsigned idx)
1064 assert(idx < width_a_);
1065 return pin(idx+width_r_);
1068 const Link& NetDivide::pin_DataA(unsigned idx) const
1070 assert(idx < width_a_);
1071 return pin(idx+width_r_);
1074 Link& NetDivide::pin_DataB(unsigned idx)
1076 assert(idx < width_b_);
1077 return pin(idx+width_r_+width_a_);
1080 const Link& NetDivide::pin_DataB(unsigned idx) const
1082 assert(idx < width_b_);
1083 return pin(idx+width_r_+width_a_);
1086 NetMult::NetMult(const string&n, unsigned wr, unsigned wa, unsigned wb,
1087 unsigned ws)
1088 : NetNode(n, 2+wr+wa+wb+ws), width_r_(wr), width_a_(wa), width_b_(wb),
1089 width_s_(ws)
1091 pin(0).set_dir(Link::INPUT); pin(0).set_name("Aclr", 0);
1092 pin(1).set_dir(Link::INPUT); pin(1).set_name("Clock", 0);
1095 unsigned p = 2;
1096 for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
1097 pin(p).set_dir(Link::OUTPUT);
1098 pin(p).set_name("Result", idx);
1100 for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
1101 pin(p).set_dir(Link::INPUT);
1102 pin(p).set_name("DataA", idx);
1104 for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
1105 pin(p).set_dir(Link::INPUT);
1106 pin(p).set_name("DataB", idx);
1108 for (unsigned idx = 0 ; idx < width_s_ ; idx += 1, p += 1) {
1109 pin(p).set_dir(Link::INPUT);
1110 pin(p).set_name("Sum", idx);
1114 NetMult::~NetMult()
1118 unsigned NetMult::width_r() const
1120 return width_r_;
1123 unsigned NetMult::width_a() const
1125 return width_a_;
1128 unsigned NetMult::width_b() const
1130 return width_b_;
1133 unsigned NetMult::width_s() const
1135 return width_s_;
1138 Link& NetMult::pin_Aclr()
1140 return pin(0);
1143 const Link& NetMult::pin_Aclr() const
1145 return pin(0);
1148 Link& NetMult::pin_Clock()
1150 return pin(1);
1153 const Link& NetMult::pin_Clock() const
1155 return pin(1);
1158 Link& NetMult::pin_Result(unsigned idx)
1160 assert(idx < width_r_);
1161 return pin(idx+2);
1164 const Link& NetMult::pin_Result(unsigned idx) const
1166 assert(idx < width_r_);
1167 return pin(idx+2);
1170 Link& NetMult::pin_DataA(unsigned idx)
1172 assert(idx < width_a_);
1173 return pin(idx+2+width_r_);
1176 const Link& NetMult::pin_DataA(unsigned idx) const
1178 assert(idx < width_a_);
1179 return pin(idx+2+width_r_);
1182 Link& NetMult::pin_DataB(unsigned idx)
1184 assert(idx < width_b_);
1185 return pin(idx+2+width_r_+width_a_);
1188 const Link& NetMult::pin_DataB(unsigned idx) const
1190 assert(idx < width_b_);
1191 return pin(idx+2+width_r_+width_a_);
1194 Link& NetMult::pin_Sum(unsigned idx)
1196 assert(idx < width_s_);
1197 return pin(idx+2+width_r_+width_a_+width_b_);
1200 const Link& NetMult::pin_Sum(unsigned idx) const
1202 assert(idx < width_s_);
1203 return pin(idx+2+width_r_+width_a_+width_b_);
1207 * The NetMux class represents an LPM_MUX device. The pinout is assigned
1208 * like so:
1209 * 0 -- Aclr (optional)
1210 * 1 -- Clock (optional)
1211 * 2 -- Result[0]
1212 * 2+N -- Result[N]
1215 NetMux::NetMux(const string&n, unsigned wi, unsigned si, unsigned sw)
1216 : NetNode(n, 2+wi+sw+wi*si), width_(wi), size_(si), swidth_(sw)
1218 pin(0).set_dir(Link::INPUT); pin(0).set_name("Aclr", 0);
1219 pin(1).set_dir(Link::INPUT); pin(1).set_name("Clock", 0);
1221 for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
1222 pin_Result(idx).set_dir(Link::OUTPUT);
1223 pin_Result(idx).set_name("Result", idx);
1225 for (unsigned jdx = 0 ; jdx < size_ ; jdx += 1) {
1226 pin_Data(idx,jdx).set_dir(Link::INPUT);
1227 pin_Data(idx,jdx).set_name("Data", jdx*width_+idx);
1231 for (unsigned idx = 0 ; idx < swidth_ ; idx += 1) {
1232 pin_Sel(idx).set_dir(Link::INPUT);
1233 pin_Sel(idx).set_name("Sel", idx);
1237 NetMux::~NetMux()
1241 unsigned NetMux::width()const
1243 return width_;
1246 unsigned NetMux::size() const
1248 return size_;
1251 unsigned NetMux::sel_width() const
1253 return swidth_;
1256 Link& NetMux::pin_Aclr()
1258 return pin(0);
1261 const Link& NetMux::pin_Aclr() const
1263 return pin(0);
1266 Link& NetMux::pin_Clock()
1268 return pin(1);
1271 const Link& NetMux::pin_Clock() const
1273 return pin(1);
1276 Link& NetMux::pin_Result(unsigned w)
1278 assert(w < width_);
1279 return pin(2+w);
1282 const Link& NetMux::pin_Result(unsigned w) const
1284 assert(w < width_);
1285 return pin(2+w);
1288 Link& NetMux::pin_Sel(unsigned w)
1290 assert(w < swidth_);
1291 return pin(2+width_+w);
1294 const Link& NetMux::pin_Sel(unsigned w) const
1296 assert(w < swidth_);
1297 return pin(2+width_+w);
1300 Link& NetMux::pin_Data(unsigned w, unsigned s)
1302 assert(w < width_);
1303 assert(s < size_);
1304 return pin(2+width_+swidth_+s*width_+w);
1307 const Link& NetMux::pin_Data(unsigned w, unsigned s) const
1309 assert(w < width_);
1310 assert(s < size_);
1311 return pin(2+width_+swidth_+s*width_+w);
1315 NetRamDq::NetRamDq(const string&n, NetMemory*mem, unsigned awid)
1316 : NetNode(n, 3+2*mem->width()+awid), mem_(mem), awidth_(awid)
1318 pin(0).set_dir(Link::INPUT); pin(0).set_name("InClock", 0);
1319 pin(1).set_dir(Link::INPUT); pin(1).set_name("OutClock", 0);
1320 pin(2).set_dir(Link::INPUT); pin(2).set_name("WE", 0);
1322 for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
1323 pin(3+idx).set_dir(Link::INPUT);
1324 pin(3+idx).set_name("Address", idx);
1327 for (unsigned idx = 0 ; idx < width() ; idx += 1) {
1328 pin(3+awidth_+idx).set_dir(Link::INPUT);
1329 pin(3+awidth_+idx).set_name("Data", idx);
1332 for (unsigned idx = 0 ; idx < width() ; idx += 1) {
1333 pin(3+awidth_+width()+idx).set_dir(Link::OUTPUT);
1334 pin(3+awidth_+width()+idx).set_name("Q", idx);
1337 next_ = mem_->ram_list_;
1338 mem_->ram_list_ = this;
1341 NetRamDq::~NetRamDq()
1343 if (mem_->ram_list_ == this) {
1344 mem_->ram_list_ = next_;
1346 } else {
1347 NetRamDq*cur = mem_->ram_list_;
1348 while (cur->next_ != this) {
1349 assert(cur->next_);
1350 cur = cur->next_;
1352 assert(cur->next_ == this);
1353 cur->next_ = next_;
1357 unsigned NetRamDq::width() const
1359 return mem_->width();
1362 unsigned NetRamDq::awidth() const
1364 return awidth_;
1367 unsigned NetRamDq::size() const
1369 return mem_->count();
1372 const NetMemory* NetRamDq::mem() const
1374 return mem_;
1377 unsigned NetRamDq::count_partners() const
1379 unsigned count = 0;
1380 for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
1381 count += 1;
1383 return count;
1386 void NetRamDq::absorb_partners()
1388 NetRamDq*cur, *tmp;
1389 for (cur = mem_->ram_list_, tmp = 0
1390 ; cur||tmp ; cur = cur? cur->next_ : tmp) {
1391 tmp = 0;
1392 if (cur == this) continue;
1394 bool ok_flag = true;
1395 for (unsigned idx = 0 ; idx < awidth() ; idx += 1)
1396 ok_flag &= pin_Address(idx).is_linked(cur->pin_Address(idx));
1398 if (!ok_flag) continue;
1400 if (pin_InClock().is_linked()
1401 && cur->pin_InClock().is_linked()
1402 && ! pin_InClock().is_linked(cur->pin_InClock()))
1403 continue;
1405 if (pin_OutClock().is_linked()
1406 && cur->pin_OutClock().is_linked()
1407 && ! pin_OutClock().is_linked(cur->pin_OutClock()))
1408 continue;
1410 if (pin_WE().is_linked()
1411 && cur->pin_WE().is_linked()
1412 && ! pin_WE().is_linked(cur->pin_WE()))
1413 continue;
1415 for (unsigned idx = 0 ; idx < width() ; idx += 1) {
1416 if (!pin_Data(idx).is_linked()) continue;
1417 if (! cur->pin_Data(idx).is_linked()) continue;
1419 ok_flag &= pin_Data(idx).is_linked(cur->pin_Data(idx));
1422 if (! ok_flag) continue;
1424 for (unsigned idx = 0 ; idx < width() ; idx += 1) {
1425 if (!pin_Q(idx).is_linked()) continue;
1426 if (! cur->pin_Q(idx).is_linked()) continue;
1428 ok_flag &= pin_Q(idx).is_linked(cur->pin_Q(idx));
1431 if (! ok_flag) continue;
1433 // I see no other reason to reject cur, so link up all
1434 // my pins and delete it.
1435 connect(pin_InClock(), cur->pin_InClock());
1436 connect(pin_OutClock(), cur->pin_OutClock());
1437 connect(pin_WE(), cur->pin_WE());
1439 for (unsigned idx = 0 ; idx < awidth() ; idx += 1)
1440 connect(pin_Address(idx), cur->pin_Address(idx));
1442 for (unsigned idx = 0 ; idx < width() ; idx += 1) {
1443 connect(pin_Data(idx), cur->pin_Data(idx));
1444 connect(pin_Q(idx), cur->pin_Q(idx));
1447 tmp = cur->next_;
1448 delete cur;
1449 cur = 0;
1453 Link& NetRamDq::pin_InClock()
1455 return pin(0);
1458 const Link& NetRamDq::pin_InClock() const
1460 return pin(0);
1463 Link& NetRamDq::pin_OutClock()
1465 return pin(1);
1468 const Link& NetRamDq::pin_OutClock() const
1470 return pin(1);
1473 Link& NetRamDq::pin_WE()
1475 return pin(2);
1478 const Link& NetRamDq::pin_WE() const
1480 return pin(2);
1483 Link& NetRamDq::pin_Address(unsigned idx)
1485 assert(idx < awidth_);
1486 return pin(3+idx);
1489 const Link& NetRamDq::pin_Address(unsigned idx) const
1491 assert(idx < awidth_);
1492 return pin(3+idx);
1495 Link& NetRamDq::pin_Data(unsigned idx)
1497 assert(idx < width());
1498 return pin(3+awidth_+idx);
1501 const Link& NetRamDq::pin_Data(unsigned idx) const
1503 assert(idx < width());
1504 return pin(3+awidth_+idx);
1507 Link& NetRamDq::pin_Q(unsigned idx)
1509 assert(idx < width());
1510 return pin(3+awidth_+width()+idx);
1513 const Link& NetRamDq::pin_Q(unsigned idx) const
1515 assert(idx < width());
1516 return pin(3+awidth_+width()+idx);
1520 * NetAssign
1523 NetAssign_::NetAssign_(const string&n, unsigned w)
1524 : NetNode(n, w), rval_(0), bmux_(0)
1526 for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
1527 pin(idx).set_dir(Link::OUTPUT);
1528 pin(idx).set_name("P", idx);
1533 NetAssign_::~NetAssign_()
1535 if (rval_) delete rval_;
1536 if (bmux_) delete bmux_;
1539 void NetAssign_::set_rval(NetExpr*r)
1541 if (rval_) delete rval_;
1542 rval_ = r;
1545 void NetAssign_::set_bmux(NetExpr*r)
1547 assert(bmux_ == 0);
1548 bmux_ = r;
1551 NetExpr* NetAssign_::rval()
1553 return rval_;
1556 const NetExpr* NetAssign_::rval() const
1558 return rval_;
1561 const NetExpr* NetAssign_::bmux() const
1563 return bmux_;
1566 NetAssign::NetAssign(const string&n, Design*des, unsigned w, NetExpr*rv)
1567 : NetAssign_(n, w)
1569 set_rval(rv);
1572 NetAssign::NetAssign(const string&n, Design*des, unsigned w,
1573 NetExpr*mu, NetExpr*rv)
1574 : NetAssign_(n, w)
1576 bool flag = rv->set_width(1);
1577 if (flag == false) {
1578 cerr << rv->get_line() << ": Expression bit width" <<
1579 " conflicts with l-value bit width." << endl;
1580 des->errors += 1;
1583 set_rval(rv);
1584 set_bmux(mu);
1587 NetAssign::~NetAssign()
1591 NetAssignNB::NetAssignNB(const string&n, Design*des, unsigned w, NetExpr*rv)
1592 : NetAssign_(n, w)
1594 if (rv->expr_width() < w) {
1595 cerr << rv->get_line() << ": Expression bit width (" <<
1596 rv->expr_width() << ") conflicts with l-value "
1597 "bit width (" << w << ")." << endl;
1598 des->errors += 1;
1601 set_rval(rv);
1604 NetAssignNB::NetAssignNB(const string&n, Design*des, unsigned w,
1605 NetExpr*mu, NetExpr*rv)
1606 : NetAssign_(n, w)
1608 bool flag = rv->set_width(1);
1609 if (flag == false) {
1610 cerr << rv->get_line() << ": Expression bit width" <<
1611 " conflicts with l-value bit width." << endl;
1612 des->errors += 1;
1615 set_rval(rv);
1616 set_bmux(mu);
1619 NetAssignNB::~NetAssignNB()
1624 NetAssignMem_::NetAssignMem_(NetMemory*m, NetNet*i, NetExpr*r)
1625 : mem_(m), index_(i), rval_(r)
1627 index_->incr_eref();
1630 NetAssignMem_::~NetAssignMem_()
1632 index_->decr_eref();
1635 NetAssignMem::NetAssignMem(NetMemory*m, NetNet*i, NetExpr*r)
1636 : NetAssignMem_(m, i, r)
1640 NetAssignMem::~NetAssignMem()
1644 NetAssignMemNB::NetAssignMemNB(NetMemory*m, NetNet*i, NetExpr*r)
1645 : NetAssignMem_(m, i, r)
1649 NetAssignMemNB::~NetAssignMemNB()
1654 NetBlock::~NetBlock()
1658 void NetBlock::append(NetProc*cur)
1660 if (last_ == 0) {
1661 last_ = cur;
1662 cur->next_ = cur;
1663 } else {
1664 cur->next_ = last_->next_;
1665 last_->next_ = cur;
1666 last_ = cur;
1670 const NetProc* NetBlock::proc_first() const
1672 if (last_ == 0)
1673 return 0;
1675 return last_->next_;
1678 const NetProc* NetBlock::proc_next(const NetProc*cur) const
1680 if (cur == last_)
1681 return 0;
1683 return cur->next_;
1686 NetBUFZ::NetBUFZ(const string&n)
1687 : NetNode(n, 2)
1689 pin(0).set_dir(Link::OUTPUT);
1690 pin(1).set_dir(Link::INPUT);
1691 pin(0).set_name("O", 0);
1692 pin(1).set_name("I", 0);
1695 NetBUFZ::~NetBUFZ()
1700 NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
1701 : type_(c), expr_(ex), nitems_(cnt)
1703 assert(expr_);
1704 items_ = new Item[nitems_];
1705 for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
1706 items_[idx].statement = 0;
1710 NetCase::~NetCase()
1712 delete expr_;
1713 for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
1714 delete items_[idx].guard;
1715 if (items_[idx].statement) delete items_[idx].statement;
1717 delete[]items_;
1720 NetCase::TYPE NetCase::type() const
1722 return type_;
1725 void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p)
1727 assert(idx < nitems_);
1728 items_[idx].guard = e;
1729 items_[idx].statement = p;
1730 if (items_[idx].guard)
1731 items_[idx].guard->set_width(expr_->expr_width());
1734 NetCaseCmp::NetCaseCmp(const string&n)
1735 : NetNode(n, 3)
1737 pin(0).set_dir(Link::OUTPUT); pin(0).set_name("O",0);
1738 pin(1).set_dir(Link::INPUT); pin(1).set_name("I",0);
1739 pin(2).set_dir(Link::INPUT); pin(2).set_name("I",1);
1742 NetCaseCmp::~NetCaseCmp()
1746 NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
1747 : expr_(ex), if_(i), else_(e)
1751 NetCondit::~NetCondit()
1753 delete expr_;
1754 if (if_) delete if_;
1755 if (else_) delete else_;
1758 const NetExpr* NetCondit::expr() const
1760 return expr_;
1763 NetExpr* NetCondit::expr()
1765 return expr_;
1768 void NetCondit::set_expr(NetExpr*ex)
1770 delete expr_;
1771 expr_ = ex;
1774 NetProc* NetCondit::if_clause()
1776 return if_;
1779 NetProc* NetCondit::else_clause()
1781 return else_;
1784 NetConst::NetConst(const string&n, verinum::V v)
1785 : NetNode(n, 1)
1787 pin(0).set_dir(Link::OUTPUT);
1788 pin(0).set_name("O", 0);
1789 value_ = new verinum::V[1];
1790 value_[0] = v;
1793 NetConst::NetConst(const string&n, const verinum&val)
1794 : NetNode(n, val.len())
1796 value_ = new verinum::V[pin_count()];
1797 for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
1798 pin(idx).set_dir(Link::OUTPUT);
1799 pin(idx).set_name("O", idx);
1800 value_[idx] = val.get(idx);
1804 NetConst::~NetConst()
1806 delete[]value_;
1809 verinum::V NetConst::value(unsigned idx) const
1811 assert(idx < pin_count());
1812 return value_[idx];
1815 NetFuncDef::NetFuncDef(NetScope*s, const svector<NetNet*>&po)
1816 : scope_(s), statement_(0), ports_(po)
1820 NetFuncDef::~NetFuncDef()
1824 const string NetFuncDef::name() const
1826 return scope_->name();
1829 void NetFuncDef::set_proc(NetProc*st)
1831 assert(statement_ == 0);
1832 assert(st != 0);
1833 statement_ = st;
1836 const NetProc* NetFuncDef::proc() const
1838 return statement_;
1841 NetScope*NetFuncDef::scope()
1843 return scope_;
1846 unsigned NetFuncDef::port_count() const
1848 return ports_.count();
1851 const NetNet* NetFuncDef::port(unsigned idx) const
1853 assert(idx < ports_.count());
1854 return ports_[idx];
1857 NetSTask::NetSTask(const string&na, const svector<NetExpr*>&pa)
1858 : name_(na), parms_(pa)
1860 assert(name_[0] == '$');
1863 NetSTask::~NetSTask()
1865 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
1866 delete parms_[idx];
1870 const NetExpr* NetSTask::parm(unsigned idx) const
1872 return parms_[idx];
1875 NetEUFunc::NetEUFunc(NetFuncDef*def, NetESignal*res, svector<NetExpr*>&p)
1876 : func_(def), result_(res), parms_(p)
1878 expr_width(result_->expr_width());
1881 NetEUFunc::~NetEUFunc()
1883 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
1884 delete parms_[idx];
1887 const string NetEUFunc::name() const
1889 return func_->name();
1892 const NetESignal*NetEUFunc::result() const
1894 return result_;
1897 unsigned NetEUFunc::parm_count() const
1899 return parms_.count();
1902 const NetExpr* NetEUFunc::parm(unsigned idx) const
1904 assert(idx < parms_.count());
1905 return parms_[idx];
1908 const NetFuncDef* NetEUFunc::definition() const
1910 return func_;
1913 NetEUFunc* NetEUFunc::dup_expr() const
1915 assert(0);
1916 return 0;
1919 NetUTask::NetUTask(NetTaskDef*def)
1920 : task_(def)
1924 NetUTask::~NetUTask()
1928 NetExpr::NetExpr(unsigned w)
1929 : width_(w)
1933 NetExpr::~NetExpr()
1937 NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
1938 : NetEBinary(op, l, r)
1940 if (l->expr_width() > r->expr_width())
1941 r->set_width(l->expr_width());
1943 if (r->expr_width() > l->expr_width())
1944 l->set_width(r->expr_width());
1946 if (l->expr_width() < r->expr_width())
1947 r->set_width(l->expr_width());
1949 if (r->expr_width() < l->expr_width())
1950 l->set_width(r->expr_width());
1952 if (r->expr_width() > l->expr_width())
1953 expr_width(r->expr_width());
1954 else
1955 expr_width(l->expr_width());
1958 NetEBAdd::~NetEBAdd()
1962 NetEBAdd* NetEBAdd::dup_expr() const
1964 NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
1965 right_->dup_expr());
1966 return result;
1969 NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r)
1970 : NetEBinary(op, l, r)
1972 /* First try to naturally adjust the size of the
1973 expressions to match. */
1974 if (l->expr_width() > r->expr_width())
1975 r->set_width(l->expr_width());
1977 if (r->expr_width() > l->expr_width())
1978 l->set_width(r->expr_width());
1980 if (l->expr_width() < r->expr_width())
1981 r->set_width(l->expr_width());
1983 if (r->expr_width() < l->expr_width())
1984 l->set_width(r->expr_width());
1986 /* If the expressions cannot be matched, pad them to fit. */
1987 if (l->expr_width() > r->expr_width())
1988 right_ = pad_to_width(r, l->expr_width());
1990 if (r->expr_width() > l->expr_width())
1991 left_ = pad_to_width(l, r->expr_width());
1993 assert(left_->expr_width() == right_->expr_width());
1994 expr_width(left_->expr_width());
1997 NetEBBits::~NetEBBits()
2001 NetEBBits* NetEBBits::dup_expr() const
2003 NetEBBits*result = new NetEBBits(op_, left_->dup_expr(),
2004 right_->dup_expr());
2005 return result;
2008 NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
2009 : NetEBinary(op, l, r)
2011 expr_width(1);
2014 NetEBComp::~NetEBComp()
2018 NetEBComp* NetEBComp::dup_expr() const
2020 NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
2021 right_->dup_expr());
2022 return result;
2025 NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
2026 : NetEBinary(op, l, r)
2028 unsigned w = l->expr_width();
2029 if (r->expr_width() > w)
2030 w = r->expr_width();
2032 expr_width(w);
2035 NetEBDiv::~NetEBDiv()
2039 NetEBDiv* NetEBDiv::dup_expr() const
2041 NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
2042 right_->dup_expr());
2043 return result;
2046 NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
2047 : op_(op), left_(l), right_(r)
2051 NetEBinary::~NetEBinary()
2053 delete left_;
2054 delete right_;
2057 NetEBinary* NetEBinary::dup_expr() const
2059 assert(0);
2062 NetEBLogic::NetEBLogic(char op, NetExpr*l, NetExpr*r)
2063 : NetEBinary(op, l, r)
2065 expr_width(1);
2068 NetEBLogic::~NetEBLogic()
2072 NetEBLogic* NetEBLogic::dup_expr() const
2074 NetEBLogic*result = new NetEBLogic(op_, left_->dup_expr(),
2075 right_->dup_expr());
2076 return result;
2079 NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
2080 : NetEBinary(op, l, r)
2082 expr_width(l->expr_width() + r->expr_width());
2085 NetEBMult::~NetEBMult()
2089 NetEBMult* NetEBMult::dup_expr() const
2091 NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
2092 right_->dup_expr());
2093 return result;
2096 NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
2097 : NetEBinary(op, l, r)
2099 expr_width(l->expr_width());
2102 NetEBShift::~NetEBShift()
2106 NetEBShift* NetEBShift::dup_expr() const
2108 NetEBShift*result = new NetEBShift(op_, left_->dup_expr(),
2109 right_->dup_expr());
2110 return result;
2113 NetEConcat::NetEConcat(unsigned cnt, unsigned r)
2114 : parms_(cnt), repeat_(r)
2116 expr_width(0);
2119 NetEConcat::~NetEConcat()
2121 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
2122 delete parms_[idx];
2125 void NetEConcat::set(unsigned idx, NetExpr*e)
2127 assert(idx < parms_.count());
2128 assert(parms_[idx] == 0);
2129 parms_[idx] = e;
2130 expr_width( expr_width() + repeat_*e->expr_width() );
2133 NetEConcat* NetEConcat::dup_expr() const
2135 NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
2136 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
2137 if (parms_[idx]) {
2138 assert(parms_[idx]->dup_expr());
2139 dup->parms_[idx] = parms_[idx]->dup_expr();
2143 dup->expr_width(expr_width());
2144 return dup;
2147 NetEConst::NetEConst(const verinum&val)
2148 : NetExpr(val.len()), value_(val)
2152 NetEConst::~NetEConst()
2156 NetEConst* NetEConst::dup_expr() const
2158 NetEConst*tmp = new NetEConst(value_);
2159 tmp->set_line(*this);
2160 return tmp;
2163 NetEIdent* NetEIdent::dup_expr() const
2165 assert(0);
2168 NetEMemory::NetEMemory(NetMemory*m, NetExpr*i)
2169 : NetExpr(m->width()), mem_(m), idx_(i)
2173 NetEMemory::~NetEMemory()
2177 NetMemory::NetMemory(NetScope*sc, const string&n, long w, long s, long e)
2178 : name_(n), width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
2180 scope_->add_memory(this);
2183 NetMemory::~NetMemory()
2185 assert(scope_);
2186 scope_->rem_memory(this);
2189 unsigned NetMemory::count() const
2191 if (idxh_ < idxl_)
2192 return idxl_ - idxh_ + 1;
2193 else
2194 return idxh_ - idxl_ + 1;
2197 unsigned NetMemory::index_to_address(long idx) const
2199 if (idxh_ < idxl_)
2200 return idx - idxh_;
2201 else
2202 return idx - idxl_;
2206 void NetMemory::set_attributes(const map<string,string>&attr)
2208 assert(attributes_.size() == 0);
2209 attributes_ = attr;
2212 NetEMemory* NetEMemory::dup_expr() const
2214 assert(0);
2217 NetEParam::NetEParam()
2218 : des_(0)
2222 NetEParam::NetEParam(Design*d, NetScope*s, const string&n)
2223 : des_(d), scope_(s), name_(n)
2227 NetEParam::~NetEParam()
2231 NetEParam* NetEParam::dup_expr() const
2233 return 0;
2236 NetEScope::NetEScope(NetScope*s)
2237 : scope_(s)
2241 NetEScope::~NetEScope()
2245 const NetScope* NetEScope::scope() const
2247 return scope_;
2250 NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np)
2251 : name_(n)
2253 expr_width(width);
2254 nparms_ = np;
2255 parms_ = new NetExpr*[np];
2256 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
2257 parms_[idx] = 0;
2260 NetESFunc::~NetESFunc()
2262 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
2263 if (parms_[idx]) delete parms_[idx];
2265 delete[]parms_;
2268 const string& NetESFunc::name() const
2270 return name_;
2273 unsigned NetESFunc::nparms() const
2275 return nparms_;
2278 void NetESFunc::parm(unsigned idx, NetExpr*v)
2280 assert(idx < nparms_);
2281 if (parms_[idx])
2282 delete parms_[idx];
2283 parms_[idx] = v;
2286 const NetExpr* NetESFunc::parm(unsigned idx) const
2288 assert(idx < nparms_);
2289 return parms_[idx];
2292 NetExpr* NetESFunc::parm(unsigned idx)
2294 assert(idx < nparms_);
2295 return parms_[idx];
2298 NetESignal::NetESignal(NetNet*n)
2299 : NetExpr(n->pin_count()), net_(n)
2301 net_->incr_eref();
2302 set_line(*n);
2305 NetESignal::~NetESignal()
2307 net_->decr_eref();
2310 const string& NetESignal::name() const
2312 return net_->name();
2315 unsigned NetESignal::pin_count() const
2317 return net_->pin_count();
2320 Link& NetESignal::pin(unsigned idx)
2322 return net_->pin(idx);
2325 NetESignal* NetESignal::dup_expr() const
2327 assert(0);
2330 NetESubSignal::NetESubSignal(NetESignal*sig, NetExpr*ex)
2331 : sig_(sig), idx_(ex)
2333 // This supports mux type indexing of an expression, so the
2334 // with is by definition 1 bit.
2335 expr_width(1);
2338 NetESubSignal::~NetESubSignal()
2340 delete idx_;
2343 NetESubSignal* NetESubSignal::dup_expr() const
2345 assert(0);
2348 NetETernary::NetETernary(NetExpr*c, NetExpr*t, NetExpr*f)
2349 : cond_(c), true_val_(t), false_val_(f)
2351 expr_width(true_val_->expr_width());
2354 NetETernary::~NetETernary()
2356 delete cond_;
2357 delete true_val_;
2358 delete false_val_;
2361 const NetExpr* NetETernary::cond_expr() const
2363 return cond_;
2366 const NetExpr* NetETernary::true_expr() const
2368 return true_val_;
2371 const NetExpr* NetETernary::false_expr() const
2373 return false_val_;
2376 NetETernary* NetETernary::dup_expr() const
2378 assert(0);
2381 NetEUnary::NetEUnary(char op, NetExpr*ex)
2382 : NetExpr(ex->expr_width()), op_(op), expr_(ex)
2384 switch (op_) {
2385 case '!': // Logical not
2386 case '&': // Reduction and
2387 case '|': // Reduction or
2388 case '^': // Reduction XOR
2389 case 'A': // Reduction NAND (~&)
2390 case 'N': // Reduction NOR (~|)
2391 case 'X': // Reduction NXOR (~^)
2392 expr_width(1);
2393 break;
2397 NetEUnary::~NetEUnary()
2399 delete expr_;
2402 NetEUnary* NetEUnary::dup_expr() const
2404 assert(0);
2407 NetEUBits::NetEUBits(char op, NetExpr*ex)
2408 : NetEUnary(op, ex)
2412 NetEUBits::~NetEUBits()
2416 NetForever::NetForever(NetProc*p)
2417 : statement_(p)
2421 NetForever::~NetForever()
2423 delete statement_;
2426 NetLogic::NetLogic(const string&n, unsigned pins, TYPE t)
2427 : NetNode(n, pins), type_(t)
2429 pin(0).set_dir(Link::OUTPUT);
2430 pin(0).set_name("O", 0);
2431 for (unsigned idx = 1 ; idx < pins ; idx += 1) {
2432 pin(idx).set_dir(Link::INPUT);
2433 pin(idx).set_name("I", idx-1);
2437 NetRepeat::NetRepeat(NetExpr*e, NetProc*p)
2438 : expr_(e), statement_(p)
2442 NetRepeat::~NetRepeat()
2444 delete expr_;
2445 delete statement_;
2448 const NetExpr* NetRepeat::expr() const
2450 return expr_;
2453 NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
2454 : name_(n), proc_(0), ports_(po)
2458 NetTaskDef::~NetTaskDef()
2460 delete proc_;
2463 void NetTaskDef::set_proc(NetProc*p)
2465 assert(proc_ == 0);
2466 proc_ = p;
2469 unsigned NetTaskDef::port_count() const
2471 return ports_.count();
2474 NetNet* NetTaskDef::port(unsigned idx)
2476 assert(idx < ports_.count());
2477 return ports_[idx];
2480 const string& NetTaskDef::name() const
2482 return name_;
2485 const NetProc*NetTaskDef::proc() const
2487 return proc_;
2491 * This method takes the input string, which contains exactly one
2492 * edge, and connects it to the correct output state. The output state
2493 * will be generated if needed, and the value compared.
2495 bool NetUDP::set_sequ_(const string&input, char output)
2497 if (output == '-')
2498 output = input[0];
2500 string frm = input;
2501 string to = input;
2502 to[0] = output;
2504 unsigned edge = frm.find_first_not_of("01x");
2505 assert(frm.find_last_not_of("01x") == edge);
2507 switch (input[edge]) {
2508 case 'r':
2509 frm[edge] = '0';
2510 to[edge] = '1';
2511 break;
2512 case 'R':
2513 frm[edge] = 'x';
2514 to[edge] = '1';
2515 break;
2516 case 'f':
2517 frm[edge] = '1';
2518 to[edge] = '0';
2519 break;
2520 case 'F':
2521 frm[edge] = 'x';
2522 to[edge] = '0';
2523 break;
2524 case 'P':
2525 frm[edge] = '0';
2526 to[edge] = 'x';
2527 break;
2528 case 'N':
2529 frm[edge] = '1';
2530 to[edge] = 'x';
2531 break;
2532 default:
2533 assert(0);
2536 state_t_*sfrm = find_state_(frm);
2537 state_t_*sto = find_state_(to);
2539 switch (to[edge]) {
2540 case '0':
2541 // Notice that I might have caught this edge already
2542 if (sfrm->pins[edge].zer != sto) {
2543 assert(sfrm->pins[edge].zer == 0);
2544 sfrm->pins[edge].zer = sto;
2546 break;
2547 case '1':
2548 // Notice that I might have caught this edge already
2549 if (sfrm->pins[edge].one != sto) {
2550 assert(sfrm->pins[edge].one == 0);
2551 sfrm->pins[edge].one = sto;
2553 break;
2554 case 'x':
2555 // Notice that I might have caught this edge already
2556 if (sfrm->pins[edge].xxx != sto) {
2557 assert(sfrm->pins[edge].xxx == 0);
2558 sfrm->pins[edge].xxx = sto;
2560 break;
2563 return true;
2566 bool NetUDP::sequ_glob_(string input, char output)
2568 for (unsigned idx = 0 ; idx < input.length() ; idx += 1)
2569 switch (input[idx]) {
2570 case '0':
2571 case '1':
2572 case 'x':
2573 case 'r':
2574 case 'R':
2575 case 'f':
2576 case 'F':
2577 case 'P':
2578 case 'N':
2579 break;
2581 case '?': // Iterate over all the levels
2582 input[idx] = '0';
2583 sequ_glob_(input, output);
2584 input[idx] = '1';
2585 sequ_glob_(input, output);
2586 input[idx] = 'x';
2587 sequ_glob_(input, output);
2588 return true;
2590 case 'n': // Iterate over (n) edges
2591 input[idx] = 'f';
2592 sequ_glob_(input, output);
2593 input[idx] = 'F';
2594 sequ_glob_(input, output);
2595 input[idx] = 'N';
2596 sequ_glob_(input, output);
2597 return true;
2599 case 'p': // Iterate over (p) edges
2600 input[idx] = 'r';
2601 sequ_glob_(input, output);
2602 input[idx] = 'R';
2603 sequ_glob_(input, output);
2604 input[idx] = 'P';
2605 sequ_glob_(input, output);
2606 return true;
2608 case '_': // Iterate over (?0) edges
2609 input[idx] = 'f';
2610 sequ_glob_(input, output);
2611 input[idx] = 'F';
2612 sequ_glob_(input, output);
2613 return true;
2615 case '*': // Iterate over all the edges
2616 input[idx] = 'r';
2617 sequ_glob_(input, output);
2618 input[idx] = 'R';
2619 sequ_glob_(input, output);
2620 input[idx] = 'f';
2621 sequ_glob_(input, output);
2622 input[idx] = 'F';
2623 sequ_glob_(input, output);
2624 input[idx] = 'P';
2625 sequ_glob_(input, output);
2626 input[idx] = 'N';
2627 sequ_glob_(input, output);
2628 return true;
2630 default:
2631 assert(0);
2634 return set_sequ_(input, output);
2638 * $Log: netlist.cc,v $
2639 * Revision 1.127 2000/05/27 19:33:23 steve
2640 * Merge similar probes within a module.
2642 * Revision 1.126 2000/05/19 01:43:16 steve
2643 * Accept different widths for add operands.
2645 * Revision 1.125 2000/05/11 23:37:27 steve
2646 * Add support for procedural continuous assignment.
2648 * Revision 1.124 2000/05/07 18:20:07 steve
2649 * Import MCD support from Stephen Tell, and add
2650 * system function parameter support to the IVL core.
2652 * Revision 1.123 2000/05/07 04:37:56 steve
2653 * Carry strength values from Verilog source to the
2654 * pform and netlist for gates.
2656 * Change vvm constants to use the driver_t to drive
2657 * a constant value. This works better if there are
2658 * multiple drivers on a signal.
2660 * Revision 1.122 2000/05/04 03:37:58 steve
2661 * Add infrastructure for system functions, move
2662 * $time to that structure and add $random.
2664 * Revision 1.121 2000/05/02 03:13:31 steve
2665 * Move memories to the NetScope object.
2667 * Revision 1.120 2000/05/02 00:58:12 steve
2668 * Move signal tables to the NetScope class.
2670 * Revision 1.119 2000/04/28 18:43:23 steve
2671 * integer division in expressions properly get width.
2673 * Revision 1.118 2000/04/23 03:45:24 steve
2674 * Add support for the procedural release statement.
2676 * Revision 1.117 2000/04/22 04:20:19 steve
2677 * Add support for force assignment.
2679 * Revision 1.116 2000/04/18 01:02:54 steve
2680 * Minor cleanup of NetTaskDef.
2682 * Revision 1.115 2000/04/16 23:32:19 steve
2683 * Synthesis of comparator in expressions.
2685 * Connect the NetEvent and related classes
2686 * together better.
2688 * Revision 1.114 2000/04/15 19:51:30 steve
2689 * fork-join support in vvm.
2691 * Revision 1.113 2000/04/12 20:02:53 steve
2692 * Finally remove the NetNEvent and NetPEvent classes,
2693 * Get synthesis working with the NetEvWait class,
2694 * and get started supporting multiple events in a
2695 * wait in vvm.
2697 * Revision 1.112 2000/04/04 03:20:15 steve
2698 * Simulate named event trigger and waits.
2700 * Revision 1.111 2000/04/02 04:26:06 steve
2701 * Remove the useless sref template.
2703 * Revision 1.110 2000/04/01 21:40:22 steve
2704 * Add support for integer division.
2706 * Revision 1.109 2000/03/29 04:37:11 steve
2707 * New and improved combinational primitives.
2709 * Revision 1.108 2000/03/12 17:09:41 steve
2710 * Support localparam.
2712 * Revision 1.107 2000/03/10 06:20:48 steve
2713 * Handle defparam to partial hierarchical names.
2715 * Revision 1.106 2000/03/08 04:36:53 steve
2716 * Redesign the implementation of scopes and parameters.
2717 * I now generate the scopes and notice the parameters
2718 * in a separate pass over the pform. Once the scopes
2719 * are generated, I can process overrides and evalutate
2720 * paremeters before elaboration begins.
2722 * Revision 1.105 2000/02/23 02:56:54 steve
2723 * Macintosh compilers do not support ident.
2725 * Revision 1.104 2000/01/13 03:35:35 steve
2726 * Multiplication all the way to simulation.
2728 * Revision 1.103 2000/01/10 01:35:24 steve
2729 * Elaborate parameters afer binding of overrides.
2731 * Revision 1.102 1999/12/30 04:19:12 steve
2732 * Propogate constant 0 in low bits of adders.