Skip to content
Newer
Older
100644 444 lines (368 sloc) 9.88 KB
30e8289 Simulate named event trigger and waits.
steve authored
1 /*
97d06b1 @caryr Add support for wait fork to the compiler and code generators
caryr authored
2 * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
30e8289 Simulate named event trigger and waits.
steve authored
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
f5aafc3 @arunpersaud updated FSF-address
arunpersaud authored
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30e8289 Simulate named event trigger and waits.
steve authored
18 */
19
badad63 All NetObj objects have lex_string base names.
steve authored
20 # include "config.h"
21 # include "compiler.h"
30e8289 Simulate named event trigger and waits.
steve authored
22 # include "netlist.h"
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
23 # include "ivl_assert.h"
30e8289 Simulate named event trigger and waits.
steve authored
24
4c67de5 Add the lex_strings string handler, and put
steve authored
25 /*
26 * NOTE: The name_ is perm-allocated by the caller.
27 */
536068b Memory and Event names use perm_string.
steve authored
28 NetEvent::NetEvent(perm_string n)
4c67de5 Add the lex_strings string handler, and put
steve authored
29 : name_(n)
30e8289 Simulate named event trigger and waits.
steve authored
30 {
31 scope_ = 0;
32 snext_ = 0;
4493e96 Finally remove the NetNEvent and NetPEvent classes,
steve authored
33 probes_ = 0;
726f7b8 Synthesis of comparator in expressions.
steve authored
34 trig_ = 0;
35 waitref_ = 0;
f1cc9d8 Support event names as expressions elements.
steve authored
36 exprref_ = 0;
c1c0168 Globally merge redundant event objects.
steve authored
37 wlist_ = 0;
30e8289 Simulate named event trigger and waits.
steve authored
38 }
39
40 NetEvent::~NetEvent()
41 {
726f7b8 Synthesis of comparator in expressions.
steve authored
42 assert(waitref_ == 0);
74c4303 Clean up unneeded NetEvent objects.
steve authored
43 if (scope_) scope_->rem_event(this);
44 while (probes_) {
45 NetEvProbe*tmp = probes_->enext_;
46 delete probes_;
ea53f2b Typo stepping ot next probe in delete.
steve authored
47 probes_ = tmp;
74c4303 Clean up unneeded NetEvent objects.
steve authored
48 }
4c67de5 Add the lex_strings string handler, and put
steve authored
49 /* name_ is lex_strings. */
30e8289 Simulate named event trigger and waits.
steve authored
50 }
51
536068b Memory and Event names use perm_string.
steve authored
52 perm_string NetEvent::name() const
30e8289 Simulate named event trigger and waits.
steve authored
53 {
54 return name_;
55 }
56
c7d97f4 Properly evaluate scope path expressions.
steve authored
57 NetScope* NetEvent::scope()
30e8289 Simulate named event trigger and waits.
steve authored
58 {
59 assert(scope_);
c7d97f4 Properly evaluate scope path expressions.
steve authored
60 return scope_;
30e8289 Simulate named event trigger and waits.
steve authored
61 }
62
a4e528f Add the ivl_event_t to ivl_target, and use that to generate
steve authored
63 const NetScope* NetEvent::scope() const
64 {
65 assert(scope_);
66 return scope_;
67 }
68
4493e96 Finally remove the NetNEvent and NetPEvent classes,
steve authored
69 unsigned NetEvent::nprobe() const
70 {
71 unsigned cnt = 0;
72 NetEvProbe*cur = probes_;
73 while (cur) {
74 cnt += 1;
75 cur = cur->enext_;
76 }
77
78 return cnt;
79 }
80
81 NetEvProbe* NetEvent::probe(unsigned idx)
82 {
83 NetEvProbe*cur = probes_;
84 while (cur && idx) {
85 cur = cur->enext_;
86 idx -= 1;
87 }
88 return cur;
89 }
90
ad8565f Add const probe method to NetEvent.
steve authored
91 const NetEvProbe* NetEvent::probe(unsigned idx) const
92 {
93 NetEvProbe*cur = probes_;
94 while (cur && idx) {
95 cur = cur->enext_;
96 idx -= 1;
97 }
98 return cur;
99 }
100
74c4303 Clean up unneeded NetEvent objects.
steve authored
101 unsigned NetEvent::ntrig() const
102 {
103 unsigned cnt = 0;
104 NetEvTrig*cur = trig_;
105 while (cur) {
106 cnt += 1;
107 cur = cur->enext_;
108 }
109
110 return cnt;
111 }
112
726f7b8 Synthesis of comparator in expressions.
steve authored
113 unsigned NetEvent::nwait() const
114 {
115 return waitref_;
116 }
117
f1cc9d8 Support event names as expressions elements.
steve authored
118 unsigned NetEvent::nexpr() const
119 {
120 return exprref_;
121 }
122
bcbd5b2 Remove limits from the similar events search.
steve authored
123 /*
124 * A "similar" event is one that has an identical non-nil set of
125 * probes.
126 */
58ec62c Rewrite find_similar_event to support doing
steve authored
127 void NetEvent::find_similar_event(list<NetEvent*>&event_list)
fd09bc3 Merge similar probes within a module.
steve authored
128 {
129 if (probes_ == 0)
58ec62c Rewrite find_similar_event to support doing
steve authored
130 return;
bcbd5b2 Remove limits from the similar events search.
steve authored
131
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
132 set<NetEvent*> candidate_events;
fd09bc3 Merge similar probes within a module.
steve authored
133
58ec62c Rewrite find_similar_event to support doing
steve authored
134 /* First, get a list of all the NetEvProbes that are connected
135 to my first probe. Then use that to create a set of
136 candidate events. These candidate events are a superset of
137 the similar events, so I will be culling this list later. */
138 list<NetEvProbe*>first_probes;
139 probes_->find_similar_probes(first_probes);
bcbd5b2 Remove limits from the similar events search.
steve authored
140
58ec62c Rewrite find_similar_event to support doing
steve authored
141 for (list<NetEvProbe*>::iterator idx = first_probes.begin()
225ca1e @caryr Change iterators to use prefix ++ since it is more efficient.
caryr authored
142 ; idx != first_probes.end() ; ++ idx ) {
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
143
144 candidate_events.insert( (*idx)->event() );
58ec62c Rewrite find_similar_event to support doing
steve authored
145 }
fd09bc3 Merge similar probes within a module.
steve authored
146
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
147 if (candidate_events.empty())
148 return;
149
150 /* Now scan the remaining probes, in each case checking that
151 the probe event is a candidate event. After each iteration,
152 events that don't have a similar probe will be removed from
153 the candidate_events set. If the candidate_events set
154 becomes empty, then give up. */
58ec62c Rewrite find_similar_event to support doing
steve authored
155 unsigned probe_count = 1;
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
156 for (NetEvProbe*cur = probes_->enext_ ; cur; cur = cur->enext_) {
58ec62c Rewrite find_similar_event to support doing
steve authored
157 list<NetEvProbe*>similar_probes;
158 cur->find_similar_probes(similar_probes);
159
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
160 set<NetEvent*> candidate_tmp;
58ec62c Rewrite find_similar_event to support doing
steve authored
161 for (list<NetEvProbe*>::iterator idx = similar_probes.begin()
225ca1e @caryr Change iterators to use prefix ++ since it is more efficient.
caryr authored
162 ; idx != similar_probes.end() ; ++ idx ) {
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
163
164 NetEvent*tmp = (*idx)->event();
165 if (candidate_events.find(tmp) != candidate_events.end())
166 candidate_tmp .insert(tmp);
58ec62c Rewrite find_similar_event to support doing
steve authored
167 }
fd09bc3 Merge similar probes within a module.
steve authored
168
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
169 // None of the candidate events match this probe? Give up!
170 if (candidate_tmp.empty())
171 return;
172
173 candidate_events = candidate_tmp;
58ec62c Rewrite find_similar_event to support doing
steve authored
174 probe_count += 1;
fd09bc3 Merge similar probes within a module.
steve authored
175 }
176
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
177 /* Scan the surviving candidate events. We know that they all
178 have probes that match the current event's probes. Check
179 for remaining compatibility details and save the survivors
180 in the event_list that the caller passed. */
181 for (set<NetEvent*>::iterator idx = candidate_events.begin()
225ca1e @caryr Change iterators to use prefix ++ since it is more efficient.
caryr authored
182 ; idx != candidate_events.end() ; ++ idx ) {
bcbd5b2 Remove limits from the similar events search.
steve authored
183
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
184 NetEvent*tmp = *idx;
bcbd5b2 Remove limits from the similar events search.
steve authored
185
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
186 // This shouldn't be possible?
58ec62c Rewrite find_similar_event to support doing
steve authored
187 if (tmp == this)
bcbd5b2 Remove limits from the similar events search.
steve authored
188 continue;
189
18edf2f Rework of automatic task/function support.
Martin Whitaker authored
190 /* For automatic tasks, the VVP runtime holds state for events
191 in the automatically allocated context. This means we can't
192 merge similar events in different automatic tasks. */
193 if (scope()->is_auto() && (tmp->scope() != scope()))
194 continue;
195
58ec62c Rewrite find_similar_event to support doing
steve authored
196 unsigned tcnt = 0;
197 for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_)
198 tcnt += 1;
bcbd5b2 Remove limits from the similar events search.
steve authored
199
58ec62c Rewrite find_similar_event to support doing
steve authored
200 if (tcnt == probe_count)
201 event_list .push_back(tmp);
fd09bc3 Merge similar probes within a module.
steve authored
202 }
203
204 }
205
58ec62c Rewrite find_similar_event to support doing
steve authored
206
c1c0168 Globally merge redundant event objects.
steve authored
207 void NetEvent::replace_event(NetEvent*that)
208 {
209 while (wlist_) {
210 wlist_->obj->replace_event(this, that);
211 }
212 }
213
9b6b081 Add structure for asynchronous logic synthesis.
steve authored
214 NexusSet* NetEvent::nex_async_()
215 {
216 /* If there are behavioral trigger statements attached to me,
217 then this is not an asynchronous event. */
218 if (trig_ != 0)
219 return 0;
220
e4ae832 Clean up spurious trailing white space.
steve authored
221
9b6b081 Add structure for asynchronous logic synthesis.
steve authored
222 NexusSet*tmp = new NexusSet;
223 for (NetEvProbe*cur = probes_ ; cur != 0 ; cur = cur->enext_) {
224 if (cur->edge() != NetEvProbe::ANYEDGE) {
225 delete tmp;
226 return 0;
227 }
228
7d6d93e @steveicarus Handle synthesis l-values that are part selects.
authored
229 for (unsigned idx = 0 ; idx < cur->pin_count() ; idx += 1) {
230 Nexus*nex = cur->pin(idx).nexus();
231 tmp->add(nex, 0, nex->vector_width());
232 }
9b6b081 Add structure for asynchronous logic synthesis.
steve authored
233 }
234
235 return tmp;
236 }
237
30e8289 Simulate named event trigger and waits.
steve authored
238 NetEvTrig::NetEvTrig(NetEvent*ev)
239 : event_(ev)
240 {
726f7b8 Synthesis of comparator in expressions.
steve authored
241 enext_ = event_->trig_;
242 event_->trig_ = this;
30e8289 Simulate named event trigger and waits.
steve authored
243 }
244
245 NetEvTrig::~NetEvTrig()
246 {
726f7b8 Synthesis of comparator in expressions.
steve authored
247 if (event_->trig_ == this) {
248 event_->trig_ = enext_;
249
250 } else {
251 NetEvTrig*cur = event_->trig_;
252 while (cur->enext_ != this) {
253 assert(cur->enext_);
254 cur = cur->enext_;
255 }
256
257 cur->enext_ = this->enext_;
258 }
30e8289 Simulate named event trigger and waits.
steve authored
259 }
260
261 const NetEvent* NetEvTrig::event() const
262 {
263 return event_;
264 }
265
27af95d Use perm_strings for named langiage items.
steve authored
266 NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
8dbd641 All events now use the NetEvent class.
steve authored
267 edge_t t, unsigned p)
27af95d Use perm_strings for named langiage items.
steve authored
268 : NetNode(s, n, p), event_(tgt), edge_(t)
8dbd641 All events now use the NetEvent class.
steve authored
269 {
270 for (unsigned idx = 0 ; idx < p ; idx += 1) {
271 pin(idx).set_dir(Link::INPUT);
272 }
4493e96 Finally remove the NetNEvent and NetPEvent classes,
steve authored
273
274 enext_ = event_->probes_;
275 event_->probes_ = this;
8dbd641 All events now use the NetEvent class.
steve authored
276 }
277
278 NetEvProbe::~NetEvProbe()
279 {
726f7b8 Synthesis of comparator in expressions.
steve authored
280 if (event_->probes_ == this) {
281 event_->probes_ = enext_;
282
283 } else {
284 NetEvProbe*cur = event_->probes_;
285 while (cur->enext_ != this) {
286 assert(cur->enext_);
287 cur = cur->enext_;
288 }
289
290 cur->enext_ = this->enext_;
291 }
8dbd641 All events now use the NetEvent class.
steve authored
292 }
293
294 NetEvProbe::edge_t NetEvProbe::edge() const
295 {
296 return edge_;
297 }
298
fd09bc3 Merge similar probes within a module.
steve authored
299 NetEvent* NetEvProbe::event()
300 {
301 return event_;
302 }
303
8dbd641 All events now use the NetEvent class.
steve authored
304 const NetEvent* NetEvProbe::event() const
305 {
306 return event_;
307 }
308
58ec62c Rewrite find_similar_event to support doing
steve authored
309 /*
310 * A similar NetEvProbe is one that is connected to all the same nexa
311 * that this probe is connected to, and also is the same edge
312 * type. Don't count myself as a similar probe.
313 */
314 void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
315 {
316 Nexus*nex = pin(0).nexus();
317
318 for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
b292a5f @steveicarus Create a branch object to be the argument to the access function.
authored
319 NetPins*obj = lcur->get_obj();
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
320 // Skip NexusSet objects
321 if (obj == 0)
322 continue;
323
58ec62c Rewrite find_similar_event to support doing
steve authored
324 if (obj->pin_count() != pin_count())
325 continue;
326
327 NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(obj);
328 if (tmp == 0)
329 continue;
330
331 if (tmp == this)
332 continue;
333
334 if (edge() != tmp->edge())
335 continue;
336
337 bool ok_flag = true;
38cce38 @steveicarus Slightly improve performance of collapsing NetEvent objects
authored
338 for (unsigned idx = 1 ; ok_flag && idx < pin_count() ; idx += 1)
339 if (! pin(idx).is_linked(tmp->pin(idx)))
58ec62c Rewrite find_similar_event to support doing
steve authored
340 ok_flag = false;
341
342 if (ok_flag == true)
343 plist .push_back(tmp);
344 }
345 }
346
b1fd927 Named events really should be expressed with PEIdent
steve authored
347 NetEvWait::NetEvWait(NetProc*pr)
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
348 : statement_(pr)
30e8289 Simulate named event trigger and waits.
steve authored
349 {
350 }
351
352 NetEvWait::~NetEvWait()
353 {
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
354 if (! events_.empty()) {
355 for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
726f7b8 Synthesis of comparator in expressions.
steve authored
356 NetEvent*tgt = events_[idx];
357 tgt->waitref_ -= 1;
c1c0168 Globally merge redundant event objects.
steve authored
358
359 struct NetEvent::wcell_*tmp = tgt->wlist_;
360 if (tmp->obj == this) {
361 tgt->wlist_ = tmp->next;
362 delete tmp;
363 } else {
364 assert(tmp->next);
365 while (tmp->next->obj != this) {
366 tmp = tmp->next;
367 assert(tmp->next);
368 }
369 tmp->next = tmp->next->next;
370 delete tmp;
371 }
726f7b8 Synthesis of comparator in expressions.
steve authored
372 }
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
373 events_.clear();
726f7b8 Synthesis of comparator in expressions.
steve authored
374 }
30e8289 Simulate named event trigger and waits.
steve authored
375 delete statement_;
376 }
377
b1fd927 Named events really should be expressed with PEIdent
steve authored
378 void NetEvWait::add_event(NetEvent*tgt)
30e8289 Simulate named event trigger and waits.
steve authored
379 {
97d06b1 @caryr Add support for wait fork to the compiler and code generators
caryr authored
380 /* A wait fork is an empty event. */
381 if (! tgt) {
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
382 assert(events_.empty());
383 events_.push_back(0);
97d06b1 @caryr Add support for wait fork to the compiler and code generators
caryr authored
384 return;
385 }
386
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
387 events_.push_back(tgt);
726f7b8 Synthesis of comparator in expressions.
steve authored
388
389 // Remember to tell the NetEvent that there is someone
390 // pointing to it.
391 tgt->waitref_ += 1;
c1c0168 Globally merge redundant event objects.
steve authored
392
393 struct NetEvent::wcell_*tmp = new NetEvent::wcell_;
394 tmp->obj = this;
395 tmp->next = tgt->wlist_;
396 tgt->wlist_ = tmp;
397 }
398
399 void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
400 {
401 unsigned idx;
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
402 for (idx = 0 ; idx < events_.size() ; idx += 1) {
c1c0168 Globally merge redundant event objects.
steve authored
403 if (events_[idx] == src)
404 break;
405 }
406
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
407 assert(idx < events_.size());
c1c0168 Globally merge redundant event objects.
steve authored
408
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
409 // First, remove me from the list held by the src NetEvent.
c1c0168 Globally merge redundant event objects.
steve authored
410 assert(src->waitref_ > 0);
411 src->waitref_ -= 1;
412 struct NetEvent::wcell_*tmp = src->wlist_;
413 if (tmp->obj == this) {
414 src->wlist_ = tmp->next;
415 delete tmp;
416 } else {
417 assert(tmp->next);
418 while (tmp->next->obj != this) {
419 tmp = tmp->next;
420 assert(tmp->next);
421 }
422 tmp->next = tmp->next->next;
423 delete tmp;
424 }
425
020e280 @steveicarus nodangle functor accounts for NexusSet links
authored
426 // Replace the src pointer with the repl pointer.
c1c0168 Globally merge redundant event objects.
steve authored
427 events_[idx] = repl;
428
429 // Remember to tell the replacement NetEvent that there is
430 // someone pointing to it.
431 repl->waitref_ += 1;
432
433 tmp = new NetEvent::wcell_;
434 tmp->obj = this;
435 tmp->next = repl->wlist_;
436 repl->wlist_ = tmp;
437
b1fd927 Named events really should be expressed with PEIdent
steve authored
438 }
439
4493e96 Finally remove the NetNEvent and NetPEvent classes,
steve authored
440 NetProc* NetEvWait::statement()
441 {
442 return statement_;
443 }
Something went wrong with that request. Please try again.