2 * Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
33 void connect(Nexus
*l
, Link
&r
)
43 while (Link
*cur
= tmp
->list_
) {
44 tmp
->list_
= cur
->next_
;
50 l
->driven_
= Nexus::NO_GUESS
;
52 assert(tmp
->list_
== 0);
56 void connect(Link
&l
, Link
&r
)
59 if (r
.is_linked() && !l
.is_linked())
66 : dir_(PASSIVE
), drive0_(STRONG
), drive1_(STRONG
), init_(verinum::Vx
),
67 inst_(0), next_(0), nexus_(0)
69 (new Nexus()) -> relink(this);
86 const Nexus
* Link::nexus() const
91 void Link::set_dir(DIR d
)
96 Link::DIR Link::get_dir() const
101 void Link::drivers_delays(NetExpr
*rise
, NetExpr
*fall
, NetExpr
*decay
)
103 nexus_
->drivers_delays(rise
, fall
, decay
);
106 void Link::drive0(Link::strength_t str
)
111 void Link::drive1(Link::strength_t str
)
116 Link::strength_t
Link::drive0() const
121 Link::strength_t
Link::drive1() const
126 void Link::set_init(verinum::V val
)
131 verinum::V
Link::get_init() const
137 void Link::cur_link(NetObj
*&net
, unsigned &pin
)
143 void Link::cur_link(const NetObj
*&net
, unsigned &pin
) const
155 nexus_
->unlink(this);
156 (new Nexus()) -> relink(this);
159 bool Link::is_equal(const Link
&that
) const
161 return (node_
== that
.node_
) && (pin_
== that
.pin_
);
164 bool Link::is_linked() const
168 if (nexus_
->first_nlink() != this)
174 bool Link::is_linked(const Link
&that
) const
176 return nexus_
== that
.nexus_
;
179 Link
* Link::next_nlink()
184 const Link
* Link::next_nlink() const
189 const NetObj
*Link::get_obj() const
194 NetObj
*Link::get_obj()
199 unsigned Link::get_pin() const
204 void Link::set_name(perm_string n
, unsigned i
)
210 perm_string
Link::get_name() const
215 unsigned Link::get_inst() const
235 verinum::V
Nexus::get_init() const
238 for (Link
*cur
= list_
; cur
; cur
= cur
->next_
) {
239 if (cur
->get_dir() == Link::OUTPUT
)
242 if ((cur
->get_dir() == Link::PASSIVE
)
243 && (cur
->get_init() != verinum::Vz
))
244 return cur
->get_init();
250 void Nexus::drivers_delays(NetExpr
*rise
, NetExpr
*fall
, NetExpr
*decay
)
252 for (Link
*cur
= list_
; cur
; cur
= cur
->next_
) {
253 if (cur
->get_dir() != Link::OUTPUT
)
256 NetObj
*obj
= cur
->get_obj();
257 obj
->rise_time(rise
);
258 obj
->fall_time(fall
);
259 obj
->decay_time(decay
);
263 void Nexus::unlink(Link
*that
)
270 /* If the link I'm removing was a driver for this nexus, then
271 cancel my guess of the driven value. */
272 if (that
->get_dir() != Link::INPUT
)
284 while (cur
->next_
!= that
) {
289 cur
->next_
= that
->next_
;
294 void Nexus::relink(Link
*that
)
301 /* If the link I'm adding is a driver for this nexus, then
302 cancel my guess of the driven value. */
303 if (that
->get_dir() != Link::INPUT
)
306 assert(that
->nexus_
== 0);
307 assert(that
->next_
== 0);
313 Link
* Nexus::first_nlink()
318 const Link
* Nexus::first_nlink() const
323 ivl_nexus_t
Nexus::t_cookie() const
328 ivl_nexus_t
Nexus::t_cookie(ivl_nexus_t val
)const
330 ivl_nexus_t tmp
= t_cookie_
;
335 unsigned Nexus::vector_width() const
337 for (const Link
*cur
= first_nlink() ; cur
; cur
= cur
->next_nlink()) {
338 const NetNet
*sig
= dynamic_cast<const NetNet
*>(cur
->get_obj());
342 return sig
->vector_width();
348 NetNet
* Nexus::pick_any_net()
350 for (Link
*cur
= first_nlink() ; cur
; cur
= cur
->next_nlink()) {
351 NetNet
*sig
= dynamic_cast<NetNet
*>(cur
->get_obj());
359 const char* Nexus::name() const
364 const NetNet
*sig
= 0;
366 for (const Link
*cur
= first_nlink()
367 ; cur
; cur
= cur
->next_nlink()) {
369 const NetNet
*cursig
= dynamic_cast<const NetNet
*>(cur
->get_obj());
375 pin
= cur
->get_pin();
379 if ((cursig
->pin_count() == 1) && (sig
->pin_count() > 1))
382 if ((cursig
->pin_count() > 1) && (sig
->pin_count() == 1)) {
384 pin
= cur
->get_pin();
388 if (cursig
->local_flag() && !sig
->local_flag())
391 if (cursig
->name() < sig
->name())
395 pin
= cur
->get_pin();
399 const Link
*lnk
= first_nlink();
400 const NetObj
*obj
= lnk
->get_obj();
401 pin
= lnk
->get_pin();
402 cerr
<< "internal error: No signal for nexus of " <<
403 obj
->name() << " pin " << pin
<< "(" <<
404 lnk
->get_name() << "<" << lnk
->get_inst() << ">)"
405 " type=" << typeid(*obj
).name() << "?" << endl
;
410 tmp
<< scope_path(sig
->scope()) << "." << sig
->name();
411 if (sig
->pin_count() > 1)
412 tmp
<< "<" << pin
<< ">";
414 const string tmps
= tmp
.str();
415 name_
= new char[strlen(tmps
.c_str()) + 1];
416 strcpy(name_
, tmps
.c_str());
427 NexusSet::~NexusSet()
437 unsigned NexusSet::count() const
442 void NexusSet::add(Nexus
*that
)
446 items_
= (Nexus
**)malloc(sizeof(Nexus
*));
452 unsigned ptr
= bsearch_(that
);
454 assert(items_
[ptr
] == that
);
458 assert(ptr
== nitems_
);
460 items_
= (Nexus
**)realloc(items_
, (nitems_
+1) * sizeof(Nexus
*));
465 void NexusSet::add(const NexusSet
&that
)
467 for (unsigned idx
= 0 ; idx
< that
.nitems_
; idx
+= 1)
468 add(that
.items_
[idx
]);
471 void NexusSet::rem(Nexus
*that
)
476 unsigned ptr
= bsearch_(that
);
487 for (unsigned idx
= ptr
; idx
< (nitems_
-1) ; idx
+= 1)
488 items_
[idx
] = items_
[idx
+1];
490 items_
= (Nexus
**)realloc(items_
, (nitems_
-1) * sizeof(Nexus
*));
494 void NexusSet::rem(const NexusSet
&that
)
496 for (unsigned idx
= 0 ; idx
< that
.nitems_
; idx
+= 1)
497 rem(that
.items_
[idx
]);
500 Nexus
* NexusSet::operator[] (unsigned idx
) const
502 assert(idx
< nitems_
);
506 unsigned NexusSet::bsearch_(Nexus
*that
) const
508 for (unsigned idx
= 0 ; idx
< nitems_
; idx
+= 1) {
509 if (items_
[idx
] == that
)
516 bool NexusSet::contains(const NexusSet
&that
) const
518 for (unsigned idx
= 0 ; idx
< that
.nitems_
; idx
+= 1) {
519 unsigned where
= bsearch_(that
[idx
]);
520 if (where
== nitems_
)
522 if (items_
[where
] != that
[idx
])
529 bool NexusSet::intersect(const NexusSet
&that
) const
531 for (unsigned idx
= 0 ; idx
< that
.nitems_
; idx
+= 1) {
532 unsigned where
= bsearch_(that
[idx
]);
533 if (where
== nitems_
)
535 if (items_
[where
] == that
[idx
])