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