1 #ifndef IVL_vvp_net_H
2 #define IVL_vvp_net_H
3 /*
4  * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com)
5  *
6  *    This source code is free software; you can redistribute it
7  *    and/or modify it in source code form under the terms of the GNU
8  *    General Public License as published by the Free Software
9  *    Foundation; either version 2 of the License, or (at your option)
10  *    any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 # include  "config.h"
23 # include  "vpi_user.h"
24 # include  "vvp_vpi_callback.h"
25 # include  "permaheap.h"
26 # include  "vvp_object.h"
27 # include  <cstddef>
28 # include  <cstdlib>
29 # include  <cstring>
30 # include  <string>
31 # include  <new>
32 # include  <cassert>
33 
34 #ifdef HAVE_IOSFWD
35 # include  <iosfwd>
36 #else
37 class ostream;
38 #endif
39 
40 # include  "ivl_alloc.h"
41 
42 using namespace std;
43 
44 
45 /* Data types */
46 class  vvp_scalar_t;
47 
48 class vvp_vector2_t;
49 class vvp_vector4_t;
50 class vvp_vector8_t;
51 
52 /* Basic netlist types. */
53 class  vvp_net_t;
54 class  vvp_net_fun_t;
55 class  vvp_net_fil_t;
56 
57 /* Core net function types. */
58 class  vvp_fun_concat;
59 class  vvp_fun_drive;
60 class  vvp_fun_part;
61 
62 class  vvp_delay_t;
63 
64 /*
65  * Storage for items declared in automatically allocated scopes (i.e. automatic
66  * tasks and functions). The first two slots in each context are reserved for
67  * linking to other contexts. The function that adds items to a context knows
68  * this, and allocates context indices accordingly.
69  */
70 typedef void**vvp_context_t;
71 
72 typedef void*vvp_context_item_t;
73 
vvp_allocate_context(unsigned nitem)74 inline vvp_context_t vvp_allocate_context(unsigned nitem)
75 {
76       return (vvp_context_t)malloc((2 + nitem) * sizeof(void*));
77 }
78 
vvp_get_next_context(vvp_context_t context)79 inline vvp_context_t vvp_get_next_context(vvp_context_t context)
80 {
81       return (vvp_context_t)context[0];
82 }
83 
vvp_set_next_context(vvp_context_t context,vvp_context_t next)84 inline void vvp_set_next_context(vvp_context_t context, vvp_context_t next)
85 {
86       context[0] = next;
87 }
88 
vvp_get_stacked_context(vvp_context_t context)89 inline vvp_context_t vvp_get_stacked_context(vvp_context_t context)
90 {
91       return (vvp_context_t)context[1];
92 }
93 
vvp_set_stacked_context(vvp_context_t context,vvp_context_t stack)94 inline void vvp_set_stacked_context(vvp_context_t context, vvp_context_t stack)
95 {
96       context[1] = stack;
97 }
98 
vvp_get_context_item(vvp_context_t context,unsigned item_idx)99 inline vvp_context_item_t vvp_get_context_item(vvp_context_t context,
100                                                unsigned item_idx)
101 {
102       return (vvp_context_item_t)context[item_idx];
103 }
104 
vvp_set_context_item(vvp_context_t context,unsigned item_idx,vvp_context_item_t item)105 inline void vvp_set_context_item(vvp_context_t context, unsigned item_idx,
106                                  vvp_context_item_t item)
107 {
108       context[item_idx] = item;
109 }
110 
111 /*
112  * An "automatic" functor is one which may be associated with an automatically
113  * allocated scope item. This provides the infrastructure needed to allocate
114  * the state information for individual instances of the item.
115  */
116 struct automatic_hooks_s {
117 
automatic_hooks_sautomatic_hooks_s118       automatic_hooks_s() {}
~automatic_hooks_sautomatic_hooks_s119       virtual ~automatic_hooks_s() {}
120 
121       virtual void alloc_instance(vvp_context_t context) = 0;
122       virtual void reset_instance(vvp_context_t context) = 0;
123 #ifdef CHECK_WITH_VALGRIND
124       virtual void free_instance(vvp_context_t context) = 0;
125 #endif
126 };
127 
128 /*
129  * This is the set of Verilog 4-value bit values. Scalars have this
130  * value along with strength, vectors are a collection of these
131  * values. The enumeration has fixed numeric values that can be
132  * expressed in 2 real bits, so that some of the internal classes can
133  * pack them tightly.
134  *
135  * WARNING: Many things rely on this encoding for the BIT4_* enumeration
136  * values, so accept that these values are cast in stone.
137  */
138 enum vvp_bit4_t {
139       BIT4_0 = 0,
140       BIT4_1 = 1,
141       BIT4_X = 3,
142       BIT4_Z = 2
143 };
144 
145   /* Return an ASCII character that represents the vvp_bit4_t value. */
vvp_bit4_to_ascii(vvp_bit4_t a)146 inline char vvp_bit4_to_ascii(vvp_bit4_t a) { return "01zx"[a]; }
147 
148 extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
149 
150 extern vvp_bit4_t scalar_to_bit4(PLI_INT32 scalar);
151 
152   /* Return TRUE if the bit is BIT4_X or BIT4_Z. The fast
153      implementation here relies on the encoding of vvp_bit4_t values. */
bit4_is_xz(vvp_bit4_t a)154 inline bool bit4_is_xz(vvp_bit4_t a) { return a >= 2; }
155 
156   /* This function converts BIT4_Z to BIT4_X, but passes other values
157      unchanged. This fast implementation relies of the encoding of the
158      vvp_bit4_t values. In particular, the BIT4_X==3 and BIT4_Z==2 */
bit4_z2x(vvp_bit4_t a)159 inline vvp_bit4_t bit4_z2x(vvp_bit4_t a)
160 { return (vvp_bit4_t) ( (int)a | ((int)a >> 1) ); }
161 
162   /* Some common boolean operators. These implement the Verilog rules
163      for 4-value bit operations. The fast implementations here rely
164      on the encoding of vvp_bit4_t values. */
165 
166   // ~BIT4_0 --> BIT4_1
167   // ~BIT4_1 --> BIT4_0
168   // ~BIT4_X --> BIT4_X
169   // ~BIT4_Z --> BIT4_X
170 inline vvp_bit4_t operator ~ (vvp_bit4_t a)
171 { return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); }
172 
173 inline vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
174 {
175       if (a==BIT4_1 || b==BIT4_1)
176 	    return BIT4_1;
177       return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
178 }
179 
180 inline vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
181 {
182       if (a==BIT4_0 || b==BIT4_0)
183 	    return BIT4_0;
184       return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
185 }
186 
187 
188 extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b);
189 extern ostream& operator<< (ostream&o, vvp_bit4_t a);
190 
191   /* Return >0, ==0 or <0 if the from-to transition represents a
192      posedge, no edge, or negedge. */
193 extern int edge(vvp_bit4_t from, vvp_bit4_t to);
194 
195   /* Support for $countdrivers. */
update_driver_counts(vvp_bit4_t bit,unsigned counts[3])196 inline void update_driver_counts(vvp_bit4_t bit, unsigned counts[3])
197 {
198       switch (bit) {
199           case BIT4_0:
200             counts[0] += 1;
201             break;
202           case BIT4_1:
203             counts[1] += 1;
204             break;
205           case BIT4_X:
206             counts[2] += 1;
207             break;
208           default:
209             break;
210       }
211 }
212 
213 /*
214  * Some of the instructions do wide addition to arrays of long. They
215  * use this add_with_carry function to help.
216  */
add_with_carry(unsigned long a,unsigned long b,unsigned long & carry)217 static inline unsigned long add_with_carry(unsigned long a, unsigned long b,
218 					   unsigned long&carry)
219 {
220       unsigned long tmp = b + carry;
221       unsigned long sum = a + tmp;
222       carry = 0;
223       if (tmp < b)
224 	    carry = 1;
225       if (sum < tmp)
226 	    carry = 1;
227       if (sum < a)
228 	    carry = 1;
229       return sum;
230 }
231 
232 extern unsigned long multiply_with_carry(unsigned long a, unsigned long b,
233 					 unsigned long&carry);
234 
235 /*
236  * This class represents scalar values collected into vectors. The
237  * vector values can be accessed individually, or treated as a
238  * unit. in any case, the elements of the vector are addressed from
239  * zero(LSB) to size-1(MSB).
240  *
241  * No strength values are stored here, if strengths are needed, use a
242  * collection of vvp_scalar_t objects instead.
243  */
244 class vvp_vector4_t {
245 
246       friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
247       friend class vvp_vector4array_t;
248       friend class vvp_vector4array_sa;
249       friend class vvp_vector4array_aa;
250 
251     public:
252       static const vvp_vector4_t nil;
253 
254     public:
255       explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
256 
257       explicit vvp_vector4_t(unsigned size, double val);
258 
259 	// Construct a vector4 from the subvalue of another
260 	// vector4. The width of the result is 'wid', and the bits are
261 	// pulled from 'that' to implement the Verilog part select
262 	// semantics. This means that part select beyond 'that'
263 	// returns X bits.
264       explicit vvp_vector4_t(const vvp_vector4_t&that,
265 			     unsigned adr, unsigned wid);
266 
267       vvp_vector4_t(const vvp_vector4_t&that);
268       vvp_vector4_t(const vvp_vector4_t&that, bool invert_flag);
269       vvp_vector4_t& operator= (const vvp_vector4_t&that);
270 
271       ~vvp_vector4_t();
272 
size()273       inline unsigned size() const { return size_; }
274       void resize(unsigned new_size, vvp_bit4_t pad_bit = BIT4_X);
275 
276 	// Get the bit at the specified address
277       vvp_bit4_t value(unsigned idx) const;
278 	// Get the vector4 subvector starting at the address
279       vvp_vector4_t subvalue(unsigned idx, unsigned size) const;
280 	// Get the 2-value bits for the subvector. This returns a new
281 	// array of longs, or a nil pointer if an XZ bit was detected
282 	// in the array.
283       unsigned long*subarray(unsigned idx, unsigned size, bool xz_to_0 =false) const;
284       void setarray(unsigned idx, unsigned size, const unsigned long*val);
285 
286 	// Set a 4-value bit or subvector into the vector. Return true
287 	// if any bits of the vector change as a result of this operation.
288       void set_bit(unsigned idx, vvp_bit4_t val);
289       bool set_vec(unsigned idx, const vvp_vector4_t&that);
290 
291         // Get the bits from another vector, but keep my size.
292       void copy_bits(const vvp_vector4_t&that);
293 
294 	// Move bits within this vector.
295       void mov(unsigned dst, unsigned src, unsigned cnt);
296 
297 	// Add that to this in the Verilog way.
298       void add(const vvp_vector4_t&that);
299 
300 	// Subtract that from this in the Verilog way.
301       void sub(const vvp_vector4_t&that);
302 
303 	// Multiply this by that in the Verilog way.
304       void mul(const vvp_vector4_t&that);
305 
306 	// Test that the vectors are exactly equal
307       bool eeq(const vvp_vector4_t&that) const;
308 
309 	// Test that the vectors are equal, with xz comparing as equal.
310       bool eq_xz(const vvp_vector4_t&that) const;
311 
312 	// Return true if there is an X or Z anywhere in the vector.
313       bool has_xz() const;
314 
315 	// Change all Z bits to X bits.
316       void change_z2x();
317 
318 	// Change all bits to X bits.
319       void set_to_x();
320 
321 	// Display the value into the buf as a string.
322       char*as_string(char*buf, size_t buf_len) const;
323 
324       void invert();
325       vvp_vector4_t& operator &= (const vvp_vector4_t&that);
326       vvp_vector4_t& operator |= (const vvp_vector4_t&that);
327       vvp_vector4_t& operator += (int64_t);
328 
329     private:
330 	// Number of vvp_bit4_t bits that can be shoved into a word.
331       enum { BITS_PER_WORD = 8*sizeof(unsigned long) };
332 	// The double value constructor requires that WORD_0_BBITS
333 	// and WORD_1_BBITS have the same value!
334 #if SIZEOF_UNSIGNED_LONG == 8
335       enum { WORD_0_ABITS = 0x0000000000000000UL,
336 	     WORD_0_BBITS = 0x0000000000000000UL };
337       enum { WORD_1_ABITS = 0xFFFFFFFFFFFFFFFFUL,
338 	     WORD_1_BBITS = 0x0000000000000000UL };
339       enum { WORD_X_ABITS = 0xFFFFFFFFFFFFFFFFUL,
340 	     WORD_X_BBITS = 0xFFFFFFFFFFFFFFFFUL };
341       enum { WORD_Z_ABITS = 0x0000000000000000UL,
342              WORD_Z_BBITS = 0xFFFFFFFFFFFFFFFFUL };
343 #elif SIZEOF_UNSIGNED_LONG == 4
344       enum { WORD_0_ABITS = 0x00000000UL, WORD_0_BBITS = 0x00000000UL };
345       enum { WORD_1_ABITS = 0xFFFFFFFFUL, WORD_1_BBITS = 0x00000000UL };
346       enum { WORD_X_ABITS = 0xFFFFFFFFUL, WORD_X_BBITS = 0xFFFFFFFFUL };
347       enum { WORD_Z_ABITS = 0x00000000UL, WORD_Z_BBITS = 0xFFFFFFFFUL };
348 #else
349 #error "WORD_X_xBITS not defined for this architecture?"
350 #endif
351 
352 	// Initialize and operator= use this private method to copy
353 	// the data from that object into this object.
354       void copy_from_(const vvp_vector4_t&that);
355       void copy_from_big_(const vvp_vector4_t&that);
356       void copy_inverted_from_(const vvp_vector4_t&that);
357 
358       void allocate_words_(unsigned long inita, unsigned long initb);
359 
360 	// Values in the vvp_vector4_t are stored split across two
361 	// arrays. For each bit in the vector, there is an abit and a
362 	// bbit. the encoding of a vvp_vector4_t is:
363 	//
364 	//         abit bbit
365 	//         ---- ----
366 	// BIT4_0    0    0   (Note that for BIT4_0 and BIT4_1, the bbit
367 	// BIT4_1    1    0    value is 0. This makes detecting XZ fast.)
368 	// BIT4_X    1    1
369 	// BIT4_Z    0    1
370 
371       unsigned size_;
372       union {
373 	    unsigned long abits_val_;
374 	    unsigned long*abits_ptr_;
375       };
376       union {
377 	    unsigned long bbits_val_;
378 	    unsigned long*bbits_ptr_;
379       };
380 };
381 
vvp_vector4_t(const vvp_vector4_t & that)382 inline vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that)
383 {
384       copy_from_(that);
385 }
386 
vvp_vector4_t(const vvp_vector4_t & that,bool invert_flag)387 inline vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that, bool invert_flag)
388 {
389       if (invert_flag)
390 	    copy_inverted_from_(that);
391       else
392 	    copy_from_(that);
393 }
394 
vvp_vector4_t(unsigned size__,vvp_bit4_t val)395 inline vvp_vector4_t::vvp_vector4_t(unsigned size__, vvp_bit4_t val)
396 : size_(size__)
397 {
398 	/* note: this relies on the bit encoding for the vvp_bit4_t. */
399       static const unsigned long init_atable[4] = {
400 	    WORD_0_ABITS,
401 	    WORD_1_ABITS,
402 	    WORD_Z_ABITS,
403 	    WORD_X_ABITS };
404       static const unsigned long init_btable[4] = {
405 	    WORD_0_BBITS,
406 	    WORD_1_BBITS,
407 	    WORD_Z_BBITS,
408 	    WORD_X_BBITS };
409 
410       allocate_words_(init_atable[val], init_btable[val]);
411 }
412 
~vvp_vector4_t()413 inline vvp_vector4_t::~vvp_vector4_t()
414 {
415       if (size_ > BITS_PER_WORD) {
416 	    delete[] abits_ptr_;
417 	      // bbits_ptr_ actually points half-way into a
418 	      // double-length array started at abits_ptr_
419       }
420 }
421 
422 inline vvp_vector4_t& vvp_vector4_t::operator= (const vvp_vector4_t&that)
423 {
424       if (this == &that)
425 	    return *this;
426 
427       if (size_ > BITS_PER_WORD)
428 	    delete[] abits_ptr_;
429 
430       copy_from_(that);
431 
432       return *this;
433 }
434 
copy_from_(const vvp_vector4_t & that)435 inline void vvp_vector4_t::copy_from_(const vvp_vector4_t&that)
436 {
437       size_ = that.size_;
438       if (size_ <= BITS_PER_WORD) {
439 	    abits_val_ = that.abits_val_;
440 	    bbits_val_ = that.bbits_val_;
441       } else {
442 	    copy_from_big_(that);
443       }
444 }
445 
value(unsigned idx)446 inline vvp_bit4_t vvp_vector4_t::value(unsigned idx) const
447 {
448       if (idx >= size_)
449 	    return BIT4_X;
450 
451       unsigned off;
452 
453       unsigned long abits, bbits;
454       if (size_ > BITS_PER_WORD) {
455 	    unsigned wdx = idx / BITS_PER_WORD;
456 	    off = idx % BITS_PER_WORD;
457 	    abits = abits_ptr_[wdx];
458 	    bbits = bbits_ptr_[wdx];
459       } else {
460 	    off = idx;
461 	    abits = abits_val_;
462 	    bbits = bbits_val_;
463       }
464 
465       abits >>= off;
466       bbits >>= off;
467       int tmp = ((bbits&1) << 1) + (abits&1);
468 	// This cast works since b==1,a==1 is X and b==1,a==0 is Z.
469       return (vvp_bit4_t)tmp;
470 }
471 
subvalue(unsigned adr,unsigned wid)472 inline vvp_vector4_t vvp_vector4_t::subvalue(unsigned adr, unsigned wid) const
473 {
474       return vvp_vector4_t(*this, adr, wid);
475 }
476 
set_bit(unsigned idx,vvp_bit4_t val)477 inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
478 {
479       assert(idx < size_);
480 
481       unsigned long off = idx % BITS_PER_WORD;
482       unsigned long mask = 1UL << off;
483 
484       if (size_ > BITS_PER_WORD) {
485 	    unsigned wdx = idx / BITS_PER_WORD;
486 	    switch (val) {
487 		case BIT4_0:
488 		  abits_ptr_[wdx] &= ~mask;
489 		  bbits_ptr_[wdx] &= ~mask;
490 		  break;
491 		case BIT4_1:
492 		  abits_ptr_[wdx] |=  mask;
493 		  bbits_ptr_[wdx] &= ~mask;
494 		  break;
495 		case BIT4_X:
496 		  abits_ptr_[wdx] |=  mask;
497 		  bbits_ptr_[wdx] |=  mask;
498 		  break;
499 		case BIT4_Z:
500 		  abits_ptr_[wdx] &= ~mask;
501 		  bbits_ptr_[wdx] |=  mask;
502 		  break;
503 	    }
504       } else {
505 	    switch (val) {
506 		case BIT4_0:
507 		  abits_val_ &= ~mask;
508 		  bbits_val_ &= ~mask;
509 		  break;
510 		case BIT4_1:
511 		  abits_val_ |=  mask;
512 		  bbits_val_ &= ~mask;
513 		  break;
514 		case BIT4_X:
515 		  abits_val_ |=  mask;
516 		  bbits_val_ |=  mask;
517 		  break;
518 		case BIT4_Z:
519 		  abits_val_ &= ~mask;
520 		  bbits_val_ |=  mask;
521 		  break;
522 	    }
523       }
524 }
525 
526 inline vvp_vector4_t operator ~ (const vvp_vector4_t&that)
527 {
528       vvp_vector4_t res (that, true);
529       return res;
530 }
531 
532 extern ostream& operator << (ostream&, const vvp_vector4_t&);
533 
534 extern vvp_bit4_t compare_gtge(const vvp_vector4_t&a,
535 			       const vvp_vector4_t&b,
536 			       vvp_bit4_t val_if_equal);
537 extern vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
538 				      const vvp_vector4_t&b,
539 				      vvp_bit4_t val_if_equal);
540 template <class T> extern T coerce_to_width(const T&that, unsigned width);
541 
542 /*
543  * These functions extract the value of the vector as a native type,
544  * if possible, and return true to indicate success. If the vector has
545  * any X or Z bits, the resulting value will have 0 bits in their
546  * place (this follows the rules of Verilog conversions from vector4
547  * to real and integers) and the return value becomes false to
548  * indicate an error.
549  *
550  * The "is_arithmetic" flag true will cause a result to be entirely 0
551  * if any bits are X/Z. That is normally what you want if this value
552  * is in the midst of an arithmetic expression. If is_arithmetic=false
553  * then the X/Z bits will be replaced with 0 bits, and the return
554  * value will be "false", but the other bits will be transferred. This
555  * is what you want if you are doing "vpi_get_value", for example.
556  */
557 template <class T> extern bool vector4_to_value(const vvp_vector4_t&a, T&val,
558 						bool is_signed,
559 						bool is_arithmetic =true);
560 
561 template <class T> extern bool vector4_to_value(const vvp_vector4_t&a,
562                                                 bool&overflow_flag, T&val);
563 
vector4_to_value(const vvp_vector4_t & a,T & val)564 template <class T> inline bool vector4_to_value(const vvp_vector4_t&a, T&val)
565 {
566       bool overflow_flag;
567       return vector4_to_value(a, overflow_flag, val);
568 }
569 
570 extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
571 
572 extern bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed);
573 
574 extern vvp_vector4_t vector4_from_text(const char*bits, unsigned wid);
575 
576 
577 /*
578  * vvp_vector4array_t
579  */
580 class vvp_vector4array_t {
581 
582     public:
583       vvp_vector4array_t(unsigned width, unsigned words);
584       virtual ~vvp_vector4array_t();
585 
width()586       unsigned width() const { return width_; }
words()587       unsigned words() const { return words_; }
588 
589       virtual vvp_vector4_t get_word(unsigned idx) const = 0;
590       virtual void set_word(unsigned idx, const vvp_vector4_t&that) = 0;
591 
592     protected:
593       struct v4cell {
594 	    union {
595 		  unsigned long abits_val_;
596 		  unsigned long*abits_ptr_;
597 	    };
598 	    union {
599 		  unsigned long bbits_val_;
600 		  unsigned long*bbits_ptr_;
601 	    };
602       };
603 
604       vvp_vector4_t get_word_(v4cell*cell) const;
605       void set_word_(v4cell*cell, const vvp_vector4_t&that);
606 
607       unsigned width_;
608       unsigned words_;
609 
610     private: // Not implemented
611       vvp_vector4array_t(const vvp_vector4array_t&);
612       vvp_vector4array_t& operator = (const vvp_vector4array_t&);
613 };
614 
615 /*
616  * Statically allocated vvp_vector4array_t
617  */
618 class vvp_vector4array_sa : public vvp_vector4array_t {
619 
620     public:
621       vvp_vector4array_sa(unsigned width, unsigned words);
622       ~vvp_vector4array_sa();
623 
624       vvp_vector4_t get_word(unsigned idx) const;
625       void set_word(unsigned idx, const vvp_vector4_t&that);
626 
627     private:
628       v4cell* array_;
629 };
630 
631 /*
632  * Automatically allocated vvp_vector4array_t
633  */
634 class vvp_vector4array_aa : public vvp_vector4array_t, public automatic_hooks_s {
635 
636     public:
637       vvp_vector4array_aa(unsigned width, unsigned words);
638       ~vvp_vector4array_aa();
639 
640       void alloc_instance(vvp_context_t context);
641       void reset_instance(vvp_context_t context);
642 #ifdef CHECK_WITH_VALGRIND
643       void free_instance(vvp_context_t context);
644 #endif
645 
646       vvp_vector4_t get_word(unsigned idx) const;
647       void set_word(unsigned idx, const vvp_vector4_t&that);
648 
649     private:
650       unsigned context_idx_;
651 };
652 
653 /* vvp_vector2_t
654  */
655 class vvp_vector2_t {
656 
657       friend vvp_vector2_t operator - (const vvp_vector2_t&);
658       friend vvp_vector2_t operator + (const vvp_vector2_t&,
659 				       const vvp_vector2_t&);
660       friend vvp_vector2_t operator * (const vvp_vector2_t&,
661 				       const vvp_vector2_t&);
662       friend bool operator >  (const vvp_vector2_t&, const vvp_vector2_t&);
663       friend bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
664       friend bool operator <  (const vvp_vector2_t&, const vvp_vector2_t&);
665       friend bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
666       friend bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
667 
668     public:
669       vvp_vector2_t();
670       vvp_vector2_t(const vvp_vector2_t&);
671       vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
672       vvp_vector2_t(const vvp_vector2_t&, unsigned base, unsigned wid);
673 	// Make a vvp_vector2_t from a vvp_vector4_t. If enable_NaN
674 	// is true and there are X or Z bits, then the result becomes
675 	// a NaN value. If enable_NaN is false then X or Z bits are
676 	// converted to 0 as per the standard Verilog rules.
677       vvp_vector2_t(const vvp_vector4_t&that, bool allow_NaN = false);
678 	// Make from a native long and a specified width.
679       vvp_vector2_t(unsigned long val, unsigned wid);
680 	// Make with the width, and filled with 1 or 0 bits.
681       enum fill_t {FILL0, FILL1};
682       vvp_vector2_t(fill_t fill, unsigned wid);
683       ~vvp_vector2_t();
684 
685       vvp_vector2_t&operator += (const vvp_vector2_t&that);
686       vvp_vector2_t&operator -= (const vvp_vector2_t&that);
687       vvp_vector2_t&operator <<= (unsigned shift);
688       vvp_vector2_t&operator >>= (unsigned shift);
689       vvp_vector2_t&operator = (const vvp_vector2_t&);
690 
691 	// Assign a vec4 to a vec2, using Verilog rules for converting
692 	// XZ values to 0.
693       vvp_vector2_t&operator = (const vvp_vector4_t&);
694 
695       bool is_NaN() const;
696       bool is_zero() const;
697       unsigned size() const;
698       int value(unsigned idx) const;
699       vvp_bit4_t value4(unsigned idx) const;
700 	// Get the vector2 subvector starting at the address
701       vvp_vector2_t subvalue(unsigned idx, unsigned size) const;
702       void set_bit(unsigned idx, int bit);
703       void set_vec(unsigned idx, const vvp_vector2_t&that);
704 	// Make the size just big enough to hold the first 1 bit.
705       void trim();
706 	// Trim off extra 1 bit since this is representing a negative value.
707 	// Always keep at least 32 bits.
708       void trim_neg();
709 
710     private:
711       enum { BITS_PER_WORD = 8 * sizeof(unsigned long) };
712       unsigned long*vec_;
713       unsigned wid_;
714 
715     private:
716       void copy_from_that_(const vvp_vector2_t&that);
717       void copy_from_that_(const vvp_vector4_t&that);
718 };
719 
720 extern bool operator >  (const vvp_vector2_t&, const vvp_vector2_t&);
721 extern bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
722 extern bool operator <  (const vvp_vector2_t&, const vvp_vector2_t&);
723 extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
724 extern bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
725 extern vvp_vector2_t operator - (const vvp_vector2_t&);
726 extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&);
727 extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&);
728 extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&);
729 extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&);
730 
731 vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&);
732 extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid);
733 
734 /* A c4string is of the form C4<...> where ... are bits. */
735 extern bool c4string_test(const char*str);
736 extern vvp_vector4_t c4string_to_vector4(const char*str);
737 
738 /* A crstring is of the form Cr<...> where ... defines are real. */
739 extern bool crstring_test(const char*str);
740 extern double crstring_to_double(const char*str);
741 
742 extern ostream& operator<< (ostream&, const vvp_vector2_t&);
743 
vvp_vector2_t(const vvp_vector2_t & that)744 inline vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
745 {
746       copy_from_that_(that);
747 }
748 
vvp_vector2_t(const vvp_vector4_t & that,bool enable_NaN)749 inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that, bool enable_NaN)
750 {
751       if (enable_NaN && that.has_xz()) {
752 	    vec_ = 0;
753 	    wid_ = 0;
754 	    return;
755       }
756       copy_from_that_(that);
757 }
758 
~vvp_vector2_t()759 inline vvp_vector2_t::~vvp_vector2_t()
760 {
761       delete[] vec_;
762 }
763 
764 /* Inline some of the vector2_t methods. */
size()765 inline unsigned vvp_vector2_t::size() const
766 {
767       return wid_;
768 }
769 
value4(unsigned idx)770 inline vvp_bit4_t vvp_vector2_t::value4(unsigned idx) const
771 {
772       if (value(idx))
773 	    return BIT4_1;
774       else
775 	    return BIT4_0;
776 }
777 
subvalue(unsigned base,unsigned wid)778 inline vvp_vector2_t vvp_vector2_t::subvalue(unsigned base, unsigned wid) const
779 {
780       return vvp_vector2_t(*this, base, wid);
781 }
782 
783 /*
784  * This class represents a scalar value with strength. These are
785  * heavier than the simple vvp_bit4_t, but more information is
786  * carried by that weight.
787  *
788  * The strength values are as defined here:
789  *   HiZ    - 0
790  *   Small  - 1
791  *   Medium - 2
792  *   Weak   - 3
793  *   Large  - 4
794  *   Pull   - 5
795  *   Strong - 6
796  *   Supply - 7
797  *
798  * There are two strengths for a value: strength0 and strength1. If
799  * the value is Z, then strength0 is the strength of the 0-value, and
800  * strength of the 1-value. If the value is 0 or 1, then the strengths
801  * are the range for that value.
802  */
803 class vvp_scalar_t {
804 
805       friend vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b);
806 
807     public:
808 	// Make a HiZ value.
809       explicit vvp_scalar_t();
810 
811 	// Make an unambiguous value.
812       explicit vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1);
813 
814 	// Get the vvp_bit4_t version of the value
815       vvp_bit4_t value() const;
816       unsigned strength0() const;
817       unsigned strength1() const;
818 
eeq(vvp_scalar_t that)819       bool eeq(vvp_scalar_t that) const { return value_ == that.value_; }
is_hiz()820       bool is_hiz() const { return (value_ & 0x77) == 0; }
821 
822     private:
823 	// This class and the vvp_vector8_t class are closely related,
824 	// so allow vvp_vector8_t access to the raw encoding so that
825 	// it can do compact vectoring of vvp_scalar_t objects.
826       friend class vvp_vector8_t;
vvp_scalar_t(unsigned char val)827       explicit vvp_scalar_t(unsigned char val) : value_(val) { }
raw()828       unsigned char raw() const { return value_; }
829 
830     private:
831       unsigned char value_;
832 };
833 
vvp_scalar_t()834 inline vvp_scalar_t::vvp_scalar_t()
835 {
836       value_ = 0;
837 }
838 
vvp_scalar_t(vvp_bit4_t val,unsigned str0,unsigned str1)839 inline vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1)
840 {
841       assert(str0 <= 7);
842       assert(str1 <= 7);
843 
844       if (str0 == 0 && str1 == 0) {
845 	    value_ = 0x00;
846       } else switch (val) {
847 	  case BIT4_0:
848 	    value_ = str0 | (str0<<4);
849 	    break;
850 	  case BIT4_1:
851 	    value_ = str1 | (str1<<4) | 0x88;
852 	    break;
853 	  case BIT4_X:
854 	    value_ = str0 | (str1<<4) | 0x80;
855 	    break;
856 	  case BIT4_Z:
857 	    value_ = 0x00;
858 	    break;
859       }
860 }
861 
value()862 inline vvp_bit4_t vvp_scalar_t::value() const
863 {
864       if ((value_ & 0x77) == 0) {
865 	    return BIT4_Z;
866       } else switch (value_ & 0x88) {
867 	  case 0x00:
868 	    return BIT4_0;
869 	  case 0x88:
870 	    return BIT4_1;
871 	  default:
872 	    return BIT4_X;
873       }
874 }
875 
876 
resolve(vvp_scalar_t a,vvp_scalar_t b)877 inline vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
878 {
879       extern vvp_scalar_t fully_featured_resolv_(vvp_scalar_t, vvp_scalar_t);
880 
881 	// If the value is HiZ, resolution is simply a matter of
882 	// returning the *other* value.
883       if (a.is_hiz())
884 	    return b;
885       if (b.is_hiz())
886 	    return a;
887 	// If the values are the identical, then resolution is simply
888 	// returning *either* value.
889       if (a .eeq( b ))
890 	    return a;
891 
892       return fully_featured_resolv_(a,b);
893 }
894 
895 extern ostream& operator<< (ostream&, vvp_scalar_t);
896 
897 /*
898  * This class is a way to carry vectors of strength modeled
899  * values. The 8 in the name is the number of possible distinct values
900  * a well defined bit may have. When you add in ambiguous values, the
901  * number of distinct values span the vvp_scalar_t.
902  *
903  * A vvp_vector8_t object can be created from a vvp_vector4_t and a
904  * strength value. The vvp_vector8_t bits have the values of the input
905  * vector, all with the strength specified. If no strength is
906  * specified, then the conversion from bit4 to a scalar will use the
907  * Verilog convention default of strong (6).
908  */
909 class vvp_vector8_t {
910 
911       friend vvp_vector8_t part_expand(const vvp_vector8_t&, unsigned, unsigned);
912 
913     public:
914       explicit vvp_vector8_t(unsigned size =0);
915 	// Make a vvp_vector8_t from a vector4 and a specified
916 	// strength.
917       explicit vvp_vector8_t(const vvp_vector4_t&that,
918 			     unsigned str0,
919 			     unsigned str1);
920       explicit vvp_vector8_t(const vvp_vector2_t&that,
921 			     unsigned str0,
922 			     unsigned str1);
923 
924       ~vvp_vector8_t();
925 
926       static const vvp_vector8_t nil;
927 
928     public:
929 
size()930       unsigned size() const { return size_; }
931       vvp_scalar_t value(unsigned idx) const;
932       vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
933       void set_bit(unsigned idx, vvp_scalar_t val);
934       void set_vec(unsigned idx, const vvp_vector8_t&that);
935 
936 	// Test that the vectors are exactly equal
937       bool eeq(const vvp_vector8_t&that) const;
938 
939       vvp_vector8_t(const vvp_vector8_t&that);
940       vvp_vector8_t& operator= (const vvp_vector8_t&that);
941 
942     private:
943       unsigned size_;
944       union {
945 	    unsigned char*ptr_;
946 	    unsigned char val_[sizeof(void*)];
947       };
948 };
949 
950   /* Resolve uses the default Verilog resolver algorithm to resolve
951      two drive vectors to a single output. */
resolve(const vvp_vector8_t & a,const vvp_vector8_t & b)952 inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
953 {
954       assert(a.size() == b.size());
955       vvp_vector8_t out (a.size());
956 
957       for (unsigned idx = 0 ;  idx < out.size() ;  idx += 1) {
958 	    out.set_bit(idx, resolve(a.value(idx), b.value(idx)));
959       }
960 
961       return out;
962 }
963 
964   /* This lookup tabke implements the strength reduction implied by
965      Verilog standard switch devices. The major dimension selects
966      between non-resistive and resistive devices. */
967 extern unsigned vvp_switch_strength_map[2][8];
968 
969   /* The reduce4 function converts a vector8 to a vector4, losing
970      strength information in the process. */
971 extern vvp_vector4_t reduce4(const vvp_vector8_t&that);
972 extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned off);
973 
974   /* A c8string is of the form C8<...> where ... are bits. */
975 extern bool c8string_test(const char*str);
976 extern vvp_vector8_t c8string_to_vector8(const char*str);
977 
978   /* Print a vector8 value to a stream. */
979 extern ostream& operator<< (ostream&, const vvp_vector8_t&);
980 
vvp_vector8_t(unsigned size__)981 inline vvp_vector8_t::vvp_vector8_t(unsigned size__)
982 : size_(size__)
983 {
984       if (size_ <= sizeof(val_)) {
985 	    memset(val_, 0, sizeof(val_));
986       } else {
987 	    ptr_ = new unsigned char[size_];
988 	    memset(ptr_, 0, size_);
989       }
990 }
991 
~vvp_vector8_t()992 inline vvp_vector8_t::~vvp_vector8_t()
993 {
994       if (size_ > sizeof(val_))
995 	    delete[]ptr_;
996 }
997 
value(unsigned idx)998 inline vvp_scalar_t vvp_vector8_t::value(unsigned idx) const
999 {
1000       assert(idx < size_);
1001       if (size_ <= sizeof(val_))
1002 	    return vvp_scalar_t(val_[idx]);
1003       else
1004 	    return vvp_scalar_t(ptr_[idx]);
1005 }
1006 
set_bit(unsigned idx,vvp_scalar_t val)1007 inline void vvp_vector8_t::set_bit(unsigned idx, vvp_scalar_t val)
1008 {
1009       assert(idx < size_);
1010       if (size_ <= sizeof(val_))
1011 	    val_[idx] = val.raw();
1012       else
1013 	    ptr_[idx] = val.raw();
1014 }
1015 
1016   // Exactly-equal for vvp_vector8_t is common and should be as tight
1017   // as possible.
eeq(const vvp_vector8_t & that)1018 inline bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const
1019 {
1020       if (size_ != that.size_)
1021 	    return false;
1022       if (size_ == 0)
1023 	    return true;
1024 
1025       if (size_ <= sizeof(val_))
1026 	      // This is equivalent to memcmp(val_, that.val_, sizeof val_)==0
1027 	    return ptr_ == that.ptr_;
1028       else
1029 	    return memcmp(ptr_, that.ptr_, size_) == 0;
1030 }
1031 
1032 /*
1033  * This class implements a pointer that points to an item within a
1034  * target. The ptr() method returns a pointer to the vvp_net_t, and
1035  * the port() method returns a 0-3 value that selects the input within
1036  * the vvp_net_t. Use this pointer to point only to the inputs of
1037  * vvp_net_t objects. To point to vvp_net_t objects as a whole, use
1038  * vvp_net_t* pointers.
1039  *
1040  * Alert! Ugly details. Protective clothing recommended!
1041  * The vvp_net_ptr_t encodes the bits of a C pointer, and two bits of
1042  * port identifier into an unsigned long. This works only if vvp_net_t*
1043  * values are always aligned on 4-byte boundaries.
1044  */
1045 template <class T> class vvp_sub_pointer_t {
1046 
1047     public:
vvp_sub_pointer_t()1048       vvp_sub_pointer_t() : bits_(0) { }
1049 
vvp_sub_pointer_t(T * ptr__,unsigned port__)1050       vvp_sub_pointer_t(T*ptr__, unsigned port__)
1051       {
1052 	    bits_ = reinterpret_cast<uintptr_t> (ptr__);
1053 	    assert( (bits_  &  3) == 0 );
1054 	    assert( (port__ & ~3) == 0 );
1055 	    bits_ |= port__;
1056       }
1057 
~vvp_sub_pointer_t()1058       ~vvp_sub_pointer_t() { }
1059 
ptr()1060       T* ptr()
1061       { return reinterpret_cast<T*> (bits_ & ~3UL); }
1062 
ptr()1063       const T* ptr() const
1064       { return reinterpret_cast<const T*> (bits_ & ~3UL); }
1065 
port()1066       unsigned  port() const { return bits_ & 3; }
1067 
nil()1068       bool nil() const { return bits_ == 0; }
1069 
1070       bool operator == (vvp_sub_pointer_t that) const { return bits_ == that.bits_; }
1071       bool operator != (vvp_sub_pointer_t that) const { return bits_ != that.bits_; }
1072 
1073     private:
1074       uintptr_t bits_;
1075 };
1076 
1077 typedef vvp_sub_pointer_t<vvp_net_t> vvp_net_ptr_t;
1078 template <class T> ostream& operator << (ostream&out, vvp_sub_pointer_t<T> val)
1079 { out << val.ptr() << "[" << val.port() << "]"; return out; }
1080 
1081 /*
1082  * This is the basic unit of netlist connectivity. It is a fan-in of
1083  * up to 4 inputs, and output pointer, and a pointer to the node's
1084  * functionality.
1085  *
1086  * A net output that is non-nil points to the input of one of its
1087  * destination nets. If there are multiple destinations, then the
1088  * referenced input port points to the next input. For example:
1089  *
1090  *   +--+--+--+--+---+
1091  *   |  |  |  |  | . |  Output from this vvp_net_t points to...
1092  *   +--+--+--+--+-|-+
1093  *                 |
1094  *                /
1095  *               /
1096  *              /
1097  *             |
1098  *             v
1099  *   +--+--+--+--+---+
1100  *   |  |  |  |  | . |  ... the fourth input of this vvp_net_t, and...
1101  *   +--+--+--+--+-|-+
1102  *             |   |
1103  *            /    .
1104  *           /     .
1105  *          |      .
1106  *          v
1107  *   +--+--+--+--+---+
1108  *   |  |  |  |  | . |  ... the third input of this vvp_net_t.
1109  *   +--+--+--+--+-|-+
1110  *
1111  * Thus, the fan-in of a vvp_net_t node is limited to 4 inputs, but
1112  * the fan-out is unlimited.
1113  *
1114  * The vvp_send_*() functions take as input a vvp_net_ptr_t and follow
1115  * all the fan-out chain, delivering the specified value. The send_*()
1116  * methods of the vvp_net_t class are similar, but they follow the
1117  * output, possibly filtered, from the vvp_net_t.
1118  */
1119 class vvp_net_t {
1120     public:
1121       vvp_net_t();
1122 
1123 #ifdef CHECK_WITH_VALGRIND
1124       vvp_net_t *pool;
1125 #endif
1126       vvp_net_ptr_t port[4];
1127       vvp_net_fun_t*fun;
1128       vvp_net_fil_t*fil;
1129 
1130     public:
1131 	// Connect the port to the output from this net.
1132       void link(vvp_net_ptr_t port);
1133 	// Disconnect the port from the output of this net.
1134       void unlink(vvp_net_ptr_t port);
1135 
1136     public: // Methods to propagate output from this node.
1137       void send_vec4(const vvp_vector4_t&val, vvp_context_t context);
1138       void send_vec8(const vvp_vector8_t&val);
1139       void send_real(double val, vvp_context_t context);
1140       void send_long(long val);
1141       void send_string(const std::string&val, vvp_context_t context);
1142       void send_object(vvp_object_t val, vvp_context_t context);
1143 
1144       void send_vec4_pv(const vvp_vector4_t&val,
1145 			unsigned base, unsigned wid, unsigned vwid,
1146 			vvp_context_t context);
1147       void send_vec8_pv(const vvp_vector8_t&val,
1148 			unsigned base, unsigned wid, unsigned vwid);
1149 
1150 
1151     public: // Methods to arrange for the output of this net to be forced.
1152 
1153 	// The intent is that all efforts at force are directed to
1154 	// operate only on the vvp_net_t whose output is to be
1155 	// forced. These methods then communicate the force to the
1156 	// attached filter to set up the actual force.
1157       void force_vec4(const vvp_vector4_t&val, const vvp_vector2_t&mask);
1158       void force_vec8(const vvp_vector8_t&val, const vvp_vector2_t&mask);
1159       void force_real(double val, const vvp_vector2_t&mask);
1160 
1161     public: // Method to support $countdrivers
1162       void count_drivers(unsigned idx, unsigned counts[4]);
1163 
1164     private:
1165       vvp_net_ptr_t out_;
1166 
1167     public: // Need a better new for these objects.
1168       static void* operator new(std::size_t size);
1169       static void operator delete(void*); // not implemented
1170     private: // not implemented
1171       static void* operator new[](std::size_t size);
1172 #if defined(__GNUC__)
1173       static void operator delete[](void*);
1174 #endif
1175 };
1176 
1177 /*
1178  * Instances of this class represent the functionality of a
1179  * node. vvp_net_t objects hold pointers to the vvp_net_fun_t
1180  * associated with it. Objects of this type take inputs that arrive at
1181  * a port and perform some sort of action in response.
1182  *
1183  * Whenever a bit is delivered to a vvp_net_t object, the associated
1184  * vvp_net_fun_t::recv_*() method is invoked with the port pointer and
1185  * the bit value. The port pointer is used to figure out which exact
1186  * input receives the bit.
1187  *
1188  * In this context, a "bit" is the thing that arrives at a single
1189  * input. The bit may be a single data bit, a bit vector, various
1190  * sorts of numbers or aggregate objects.
1191  *
1192  * recv_vec4 is the most common way for a datum to arrive at a
1193  * port. The value is a vvp_vector4_t.
1194  *
1195  * Most nodes do not care about the specific strengths of bits, so the
1196  * default behavior for recv_vec8 and recv_vec8_pv is to reduce the
1197  * operand to a vvp_vector4_t and pass it on to the recv_vec4 or
1198  * recv_vec4_pv method.
1199  *
1200  * The recv_vec4, recv_vec4_pv, and recv_real methods are also
1201  * passed a context pointer. When the received bit has propagated
1202  * from a statically allocated node, this will be a null pointer.
1203  * When the received bit has propagated from an automatically
1204  * allocated node, this will be a pointer to the context that
1205  * contains the instance of that bit that has just been modified.
1206  * When the received bit was from a procedural assignment or from
1207  * a VPI set_value() operation, this will be a pointer to the
1208  * writable context associated with the currently running thread.
1209  */
1210 class vvp_net_fun_t {
1211 
1212     public:
1213       vvp_net_fun_t();
1214       virtual ~vvp_net_fun_t();
1215 
1216       virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1217                              vvp_context_t context);
1218       virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
1219       virtual void recv_real(vvp_net_ptr_t port, double bit,
1220                              vvp_context_t context);
1221       virtual void recv_long(vvp_net_ptr_t port, long bit);
1222       virtual void recv_string(vvp_net_ptr_t port, const std::string&bit,
1223 			       vvp_context_t context);
1224       virtual void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
1225 			       vvp_context_t context);
1226 
1227 	// Part select variants of above
1228       virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
1229 				unsigned base, unsigned wid, unsigned vwid,
1230                                 vvp_context_t context);
1231       virtual void recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit,
1232 				unsigned base, unsigned wid, unsigned vwid);
1233       virtual void recv_long_pv(vvp_net_ptr_t port, long bit,
1234                                 unsigned base, unsigned wid);
1235 
1236 	// This method is called when the net is forced or
1237 	// released. This is very rarely needed; island ports use it
1238 	// to know that the net is being forced and that it needs to
1239 	// do something about it.
1240       virtual void force_flag(bool run_now);
1241 
1242    protected:
1243       void recv_vec4_pv_(vvp_net_ptr_t p, const vvp_vector4_t&bit,
1244 			 unsigned base, unsigned wid, unsigned vwid,
1245                          vvp_context_t context);
1246       void recv_vec8_pv_(vvp_net_ptr_t p, const vvp_vector8_t&bit,
1247 			 unsigned base, unsigned wid, unsigned vwid);
1248 
1249     public: // These objects are only permallocated.
new(std::size_t size)1250       static void* operator new(std::size_t size) { return heap_.alloc(size); }
1251       static void operator delete(void*); // not implemented
1252 
heap_total()1253       static std::size_t heap_total() { return heap_.heap_total(); }
1254 
1255     protected:
1256       static permaheap heap_;
1257 
1258     private: // not implemented
1259       vvp_net_fun_t(const vvp_net_fun_t&);
1260       vvp_net_fun_t& operator= (const vvp_net_fun_t&);
1261       static void* operator new[](std::size_t size);
1262       static void operator delete[](void*);
1263 };
1264 
1265 /*
1266  * A vvp_net_fil_t is a filter object that filters an output from a
1267  * vvp_net_t. The send_*() methods of the vvp_net_t object invoke the
1268  * filter of the output being transmitted. The filter function will
1269  * decide if this value is to be propagated, and how, and return a
1270  * prop_t enumeration to reflect the choice.
1271  *
1272  * The filter object also provides an implementation hooks for
1273  * force/release.
1274  */
1275 class vvp_net_fil_t  : public vvp_vpi_callback {
1276 
1277     public:
1278       vvp_net_fil_t();
1279       virtual ~vvp_net_fil_t();
1280 
1281     public:
1282       enum prop_t { STOP=0, PROP, REPL };
1283 
1284 
1285 	// These filter methods are used by the vvp_net_t::send_*()
1286 	// methods to test the output (from the functor) bit value
1287 	// against any force filters. If none of the bits are forced,
1288 	// then the method returns PROP and the caller propagates the
1289 	// bit value. If bits were changed by the force mask, then the
1290 	// method returns REPL and the caller should propagate the rep
1291 	// value instead. If the function returns STOP, then all the
1292 	// output bits are filtered by the force mask and there is
1293 	// nothing to propagate.
1294       virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
1295 				 unsigned base, unsigned vwid);
1296       virtual prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
1297 				 unsigned base, unsigned vwid);
1298       virtual prop_t filter_real(double&val);
1299       virtual prop_t filter_long(long&val);
1300       virtual prop_t filter_object(vvp_object_t&val);
1301       virtual prop_t filter_string(const std::string&val);
1302 
1303       virtual void release(vvp_net_ptr_t ptr, bool net_flag) =0;
1304       virtual void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag) =0;
1305 
1306 	// The %force/link instruction needs a place to write the
1307 	// source node of the force, so that subsequent %force and
1308 	// %release instructions can undo the link as needed. */
1309       void force_link(vvp_net_t*dst, vvp_net_t*src);
1310       void force_unlink(void);
1311 
1312       virtual unsigned filter_size() const =0;
1313 
1314     public:
1315 	// Support for force methods. These are called by the
1316 	// vvp_net_t::force_* methods to set the force value and mask
1317 	// for the filter.
1318       virtual void force_fil_vec4(const vvp_vector4_t&val, const vvp_vector2_t&mask) =0;
1319       virtual void force_fil_vec8(const vvp_vector8_t&val, const vvp_vector2_t&mask) =0;
1320       virtual void force_fil_real(double val, const vvp_vector2_t&mask) =0;
1321 
1322     public: // These objects are only permallocated.
new(std::size_t size)1323       static void* operator new(std::size_t size) { return heap_.alloc(size); }
1324       static void operator delete(void*); // not implemented
1325 
heap_total()1326       static size_t heap_total() { return heap_.heap_total(); }
1327 
1328     private:
1329       static permaheap heap_;
1330 
1331     private: // not implemented
1332       vvp_net_fil_t(const vvp_net_fil_t&);
1333       vvp_net_fil_t& operator= (const vvp_net_fil_t&);
1334       static void* operator new[](std::size_t size);
1335       static void operator delete[](void*);
1336 
1337     protected:
1338 	// Set bits of the filter force mask
1339       void force_mask(const vvp_vector2_t&mask);
1340 	// Release the force on the bits set in the mask.
1341       void release_mask(const vvp_vector2_t&mask);
1342 	// Test bits of the filter force mask;
1343       bool test_force_mask(unsigned bit) const;
1344       bool test_force_mask_is_zero() const;
1345 
1346 	// This template method is used by derived classes to process
1347 	// the val through the force mask. The force value is the
1348 	// currently forced value, and the buf is a value that this
1349 	// method will use to hold a filtered value, if needed. This
1350 	// method returns the replacement value into the "rep"
1351 	// argument and returns a code indicating whether any changes
1352 	// were made.
1353       template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
1354 	// This template method is similar to the above, but works for
1355 	// native types that are not so expensive to edit in place.
1356       template <class T> prop_t filter_mask_(T&val, T force);
1357 
1358 	// These templates are similar to filter_mask_, but are
1359 	// idempotent. Then do not trigger callbacks or otherwise
1360 	// cause any local changes. These methods are used to test
1361 	// arbitrary values against the force mask.
1362       template <class T> prop_t filter_input_mask_(const T&val, const T&force, T&rep) const;
1363 
1364     private:
1365 	// Mask of forced bits
1366       vvp_vector2_t force_mask_;
1367 	// True if the next filter must propagate. Need this to allow
1368 	// the forced value to get through.
1369       bool force_propagate_;
1370 	// force link back.
1371       class vvp_net_t*force_link_;
1372 };
1373 
1374 /* **** Some core net functions **** */
1375 
1376 /* vvp_fun_concat
1377  * This node function creates vectors (vvp_vector4_t) from the
1378  * concatenation of the inputs. The inputs (4) may be vector or
1379  * vector8 objects, but they are reduced to vector4 values and
1380  * strength information lost.
1381  *
1382  * The expected widths of the input vectors must be given up front so
1383  * that the positions in the output vector (and also the size of the
1384  * output vector) can be worked out. The input vectors must match the
1385  * expected width.
1386  */
1387 class vvp_fun_concat  : public vvp_net_fun_t {
1388 
1389     public:
1390       vvp_fun_concat(unsigned w0, unsigned w1,
1391 		     unsigned w2, unsigned w3);
1392       ~vvp_fun_concat();
1393 
1394       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1395                      vvp_context_t context);
1396 
1397       void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1398 			unsigned base, unsigned wid, unsigned vwid,
1399                         vvp_context_t);
1400     private:
1401       unsigned wid_[4];
1402       vvp_vector4_t val_;
1403 };
1404 
1405 class vvp_fun_concat8  : public vvp_net_fun_t {
1406 
1407     public:
1408       vvp_fun_concat8(unsigned w0, unsigned w1,
1409 		     unsigned w2, unsigned w3);
1410       ~vvp_fun_concat8();
1411 
1412       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1413                      vvp_context_t context);
1414       void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
1415 
1416       void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1417 			unsigned base, unsigned wid, unsigned vwid,
1418                         vvp_context_t);
1419       void recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit,
1420 			unsigned base, unsigned wid, unsigned vwid);
1421 
1422     private:
1423       unsigned wid_[4];
1424       vvp_vector8_t val_;
1425 };
1426 
1427 /*
1428  * The vvp_fun_force class objects are net functors that use their input
1429  * to force the associated filter. They do not actually  have an
1430  * output, they instead drive the force_* methods of the net filter.
1431  *
1432  * This functor is also special in that we know a priori that only
1433  * port-0 is used, so we can use ports 1-3 for local storage. See the
1434  * implementation of vvp_filter_wire_base::force_link in
1435  * vvp_net_sig.cc for details.
1436  */
1437 class vvp_fun_force : public vvp_net_fun_t {
1438 
1439     public:
1440       vvp_fun_force();
1441       ~vvp_fun_force();
1442 
1443       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1444 		     vvp_context_t context);
1445       void recv_real(vvp_net_ptr_t port, double bit, vvp_context_t);
1446 };
1447 
1448 /* vvp_fun_repeat
1449  * This node function create vectors by repeating the input. The width
1450  * is the width of the output vector, and the repeat is the number of
1451  * times to repeat the input. The width of the input vector is
1452  * implicit from these values.
1453  */
1454 class vvp_fun_repeat  : public vvp_net_fun_t {
1455 
1456     public:
1457       vvp_fun_repeat(unsigned width, unsigned repeat);
1458       ~vvp_fun_repeat();
1459 
1460       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1461                      vvp_context_t context);
1462 
1463     private:
1464       unsigned wid_;
1465       unsigned rep_;
1466 };
1467 
1468 /* vvp_fun_drive
1469  * This node function takes an input vvp_vector4_t as input, and
1470  * repeats that value as a vvp_vector8_t with all the bits given the
1471  * strength of the drive. This is the way vvp_scalar8_t objects are
1472  * created. Input 0 is the value to be driven (vvp_vector4_t) and
1473  * inputs 1 and two are the strength0 and strength1 values to use. The
1474  * strengths may be taken as constant values, or adjusted as longs
1475  * from the network.
1476  *
1477  * This functor only propagates vvp_vector8_t values.
1478  */
1479 class vvp_fun_drive  : public vvp_net_fun_t {
1480 
1481     public:
1482       vvp_fun_drive(unsigned str0 =6, unsigned str1 =6);
1483       ~vvp_fun_drive();
1484 
1485       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1486                      vvp_context_t context);
1487 	//void recv_long(vvp_net_ptr_t port, long bit);
1488 
1489       void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1490 			unsigned base, unsigned wid, unsigned vwid,
1491                         vvp_context_t);
1492     private:
1493       unsigned char drive0_;
1494       unsigned char drive1_;
1495 };
1496 
1497 /*
1498  * EXTEND functors expand an input vector to the desired output
1499  * width. The extend_signed functor sign extends the input. If the
1500  * input is already wider than the desired output, then it is passed
1501  * unmodified.
1502  */
1503 class vvp_fun_extend_signed  : public vvp_net_fun_t {
1504 
1505     public:
1506       explicit vvp_fun_extend_signed(unsigned wid);
1507       ~vvp_fun_extend_signed();
1508 
1509       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1510                      vvp_context_t context);
1511 
1512       void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1513 			unsigned base, unsigned wid, unsigned vwid,
1514                         vvp_context_t);
1515     private:
1516       unsigned width_;
1517 };
1518 
1519 /*
1520  * Wide Functors:
1521  * Wide functors represent special devices that may have more than 4
1522  * input ports. These devices need a set of N/4 actual functors to
1523  * catch the inputs, and use another to deliver the output.
1524  *
1525  *  vvp_wide_fun_t --+--> vvp_wide_fun_core --> ...
1526  *                   |
1527  *  vvp_wide_fun_t --+
1528  *                   |
1529  *  vvp_wide_fun_t --+
1530  *
1531  * There are enough input functors to take all the functor inputs, 4
1532  * per functor. These inputs deliver the changed input value to the
1533  * wide_fun_core, which carries the infrastructure for the thread. The
1534  * wide_fun_core is also a functor whose output is connected to the rest
1535  * of the netlist. This is where the result is delivered back to the
1536  * netlist.
1537  *
1538  * The vvp_wide_fun_core keeps a store of the inputs from all the
1539  * input functors, and makes them available to the derived class that
1540  * does the processing.
1541  */
1542 
1543 class vvp_wide_fun_core : public vvp_net_fun_t {
1544 
1545     public:
1546       vvp_wide_fun_core(vvp_net_t*net, unsigned nports);
1547       virtual ~vvp_wide_fun_core();
1548 	// These objects are not perm allocated.
new(std::size_t size)1549       void* operator new(std::size_t size) { return ::new char[size]; }
delete(void * ptr)1550       void operator delete(void* ptr) { ::delete[]((char*)ptr); }
1551 
1552     protected:
1553       void propagate_vec4(const vvp_vector4_t&bit, vvp_time64_t delay =0);
1554       void propagate_real(double bit, vvp_time64_t delay =0);
1555       unsigned port_count() const;
1556 
1557       vvp_vector4_t& value(unsigned);
1558       double value_r(unsigned);
1559 
1560     private:
1561 	// the derived class implements this to receive an indication
1562 	// that one of the port input values changed.
1563       virtual void recv_vec4_from_inputs(unsigned port) =0;
1564       virtual void recv_real_from_inputs(unsigned port);
1565 
1566       friend class vvp_wide_fun_t;
1567       void dispatch_vec4_from_input_(unsigned port, vvp_vector4_t bit);
1568       void dispatch_real_from_input_(unsigned port, double bit);
1569 
1570     private:
1571 	// Back-point to the vvp_net_t that points to me.
1572       vvp_net_t*ptr_;
1573 	// Structure to track the input values from the input functors.
1574       unsigned nports_;
1575       vvp_vector4_t*port_values_;
1576       double*port_rvalues_;
1577 };
1578 
1579 /*
1580  * The job of the input functor is only to monitor inputs to the
1581  * function and pass them to the ufunc_core object. Each functor takes
1582  * up to 4 inputs, with the base the port number for the first
1583  * function input that this functor represents.
1584  */
1585 class vvp_wide_fun_t : public vvp_net_fun_t {
1586 
1587     public:
1588       vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base);
1589       ~vvp_wide_fun_t();
1590 
1591       void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1592                      vvp_context_t context);
1593       void recv_real(vvp_net_ptr_t port, double bit,
1594                      vvp_context_t context);
1595 
1596       void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
1597 			unsigned base, unsigned wid, unsigned vwid,
1598                         vvp_context_t context);
1599 
1600     private:
1601       vvp_wide_fun_core*core_;
1602       unsigned port_base_;
1603 };
1604 
1605 
vvp_send_vec4(vvp_net_ptr_t ptr,const vvp_vector4_t & val,vvp_context_t context)1606 inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val, vvp_context_t context)
1607 {
1608       while (class vvp_net_t*cur = ptr.ptr()) {
1609 	    vvp_net_ptr_t next = cur->port[ptr.port()];
1610 
1611 	    if (cur->fun)
1612 		  cur->fun->recv_vec4(ptr, val, context);
1613 
1614 	    ptr = next;
1615       }
1616 }
1617 
1618 extern void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val);
1619 extern void vvp_send_real(vvp_net_ptr_t ptr, double val,
1620                           vvp_context_t context);
1621 extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
1622 extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
1623                              unsigned base, unsigned width);
1624 
vvp_send_string(vvp_net_ptr_t ptr,const std::string & val,vvp_context_t context)1625 inline void vvp_send_string(vvp_net_ptr_t ptr, const std::string&val, vvp_context_t context)
1626 {
1627       while (vvp_net_t*cur = ptr.ptr()) {
1628 	    vvp_net_ptr_t next = cur->port[ptr.port()];
1629 
1630 	    if (cur->fun)
1631 		  cur->fun->recv_string(ptr, val, context);
1632 
1633 	    ptr = next;
1634       }
1635 }
1636 
vvp_send_object(vvp_net_ptr_t ptr,vvp_object_t val,vvp_context_t context)1637 inline void vvp_send_object(vvp_net_ptr_t ptr, vvp_object_t val, vvp_context_t context)
1638 {
1639       while (vvp_net_t*cur = ptr.ptr()) {
1640 	    vvp_net_ptr_t next = cur->port[ptr.port()];
1641 
1642 	    if (cur->fun)
1643 		  cur->fun->recv_object(ptr, val, context);
1644 
1645 	    ptr = next;
1646       }
1647 }
1648 
1649 /*
1650  * Part-vector versions of above functions. This function uses the
1651  * corresponding recv_vec4_pv method in the vvp_net_fun_t functor to
1652  * deliver parts of a vector.
1653  *
1654  * The ptr is the destination input port to write to.
1655  *
1656  * <val> is the vector to be written. The width of this vector must
1657  * exactly match the <wid> vector.
1658  *
1659  * The <base> is where in the receiver the bit vector is to be
1660  * written. This address is given in canonical units; 0 is the LSB, 1
1661  * is the next bit, and so on.
1662  *
1663  * The <vwid> is the width of the destination vector that this part is
1664  * part of. This is used by intermediate nodes, i.e. resolvers, to
1665  * know how wide to pad with Z, if it needs to transform the part to a
1666  * mirror of the destination vector.
1667  */
vvp_send_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & val,unsigned base,unsigned wid,unsigned vwid,vvp_context_t context)1668 inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
1669 			     unsigned base, unsigned wid, unsigned vwid,
1670 			     vvp_context_t context)
1671 {
1672       while (class vvp_net_t*cur = ptr.ptr()) {
1673 	    vvp_net_ptr_t next = cur->port[ptr.port()];
1674 
1675 	    if (cur->fun)
1676 		  cur->fun->recv_vec4_pv(ptr, val, base, wid, vwid, context);
1677 
1678 	    ptr = next;
1679       }
1680 }
1681 
vvp_send_vec8_pv(vvp_net_ptr_t ptr,const vvp_vector8_t & val,unsigned base,unsigned wid,unsigned vwid)1682 inline void vvp_send_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&val,
1683 			     unsigned base, unsigned wid, unsigned vwid)
1684 {
1685       while (class vvp_net_t*cur = ptr.ptr()) {
1686 	    vvp_net_ptr_t next = cur->port[ptr.port()];
1687 
1688 	    if (cur->fun)
1689 		  cur->fun->recv_vec8_pv(ptr, val, base, wid, vwid);
1690 
1691 	    ptr = next;
1692       }
1693 }
1694 
send_vec4(const vvp_vector4_t & val,vvp_context_t context)1695 inline void vvp_net_t::send_vec4(const vvp_vector4_t&val, vvp_context_t context)
1696 {
1697       if (fil == 0) {
1698 	    vvp_send_vec4(out_, val, context);
1699 	    return;
1700       }
1701 
1702       vvp_vector4_t rep;
1703       switch (fil->filter_vec4(val, rep, 0, val.size())) {
1704 	  case vvp_net_fil_t::STOP:
1705 	    break;
1706 	  case vvp_net_fil_t::PROP:
1707 	    vvp_send_vec4(out_, val, context);
1708 	    break;
1709 	  case vvp_net_fil_t::REPL:
1710 	    vvp_send_vec4(out_, rep, context);
1711 	    break;
1712       }
1713 }
1714 
send_vec4_pv(const vvp_vector4_t & val,unsigned base,unsigned wid,unsigned vwid,vvp_context_t context)1715 inline void vvp_net_t::send_vec4_pv(const vvp_vector4_t&val,
1716 				    unsigned base, unsigned wid, unsigned vwid,
1717 				    vvp_context_t context)
1718 {
1719       if (fil == 0) {
1720 	    vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
1721 	    return;
1722       }
1723 
1724       assert(val.size() == wid);
1725       vvp_vector4_t rep;
1726       switch (fil->filter_vec4(val, rep, base, vwid)) {
1727 	  case vvp_net_fil_t::STOP:
1728 	    break;
1729 	  case vvp_net_fil_t::PROP:
1730 	    vvp_send_vec4_pv(out_, val, base, wid, vwid, context);
1731 	    break;
1732 	  case vvp_net_fil_t::REPL:
1733 	    vvp_send_vec4_pv(out_, rep, base, wid, vwid, context);
1734 	    break;
1735       }
1736 }
1737 
send_vec8(const vvp_vector8_t & val)1738 inline void vvp_net_t::send_vec8(const vvp_vector8_t&val)
1739 {
1740       if (fil == 0) {
1741 	    vvp_send_vec8(out_, val);
1742 	    return;
1743       }
1744 
1745       vvp_vector8_t rep;
1746       switch (fil->filter_vec8(val, rep, 0, val.size())) {
1747 	  case vvp_net_fil_t::STOP:
1748 	    break;
1749 	  case vvp_net_fil_t::PROP:
1750 	    vvp_send_vec8(out_, val);
1751 	    break;
1752 	  case vvp_net_fil_t::REPL:
1753 	    vvp_send_vec8(out_, rep);
1754 	    break;
1755       }
1756 }
1757 
send_vec8_pv(const vvp_vector8_t & val,unsigned base,unsigned wid,unsigned vwid)1758 inline void vvp_net_t::send_vec8_pv(const vvp_vector8_t&val,
1759 				    unsigned base, unsigned wid, unsigned vwid)
1760 {
1761       if (fil == 0) {
1762 	    vvp_send_vec8_pv(out_, val, base, wid, vwid);
1763 	    return;
1764       }
1765 
1766       assert(val.size() == wid);
1767       vvp_vector8_t rep;
1768       switch (fil->filter_vec8(val, rep, base, vwid)) {
1769 	  case vvp_net_fil_t::STOP:
1770 	    break;
1771 	  case vvp_net_fil_t::PROP:
1772 	    vvp_send_vec8_pv(out_, val, base, wid, vwid);
1773 	    break;
1774 	  case vvp_net_fil_t::REPL:
1775 	    vvp_send_vec8_pv(out_, rep, base, wid, vwid);
1776 	    break;
1777       }
1778 }
1779 
send_real(double val,vvp_context_t context)1780 inline void vvp_net_t::send_real(double val, vvp_context_t context)
1781 {
1782       if (fil && ! fil->filter_real(val))
1783 	    return;
1784 
1785       vvp_send_real(out_, val, context);
1786 }
1787 
1788 
send_string(const std::string & val,vvp_context_t context)1789 inline void vvp_net_t::send_string(const std::string&val, vvp_context_t context)
1790 {
1791       if (fil && !fil->filter_string(val))
1792 	    return;
1793 
1794       vvp_send_string(out_, val, context);
1795 }
1796 
1797 
send_object(vvp_object_t val,vvp_context_t context)1798 inline void vvp_net_t::send_object(vvp_object_t val, vvp_context_t context)
1799 {
1800       if (fil && ! fil->filter_object(val))
1801 	    return;
1802 
1803       vvp_send_object(out_, val, context);
1804 }
1805 
1806 
test_force_mask(unsigned bit)1807 inline bool vvp_net_fil_t::test_force_mask(unsigned bit) const
1808 {
1809       if (bit >= force_mask_.size())
1810 	    return false;
1811       if (force_mask_.value(bit))
1812 	    return true;
1813       else
1814 	    return false;
1815 }
1816 
test_force_mask_is_zero(void)1817 inline bool vvp_net_fil_t::test_force_mask_is_zero(void) const
1818 {
1819       if (force_mask_.size() == 0)
1820 	    return true;
1821       if (force_mask_.is_zero())
1822 	    return true;
1823       return false;
1824 }
1825 
1826 /*
1827  * Undefine the ivl_alloc.h definitions so they don't leak out of this file.
1828  */
1829 #undef malloc
1830 #undef realloc
1831 #undef calloc
1832 #undef __ivl_alloc_H
1833 
1834 #endif /* IVL_vvp_net_H */
1835