1 /*
2 * Copyright (c) 2005-2019 Stephen Williams (steve@icarus.com)
3 *
4 * (This is a rewrite of code that was ...
5 * Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
6 *
7 * This source code is free software; you can redistribute it
8 * and/or modify it in source code form under the terms of the GNU
9 * General Public License as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 #include "udp.h"
24 #include "schedule.h"
25 #include "symbols.h"
26 #include "compile.h"
27 #include "config.h"
28 #include <cassert>
29 #include <cstdlib>
30 #include <cstring>
31 #include <cstdio>
32 #include <iostream>
33 #ifdef CHECK_WITH_VALGRIND
34 #include "vvp_cleanup.h"
35 #include "ivl_alloc.h"
36 #endif
37
38 // We may need these later when we build the VPI interface to
39 // UDP definitions.
40 #ifdef CHECK_WITH_VALGRIND
41 static vvp_udp_s **udp_defns = 0;
42 static unsigned udp_defns_count = 0;
43
udp_defns_delete()44 void udp_defns_delete()
45 {
46 for (unsigned idx = 0; idx < udp_defns_count; idx += 1) {
47 if (udp_defns[idx]->is_sequential()) {
48 vvp_udp_seq_s *obj = static_cast<vvp_udp_seq_s *>
49 (udp_defns[idx]);
50 delete obj;
51 } else {
52 vvp_udp_comb_s *obj = static_cast<vvp_udp_comb_s *>
53 (udp_defns[idx]);
54 delete obj;
55 }
56 }
57 free(udp_defns);
58 udp_defns = 0;
59 udp_defns_count = 0;
60 }
61 #endif
62
63 static symbol_table_t udp_table;
64
delete_udp_symbols()65 void delete_udp_symbols()
66 {
67 delete_symbol_table(udp_table);
68 udp_table = 0;
69 }
70
udp_find(const char * label)71 struct vvp_udp_s *udp_find(const char *label)
72 {
73 symbol_value_t v = sym_get_value(udp_table, label);
74 return (struct vvp_udp_s *)v.ptr;
75 }
76
operator <<(ostream & o,const struct udp_levels_table & table)77 ostream& operator <<(ostream&o, const struct udp_levels_table&table)
78 {
79 o << "[" << hex << table.mask0
80 << "/" << hex << table.mask1
81 << "/" << hex << table.maskx << "]";
82 return o;
83 }
84
vvp_udp_s(char * label,char * name__,unsigned ports,vvp_bit4_t init,bool type)85 vvp_udp_s::vvp_udp_s(char*label, char*name__, unsigned ports,
86 vvp_bit4_t init, bool type)
87 : name_(name__), ports_(ports), init_(init), seq_(type)
88 {
89 if (!udp_table)
90 udp_table = new_symbol_table();
91
92 assert( !udp_find(label) );
93
94 symbol_value_t v;
95 v.ptr = this;
96 sym_set_value(udp_table, label, v);
97
98 #ifdef CHECK_WITH_VALGRIND
99 udp_defns_count += 1;
100 udp_defns = (vvp_udp_s **) realloc(udp_defns,
101 udp_defns_count*sizeof(vvp_udp_s **));
102 udp_defns[udp_defns_count-1] = this;
103 #endif
104 }
105
~vvp_udp_s()106 vvp_udp_s::~vvp_udp_s()
107 {
108 delete[] name_;
109 }
110
port_count() const111 unsigned vvp_udp_s::port_count() const
112 {
113 return ports_;
114 }
115
get_init() const116 vvp_bit4_t vvp_udp_s::get_init() const
117 {
118 return init_;
119 }
120
vvp_udp_comb_s(char * label,char * name__,unsigned ports)121 vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name__, unsigned ports)
122 : vvp_udp_s(label, name__, ports, BIT4_X, false)
123 {
124 levels0_ = 0;
125 levels1_ = 0;
126 nlevels0_ = 0;
127 nlevels1_ = 0;
128 }
129
~vvp_udp_comb_s()130 vvp_udp_comb_s::~vvp_udp_comb_s()
131 {
132 delete[] levels0_;
133 delete[] levels1_;
134 }
135
136 /*
137 * The cur table that is passed in must have for every valid bit
138 * position exactly one of the three mask bits set. This represents an
139 * actual vector of inputs to be tested.
140 *
141 * The levels0_ and levels1_ tables have levels_table objects that
142 * each represent a single row. For the row to match the input vector,
143 * all the bits that are set in the cur table must also be set in the
144 * row being tested.
145 *
146 * It is possible for a row to match multiple different vectors. This
147 * is seen from the compile_table function, where bit positions for
148 * multiple masks can be test for certain row positions. For example,
149 * if the row bit position is '?', then mask 0/1/x are all set in the
150 * row for that bit position. This means it doesn't matter which of
151 * the three bit positions is set in the cur input table, the bit
152 * position will generate a match.
153 */
test_levels(const udp_levels_table & cur)154 vvp_bit4_t vvp_udp_comb_s::test_levels(const udp_levels_table&cur)
155 {
156 /* To test for a row match, test that the mask0, mask1 and
157 maskx vectors all have bits set where the matching
158 cur.mask0/1/x vectors have bits set. It is possible that a
159 levels0_[idx] vector has more bits set then the cur mask,
160 but this is OK and these bits are to be ignored. */
161
162 for (unsigned idx = 0 ; idx < nlevels0_ ; idx += 1) {
163 if (cur.mask0 != (cur.mask0 & levels0_[idx].mask0))
164 continue;
165 if (cur.mask1 != (cur.mask1 & levels0_[idx].mask1))
166 continue;
167 if (cur.maskx != (cur.maskx & levels0_[idx].maskx))
168 continue;
169
170 return BIT4_0;
171 }
172
173 for (unsigned idx = 0 ; idx < nlevels1_ ; idx += 1) {
174 if (cur.mask0 != (cur.mask0 & levels1_[idx].mask0))
175 continue;
176 if (cur.mask1 != (cur.mask1 & levels1_[idx].mask1))
177 continue;
178 if (cur.maskx != (cur.maskx & levels1_[idx].maskx))
179 continue;
180
181 return BIT4_1;
182 }
183
184 return BIT4_X;
185 }
186
calculate_output(const udp_levels_table & cur,const udp_levels_table &,vvp_bit4_t)187 vvp_bit4_t vvp_udp_comb_s::calculate_output(const udp_levels_table&cur,
188 const udp_levels_table&,
189 vvp_bit4_t)
190 {
191 return test_levels(cur);
192 }
193
or_based_on_char(udp_levels_table & cur,char flag,unsigned long mask_bit)194 static void or_based_on_char(udp_levels_table&cur, char flag,
195 unsigned long mask_bit)
196 {
197 switch (flag) {
198 case '0':
199 cur.mask0 |= mask_bit;
200 break;
201 case '1':
202 cur.mask1 |= mask_bit;
203 break;
204 case 'x':
205 cur.maskx |= mask_bit;
206 break;
207 case 'b':
208 cur.mask0 |= mask_bit;
209 cur.mask1 |= mask_bit;
210 break;
211 case 'l':
212 cur.mask0 |= mask_bit;
213 cur.maskx |= mask_bit;
214 break;
215 case 'h':
216 cur.maskx |= mask_bit;
217 cur.mask1 |= mask_bit;
218 break;
219 case '?':
220 cur.mask0 |= mask_bit;
221 cur.maskx |= mask_bit;
222 cur.mask1 |= mask_bit;
223 break;
224 default:
225 fprintf(stderr, "Unsupported flag %c(%d).\n", flag, flag);
226 assert(0);
227 }
228 }
229
compile_table(char ** tab)230 void vvp_udp_comb_s::compile_table(char**tab)
231 {
232 unsigned nrows0 = 0, nrows1 = 0;
233
234 /* First run through the table to figure out the number of
235 rows I need for each kind of table. */
236 for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
237 assert(strlen(tab[idx]) == port_count() + 1);
238 switch (tab[idx][port_count()]) {
239 case '0':
240 nrows0 += 1;
241 break;
242 case '1':
243 nrows1 += 1;
244 break;
245 case 'x':
246 break;
247 default:
248 fprintf(stderr, "Unsupported entry %c(%d).\n",
249 tab[idx][port_count()], tab[idx][port_count()]);
250 assert(0);
251 }
252 }
253
254 nlevels0_ = nrows0;
255 levels0_ = new udp_levels_table[nlevels0_];
256
257 nlevels1_ = nrows1;
258 levels1_ = new udp_levels_table[nlevels1_];
259
260 nrows0 = 0;
261 nrows1 = 0;
262 for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
263 struct udp_levels_table cur;
264 cur.mask0 = 0;
265 cur.mask1 = 0;
266 cur.maskx = 0;
267 if (port_count() > 8*sizeof(cur.mask0)) {
268 fprintf(stderr, "internal error: primitive port count=%u "
269 " > %zu\n", port_count(), sizeof(cur.mask0));
270 assert(port_count() <= 8*sizeof(cur.mask0));
271 }
272 for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
273 unsigned long mask_bit = 1UL << pp;
274 or_based_on_char(cur, tab[idx][pp], mask_bit);
275 }
276
277 switch (tab[idx][port_count()]) {
278 case '0':
279 levels0_[nrows0++] = cur;
280 break;
281 case '1':
282 levels1_[nrows1++] = cur;
283 break;
284 default:
285 break;
286 }
287 delete[] tab[idx];
288 }
289 free(tab);
290
291 assert(nrows0 == nlevels0_);
292 assert(nrows1 == nlevels1_);
293 }
294
vvp_udp_seq_s(char * label,char * name__,unsigned ports,vvp_bit4_t init)295 vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name__,
296 unsigned ports, vvp_bit4_t init)
297 : vvp_udp_s(label, name__, ports, init, true)
298 {
299 levels0_ = 0;
300 levels1_ = 0;
301 levelsx_ = 0;
302 levelsL_ = 0;
303
304 nlevels0_ = 0;
305 nlevels1_ = 0;
306 nlevelsx_ = 0;
307 nlevelsL_ = 0;
308
309 edges0_ = 0;
310 edges1_ = 0;
311 edgesL_ = 0;
312
313 nedges0_ = 0;
314 nedges1_ = 0;
315 nedgesL_ = 0;
316 }
317
~vvp_udp_seq_s()318 vvp_udp_seq_s::~vvp_udp_seq_s()
319 {
320 delete[] levels0_;
321 delete[] levels1_;
322 delete[] levelsx_;
323 delete[] levelsL_;
324 delete[] edges0_;
325 delete[] edges1_;
326 delete[] edgesL_;
327 }
328
edge_based_on_char(struct udp_edges_table & cur,char chr,unsigned pos)329 void edge_based_on_char(struct udp_edges_table&cur, char chr, unsigned pos)
330 {
331 unsigned long mask_bit = 1 << pos;
332
333 switch (chr) {
334 case '0':
335 cur.mask0 |= mask_bit;
336 break;
337 case '1':
338 cur.mask1 |= mask_bit;
339 break;
340 case 'x':
341 cur.maskx |= mask_bit;
342 break;
343 case 'b':
344 cur.mask0 |= mask_bit;
345 cur.mask1 |= mask_bit;
346 break;
347 case 'l':
348 cur.mask0 |= mask_bit;
349 cur.maskx |= mask_bit;
350 break;
351 case 'h':
352 cur.maskx |= mask_bit;
353 cur.mask1 |= mask_bit;
354 break;
355 case '?':
356 cur.mask0 |= mask_bit;
357 cur.maskx |= mask_bit;
358 cur.mask1 |= mask_bit;
359 break;
360
361 case 'B': // (x?) edge
362 cur.mask0 |= mask_bit;
363 cur.mask1 |= mask_bit;
364 cur.edge_position = pos;
365 cur.edge_mask0 = 0;
366 cur.edge_maskx = 1;
367 cur.edge_mask1 = 0;
368 break;
369 case 'f': // (10) edge
370 cur.mask0 |= mask_bit;
371 cur.edge_position = pos;
372 cur.edge_mask0 = 0;
373 cur.edge_maskx = 0;
374 cur.edge_mask1 = 1;
375 break;
376 case 'F': // (x0) edge
377 cur.mask0 |= mask_bit;
378 cur.edge_position = pos;
379 cur.edge_mask0 = 0;
380 cur.edge_maskx = 1;
381 cur.edge_mask1 = 0;
382 break;
383 case 'M': // (1x) edge
384 cur.maskx |= mask_bit;
385 cur.edge_position = pos;
386 cur.edge_mask0 = 0;
387 cur.edge_maskx = 0;
388 cur.edge_mask1 = 1;
389 break;
390 case 'N': // (1x) and (10) edge
391 cur.mask0 |= mask_bit;
392 cur.maskx |= mask_bit;
393 cur.edge_position = pos;
394 cur.edge_mask0 = 0;
395 cur.edge_maskx = 0;
396 cur.edge_mask1 = 1;
397 break;
398 case 'P': // (0x) and (01) edge
399 cur.maskx |= mask_bit;
400 cur.mask1 |= mask_bit;
401 cur.edge_position = pos;
402 cur.edge_mask0 = 1;
403 cur.edge_maskx = 0;
404 cur.edge_mask1 = 0;
405 break;
406 case 'q': // (bx) edge
407 cur.maskx |= mask_bit;
408 cur.edge_position = pos;
409 cur.edge_mask0 = 1;
410 cur.edge_maskx = 0;
411 cur.edge_mask1 = 1;
412 break;
413 case 'Q': // (0x) edge
414 cur.maskx |= mask_bit;
415 cur.edge_position = pos;
416 cur.edge_mask0 = 1;
417 cur.edge_maskx = 0;
418 cur.edge_mask1 = 0;
419 break;
420 case 'r': // (01) edge
421 cur.mask1 |= mask_bit;
422 cur.edge_position = pos;
423 cur.edge_mask0 = 1;
424 cur.edge_maskx = 0;
425 cur.edge_mask1 = 0;
426 break;
427 case 'R': // (x1) edge
428 cur.mask1 |= mask_bit;
429 cur.edge_position = pos;
430 cur.edge_mask0 = 0;
431 cur.edge_maskx = 1;
432 cur.edge_mask1 = 0;
433 break;
434 case '%': // (?x) edge
435 cur.maskx |= mask_bit;
436 cur.edge_position = pos;
437 cur.edge_mask0 = 1;
438 cur.edge_maskx = 0;
439 cur.edge_mask1 = 1;
440 break;
441 case '+': // (?1) edge
442 cur.mask1 |= mask_bit;
443 cur.edge_position = pos;
444 cur.edge_mask0 = 1;
445 cur.edge_maskx = 1;
446 cur.edge_mask1 = 0;
447 break;
448 case '_': // (?0) edge
449 cur.mask0 |= mask_bit;
450 cur.edge_position = pos;
451 cur.edge_mask0 = 0;
452 cur.edge_maskx = 1;
453 cur.edge_mask1 = 1;
454 break;
455 default:
456 fprintf(stderr, "internal error: unknown edge code: %c\n", chr);
457 assert(0);
458 }
459 }
460
compile_table(char ** tab)461 void vvp_udp_seq_s::compile_table(char**tab)
462 {
463
464 for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
465 const char*row = tab[idx];
466 assert(strlen(row) == port_count() + 2);
467
468 if (strspn(row, "01xblh?") >= port_count()+1) {
469
470 switch (row[port_count()+1]) {
471 case '0':
472 nlevels0_ += 1;
473 break;
474 case '1':
475 nlevels1_ += 1;
476 break;
477 case 'x':
478 nlevelsx_ += 1;
479 break;
480 case '-':
481 nlevelsL_ += 1;
482 break;
483 default:
484 fprintf(stderr, "Unsupported entry %c(%d).\n",
485 row[port_count()+1], row[port_count()+1]);
486 assert(0);
487 break;
488 }
489
490 } else {
491 /* Rows that have n or p edges will need to be
492 expanded into 2 rows. */
493 unsigned extra = 0;
494 if (strchr(row,'n'))
495 extra = 1;
496 if (strchr(row,'p'))
497 extra = 1;
498 if (strchr(row,'*'))
499 extra = 2;
500
501 switch (row[port_count()+1]) {
502 case '0':
503 nedges0_ += 1 + extra;
504 break;
505 case '1':
506 nedges1_ += 1 + extra;
507 break;
508 case 'x':
509 break;
510 case '-':
511 nedgesL_ += 1 + extra;
512 break;
513 default:
514 fprintf(stderr, "Unsupported entry %c(%d).\n",
515 row[port_count()+1], row[port_count()+1]);
516 assert(0);
517 break;
518 }
519 }
520 }
521
522 levels0_ = new udp_levels_table[nlevels0_];
523 levels1_ = new udp_levels_table[nlevels1_];
524 levelsx_ = new udp_levels_table[nlevelsx_];
525 levelsL_ = new udp_levels_table[nlevelsL_];
526 edges0_ = new udp_edges_table[nedges0_];
527 edges1_ = new udp_edges_table[nedges1_];
528 edgesL_ = new udp_edges_table[nedgesL_];
529
530 unsigned idx_lev0 = 0;
531 unsigned idx_lev1 = 0;
532 unsigned idx_levx = 0;
533 unsigned idx_levL = 0;
534 unsigned idx_edg0 = 0;
535 unsigned idx_edg1 = 0;
536 unsigned idx_edgL = 0;
537
538 for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
539 const char*row = tab[idx];
540
541 if (strspn(row, "01xblh?") >= port_count()+1) {
542 struct udp_levels_table cur;
543 cur.mask0 = 0;
544 cur.mask1 = 0;
545 cur.maskx = 0;
546 for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
547 unsigned long mask_bit = 1UL << pp;
548 or_based_on_char(cur, row[pp+1], mask_bit);
549 }
550
551 or_based_on_char(cur, row[0], 1UL << port_count());
552
553 switch (row[port_count()+1]) {
554 case '0':
555 levels0_[idx_lev0++] = cur;
556 break;
557 case '1':
558 levels1_[idx_lev1++] = cur;
559 break;
560 case 'x':
561 levelsx_[idx_levx++] = cur;
562 break;
563 case '-':
564 levelsL_[idx_levL++] = cur;
565 break;
566 default:
567 fprintf(stderr, "Unsupported entry %c(%d).\n",
568 row[port_count()+1], row[port_count()+1]);
569 assert(0);
570 break;
571 }
572
573 } else {
574 struct udp_edges_table cur;
575 cur.mask0 = 0;
576 cur.mask1 = 0;
577 cur.maskx = 0;
578 cur.edge_position = 0;
579 cur.edge_mask0 = 0;
580 cur.edge_mask1 = 0;
581 cur.edge_maskx = 0;
582
583 bool need_ext0_table = false;
584 struct udp_edges_table ext0;
585 ext0.mask0 = 0;
586 ext0.mask1 = 0;
587 ext0.maskx = 0;
588 ext0.edge_position = 0;
589 ext0.edge_mask0 = 0;
590 ext0.edge_mask1 = 0;
591 ext0.edge_maskx = 0;
592
593 bool need_ext1_table = false;
594 struct udp_edges_table ext1;
595 ext1.mask0 = 0;
596 ext1.mask1 = 0;
597 ext1.maskx = 0;
598 ext1.edge_position = 0;
599 ext1.edge_mask0 = 0;
600 ext1.edge_mask1 = 0;
601 ext1.edge_maskx = 0;
602
603 for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
604 switch (row[pp+1]) {
605 case 'n':
606 edge_based_on_char(cur, 'N', pp);
607 edge_based_on_char(ext0, '_', pp);
608 need_ext0_table = true;
609 break;
610 case 'p':
611 edge_based_on_char(cur, 'P', pp);
612 edge_based_on_char(ext0, '+', pp);
613 need_ext0_table = true;
614 break;
615 case '*':
616 edge_based_on_char(cur, 'P', pp);
617 edge_based_on_char(ext0, 'N', pp);
618 edge_based_on_char(ext1, 'B', pp);
619 need_ext0_table = true;
620 need_ext1_table = true;
621 break;
622 default:
623 edge_based_on_char(cur, row[pp+1], pp);
624 edge_based_on_char(ext0, row[pp+1], pp);
625 edge_based_on_char(ext1, row[pp+1], pp);
626 break;
627 }
628 }
629 edge_based_on_char(cur, row[0], port_count());
630 edge_based_on_char(ext0, row[0], port_count());
631 edge_based_on_char(ext1, row[0], port_count());
632
633 switch (row[port_count()+1]) {
634 case '0':
635 edges0_[idx_edg0++] = cur;
636 if (need_ext0_table)
637 edges0_[idx_edg0++] = ext0;
638 if (need_ext1_table)
639 edges0_[idx_edg0++] = ext1;
640 break;
641 case '1':
642 edges1_[idx_edg1++] = cur;
643 if (need_ext0_table)
644 edges1_[idx_edg1++] = ext0;
645 if (need_ext1_table)
646 edges1_[idx_edg1++] = ext1;
647 break;
648 case 'x':
649 break;
650 case '-':
651 edgesL_[idx_edgL++] = cur;
652 if (need_ext0_table)
653 edgesL_[idx_edgL++] = ext0;
654 if (need_ext1_table)
655 edgesL_[idx_edgL++] = ext1;
656 break;
657 default:
658 fprintf(stderr, "Unsupported entry %c(%d).\n",
659 row[port_count()+1], row[port_count()+1]);
660 assert(0);
661 break;
662 }
663
664 }
665 delete[] tab[idx];
666 }
667 free(tab);
668
669 assert(idx_edg0 == nedges0_);
670 assert(idx_edg1 == nedges1_);
671 assert(idx_edgL == nedgesL_);
672
673 }
674
operator ==(const udp_levels_table & a,const udp_levels_table & b)675 bool operator == (const udp_levels_table&a, const udp_levels_table&b)
676 {
677 if (a.mask0 != b.mask0)
678 return false;
679 if (a.mask1 != b.mask1)
680 return false;
681 if (a.maskx != b.maskx)
682 return false;
683 return true;
684 }
685
calculate_output(const udp_levels_table & cur,const udp_levels_table & prev,vvp_bit4_t cur_out)686 vvp_bit4_t vvp_udp_seq_s::calculate_output(const udp_levels_table&cur,
687 const udp_levels_table&prev,
688 vvp_bit4_t cur_out)
689 {
690 if (cur == prev)
691 return cur_out;
692
693 udp_levels_table cur_tmp = cur;
694
695 unsigned long mask_out = 1UL << port_count();
696 switch (cur_out) {
697 case BIT4_0:
698 cur_tmp.mask0 |= mask_out;
699 break;
700 case BIT4_1:
701 cur_tmp.mask1 |= mask_out;
702 break;
703 default:
704 cur_tmp.maskx |= mask_out;
705 break;
706 }
707
708 vvp_bit4_t lev = test_levels_(cur_tmp);
709 if (lev == BIT4_Z) {
710 lev = test_edges_(cur_tmp, prev);
711 }
712
713 return lev;
714 }
715
716 /*
717 * This function tests the levels of the input with the additional
718 * check match for the current output. It uses this to calculate a
719 * next output, or Z if there was no match. (This is different from
720 * the combinational version of this function, which returns X for the
721 * cases that don't match.) This method assumes that the caller has
722 * set the mask bit in bit position [port_count()] to reflect the
723 * current output.
724 */
test_levels_(const udp_levels_table & cur)725 vvp_bit4_t vvp_udp_seq_s::test_levels_(const udp_levels_table&cur)
726 {
727 for (unsigned idx = 0 ; idx < nlevels0_ ; idx += 1) {
728 if (cur.mask0 != (cur.mask0 & levels0_[idx].mask0))
729 continue;
730 if (cur.mask1 != (cur.mask1 & levels0_[idx].mask1))
731 continue;
732 if (cur.maskx != (cur.maskx & levels0_[idx].maskx))
733 continue;
734
735 return BIT4_0;
736 }
737
738 for (unsigned idx = 0 ; idx < nlevels1_ ; idx += 1) {
739 if (cur.mask0 != (cur.mask0 & levels1_[idx].mask0))
740 continue;
741 if (cur.mask1 != (cur.mask1 & levels1_[idx].mask1))
742 continue;
743 if (cur.maskx != (cur.maskx & levels1_[idx].maskx))
744 continue;
745
746 return BIT4_1;
747 }
748
749 /* We need to test against an explicit X-output table, since
750 we need to distinguish from an X output and no match. */
751 for (unsigned idx = 0 ; idx < nlevelsx_ ; idx += 1) {
752 if (cur.mask0 != (cur.mask0 & levelsx_[idx].mask0))
753 continue;
754 if (cur.mask1 != (cur.mask1 & levelsx_[idx].mask1))
755 continue;
756 if (cur.maskx != (cur.maskx & levelsx_[idx].maskx))
757 continue;
758
759 return BIT4_X;
760 }
761
762 /* Test the table that requests the next output be the same as
763 the current output. This gets the current output from the
764 levels table that was passed in. */
765 for (unsigned idx = 0 ; idx < nlevelsL_ ; idx += 1) {
766 if (cur.mask0 != (cur.mask0 & levelsL_[idx].mask0))
767 continue;
768 if (cur.mask1 != (cur.mask1 & levelsL_[idx].mask1))
769 continue;
770 if (cur.maskx != (cur.maskx & levelsL_[idx].maskx))
771 continue;
772
773 if (cur.mask0 & (1 << port_count()))
774 return BIT4_0;
775 if (cur.mask1 & (1 << port_count()))
776 return BIT4_1;
777 if (cur.maskx & (1 << port_count()))
778 return BIT4_X;
779
780 assert(0);
781 return BIT4_X;
782 }
783
784 /* No explicit levels entry match. Return a Z to signal that
785 further testing is needed. */
786 return BIT4_Z;
787 }
788
test_edges_(const udp_levels_table & cur,const udp_levels_table & prev)789 vvp_bit4_t vvp_udp_seq_s::test_edges_(const udp_levels_table&cur,
790 const udp_levels_table&prev)
791 {
792 /* The edge_mask is true for all bits that are different in
793 the cur and prev tables. */
794 unsigned long edge0_mask = cur.mask0 ^ prev.mask0;
795 unsigned long edgex_mask = cur.maskx ^ prev.maskx;
796 unsigned long edge1_mask = cur.mask1 ^ prev.mask1;
797
798 unsigned long edge_mask = edge0_mask|edgex_mask|edge1_mask;
799 edge_mask &= ~ (-1UL << port_count());
800
801 /* If there are no differences, then there are no edges. Give
802 up now. */
803 if (edge_mask == 0)
804 return BIT4_X;
805
806 unsigned edge_position = 0;
807 while ((edge_mask&1) == 0) {
808 edge_mask >>= 1;
809 edge_position += 1;
810 }
811
812 /* We expect that there is exactly one edge in here. */
813 assert(edge_mask == 1);
814
815 edge_mask = 1UL << edge_position;
816
817 unsigned edge_mask0 = (prev.mask0&edge_mask)? 1 : 0;
818 unsigned edge_maskx = (prev.maskx&edge_mask)? 1 : 0;
819 unsigned edge_mask1 = (prev.mask1&edge_mask)? 1 : 0;
820
821
822 /* Now the edge_position and edge_mask* variables have the
823 values we use to test the applicability of the edge_table
824 entries. */
825
826 for (unsigned idx = 0 ; idx < nedges0_ ; idx += 1) {
827 struct udp_edges_table*row = edges0_ + idx;
828
829 if (row->edge_position != edge_position)
830 continue;
831 if (edge_mask0 && !row->edge_mask0)
832 continue;
833 if (edge_maskx && !row->edge_maskx)
834 continue;
835 if (edge_mask1 && !row->edge_mask1)
836 continue;
837 if (cur.mask0 != (cur.mask0 & row->mask0))
838 continue;
839 if (cur.maskx != (cur.maskx & row->maskx))
840 continue;
841 if (cur.mask1 != (cur.mask1 & row->mask1))
842 continue;
843
844 return BIT4_0;
845 }
846
847 for (unsigned idx = 0 ; idx < nedges1_ ; idx += 1) {
848 struct udp_edges_table*row = edges1_ + idx;
849
850 if (row->edge_position != edge_position)
851 continue;
852 if (edge_mask0 && !row->edge_mask0)
853 continue;
854 if (edge_maskx && !row->edge_maskx)
855 continue;
856 if (edge_mask1 && !row->edge_mask1)
857 continue;
858 if (cur.mask0 != (cur.mask0 & row->mask0))
859 continue;
860 if (cur.maskx != (cur.maskx & row->maskx))
861 continue;
862 if (cur.mask1 != (cur.mask1 & row->mask1))
863 continue;
864
865 return BIT4_1;
866 }
867
868 for (unsigned idx = 0 ; idx < nedgesL_ ; idx += 1) {
869 struct udp_edges_table*row = edgesL_ + idx;
870
871 if (row->edge_position != edge_position)
872 continue;
873 if (edge_mask0 && !row->edge_mask0)
874 continue;
875 if (edge_maskx && !row->edge_maskx)
876 continue;
877 if (edge_mask1 && !row->edge_mask1)
878 continue;
879 if (cur.mask0 != (cur.mask0 & row->mask0))
880 continue;
881 if (cur.maskx != (cur.maskx & row->maskx))
882 continue;
883 if (cur.mask1 != (cur.mask1 & row->mask1))
884 continue;
885
886 if (cur.mask0 & (1 << port_count()))
887 return BIT4_0;
888 if (cur.mask1 & (1 << port_count()))
889 return BIT4_1;
890 if (cur.maskx & (1 << port_count()))
891 return BIT4_X;
892
893 assert(0);
894 return BIT4_X;
895 }
896
897 return BIT4_X;
898 }
899
vvp_udp_fun_core(vvp_net_t * net,vvp_udp_s * def)900 vvp_udp_fun_core::vvp_udp_fun_core(vvp_net_t*net, vvp_udp_s*def)
901 : vvp_wide_fun_core(net, def->port_count())
902 {
903 def_ = def;
904 cur_out_ = def_->get_init();
905 // Assume initially that all the inputs are 1'bx
906 current_.mask0 = 0;
907 current_.mask1 = 0;
908 current_.maskx = ~ ((-1UL) << port_count());
909
910 // If the initial value is 0 or 1, schedule the initial assignment
911 // normally, so that any sensitive always processes can be started
912 // first.
913 if (cur_out_ != BIT4_X)
914 schedule_generic(this, 0, false);
915 else
916 schedule_functor(this);
917 }
918
~vvp_udp_fun_core()919 vvp_udp_fun_core::~vvp_udp_fun_core()
920 {
921 }
922
923 /*
924 * This method is used to propagate the initial value on startup.
925 */
run_run()926 void vvp_udp_fun_core::run_run()
927 {
928 vvp_vector4_t tmp (1);
929 tmp.set_bit(0, cur_out_);
930 propagate_vec4(tmp);
931 }
932
recv_vec4_from_inputs(unsigned port)933 void vvp_udp_fun_core::recv_vec4_from_inputs(unsigned port)
934 {
935 /* For now, assume udps are 1-bit wide. */
936 assert(value(port).size() == 1);
937
938 unsigned long mask = 1UL << port;
939
940 udp_levels_table prev = current_;
941
942 switch (value(port).value(0)) {
943
944 case BIT4_0:
945 current_.mask0 |= mask;
946 current_.mask1 &= ~mask;
947 current_.maskx &= ~mask;
948 break;
949 case BIT4_1:
950 current_.mask0 &= ~mask;
951 current_.mask1 |= mask;
952 current_.maskx &= ~mask;
953 break;
954 default:
955 current_.mask0 &= ~mask;
956 current_.mask1 &= ~mask;
957 current_.maskx |= mask;
958 break;
959 }
960
961 vvp_bit4_t out_bit = def_->calculate_output(current_, prev, cur_out_);
962
963 if (out_bit == cur_out_)
964 return;
965
966 cur_out_ = out_bit;
967 schedule_functor(this);
968 }
969
970
971 /*
972 * This function is called by the parser in response to a .udp
973 * node. We create the nodes needed to integrate the UDP into the
974 * netlist. The definition should be parsed already.
975 */
compile_udp_functor(char * label,char * type,unsigned argc,struct symb_s * argv)976 void compile_udp_functor(char*label, char*type,
977 unsigned argc, struct symb_s*argv)
978 {
979 struct vvp_udp_s *def = udp_find(type);
980 assert(def);
981 free(type);
982
983 vvp_net_t*ptr = new vvp_net_t;
984 vvp_udp_fun_core*core = new vvp_udp_fun_core(ptr, def);
985 ptr->fun = core;
986
987 define_functor_symbol(label, ptr);
988 free(label);
989
990 wide_inputs_connect(core, argc, argv);
991 free(argv);
992 }
993