Implement $feof() from 1364-2005.
[iverilog.git] / net_event.cc
bloba214cdd48d7759eb828238e4d445d311af60fd51
1 /*
2 * Copyright (c) 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 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: net_event.cc,v 1.27 2007/06/02 03:42:13 steve Exp $"
21 #endif
23 # include "config.h"
24 # include "compiler.h"
25 # include "netlist.h"
28 * NOTE: The name_ is perm-allocated by the caller.
30 NetEvent::NetEvent(perm_string n)
31 : name_(n)
33 scope_ = 0;
34 snext_ = 0;
35 probes_ = 0;
36 trig_ = 0;
37 waitref_ = 0;
38 exprref_ = 0;
39 wlist_ = 0;
42 NetEvent::~NetEvent()
44 assert(waitref_ == 0);
45 if (scope_) scope_->rem_event(this);
46 while (probes_) {
47 NetEvProbe*tmp = probes_->enext_;
48 delete probes_;
49 probes_ = tmp;
51 /* name_ is lex_strings. */
54 perm_string NetEvent::name() const
56 return name_;
59 NetScope* NetEvent::scope()
61 assert(scope_);
62 return scope_;
65 const NetScope* NetEvent::scope() const
67 assert(scope_);
68 return scope_;
71 unsigned NetEvent::nprobe() const
73 unsigned cnt = 0;
74 NetEvProbe*cur = probes_;
75 while (cur) {
76 cnt += 1;
77 cur = cur->enext_;
80 return cnt;
83 NetEvProbe* NetEvent::probe(unsigned idx)
85 NetEvProbe*cur = probes_;
86 while (cur && idx) {
87 cur = cur->enext_;
88 idx -= 1;
90 return cur;
93 const NetEvProbe* NetEvent::probe(unsigned idx) const
95 NetEvProbe*cur = probes_;
96 while (cur && idx) {
97 cur = cur->enext_;
98 idx -= 1;
100 return cur;
103 unsigned NetEvent::ntrig() const
105 unsigned cnt = 0;
106 NetEvTrig*cur = trig_;
107 while (cur) {
108 cnt += 1;
109 cur = cur->enext_;
112 return cnt;
115 unsigned NetEvent::nwait() const
117 return waitref_;
120 unsigned NetEvent::nexpr() const
122 return exprref_;
126 * A "similar" event is one that has an identical non-nil set of
127 * probes.
129 void NetEvent::find_similar_event(list<NetEvent*>&event_list)
131 if (probes_ == 0)
132 return;
134 map<NetEvent*,unsigned> event_matches;
136 /* First, get a list of all the NetEvProbes that are connected
137 to my first probe. Then use that to create a set of
138 candidate events. These candidate events are a superset of
139 the similar events, so I will be culling this list later. */
140 list<NetEvProbe*>first_probes;
141 probes_->find_similar_probes(first_probes);
143 for (list<NetEvProbe*>::iterator idx = first_probes.begin()
144 ; idx != first_probes.end() ; idx ++) {
145 event_matches[ (*idx)->event() ] = 1;
148 /* Now scan the remaining probes, in each case ticking the
149 candidate event. The events that really are similar to this
150 one will turn up in every probe list. */
151 unsigned probe_count = 1;
152 for (NetEvProbe*cur = probes_->enext_ ; cur ; cur = cur->enext_) {
153 list<NetEvProbe*>similar_probes;
154 cur->find_similar_probes(similar_probes);
156 for (list<NetEvProbe*>::iterator idx = similar_probes.begin()
157 ; idx != similar_probes.end() ; idx ++) {
158 event_matches[ (*idx)->event() ] += 1;
161 probe_count += 1;
164 /* Now scan the candidate events. Those events that are
165 connected to all my probes (match_count[x] == probe_count)
166 are possible. If those events have the same number of
167 events, then jackpot. */
168 for (map<NetEvent*,unsigned>::iterator idx = event_matches.begin()
169 ; idx != event_matches.end() ; idx ++) {
171 NetEvent*tmp = (*idx).first;
173 if (tmp == this)
174 continue;
176 if ((*idx).second != probe_count)
177 continue;
179 unsigned tcnt = 0;
180 for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_)
181 tcnt += 1;
183 if (tcnt == probe_count)
184 event_list .push_back(tmp);
190 void NetEvent::replace_event(NetEvent*that)
192 while (wlist_) {
193 wlist_->obj->replace_event(this, that);
197 NexusSet* NetEvent::nex_async_()
199 /* If there are behavioral trigger statements attached to me,
200 then this is not an asynchronous event. */
201 if (trig_ != 0)
202 return 0;
205 NexusSet*tmp = new NexusSet;
206 for (NetEvProbe*cur = probes_ ; cur != 0 ; cur = cur->enext_) {
207 if (cur->edge() != NetEvProbe::ANYEDGE) {
208 delete tmp;
209 return 0;
212 for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1)
213 tmp->add(cur->pin(idx).nexus());
217 return tmp;
220 NetEvTrig::NetEvTrig(NetEvent*ev)
221 : event_(ev)
223 enext_ = event_->trig_;
224 event_->trig_ = this;
227 NetEvTrig::~NetEvTrig()
229 if (event_->trig_ == this) {
230 event_->trig_ = enext_;
232 } else {
233 NetEvTrig*cur = event_->trig_;
234 while (cur->enext_ != this) {
235 assert(cur->enext_);
236 cur = cur->enext_;
239 cur->enext_ = this->enext_;
243 const NetEvent* NetEvTrig::event() const
245 return event_;
248 NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
249 edge_t t, unsigned p)
250 : NetNode(s, n, p), event_(tgt), edge_(t)
252 for (unsigned idx = 0 ; idx < p ; idx += 1) {
253 pin(idx).set_dir(Link::INPUT);
254 pin(idx).set_name(perm_string::literal("P"), idx);
257 enext_ = event_->probes_;
258 event_->probes_ = this;
261 NetEvProbe::~NetEvProbe()
263 if (event_->probes_ == this) {
264 event_->probes_ = enext_;
266 } else {
267 NetEvProbe*cur = event_->probes_;
268 while (cur->enext_ != this) {
269 assert(cur->enext_);
270 cur = cur->enext_;
273 cur->enext_ = this->enext_;
277 NetEvProbe::edge_t NetEvProbe::edge() const
279 return edge_;
282 NetEvent* NetEvProbe::event()
284 return event_;
287 const NetEvent* NetEvProbe::event() const
289 return event_;
293 * A similar NetEvProbe is one that is connected to all the same nexa
294 * that this probe is connected to, and also is the same edge
295 * type. Don't count myself as a similar probe.
297 void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
299 Nexus*nex = pin(0).nexus();
301 for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
302 NetObj*obj = lcur->get_obj();
303 if (obj->pin_count() != pin_count())
304 continue;
306 NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(obj);
307 if (tmp == 0)
308 continue;
310 if (tmp == this)
311 continue;
313 if (edge() != tmp->edge())
314 continue;
316 bool ok_flag = true;
317 for (unsigned idx = 1 ; idx < pin_count() ; idx += 1)
318 if (pin(idx).nexus() != tmp->pin(idx).nexus()) {
319 ok_flag = false;
320 break;
323 if (ok_flag == true)
324 plist .push_back(tmp);
328 NetEvWait::NetEvWait(NetProc*pr)
329 : statement_(pr), nevents_(0), events_(0)
333 NetEvWait::~NetEvWait()
335 if (events_) {
336 for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
337 NetEvent*tgt = events_[idx];
338 tgt->waitref_ -= 1;
340 struct NetEvent::wcell_*tmp = tgt->wlist_;
341 if (tmp->obj == this) {
342 tgt->wlist_ = tmp->next;
343 delete tmp;
344 } else {
345 assert(tmp->next);
346 while (tmp->next->obj != this) {
347 tmp = tmp->next;
348 assert(tmp->next);
350 tmp->next = tmp->next->next;
351 delete tmp;
354 delete[]events_;
356 delete statement_;
359 void NetEvWait::add_event(NetEvent*tgt)
361 assert(tgt);
362 if (nevents_ == 0) {
363 events_ = new NetEvent*[1];
365 } else {
366 NetEvent**tmp = new NetEvent*[nevents_+1];
367 for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
368 tmp[idx] = events_[idx];
369 assert(tmp[idx] != tgt);
371 delete[]events_;
372 events_ = tmp;
375 events_[nevents_] = tgt;
376 nevents_ += 1;
378 // Remember to tell the NetEvent that there is someone
379 // pointing to it.
380 tgt->waitref_ += 1;
382 struct NetEvent::wcell_*tmp = new NetEvent::wcell_;
383 tmp->obj = this;
384 tmp->next = tgt->wlist_;
385 tgt->wlist_ = tmp;
388 void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
390 unsigned idx;
391 for (idx = 0 ; idx < nevents_ ; idx += 1) {
392 if (events_[idx] == src)
393 break;
396 assert(idx < nevents_);
398 /* First, remove me from the list held by the src NetEvent. */
399 assert(src->waitref_ > 0);
400 src->waitref_ -= 1;
401 struct NetEvent::wcell_*tmp = src->wlist_;
402 if (tmp->obj == this) {
403 src->wlist_ = tmp->next;
404 delete tmp;
405 } else {
406 assert(tmp->next);
407 while (tmp->next->obj != this) {
408 tmp = tmp->next;
409 assert(tmp->next);
411 tmp->next = tmp->next->next;
412 delete tmp;
415 events_[idx] = repl;
417 // Remember to tell the replacement NetEvent that there is
418 // someone pointing to it.
419 repl->waitref_ += 1;
421 tmp = new NetEvent::wcell_;
422 tmp->obj = this;
423 tmp->next = repl->wlist_;
424 repl->wlist_ = tmp;
428 unsigned NetEvWait::nevents() const
430 return nevents_;
433 const NetEvent* NetEvWait::event(unsigned idx) const
435 assert(idx < nevents_);
436 return events_[idx];
439 NetEvent* NetEvWait::event(unsigned idx)
441 assert(idx < nevents_);
442 return events_[idx];
445 NetProc* NetEvWait::statement()
447 return statement_;
451 * $Log: net_event.cc,v $
452 * Revision 1.27 2007/06/02 03:42:13 steve
453 * Properly evaluate scope path expressions.
455 * Revision 1.26 2004/10/04 01:10:54 steve
456 * Clean up spurious trailing white space.
458 * Revision 1.25 2004/02/19 06:57:10 steve
459 * Memory and Event names use perm_string.
461 * Revision 1.24 2004/02/18 17:11:56 steve
462 * Use perm_strings for named langiage items.
464 * Revision 1.23 2003/04/22 04:48:29 steve
465 * Support event names as expressions elements.
467 * Revision 1.22 2003/03/06 00:28:41 steve
468 * All NetObj objects have lex_string base names.
470 * Revision 1.21 2003/03/01 06:25:30 steve
471 * Add the lex_strings string handler, and put
472 * scope names and system task/function names
473 * into this table. Also, permallocate event
474 * names from the beginning.
476 * Revision 1.20 2002/08/12 01:34:59 steve
477 * conditional ident string using autoconfig.
479 * Revision 1.19 2002/07/24 16:24:45 steve
480 * Rewrite find_similar_event to support doing
481 * all event matching and replacement in one
482 * shot, saving time in the scans.
484 * Revision 1.18 2002/06/30 02:21:31 steve
485 * Add structure for asynchronous logic synthesis.
487 * Revision 1.17 2002/02/02 06:13:38 steve
488 * event find_similar should not find self.
490 * Revision 1.16 2001/10/28 01:14:53 steve
491 * NetObj constructor finally requires a scope.
493 * Revision 1.15 2001/07/25 03:10:49 steve
494 * Create a config.h.in file to hold all the config
495 * junk, and support gcc 3.0. (Stephan Boettcher)
497 * Revision 1.14 2001/03/29 02:52:19 steve
498 * Add const probe method to NetEvent.
500 * Revision 1.13 2001/03/28 06:07:39 steve
501 * Add the ivl_event_t to ivl_target, and use that to generate
502 * .event statements in vvp way ahead of the thread that uses it.
504 * Revision 1.12 2000/12/15 17:45:07 steve
505 * Remove limits from the similar events search.
507 * Revision 1.11 2000/10/04 16:30:39 steve
508 * Use char8 instead of string to store name.
510 * Revision 1.10 2000/09/19 03:00:36 steve
511 * Typo stepping ot next probe in delete.
513 * Revision 1.9 2000/07/29 03:55:38 steve
514 * fix problem coalescing events w/ probes.
516 * Revision 1.8 2000/05/31 02:26:49 steve
517 * Globally merge redundant event objects.
519 * Revision 1.7 2000/05/27 19:33:23 steve
520 * Merge similar probes within a module.
522 * Revision 1.6 2000/04/18 04:50:20 steve
523 * Clean up unneeded NetEvent objects.
525 * Revision 1.5 2000/04/16 23:32:18 steve
526 * Synthesis of comparator in expressions.
528 * Connect the NetEvent and related classes
529 * together better.
531 * Revision 1.4 2000/04/12 20:02:53 steve
532 * Finally remove the NetNEvent and NetPEvent classes,
533 * Get synthesis working with the NetEvWait class,
534 * and get started supporting multiple events in a
535 * wait in vvm.
537 * Revision 1.3 2000/04/12 04:23:58 steve
538 * Named events really should be expressed with PEIdent
539 * objects in the pform,
541 * Handle named events within the mix of net events
542 * and edges. As a unified lot they get caught together.
543 * wait statements are broken into more complex statements
544 * that include a conditional.
546 * Do not generate NetPEvent or NetNEvent objects in
547 * elaboration. NetEvent, NetEvWait and NetEvProbe
548 * take over those functions in the netlist.
550 * Revision 1.2 2000/04/10 05:26:06 steve
551 * All events now use the NetEvent class.
553 * Revision 1.1 2000/04/04 03:20:15 steve
554 * Simulate named event trigger and waits.