1 /*
2 * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com)
3 *
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "config.h"
21 # include "vvp_net.h"
22 # include "vvp_net_sig.h"
23 # include "vvp_island.h"
24 # include "vpi_priv.h"
25 # include "resolv.h"
26 # include "schedule.h"
27 # include "statistics.h"
28 # include <cstdio>
29 # include <cstring>
30 # include <cstdlib>
31 # include <iostream>
32 # include <typeinfo>
33 # include <climits>
34 # include <cmath>
35 # include <cassert>
36 #ifdef CHECK_WITH_VALGRIND
37 # include <valgrind/memcheck.h>
38 # include <map>
39 # include "sfunc.h"
40 # include "udp.h"
41 # include "ivl_alloc.h"
42 #endif
43
44 /* This is the size of an unsigned long in bits. This is just a
45 convenience macro. */
46 # define CPU_WORD_BITS (8*sizeof(unsigned long))
47 # define TOP_BIT (1UL << (CPU_WORD_BITS-1))
48
49 permaheap vvp_net_fun_t::heap_;
50 permaheap vvp_net_fil_t::heap_;
51
52 // Allocate around 1Megabyte/chunk.
53 static const size_t VVP_NET_CHUNK = 1024*1024/sizeof(vvp_net_t);
54 static vvp_net_t*vvp_net_alloc_table = NULL;
55 #ifdef CHECK_WITH_VALGRIND
56 static vvp_net_t **vvp_net_pool = NULL;
57 static unsigned vvp_net_pool_count = 0;
58 #endif
59 static size_t vvp_net_alloc_remaining = 0;
60 // For statistics, count the vvp_nets allocated and the bytes of alloc
61 // chunks allocated.
62 unsigned long count_vvp_nets = 0;
63 size_t size_vvp_nets = 0;
64
operator new(size_t size)65 void* vvp_net_t::operator new (size_t size)
66 {
67 assert(size == sizeof(vvp_net_t));
68 if (vvp_net_alloc_remaining == 0) {
69 vvp_net_alloc_table = ::new vvp_net_t[VVP_NET_CHUNK];
70 vvp_net_alloc_remaining = VVP_NET_CHUNK;
71 size_vvp_nets += size*VVP_NET_CHUNK;
72 #ifdef CHECK_WITH_VALGRIND
73 VALGRIND_MAKE_MEM_NOACCESS(vvp_net_alloc_table, size*VVP_NET_CHUNK);
74 VALGRIND_CREATE_MEMPOOL(vvp_net_alloc_table, 0, 0);
75 vvp_net_pool_count += 1;
76 vvp_net_pool = (vvp_net_t **) realloc(vvp_net_pool,
77 vvp_net_pool_count*sizeof(vvp_net_t **));
78 vvp_net_pool[vvp_net_pool_count-1] = vvp_net_alloc_table;
79 #endif
80 }
81
82 vvp_net_t*return_this = vvp_net_alloc_table;
83 #ifdef CHECK_WITH_VALGRIND
84 VALGRIND_MEMPOOL_ALLOC(vvp_net_pool[vvp_net_pool_count-1],
85 return_this, size);
86 return_this->pool = vvp_net_pool[vvp_net_pool_count-1];
87 #endif
88 vvp_net_alloc_table += 1;
89 vvp_net_alloc_remaining -= 1;
90 count_vvp_nets += 1;
91 return return_this;
92 }
93
94 #ifdef CHECK_WITH_VALGRIND
95 static map<vvp_net_t*, bool> vvp_net_map;
96 static map<sfunc_core*, bool> sfunc_map;
97 static map<vvp_udp_fun_core*, bool> udp_map;
98 static map<resolv_core*, bool> resolv_map;
99 static vvp_net_t **local_net_pool = 0;
100 static unsigned local_net_pool_count = 0;
101
pool_local_net(vvp_net_t * net)102 void pool_local_net(vvp_net_t*net)
103 {
104 local_net_pool_count += 1;
105 local_net_pool = (vvp_net_t **) realloc(local_net_pool,
106 local_net_pool_count*sizeof(vvp_net_t **));
107 local_net_pool[local_net_pool_count-1] = net;
108 }
109
vvp_net_delete(vvp_net_t * item)110 void vvp_net_delete(vvp_net_t *item)
111 {
112 vvp_net_map[item] = true;
113 if (sfunc_core*tmp = dynamic_cast<sfunc_core*> (item->fun)) {
114 sfunc_map[tmp] = true;
115 }
116 if (vvp_udp_fun_core*tmp = dynamic_cast<vvp_udp_fun_core*> (item->fun)) {
117 udp_map[tmp] = true;
118 }
119 if (resolv_core*tmp = dynamic_cast<resolv_core*> (item->fun)) {
120 resolv_map[tmp] = true;
121 }
122 /* Only delete static object variables. */
123 if (vvp_fun_signal_object_sa*tmp = dynamic_cast<vvp_fun_signal_object_sa*> (item->fun)) {
124 delete tmp;
125 }
126 /* Only delete static string variables. */
127 if (vvp_fun_signal_string_sa*tmp = dynamic_cast<vvp_fun_signal_string_sa*> (item->fun)) {
128 delete tmp;
129 }
130 }
131
vvp_net_pool_delete()132 void vvp_net_pool_delete()
133 {
134 unsigned long vvp_nets_del = 0;
135
136 for (unsigned idx = 0; idx < local_net_pool_count; idx += 1) {
137 vvp_net_delete(local_net_pool[idx]);
138 }
139 free(local_net_pool);
140 local_net_pool = 0;
141 local_net_pool_count = 0;
142
143 map<vvp_net_t*, bool>::iterator iter;
144 for (iter = vvp_net_map.begin(); iter != vvp_net_map.end(); ++ iter ) {
145 vvp_nets_del += 1;
146 VALGRIND_MEMPOOL_FREE(iter->first->pool, iter->first);
147 }
148 vvp_net_map.clear();
149
150 map<sfunc_core*, bool>::iterator siter;
151 for (siter = sfunc_map.begin(); siter != sfunc_map.end(); ++ siter ) {
152 delete siter->first;
153 }
154 sfunc_map.clear();
155
156 map<vvp_udp_fun_core*, bool>::iterator uiter;
157 for (uiter = udp_map.begin(); uiter != udp_map.end(); ++ uiter ) {
158 delete uiter->first;
159 }
160 udp_map.clear();
161
162 map<resolv_core*, bool>::iterator riter;
163 for (riter = resolv_map.begin(); riter != resolv_map.end(); ++ riter ) {
164 delete riter->first;
165 }
166 resolv_map.clear();
167
168 if (RUNNING_ON_VALGRIND && (vvp_nets_del != count_vvp_nets)) {
169 fflush(NULL);
170 VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu net(s).",
171 (long) count_vvp_nets - vvp_nets_del,
172 count_vvp_nets);
173 }
174
175 for (unsigned idx = 0; idx < vvp_net_pool_count; idx += 1) {
176 VALGRIND_DESTROY_MEMPOOL(vvp_net_pool[idx]);
177 ::delete [] vvp_net_pool[idx];
178 }
179 free(vvp_net_pool);
180 vvp_net_pool = NULL;
181 vvp_net_pool_count = 0;
182 }
183 #endif
184
operator delete(void *)185 void vvp_net_t::operator delete(void*)
186 {
187 assert(0);
188 }
189
vvp_net_t()190 vvp_net_t::vvp_net_t()
191 : out_(vvp_net_ptr_t(0,0))
192 {
193 fun = 0;
194 fil = 0;
195 }
196
link(vvp_net_ptr_t port_to_link)197 void vvp_net_t::link(vvp_net_ptr_t port_to_link)
198 {
199 vvp_net_t*net = port_to_link.ptr();
200 net->port[port_to_link.port()] = out_;
201 out_ = port_to_link;
202 }
203
204 /*
205 * Unlink a ptr object from the driver. The input is the driver in the
206 * form of a vvp_net_t pointer. The .out member of that object is the
207 * driver. The dst_ptr argument is the receiver pin to be located and
208 * removed from the fan-out list.
209 */
unlink(vvp_net_ptr_t dst_ptr)210 void vvp_net_t::unlink(vvp_net_ptr_t dst_ptr)
211 {
212 vvp_net_t*net = dst_ptr.ptr();
213 unsigned net_port = dst_ptr.port();
214
215 if (out_ == dst_ptr) {
216 /* If the drive fan-out list starts with this pointer,
217 then the unlink is easy. Pull the list forward. */
218 out_ = net->port[net_port];
219 } else if (! out_.nil()) {
220 /* Scan the linked list, looking for the net_ptr_t
221 pointer *before* the one we wish to remove. */
222 vvp_net_ptr_t cur = out_;
223 assert(!cur.nil());
224 vvp_net_t*cur_net = cur.ptr();
225 unsigned cur_port = cur.port();
226 while (cur_net && cur_net->port[cur_port] != dst_ptr) {
227 cur = cur_net->port[cur_port];
228 cur_net = cur.ptr();
229 cur_port = cur.port();
230 }
231 /* Unlink. */
232 if (cur_net) cur_net->port[cur_port] = net->port[net_port];
233 }
234
235 net->port[net_port] = vvp_net_ptr_t(0,0);
236 }
237
count_drivers(unsigned idx,unsigned counts[4])238 void vvp_net_t::count_drivers(unsigned idx, unsigned counts[4])
239 {
240 counts[0] = 0;
241 counts[1] = 0;
242 counts[2] = 0;
243 counts[3] = 0;
244
245 /* $countdrivers can only be used on wires. */
246 vvp_wire_base*wire=dynamic_cast<vvp_wire_base*>(fil);
247 assert(wire);
248
249 if (wire->is_forced(idx))
250 counts[3] = 1;
251
252 /* If the net has multiple drivers, we need to interrogate the
253 resolver network to get the driven values. */
254 if (resolv_core*resolver = dynamic_cast<resolv_core*>(fun)) {
255 resolver->count_drivers(idx, counts);
256 return;
257 }
258 if (vvp_island_port*resolver = dynamic_cast<vvp_island_port*>(fun)) {
259 resolver->count_drivers(idx, counts);
260 return;
261 }
262
263 /* If the functor is not a resolver, there is only one driver, so
264 we can just interrogate the filter to get the driven value. */
265 update_driver_counts(wire->driven_value(idx), counts);
266 }
267
operator delete(void *)268 void vvp_net_fun_t::operator delete(void*)
269 {
270 #ifndef CHECK_WITH_VALGRIND
271 assert(0);
272 #endif
273 }
274
275
vvp_net_fil_t()276 vvp_net_fil_t::vvp_net_fil_t()
277 {
278 force_link_ = 0;
279 force_propagate_ = false;
280 count_filters += 1;
281 }
282
~vvp_net_fil_t()283 vvp_net_fil_t::~vvp_net_fil_t()
284 {
285 assert(force_link_ == 0);
286 }
287
filter_vec4(const vvp_vector4_t &,vvp_vector4_t &,unsigned,unsigned)288 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec4(const vvp_vector4_t&,
289 vvp_vector4_t&,
290 unsigned, unsigned)
291 {
292 return PROP;
293 }
294
filter_vec8(const vvp_vector8_t &,vvp_vector8_t &,unsigned,unsigned)295 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_vec8(const vvp_vector8_t&,
296 vvp_vector8_t&,
297 unsigned, unsigned)
298 {
299 return PROP;
300 }
301
filter_real(double &)302 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_real(double&)
303 {
304 return PROP;
305 }
306
filter_long(long &)307 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_long(long&)
308 {
309 return PROP;
310 }
311
filter_string(const string &)312 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_string(const string&)
313 {
314 return PROP;
315 }
316
filter_object(vvp_object_t &)317 vvp_net_fil_t::prop_t vvp_net_fil_t::filter_object(vvp_object_t&)
318 {
319 return PROP;
320 }
321
force_mask(const vvp_vector2_t & mask)322 void vvp_net_fil_t::force_mask(const vvp_vector2_t&mask)
323 {
324 if (force_mask_.size() == 0)
325 force_mask_ = vvp_vector2_t(vvp_vector2_t::FILL0, mask.size());
326
327 assert(force_mask_.size() == mask.size());
328 for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
329 if (mask.value(idx) == 0)
330 continue;
331
332 force_mask_.set_bit(idx, 1);
333 force_propagate_ = true;
334 }
335 }
336
release_mask(const vvp_vector2_t & mask)337 void vvp_net_fil_t::release_mask(const vvp_vector2_t&mask)
338 {
339 if (force_mask_.size() == 0)
340 return;
341
342 assert(force_mask_.size() == mask.size());
343 for (unsigned idx = 0 ; idx < mask.size() ; idx += 1) {
344 if (mask.value(idx))
345 force_mask_.set_bit(idx, 0);
346 }
347
348 if (force_mask_.is_zero())
349 force_mask_ = vvp_vector2_t();
350 }
351
352 /*
353 * Force link/unlink uses a thunk vvp_net_t node with a vvp_fun_force
354 * functor to translate the net values to filter commands. The ports
355 * of this vvp_net_t object are use a little differently:
356 *
357 * port[3] - Point to the destination node where the forced
358 * filter resides.
359 *
360 * port[2] - Point to the input node that drives port[0] for use
361 * by the unlink method.
362 *
363 * port[0] - This is the normal input.
364 */
force_link(vvp_net_t * dst,vvp_net_t * src)365 void vvp_net_fil_t::force_link(vvp_net_t*dst, vvp_net_t*src)
366 {
367 assert(dst->fil == this);
368
369 if (force_link_ == 0) {
370 force_link_ = new vvp_net_t;
371 // Use port[3] to hold the force destination.
372 force_link_->port[3] = vvp_net_ptr_t(dst, 0);
373 force_link_->port[2] = vvp_net_ptr_t(0,0);
374 force_link_->fun = new vvp_fun_force;
375 }
376
377 force_unlink();
378 assert(force_link_->port[2] == vvp_net_ptr_t(0,0));
379
380 // Use port[2] to hold the force source.
381 force_link_->port[2] = vvp_net_ptr_t(src,0);
382
383 vvp_net_ptr_t dst_ptr(force_link_, 0);
384 src->link(dst_ptr);
385 }
386
operator delete(void *)387 void vvp_net_fil_t::operator delete(void*)
388 {
389 assert(0);
390 }
391
force_unlink(void)392 void vvp_net_fil_t::force_unlink(void)
393 {
394 if (force_link_ == 0) return;
395 vvp_net_t*src = force_link_->port[2].ptr();
396 if (src == 0) return;
397
398 src->unlink(vvp_net_ptr_t(force_link_,0));
399 force_link_->port[2] = vvp_net_ptr_t(0,0);
400 }
401
402 /* *** BIT operations *** */
add_with_carry(vvp_bit4_t a,vvp_bit4_t b,vvp_bit4_t & c)403 vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
404 {
405 if (bit4_is_xz(a) || bit4_is_xz(b) || bit4_is_xz(c)) {
406 c = BIT4_X;
407 return BIT4_X;
408 }
409
410 // NOTE: This relies on the facts that XZ values have been
411 // weeded out, and that BIT4_1 is 1 and BIT4_0 is 0.
412 int sum = (int)a + (int)b + (int)c;
413
414 switch (sum) {
415 case 0:
416 // c must already be 0.
417 return BIT4_0;
418 case 1:
419 c = BIT4_0;
420 return BIT4_1;
421 case 2:
422 c = BIT4_1;
423 return BIT4_0;
424 case 3:
425 c = BIT4_1;
426 return BIT4_1;
427 }
428 fprintf(stderr, "Incorrect result %d.\n", sum);
429 assert(0);
430 return BIT4_X;
431 }
432
scalar_to_bit4(PLI_INT32 scalar)433 vvp_bit4_t scalar_to_bit4(PLI_INT32 scalar)
434 {
435 switch(scalar) {
436 case vpi0:
437 return BIT4_0;
438 case vpi1:
439 return BIT4_1;
440 case vpiX:
441 return BIT4_X;
442 case vpiZ:
443 return BIT4_Z;
444 }
445 fprintf(stderr, "Unsupported scalar value %d.\n", (int)scalar);
446 assert(0);
447 return BIT4_X;
448 }
449
operator ^(vvp_bit4_t a,vvp_bit4_t b)450 vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b)
451 {
452 if (bit4_is_xz(a))
453 return BIT4_X;
454 if (bit4_is_xz(b))
455 return BIT4_X;
456 if (a == BIT4_0)
457 return b;
458 if (b == BIT4_0)
459 return a;
460 return BIT4_0;
461 }
462
operator <<(ostream & out,vvp_bit4_t bit)463 ostream& operator<<(ostream&out, vvp_bit4_t bit)
464 {
465 switch (bit) {
466 case BIT4_0:
467 out << "0";
468 break;
469 case BIT4_1:
470 out << "1";
471 break;
472 case BIT4_X:
473 out << "X";
474 break;
475 case BIT4_Z:
476 out << "Z";
477 break;
478 default:
479 out << "?";
480 break;
481 }
482 return out;
483 }
484
485 typedef unsigned short edge_t;
486
VVP_EDGE(vvp_bit4_t from,vvp_bit4_t to)487 inline edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
488 {
489 return 1 << ((from << 2) | to);
490 }
491
492 const edge_t vvp_edge_posedge
493 = VVP_EDGE(BIT4_0,BIT4_1)
494 | VVP_EDGE(BIT4_0,BIT4_X)
495 | VVP_EDGE(BIT4_0,BIT4_Z)
496 | VVP_EDGE(BIT4_X,BIT4_1)
497 | VVP_EDGE(BIT4_Z,BIT4_1)
498 ;
499
500 const edge_t vvp_edge_negedge
501 = VVP_EDGE(BIT4_1,BIT4_0)
502 | VVP_EDGE(BIT4_1,BIT4_X)
503 | VVP_EDGE(BIT4_1,BIT4_Z)
504 | VVP_EDGE(BIT4_X,BIT4_0)
505 | VVP_EDGE(BIT4_Z,BIT4_0)
506 ;
507
edge(vvp_bit4_t from,vvp_bit4_t to)508 int edge(vvp_bit4_t from, vvp_bit4_t to)
509 {
510 edge_t mask = VVP_EDGE(from, to);
511 if (mask & vvp_edge_posedge)
512 return 1;
513 if (mask & vvp_edge_negedge)
514 return -1;
515 return 0;
516 }
517
multiply_with_carry(unsigned long a,unsigned long b,unsigned long & carry)518 unsigned long multiply_with_carry(unsigned long a, unsigned long b,
519 unsigned long&carry)
520 {
521 const unsigned long mask = (1UL << (CPU_WORD_BITS/2)) - 1;
522 unsigned long a0 = a & mask;
523 unsigned long a1 = (a >> (CPU_WORD_BITS/2)) & mask;
524 unsigned long b0 = b & mask;
525 unsigned long b1 = (b >> (CPU_WORD_BITS/2)) & mask;
526
527 unsigned long tmp = a0 * b0;
528
529 unsigned long r00 = tmp & mask;
530 unsigned long c00 = (tmp >> (CPU_WORD_BITS/2)) & mask;
531
532 tmp = a0 * b1;
533
534 unsigned long r01 = tmp & mask;
535 unsigned long c01 = (tmp >> (CPU_WORD_BITS/2)) & mask;
536
537 tmp = a1 * b0;
538
539 unsigned long r10 = tmp & mask;
540 unsigned long c10 = (tmp >> (CPU_WORD_BITS/2)) & mask;
541
542 tmp = a1 * b1;
543
544 unsigned long r11 = tmp & mask;
545 unsigned long c11 = (tmp >> (CPU_WORD_BITS/2)) & mask;
546
547 unsigned long r1 = c00 + r01 + r10;
548 unsigned long r2 = (r1 >> (CPU_WORD_BITS/2)) & mask;
549 r1 &= mask;
550 r2 += c01 + c10 + r11;
551 unsigned long r3 = (r2 >> (CPU_WORD_BITS/2)) & mask;
552 r2 &= mask;
553 r3 += c11;
554 r3 &= mask;
555
556 carry = (r3 << (CPU_WORD_BITS/2)) + r2;
557 return (r1 << (CPU_WORD_BITS/2)) + r00;
558 }
559
560
vvp_send_vec8(vvp_net_ptr_t ptr,const vvp_vector8_t & val)561 void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val)
562 {
563 while (vvp_net_t*cur = ptr.ptr()) {
564 vvp_net_ptr_t next = cur->port[ptr.port()];
565
566 if (cur->fun)
567 cur->fun->recv_vec8(ptr, val);
568
569 ptr = next;
570 }
571 }
572
vvp_send_real(vvp_net_ptr_t ptr,double val,vvp_context_t context)573 void vvp_send_real(vvp_net_ptr_t ptr, double val, vvp_context_t context)
574 {
575 while (vvp_net_t*cur = ptr.ptr()) {
576 vvp_net_ptr_t next = cur->port[ptr.port()];
577
578 if (cur->fun)
579 cur->fun->recv_real(ptr, val, context);
580
581 ptr = next;
582 }
583 }
584
vvp_send_long(vvp_net_ptr_t ptr,long val)585 void vvp_send_long(vvp_net_ptr_t ptr, long val)
586 {
587 while (vvp_net_t*cur = ptr.ptr()) {
588 vvp_net_ptr_t next = cur->port[ptr.port()];
589
590 if (cur->fun)
591 cur->fun->recv_long(ptr, val);
592
593 ptr = next;
594 }
595 }
596
vvp_send_long_pv(vvp_net_ptr_t ptr,long val,unsigned base,unsigned wid)597 void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
598 unsigned base, unsigned wid)
599 {
600 while (vvp_net_t*cur = ptr.ptr()) {
601 vvp_net_ptr_t next = cur->port[ptr.port()];
602
603 if (cur->fun)
604 cur->fun->recv_long_pv(ptr, val, base, wid);
605
606 ptr = next;
607 }
608 }
609
610 const vvp_vector4_t vvp_vector4_t::nil;
611
copy_bits(const vvp_vector4_t & that)612 void vvp_vector4_t::copy_bits(const vvp_vector4_t&that)
613 {
614
615 if (size_ == that.size_) {
616 if (size_ > BITS_PER_WORD) {
617 unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
618 for (unsigned idx = 0 ; idx < words ; idx += 1)
619 abits_ptr_[idx] = that.abits_ptr_[idx];
620 for (unsigned idx = 0 ; idx < words ; idx += 1)
621 bbits_ptr_[idx] = that.bbits_ptr_[idx];
622 } else {
623 abits_val_ = that.abits_val_;
624 bbits_val_ = that.bbits_val_;
625 }
626 return;
627 }
628
629 /* Now we know that the sizes of this and that are definitely
630 different. We can use that in code below. In any case, we
631 need to copy only the smaller of the sizes. */
632
633 /* If source and destination are both short, then mask/copy
634 the bit values. */
635 if (size_ <= BITS_PER_WORD && that.size_ <= BITS_PER_WORD) {
636 unsigned bits_to_copy = (that.size_ < size_) ? that.size_ : size_;
637 unsigned long mask = (1UL << bits_to_copy) - 1UL;
638 abits_val_ &= ~mask;
639 bbits_val_ &= ~mask;
640 abits_val_ |= that.abits_val_&mask;
641 bbits_val_ |= that.bbits_val_&mask;
642 return;
643 }
644
645 /* Now we know that either source or destination are long. If
646 the destination is short, then mask/copy from the low word
647 of the long source. */
648 if (size_ <= BITS_PER_WORD) {
649 abits_val_ = that.abits_ptr_[0];
650 bbits_val_ = that.bbits_ptr_[0];
651 if (size_ < BITS_PER_WORD) {
652 unsigned long mask = (1UL << size_) - 1UL;
653 abits_val_ &= mask;
654 bbits_val_ &= mask;
655 }
656 return;
657 }
658
659 /* Now we know that the destination must be long. If the
660 source is short, then mask/copy from its value. */
661 if (that.size_ <= BITS_PER_WORD) {
662 unsigned long mask;
663 if (that.size_ < BITS_PER_WORD) {
664 mask = (1UL << that.size_) - 1UL;
665 abits_ptr_[0] &= ~mask;
666 bbits_ptr_[0] &= ~mask;
667 } else {
668 mask = -1UL;
669 }
670 abits_ptr_[0] |= that.abits_val_&mask;
671 bbits_ptr_[0] |= that.bbits_val_&mask;
672 return;
673 }
674
675 /* Finally, we know that source and destination are long. copy
676 words until we get to the last. */
677 unsigned bits_to_copy = (that.size_ < size_) ? that.size_ : size_;
678 unsigned word = 0;
679 while (bits_to_copy >= BITS_PER_WORD) {
680 abits_ptr_[word] = that.abits_ptr_[word];
681 bbits_ptr_[word] = that.bbits_ptr_[word];
682 bits_to_copy -= BITS_PER_WORD;
683 word += 1;
684 }
685 if (bits_to_copy > 0) {
686 unsigned long mask = (1UL << bits_to_copy) - 1UL;
687 abits_ptr_[word] &= ~mask;
688 bbits_ptr_[word] &= ~mask;
689 abits_ptr_[word] |= that.abits_ptr_[word] & mask;
690 bbits_ptr_[word] |= that.bbits_ptr_[word] & mask;
691 }
692 }
693
694 /*
695 * This function should ONLY BE CALLED FROM vvp_vector4_t::copy_from_,
696 * as it performs part of that functions tasks.
697 */
copy_from_big_(const vvp_vector4_t & that)698 void vvp_vector4_t::copy_from_big_(const vvp_vector4_t&that)
699 {
700 unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
701 abits_ptr_ = new unsigned long[2*words];
702 bbits_ptr_ = abits_ptr_ + words;
703
704 for (unsigned idx = 0 ; idx < words ; idx += 1)
705 abits_ptr_[idx] = that.abits_ptr_[idx];
706 for (unsigned idx = 0 ; idx < words ; idx += 1)
707 bbits_ptr_[idx] = that.bbits_ptr_[idx];
708 }
709
710 /*
711 * The copy_inverted_from_ method is just like the copy_from_ method,
712 * except that we combine that with an invert. This allows the ~ and
713 * the assignment to be blended in many common cases.
714 */
copy_inverted_from_(const vvp_vector4_t & that)715 void vvp_vector4_t::copy_inverted_from_(const vvp_vector4_t&that)
716 {
717 size_ = that.size_;
718 if (size_ > BITS_PER_WORD) {
719 unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
720 abits_ptr_ = new unsigned long[2*words];
721 bbits_ptr_ = abits_ptr_ + words;
722
723 unsigned remaining = size_;
724 unsigned idx = 0;
725 while (remaining >= BITS_PER_WORD) {
726 abits_ptr_[idx] = that.bbits_ptr_[idx] | ~that.abits_ptr_[idx];
727 idx += 1;
728 remaining -= BITS_PER_WORD;
729 }
730 if (remaining > 0) {
731 unsigned long mask = (1UL<<remaining) - 1UL;
732 abits_ptr_[idx] = mask & (that.bbits_ptr_[idx] | ~that.abits_ptr_[idx]);
733 }
734
735 for (idx = 0 ; idx < words ; idx += 1)
736 bbits_ptr_[idx] = that.bbits_ptr_[idx];
737
738 } else {
739 unsigned long mask = (size_<BITS_PER_WORD)? (1UL<<size_)-1UL : -1UL;
740 abits_val_ = mask & (that.bbits_val_ | ~that.abits_val_);
741 bbits_val_ = that.bbits_val_;
742 }
743 }
744
745 /* Make sure to set size_ before calling this routine. */
allocate_words_(unsigned long inita,unsigned long initb)746 void vvp_vector4_t::allocate_words_(unsigned long inita, unsigned long initb)
747 {
748 if (size_ > BITS_PER_WORD) {
749 unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
750 abits_ptr_ = new unsigned long[2*cnt];
751 bbits_ptr_ = abits_ptr_ + cnt;
752 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
753 abits_ptr_[idx] = inita;
754 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
755 bbits_ptr_[idx] = initb;
756
757 } else {
758 abits_val_ = inita;
759 bbits_val_ = initb;
760 }
761 }
762
vvp_vector4_t(unsigned size__,double val)763 vvp_vector4_t::vvp_vector4_t(unsigned size__, double val)
764 : size_(size__)
765 {
766 bool is_neg = false;
767 double fraction;
768 int exponent;
769
770 /* We return 'bx for a NaN or +/- infinity. */
771 if (val != val || (val && (val == 0.5*val))) {
772 allocate_words_(WORD_X_ABITS, WORD_X_BBITS);
773 return;
774 }
775
776 /* Convert to a positive result. */
777 if (val < 0.0) {
778 is_neg = true;
779 val = -val;
780 }
781 allocate_words_(WORD_0_ABITS, WORD_0_BBITS);
782
783 /* Get the exponent and fractional part of the number. */
784 fraction = frexp(val, &exponent);
785
786 /* If the value is small enough just use lround(). */
787 if (exponent < BITS_PER_WORD-2) {
788 if (is_neg) this->invert(); // Invert the bits if negative.
789 long sval = lround(val);
790 if (is_neg) sval = -sval;
791 /* This requires that 0 and 1 have the same bbit value. */
792 if (size_ > BITS_PER_WORD) {
793 abits_ptr_[0] = sval;
794 } else {
795 abits_val_ = sval;
796 }
797 return;
798 }
799
800 unsigned nwords = (exponent-1) / BITS_PER_WORD;
801 unsigned my_words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD - 1;
802
803 fraction = ldexp(fraction, (exponent-1) % BITS_PER_WORD + 1);
804
805 /* Skip any leading bits. */
806 for (int idx = (signed) nwords; idx > (signed) my_words; idx -=1) {
807 unsigned long bits = (unsigned long) fraction;
808 fraction = fraction - (double) bits;
809 fraction = ldexp(fraction, BITS_PER_WORD);
810 }
811
812 /* Convert the remaining bits as appropriate. */
813 if (my_words == 0) {
814 unsigned long bits = (unsigned long) fraction;
815 abits_val_ = bits;
816 fraction = fraction - (double) bits;
817 /* Round any fractional part up. */
818 if (fraction >= 0.5) *this += (int64_t) 1;
819 } else {
820 if (nwords < my_words) my_words = nwords;
821 for (int idx = (signed)my_words; idx >= 0; idx -= 1) {
822 unsigned long bits = (unsigned long) fraction;
823 abits_ptr_[idx] = bits;
824 fraction = fraction - (double) bits;
825 fraction = ldexp(fraction, BITS_PER_WORD);
826 }
827 /* Round any fractional part up. */
828 if (fraction >= ldexp(0.5, BITS_PER_WORD)) *this += (int64_t) 1;
829 }
830
831 /* Convert to a negative number if needed. */
832 if (is_neg) {
833 this->invert();
834 *this += (int64_t) 1;
835 }
836 }
837
vvp_vector4_t(const vvp_vector4_t & that,unsigned adr,unsigned wid)838 vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that,
839 unsigned adr, unsigned wid)
840 {
841 // Set up and initialize the destination.
842 size_ = wid;
843 allocate_words_(WORD_X_ABITS, WORD_X_BBITS);
844
845 // Special case: selecting from far beyond the source vector,
846 // to the result is all X bits. We're done.
847 if (adr >= that.size_)
848 return;
849
850 // Special case: The source is not quite big enough to supply
851 // all bits, so get the bits that we can. The remainder will
852 // be left at BIT4_X.
853 if ((adr + wid) > that.size_) {
854 unsigned use_wid = that.size_ - adr;
855 for (unsigned idx = 0 ; idx < use_wid ; idx += 1)
856 set_bit(idx, that.value(adr+idx));
857
858 return;
859 }
860
861 // At the point, we know that the source part is entirely
862 // contained in the source vector.
863 // assert((adr + wid) <= that.size_);
864
865 if (wid > BITS_PER_WORD) {
866 /* In this case, the subvector and the source vector are
867 long. Do the transfer reasonably efficiently. */
868 unsigned ptr = adr / BITS_PER_WORD;
869 unsigned long off = adr % BITS_PER_WORD;
870 unsigned long noff = BITS_PER_WORD - off;
871 unsigned long lmask = (1UL << off) - 1UL;
872 unsigned trans = 0;
873 unsigned dst = 0;
874 while (trans < wid) {
875 // The low bits of the result.
876 abits_ptr_[dst] = (that.abits_ptr_[ptr] & ~lmask) >> off;
877 bbits_ptr_[dst] = (that.bbits_ptr_[ptr] & ~lmask) >> off;
878 trans += noff;
879
880 if (trans >= wid)
881 break;
882
883 ptr += 1;
884
885 // The high bits of the result. Skip this if the
886 // source and destination are perfectly aligned.
887 if (noff != BITS_PER_WORD) {
888 abits_ptr_[dst] |= (that.abits_ptr_[ptr]&lmask) << noff;
889 bbits_ptr_[dst] |= (that.bbits_ptr_[ptr]&lmask) << noff;
890 trans += off;
891 }
892
893 dst += 1;
894 }
895
896 } else if (that.size_ > BITS_PER_WORD) {
897 /* In this case, the subvector fits in a single word,
898 but the source is large. */
899 unsigned ptr = adr / BITS_PER_WORD;
900 unsigned long off = adr % BITS_PER_WORD;
901 unsigned trans = BITS_PER_WORD - off;
902 if (trans > wid)
903 trans = wid;
904
905 if (trans == BITS_PER_WORD) {
906 // Very special case: Copy exactly 1 perfectly
907 // aligned word.
908 abits_val_ = that.abits_ptr_[ptr];
909 bbits_val_ = that.bbits_ptr_[ptr];
910
911 } else {
912 // lmask is the low bits of the destination,
913 // masked into the source.
914 unsigned long lmask = (1UL<<trans) - 1UL;
915 lmask <<= off;
916
917 // The low bits of the result.
918 abits_val_ = (that.abits_ptr_[ptr] & lmask) >> off;
919 bbits_val_ = (that.bbits_ptr_[ptr] & lmask) >> off;
920
921 if (trans < wid) {
922 // If there are more bits, then get them
923 // from the bottom of the next word of the
924 // source.
925 unsigned long hmask = (1UL << (wid-trans)) - 1UL;
926
927 // The high bits of the result.
928 abits_val_ |= (that.abits_ptr_[ptr+1]&hmask) << trans;
929 bbits_val_ |= (that.bbits_ptr_[ptr+1]&hmask) << trans;
930 }
931 }
932
933 } else if (size_ == BITS_PER_WORD) {
934 /* We know that source and destination are short. If the
935 destination is a full word, then we know the copy is
936 aligned and complete. */
937 abits_val_ = that.abits_val_;
938 bbits_val_ = that.bbits_val_;
939
940 } else {
941 /* Finally, the source and destination vectors are both
942 short, so there is a single mask/shift/copy. */
943 unsigned long mask = (1UL << size_) - 1UL;
944 mask <<= adr;
945
946 abits_val_ = (that.abits_val_ & mask) >> adr;
947 bbits_val_ = (that.bbits_val_ & mask) >> adr;
948 }
949
950 }
951
952 /*
953 * Change the size of the vvp_vector4_t vector to the new size. Copy
954 * the old values, as many as well fit, into the new vector.
955 */
resize(unsigned newsize,vvp_bit4_t pad_bit)956 void vvp_vector4_t::resize(unsigned newsize, vvp_bit4_t pad_bit)
957 {
958 if (size_ == newsize)
959 return;
960
961 unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
962 unsigned long word_pad_abits = 0;
963 unsigned long word_pad_bbits = 0;
964 switch (pad_bit) {
965 case BIT4_0:
966 word_pad_abits = WORD_0_ABITS;
967 word_pad_bbits = WORD_0_BBITS;
968 break;
969 case BIT4_1:
970 word_pad_abits = WORD_1_ABITS;
971 word_pad_bbits = WORD_1_BBITS;
972 break;
973 case BIT4_X:
974 word_pad_abits = WORD_X_ABITS;
975 word_pad_bbits = WORD_X_BBITS;
976 break;
977 case BIT4_Z:
978 word_pad_abits = WORD_Z_ABITS;
979 word_pad_bbits = WORD_Z_BBITS;
980 break;
981 }
982
983 if (newsize > BITS_PER_WORD) {
984 unsigned newcnt = (newsize + BITS_PER_WORD - 1) / BITS_PER_WORD;
985 if (newcnt == cnt) {
986 // If the word count doesn't change, then there is
987 // no need for re-allocation so we are done now.
988 if (newsize > size_) {
989 if (unsigned fill = size_ % BITS_PER_WORD) {
990 abits_ptr_[cnt-1] &= ~((-1UL) << fill);
991 bbits_ptr_[cnt-1] &= ~((-1UL) << fill);
992 abits_ptr_[cnt-1] |= word_pad_abits << fill;
993 bbits_ptr_[cnt-1] |= word_pad_bbits << fill;
994 }
995 }
996 size_ = newsize;
997 return;
998 }
999
1000 unsigned long*newbits = new unsigned long[2*newcnt];
1001
1002 if (cnt > 1) {
1003 unsigned trans = cnt;
1004 if (trans > newcnt)
1005 trans = newcnt;
1006
1007 for (unsigned idx = 0 ; idx < trans ; idx += 1)
1008 newbits[idx] = abits_ptr_[idx];
1009 for (unsigned idx = 0 ; idx < trans ; idx += 1)
1010 newbits[newcnt+idx] = bbits_ptr_[idx];
1011
1012 delete[]abits_ptr_;
1013
1014 } else {
1015 newbits[0] = abits_val_;
1016 newbits[newcnt] = bbits_val_;
1017 }
1018
1019 if (newsize > size_) {
1020 if (unsigned fill = size_ % BITS_PER_WORD) {
1021 newbits[cnt-1] &= ~((-1UL) << fill);
1022 newbits[cnt-1] |= word_pad_abits << fill;
1023 newbits[newcnt+cnt-1] &= ~((-1UL) << fill);
1024 newbits[newcnt+cnt-1] |= word_pad_bbits << fill;
1025 }
1026 for (unsigned idx = cnt ; idx < newcnt ; idx += 1)
1027 newbits[idx] = word_pad_abits;
1028 for (unsigned idx = cnt ; idx < newcnt ; idx += 1)
1029 newbits[newcnt+idx] = word_pad_bbits;
1030 }
1031
1032 size_ = newsize;
1033 abits_ptr_ = newbits;
1034 bbits_ptr_ = newbits + newcnt;
1035
1036 } else {
1037 if (cnt > 1) {
1038 unsigned long newvala = abits_ptr_[0];
1039 unsigned long newvalb = bbits_ptr_[0];
1040 delete[]abits_ptr_;
1041 abits_val_ = newvala;
1042 bbits_val_ = newvalb;
1043 }
1044
1045 if (newsize > size_) {
1046 abits_val_ &= ~((-1UL) << size_);
1047 bbits_val_ &= ~((-1UL) << size_);
1048 abits_val_ |= word_pad_abits << size_;
1049 bbits_val_ |= word_pad_bbits << size_;
1050 }
1051
1052 size_ = newsize;
1053 }
1054 }
1055
1056
subarray(unsigned adr,unsigned wid,bool xz_to_0) const1057 unsigned long* vvp_vector4_t::subarray(unsigned adr, unsigned wid, bool xz_to_0) const
1058 {
1059 const unsigned BIT2_PER_WORD = 8*sizeof(unsigned long);
1060 unsigned awid = (wid + BIT2_PER_WORD - 1) / (BIT2_PER_WORD);
1061 unsigned long*val = new unsigned long[awid];
1062
1063 for (unsigned idx = 0 ; idx < awid ; idx += 1)
1064 val[idx] = 0;
1065
1066 if (size_ <= BITS_PER_WORD) {
1067 /* Handle the special case that the array is small. The
1068 entire value of the vector4 is within the xbits_val_
1069 so we know that the result is a single word, the
1070 source is a single word, and we just have to loop
1071 through that word. */
1072 unsigned long atmp = abits_val_ >> adr;
1073 unsigned long btmp = bbits_val_ >> adr;
1074 if (wid < BIT2_PER_WORD) {
1075 atmp &= (1UL << wid) - 1;
1076 btmp &= (1UL << wid) - 1;
1077 }
1078 if (btmp) {
1079 if (xz_to_0)
1080 atmp &= ~btmp;
1081 else
1082 goto x_out;
1083 }
1084
1085 val[0] = atmp;
1086
1087 } else {
1088
1089 unsigned val_ptr = 0;
1090 unsigned val_off = 0;
1091
1092 /* Get the first word we are scanning. We may in fact be
1093 somewhere in the middle of that word. */
1094 while (wid > 0) {
1095 unsigned long atmp = abits_ptr_[adr/BITS_PER_WORD];
1096 unsigned long btmp = bbits_ptr_[adr/BITS_PER_WORD];
1097 unsigned long off = adr%BITS_PER_WORD;
1098 atmp >>= off;
1099 btmp >>= off;
1100
1101 unsigned long trans = BITS_PER_WORD - off;
1102 if (trans > (BIT2_PER_WORD - val_off))
1103 trans = BIT2_PER_WORD - val_off;
1104 if (wid < trans)
1105 trans = wid;
1106 if (trans < BIT2_PER_WORD) {
1107 atmp &= (1UL << trans) - 1;
1108 btmp &= (1UL << trans) - 1;
1109 }
1110 if (btmp) {
1111 if (xz_to_0)
1112 atmp &= ~btmp;
1113 else
1114 goto x_out;
1115 }
1116
1117 val[val_ptr] |= atmp << val_off;
1118 adr += trans;
1119 wid -= trans;
1120 val_off += trans;
1121 if (val_off == BIT2_PER_WORD) {
1122 val_ptr += 1;
1123 val_off = 0;
1124 }
1125 }
1126 }
1127
1128 return val;
1129
1130 x_out:
1131 delete[]val;
1132 return 0;
1133 }
1134
setarray(unsigned adr,unsigned wid,const unsigned long * val)1135 void vvp_vector4_t::setarray(unsigned adr, unsigned wid, const unsigned long*val)
1136 {
1137 assert(adr+wid <= size_);
1138
1139 const unsigned BIT2_PER_WORD = 8*sizeof(unsigned long);
1140
1141 if (size_ <= BITS_PER_WORD) {
1142 // We know here that both the source and the target are
1143 // within a single word. Write the bits into the
1144 // abits_val_ directly.
1145
1146 assert(BIT2_PER_WORD <= BITS_PER_WORD);
1147 unsigned long lmask = (1UL << adr) - 1UL;
1148 unsigned long hmask = ((adr+wid) < BITS_PER_WORD)
1149 ? -1UL << (adr+wid)
1150 : 0;
1151 unsigned long mask = ~(hmask | lmask);
1152
1153 abits_val_ &= ~mask;
1154 bbits_val_ &= ~mask;
1155
1156 abits_val_ |= mask & (val[0] << adr);
1157
1158 } else {
1159 // The general case, there are multiple words of
1160 // destination, and possibly multiple words of source
1161 // data. Shift and mask as we go.
1162 unsigned off = adr % BITS_PER_WORD;
1163 unsigned ptr = adr / BITS_PER_WORD;
1164 unsigned val_off = 0;
1165 unsigned val_ptr = 0;
1166 while (wid > 0) {
1167 unsigned trans = wid;
1168 if (trans > (BIT2_PER_WORD-val_off))
1169 trans = BIT2_PER_WORD-val_off;
1170 if (trans > (BITS_PER_WORD-off))
1171 trans = BITS_PER_WORD-off;
1172
1173 unsigned long lmask = (1UL << off) - 1UL;
1174 unsigned long hmask = ((off+trans) < BITS_PER_WORD)
1175 ? -1UL << (off+trans)
1176 : 0;
1177 unsigned long mask = ~(hmask | lmask);
1178
1179 abits_ptr_[ptr] &= ~mask;
1180 bbits_ptr_[ptr] &= ~mask;
1181 if (val_off >= off)
1182 abits_ptr_[ptr] |= mask & (val[val_ptr] >> (val_off-off));
1183 else
1184 abits_ptr_[ptr] |= mask & (val[val_ptr] << (off-val_off));
1185
1186 wid -= trans;
1187 val_off += trans;
1188 if (val_off == BIT2_PER_WORD) {
1189 val_off = 0;
1190 val_ptr += 1;
1191 }
1192 off += trans;
1193 if (off == BITS_PER_WORD) {
1194 off = 0;
1195 ptr += 1;
1196 }
1197 }
1198 }
1199 }
1200
1201 /*
1202 * Set the bits of that vector, which must be a subset of this vector,
1203 * into the addressed part of this vector. Use bit masking and word
1204 * copies to go as fast as reasonably possible.
1205 */
set_vec(unsigned adr,const vvp_vector4_t & that)1206 bool vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
1207 {
1208 assert(adr+that.size_ <= size_);
1209 bool diff_flag = false;
1210
1211 if (size_ <= BITS_PER_WORD) {
1212
1213 /* The destination vector (me!) is within a bits_val_
1214 word, so the subvector is certainly within a
1215 bits_val_ word. Therefore, the entire operation is a
1216 matter of writing the bits of that into the addressed
1217 bits of this. The mask below is calculated to be 1
1218 for all the bits that are to come from that. Do the
1219 job by some shifting, masking and OR. */
1220
1221 unsigned long lmask = (1UL << adr) - 1;
1222 unsigned long hmask;
1223 unsigned long hshift = adr+that.size_;
1224 if (hshift >= BITS_PER_WORD)
1225 hmask = -1UL;
1226 else
1227 hmask = (1UL << (adr+that.size_)) - 1;
1228 unsigned long mask = hmask & ~lmask;
1229
1230 unsigned long tmp = (that.abits_val_<<adr)&mask;
1231 if ((abits_val_&mask) != tmp) {
1232 diff_flag = true;
1233 abits_val_ = (abits_val_ & ~mask) | tmp;
1234 }
1235 tmp = (that.bbits_val_<<adr) & mask;
1236 if ((bbits_val_&mask) != tmp) {
1237 diff_flag = true;
1238 bbits_val_ = (bbits_val_ & ~mask) | tmp;
1239 }
1240
1241 } else if (that.size_ <= BITS_PER_WORD) {
1242
1243 /* This vector is more than a word, but that vector is
1244 still small. Write into the destination, possibly
1245 spanning two destination words, depending on whether
1246 the source vector spans a word transition. */
1247 unsigned long dptr = adr / BITS_PER_WORD;
1248 unsigned long doff = adr % BITS_PER_WORD;
1249
1250 unsigned long lmask = (1UL << doff) - 1;
1251 unsigned long hshift = doff+that.size_;
1252 unsigned long hmask;
1253 if (hshift >= BITS_PER_WORD)
1254 hmask = -1UL;
1255 else
1256 hmask = (1UL << hshift) - 1UL;
1257
1258 unsigned long mask = hmask & ~lmask;
1259 unsigned long tmp;
1260
1261 tmp = (that.abits_val_ << doff) & mask;
1262 if ((abits_ptr_[dptr] & mask) != tmp) {
1263 diff_flag = true;
1264 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
1265 }
1266 tmp = (that.bbits_val_ << doff) & mask;
1267 if ((bbits_ptr_[dptr] & mask) != tmp) {
1268 diff_flag = true;
1269 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
1270 }
1271
1272 if ((doff + that.size_) > BITS_PER_WORD) {
1273 unsigned tail = doff + that.size_ - BITS_PER_WORD;
1274 mask = (1UL << tail) - 1;
1275
1276 dptr += 1;
1277 tmp = (that.abits_val_ >> (that.size_-tail)) & mask;
1278 if ((abits_ptr_[dptr] & mask) != tmp) {
1279 diff_flag = true;
1280 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
1281 }
1282 tmp = (that.bbits_val_ >> (that.size_-tail)) & mask;
1283 if ((bbits_ptr_[dptr] & mask) != tmp) {
1284 diff_flag = true;
1285 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
1286 }
1287 }
1288
1289 } else if (adr%BITS_PER_WORD == 0) {
1290
1291 /* In this case, both vectors are long, but the
1292 destination is neatly aligned. That means all but the
1293 last word can be simply copied with no masking. */
1294
1295 unsigned remain = that.size_;
1296 unsigned sptr = 0;
1297 unsigned dptr = adr / BITS_PER_WORD;
1298 while (remain >= BITS_PER_WORD) {
1299 if (abits_ptr_[dptr] != that.abits_ptr_[sptr]) {
1300 diff_flag = true;
1301 abits_ptr_[dptr] = that.abits_ptr_[sptr];
1302 }
1303 if (bbits_ptr_[dptr] != that.bbits_ptr_[sptr]) {
1304 diff_flag = true;
1305 bbits_ptr_[dptr] = that.bbits_ptr_[sptr];
1306 }
1307 dptr += 1;
1308 sptr += 1;
1309 remain -= BITS_PER_WORD;
1310 }
1311
1312 if (remain > 0) {
1313 unsigned long mask = (1UL << remain) - 1;
1314 unsigned long tmp;
1315
1316 tmp = that.abits_ptr_[sptr] & mask;
1317 if ((abits_ptr_[dptr] & mask) != tmp) {
1318 diff_flag = true;
1319 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
1320 }
1321 tmp = that.bbits_ptr_[sptr] & mask;
1322 if ((bbits_ptr_[dptr] & mask) != tmp) {
1323 diff_flag = true;
1324 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
1325 }
1326 }
1327
1328 } else {
1329
1330 /* We know that there are two long vectors, and we know
1331 that the destination is definitely NOT aligned. */
1332
1333 unsigned remain = that.size_;
1334 unsigned sptr = 0;
1335 unsigned dptr = adr / BITS_PER_WORD;
1336 unsigned doff = adr % BITS_PER_WORD;
1337 unsigned long lmask = (1UL << doff) - 1;
1338 unsigned ndoff = BITS_PER_WORD - doff;
1339 while (remain >= BITS_PER_WORD) {
1340 unsigned long tmp;
1341
1342 tmp = (that.abits_ptr_[sptr] << doff) & ~lmask;
1343 if ((abits_ptr_[dptr] & ~lmask) != tmp) {
1344 diff_flag = true;
1345 abits_ptr_[dptr] = (abits_ptr_[dptr] & lmask) | tmp;
1346 }
1347 tmp = (that.bbits_ptr_[sptr] << doff) & ~lmask;
1348 if ((bbits_ptr_[dptr] & ~lmask) != tmp) {
1349 diff_flag = true;
1350 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & lmask) | tmp;
1351 }
1352 dptr += 1;
1353
1354 tmp = (that.abits_ptr_[sptr] >> ndoff) & lmask;
1355 if ((abits_ptr_[dptr] & lmask) != tmp) {
1356 diff_flag = true;
1357 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~lmask) | tmp;
1358 }
1359 tmp = (that.bbits_ptr_[sptr] >> ndoff) & lmask;
1360 if ((bbits_ptr_[dptr] & lmask) != tmp) {
1361 diff_flag = true;
1362 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~lmask) | tmp;
1363 }
1364
1365 remain -= BITS_PER_WORD;
1366 sptr += 1;
1367 }
1368
1369 if (remain > 0) {
1370 unsigned long hshift = doff+remain;
1371 unsigned long hmask;
1372 if (hshift >= BITS_PER_WORD)
1373 hmask = -1UL;
1374 else
1375 hmask = (1UL << (doff+remain)) - 1;
1376
1377 unsigned long mask = hmask & ~lmask;
1378 unsigned long tmp;
1379
1380 tmp = (that.abits_ptr_[sptr] << doff) & mask;
1381 if ((abits_ptr_[dptr] & mask) != tmp) {
1382 diff_flag = true;
1383 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
1384 }
1385 tmp = (that.bbits_ptr_[sptr] << doff) & mask;
1386 if ((bbits_ptr_[dptr] & mask) != tmp) {
1387 diff_flag = true;
1388 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
1389 }
1390
1391 if ((doff + remain) > BITS_PER_WORD) {
1392 unsigned tail = doff + remain - BITS_PER_WORD;
1393 if (tail >= BITS_PER_WORD)
1394 mask = -1UL;
1395 else
1396 mask = (1UL << tail) - 1;
1397
1398 dptr += 1;
1399
1400 tmp = (that.abits_ptr_[sptr] >> (remain-tail))&mask;
1401 if ((abits_ptr_[dptr] & mask) != tmp) {
1402 diff_flag = true;
1403 abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) | tmp;
1404 }
1405 tmp = (that.bbits_ptr_[sptr] >> (remain-tail))&mask;
1406 if ((bbits_ptr_[dptr] & mask) != tmp) {
1407 diff_flag = true;
1408 bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) | tmp;
1409 }
1410 }
1411 }
1412 }
1413
1414 return diff_flag;
1415 }
1416
1417 /*
1418 * Add that vector to this vector. Do it in the Verilog way, which
1419 * means if we detect any X or Z bits, change the entire results to
1420 * all X.
1421 *
1422 * Assume both vectors are the same size.
1423 */
add(const vvp_vector4_t & that)1424 void vvp_vector4_t::add(const vvp_vector4_t&that)
1425 {
1426 assert(size_ == that.size_);
1427
1428 if (size_ < BITS_PER_WORD) {
1429 unsigned long mask = ~(-1UL << size_);
1430 if ((bbits_val_|that.bbits_val_) & mask) {
1431 abits_val_ |= mask;
1432 bbits_val_ |= mask;
1433 return;
1434 }
1435
1436 abits_val_ += that.abits_val_;
1437 abits_val_ &= mask;
1438 return;
1439 }
1440
1441 if (size_ == BITS_PER_WORD) {
1442 if (bbits_val_ | that.bbits_val_) {
1443 abits_val_ = WORD_X_ABITS;
1444 bbits_val_ = WORD_X_BBITS;
1445 } else {
1446 abits_val_ += that.abits_val_;
1447 }
1448 return;
1449 }
1450
1451 int cnt = size_ / BITS_PER_WORD;
1452 unsigned long carry = 0;
1453 for (int idx = 0 ; idx < cnt ; idx += 1) {
1454 if (bbits_ptr_[idx] | that.bbits_ptr_[idx])
1455 goto x_out;
1456
1457 abits_ptr_[idx] = add_with_carry(abits_ptr_[idx], that.abits_ptr_[idx], carry);
1458 }
1459
1460 if (unsigned tail = size_ % BITS_PER_WORD) {
1461 unsigned long mask = ~( -1UL << tail );
1462 if ((bbits_ptr_[cnt] | that.bbits_ptr_[cnt])&mask)
1463 goto x_out;
1464
1465 abits_ptr_[cnt] = add_with_carry(abits_ptr_[cnt], that.abits_ptr_[cnt], carry);
1466 abits_ptr_[cnt] &= mask;
1467 }
1468
1469 return;
1470
1471 x_out:
1472 for (int idx = 0 ; idx < cnt ; idx += 1) {
1473 abits_ptr_[idx] = WORD_X_ABITS;
1474 bbits_ptr_[idx] = WORD_X_BBITS;
1475 }
1476 if (unsigned tail = size_%BITS_PER_WORD) {
1477 unsigned long mask = ~( -1UL << tail );
1478 abits_ptr_[cnt] = WORD_X_ABITS&mask;
1479 bbits_ptr_[cnt] = WORD_X_BBITS&mask;
1480 }
1481 }
1482
sub(const vvp_vector4_t & that)1483 void vvp_vector4_t::sub(const vvp_vector4_t&that)
1484 {
1485 assert(size_ == that.size_);
1486
1487 if (size_ < BITS_PER_WORD) {
1488 unsigned long mask = ~(-1UL << size_);
1489 if ((bbits_val_|that.bbits_val_) & mask) {
1490 abits_val_ |= mask;
1491 bbits_val_ |= mask;
1492 return;
1493 }
1494
1495 abits_val_ -= that.abits_val_;
1496 abits_val_ &= mask;
1497 return;
1498 }
1499
1500 if (size_ == BITS_PER_WORD) {
1501 if (bbits_val_ | that.bbits_val_) {
1502 abits_val_ = WORD_X_ABITS;
1503 bbits_val_ = WORD_X_BBITS;
1504 } else {
1505 abits_val_ -= that.abits_val_;
1506 }
1507 return;
1508 }
1509
1510 int cnt = size_ / BITS_PER_WORD;
1511 unsigned long carry = 1;
1512 for (int idx = 0 ; idx < cnt ; idx += 1) {
1513 if (bbits_ptr_[idx] | that.bbits_ptr_[idx])
1514 goto x_out;
1515
1516 abits_ptr_[idx] = add_with_carry(abits_ptr_[idx], ~that.abits_ptr_[idx], carry);
1517 }
1518
1519 if (unsigned tail = size_ % BITS_PER_WORD) {
1520 unsigned long mask = ~( -1UL << tail );
1521 if ((bbits_ptr_[cnt] | that.bbits_ptr_[cnt])&mask)
1522 goto x_out;
1523
1524 abits_ptr_[cnt] = add_with_carry(abits_ptr_[cnt], ~that.abits_ptr_[cnt], carry);
1525 abits_ptr_[cnt] &= mask;
1526 }
1527
1528 return;
1529
1530 x_out:
1531 for (int idx = 0 ; idx < cnt ; idx += 1) {
1532 abits_ptr_[idx] = WORD_X_ABITS;
1533 bbits_ptr_[idx] = WORD_X_BBITS;
1534 }
1535 if (unsigned tail = size_%BITS_PER_WORD) {
1536 unsigned long mask = ~( -1UL << tail );
1537 abits_ptr_[cnt] = WORD_X_ABITS&mask;
1538 bbits_ptr_[cnt] = WORD_X_BBITS&mask;
1539 }
1540
1541 }
1542
mov(unsigned dst,unsigned src,unsigned cnt)1543 void vvp_vector4_t::mov(unsigned dst, unsigned src, unsigned cnt)
1544 {
1545 assert(dst+cnt <= size_);
1546 assert(src+cnt <= size_);
1547
1548 if (size_ <= BITS_PER_WORD) {
1549 unsigned long vmask = (1UL << cnt) - 1;
1550 unsigned long tmp;
1551
1552 tmp = (abits_val_ >> src) & vmask;
1553 abits_val_ &= ~ (vmask << dst);
1554 abits_val_ |= tmp << dst;
1555
1556 tmp = (bbits_val_ >> src) & vmask;
1557 bbits_val_ &= ~ (vmask << dst);
1558 bbits_val_ |= tmp << dst;
1559
1560 } else {
1561 unsigned sptr = src / BITS_PER_WORD;
1562 unsigned dptr = dst / BITS_PER_WORD;
1563 unsigned soff = src % BITS_PER_WORD;
1564 unsigned doff = dst % BITS_PER_WORD;
1565
1566 while (cnt > 0) {
1567 unsigned trans = cnt;
1568 if ((soff+trans) > BITS_PER_WORD)
1569 trans = BITS_PER_WORD - soff;
1570
1571 if ((doff+trans) > BITS_PER_WORD)
1572 trans = BITS_PER_WORD - doff;
1573
1574 if (trans == BITS_PER_WORD) {
1575 // Special case: the transfer count is
1576 // exactly an entire word. For this to be
1577 // true, it must also be true that the
1578 // pointers are aligned. The work is easy,
1579 abits_ptr_[dptr] = abits_ptr_[sptr];
1580 bbits_ptr_[dptr] = bbits_ptr_[sptr];
1581 dptr += 1;
1582 sptr += 1;
1583 cnt -= BITS_PER_WORD;
1584 continue;
1585 }
1586
1587 // Here we know that either the source or
1588 // destination is unaligned, and also we know that
1589 // the count is less than a full word.
1590 unsigned long vmask = (1UL << trans) - 1;
1591 unsigned long tmp;
1592
1593 tmp = (abits_ptr_[sptr] >> soff) & vmask;
1594 abits_ptr_[dptr] &= ~ (vmask << doff);
1595 abits_ptr_[dptr] |= tmp << doff;
1596
1597 tmp = (bbits_ptr_[sptr] >> soff) & vmask;
1598 bbits_ptr_[dptr] &= ~ (vmask << doff);
1599 bbits_ptr_[dptr] |= tmp << doff;
1600
1601 cnt -= trans;
1602 soff += trans;
1603 if (soff >= BITS_PER_WORD) {
1604 soff = 0;
1605 sptr += 1;
1606 }
1607 doff += trans;
1608 if (doff >= BITS_PER_WORD) {
1609 doff = 0;
1610 dptr += 1;
1611 }
1612 }
1613 }
1614 }
1615
mul(const vvp_vector4_t & that)1616 void vvp_vector4_t::mul(const vvp_vector4_t&that)
1617 {
1618 assert(size_ == that.size_);
1619
1620 if (size_ < BITS_PER_WORD) {
1621 unsigned long mask = ~(-1UL << size_);
1622 if ((bbits_val_|that.bbits_val_) & mask) {
1623 abits_val_ |= mask;
1624 bbits_val_ |= mask;
1625 return;
1626 }
1627
1628 abits_val_ *= that.abits_val_;
1629 abits_val_ &= mask;
1630 return;
1631 }
1632
1633 if (size_ == BITS_PER_WORD) {
1634 if (bbits_val_ || that.bbits_val_) {
1635 abits_val_ = WORD_X_ABITS;
1636 bbits_val_ = WORD_X_BBITS;
1637 } else {
1638 abits_val_ *= that.abits_val_;
1639 }
1640 return;
1641 }
1642
1643 const int cnt = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
1644
1645 unsigned long mask;
1646 if (unsigned tail = size_%BITS_PER_WORD) {
1647 mask = ~( -1UL << tail );
1648 } else {
1649 mask = ~0UL;
1650 }
1651
1652 // Check for any XZ values ahead of time in a first pass. If
1653 // we find any, then force the entire result to be X and be
1654 // done.
1655 for (int idx = 0 ; idx < cnt ; idx += 1) {
1656 unsigned long lval = bbits_ptr_[idx];
1657 unsigned long rval = that.bbits_ptr_[idx];
1658 if (idx == (cnt-1)) {
1659 lval &= mask;
1660 rval &= mask;
1661 }
1662 if (lval || rval) {
1663 for (int xdx = 0 ; xdx < cnt-1 ; xdx += 1) {
1664 abits_ptr_[xdx] = WORD_X_ABITS;
1665 bbits_ptr_[xdx] = WORD_X_BBITS;
1666 }
1667 abits_ptr_[cnt-1] = WORD_X_ABITS & mask;
1668 bbits_ptr_[cnt-1] = WORD_X_BBITS & mask;
1669 return;
1670 }
1671 }
1672
1673 // Calculate the result into a res array. We need to keep is
1674 // separate from the "this" array because we are making
1675 // multiple passes.
1676 unsigned long*res = new unsigned long[cnt];
1677 for (int idx = 0 ; idx < cnt ; idx += 1)
1678 res[idx] = 0;
1679
1680 for (int mul_a = 0 ; mul_a < cnt ; mul_a += 1) {
1681 unsigned long lval = abits_ptr_[mul_a];
1682 if (mul_a == (cnt-1))
1683 lval &= mask;
1684
1685 for (int mul_b = 0 ; mul_b < (cnt-mul_a) ; mul_b += 1) {
1686 unsigned long rval = that.abits_ptr_[mul_b];
1687 if (mul_b == (cnt-1))
1688 rval &= mask;
1689
1690 unsigned long sum;
1691 unsigned long tmp = multiply_with_carry(lval, rval, sum);
1692 int base = mul_a + mul_b;
1693 unsigned long carry = 0;
1694 res[base] = add_with_carry(res[base], tmp, carry);
1695 for (int add_idx = base+1 ; add_idx < cnt ; add_idx += 1) {
1696 res[add_idx] = add_with_carry(res[add_idx], sum, carry);
1697 sum = 0;
1698 }
1699 }
1700 }
1701
1702 // Replace the "this" value with the calculated result. We
1703 // know a-priori that the bbits are zero and unchanged.
1704 res[cnt-1] &= mask;
1705 for (int idx = 0 ; idx < cnt ; idx += 1)
1706 abits_ptr_[idx] = res[idx];
1707
1708 delete[]res;
1709 return;
1710
1711
1712 }
1713
eeq(const vvp_vector4_t & that) const1714 bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
1715 {
1716 if (size_ != that.size_)
1717 return false;
1718
1719 if (size_ < BITS_PER_WORD) {
1720 unsigned long mask = (1UL << size_) - 1;
1721 return (abits_val_&mask) == (that.abits_val_&mask)
1722 && (bbits_val_&mask) == (that.bbits_val_&mask);
1723 }
1724
1725 if (size_ == BITS_PER_WORD) {
1726 return (abits_val_ == that.abits_val_)
1727 && (bbits_val_ == that.bbits_val_);
1728 }
1729
1730 unsigned words = size_ / BITS_PER_WORD;
1731 for (unsigned idx = 0 ; idx < words ; idx += 1) {
1732 if (abits_ptr_[idx] != that.abits_ptr_[idx])
1733 return false;
1734 if (bbits_ptr_[idx] != that.bbits_ptr_[idx])
1735 return false;
1736 }
1737
1738 unsigned long mask = size_%BITS_PER_WORD;
1739 if (mask > 0) {
1740 mask = (1UL << mask) - 1;
1741 return (abits_ptr_[words]&mask) == (that.abits_ptr_[words]&mask)
1742 && (bbits_ptr_[words]&mask) == (that.bbits_ptr_[words]&mask);
1743 }
1744
1745 return true;
1746 }
1747
eq_xz(const vvp_vector4_t & that) const1748 bool vvp_vector4_t::eq_xz(const vvp_vector4_t&that) const
1749 {
1750 if (size_ != that.size_)
1751 return false;
1752
1753 if (size_ < BITS_PER_WORD) {
1754 unsigned long mask = (1UL << size_) - 1;
1755 return ((abits_val_|bbits_val_)&mask) == ((that.abits_val_|that.bbits_val_)&mask)
1756 && (bbits_val_&mask) == (that.bbits_val_&mask);
1757 }
1758
1759 if (size_ == BITS_PER_WORD) {
1760 return ((abits_val_|bbits_val_) == (that.abits_val_|that.bbits_val_))
1761 && (bbits_val_ == that.bbits_val_);
1762 }
1763
1764 unsigned words = size_ / BITS_PER_WORD;
1765 for (unsigned idx = 0 ; idx < words ; idx += 1) {
1766 if ((abits_ptr_[idx]|bbits_ptr_[idx]) != (that.abits_ptr_[idx]|that.bbits_ptr_[idx]))
1767 return false;
1768 if (bbits_ptr_[idx] != that.bbits_ptr_[idx])
1769 return false;
1770 }
1771
1772 unsigned long mask = size_%BITS_PER_WORD;
1773 if (mask > 0) {
1774 mask = (1UL << mask) - 1;
1775 return ((abits_ptr_[words]|bbits_ptr_[words])&mask) == ((that.abits_ptr_[words]|that.bbits_ptr_[words])&mask)
1776 && (bbits_ptr_[words]&mask) == (that.bbits_ptr_[words]&mask);
1777 }
1778
1779 return true;
1780 }
1781
has_xz() const1782 bool vvp_vector4_t::has_xz() const
1783 {
1784 if (size_ < BITS_PER_WORD) {
1785 unsigned long mask = -1UL >> (BITS_PER_WORD - size_);
1786 return bbits_val_&mask;
1787 }
1788
1789 if (size_ == BITS_PER_WORD) {
1790 return bbits_val_;
1791 }
1792
1793 unsigned words = size_ / BITS_PER_WORD;
1794 for (unsigned idx = 0 ; idx < words ; idx += 1) {
1795 if (bbits_ptr_[idx])
1796 return true;
1797 }
1798
1799 unsigned long mask = size_%BITS_PER_WORD;
1800 if (mask > 0) {
1801 mask = -1UL >> (BITS_PER_WORD - mask);
1802 return bbits_ptr_[words]&mask;
1803 }
1804
1805 return false;
1806 }
1807
change_z2x()1808 void vvp_vector4_t::change_z2x()
1809 {
1810 // This method relies on the fact that both BIT4_X and BIT4_Z
1811 // have the bbit set in the vector4 encoding, and also that
1812 // the BIT4_X has abit set in the vector4 encoding. By simply
1813 // or-ing the bbit into the abit, BIT4_X and BIT4_Z both
1814 // become BIT4_X.
1815
1816 if (size_ <= BITS_PER_WORD) {
1817 abits_val_ |= bbits_val_;
1818 } else {
1819 unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
1820 for (unsigned idx = 0 ; idx < words ; idx += 1)
1821 abits_ptr_[idx] |= bbits_ptr_[idx];
1822 }
1823 }
1824
set_to_x()1825 void vvp_vector4_t::set_to_x()
1826 {
1827 if (size_ <= BITS_PER_WORD) {
1828 abits_val_ = vvp_vector4_t::WORD_X_ABITS;
1829 bbits_val_ = vvp_vector4_t::WORD_X_BBITS;
1830 } else {
1831 unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
1832 for (unsigned idx = 0 ; idx < words ; idx += 1) {
1833 abits_ptr_[idx] = vvp_vector4_t::WORD_X_ABITS;
1834 bbits_ptr_[idx] = vvp_vector4_t::WORD_X_BBITS;
1835 }
1836 }
1837 }
1838
as_string(char * buf,size_t buf_len) const1839 char* vvp_vector4_t::as_string(char*buf, size_t buf_len) const
1840 {
1841 char*res = buf;
1842 *buf++ = 'C';
1843 *buf++ = '4';
1844 *buf++ = '<';
1845 buf_len -= 3;
1846
1847 for (unsigned idx = 0 ; idx < size() && buf_len >= 2 ; idx += 1) {
1848 switch (value(size()-idx-1)) {
1849 case BIT4_0:
1850 *buf++ = '0';
1851 break;
1852 case BIT4_1:
1853 *buf++ = '1';
1854 break;
1855 case BIT4_X:
1856 *buf++ = 'x';
1857 break;
1858 case BIT4_Z:
1859 *buf++ = 'z';
1860 }
1861 buf_len -= 1;
1862 }
1863
1864 *buf++ = '>';
1865 *buf++ = 0;
1866 return res;
1867 }
1868
invert()1869 void vvp_vector4_t::invert()
1870 {
1871 if (size_ <= BITS_PER_WORD) {
1872 unsigned long mask = (size_<BITS_PER_WORD)? (1UL<<size_)-1UL : -1UL;
1873 abits_val_ = mask & ~abits_val_;
1874 abits_val_ |= bbits_val_;
1875 } else {
1876 unsigned remaining = size_;
1877 unsigned idx = 0;
1878 while (remaining >= BITS_PER_WORD) {
1879 abits_ptr_[idx] = ~abits_ptr_[idx];
1880 abits_ptr_[idx] |= bbits_ptr_[idx];
1881 idx += 1;
1882 remaining -= BITS_PER_WORD;
1883 }
1884 if (remaining > 0) {
1885 unsigned long mask = (1UL<<remaining) - 1UL;
1886 abits_ptr_[idx] = mask & ~abits_ptr_[idx];
1887 abits_ptr_[idx] |= bbits_ptr_[idx];
1888 }
1889 }
1890 }
1891
operator &=(const vvp_vector4_t & that)1892 vvp_vector4_t& vvp_vector4_t::operator &= (const vvp_vector4_t&that)
1893 {
1894 // The truth table is:
1895 // 00 01 11 10
1896 // 00 00 00 00 00
1897 // 01 00 01 11 11
1898 // 11 00 11 11 11
1899 // 10 00 11 11 11
1900 if (size_ <= BITS_PER_WORD) {
1901 unsigned long tmp1 = abits_val_ | bbits_val_;
1902 unsigned long tmp2 = that.abits_val_ | that.bbits_val_;
1903 abits_val_ = tmp1 & tmp2;
1904 bbits_val_ = (tmp1 & that.bbits_val_) | (tmp2 & bbits_val_);
1905 } else {
1906 unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
1907 for (unsigned idx = 0; idx < words ; idx += 1) {
1908 unsigned long tmp1 = abits_ptr_[idx] | bbits_ptr_[idx];
1909 unsigned long tmp2 = that.abits_ptr_[idx] |
1910 that.bbits_ptr_[idx];
1911 abits_ptr_[idx] = tmp1 & tmp2;
1912 bbits_ptr_[idx] = (tmp1 & that.bbits_ptr_[idx]) |
1913 (tmp2 & bbits_ptr_[idx]);
1914 }
1915 }
1916
1917 return *this;
1918 }
1919
operator |=(const vvp_vector4_t & that)1920 vvp_vector4_t& vvp_vector4_t::operator |= (const vvp_vector4_t&that)
1921 {
1922 // The truth table is:
1923 // 00 01 11 10
1924 // 00 00 01 11 11
1925 // 01 01 01 01 01
1926 // 11 11 01 11 11
1927 // 10 11 01 11 11
1928 if (size_ <= BITS_PER_WORD) {
1929 unsigned long tmp = abits_val_ | bbits_val_ |
1930 that.abits_val_ | that.bbits_val_;
1931 bbits_val_ = ((~abits_val_ | bbits_val_) & that.bbits_val_) |
1932 ((~that.abits_val_ | that.bbits_val_) & bbits_val_);
1933 abits_val_ = tmp;
1934
1935 } else {
1936 unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
1937 for (unsigned idx = 0; idx < words ; idx += 1) {
1938 unsigned long tmp = abits_ptr_[idx] | bbits_ptr_[idx] |
1939 that.abits_ptr_[idx] | that.bbits_ptr_[idx];
1940 bbits_ptr_[idx] = ((~abits_ptr_[idx] | bbits_ptr_[idx]) &
1941 that.bbits_ptr_[idx]) |
1942 ((~that.abits_ptr_[idx] |
1943 that.bbits_ptr_[idx]) & bbits_ptr_[idx]);
1944 abits_ptr_[idx] = tmp;
1945 }
1946 }
1947
1948 return *this;
1949 }
1950
1951 /*
1952 * Add an integer to the vvp_vector4_t in place, bit by bit so that
1953 * there is no size limitations.
1954 */
operator +=(int64_t that)1955 vvp_vector4_t& vvp_vector4_t::operator += (int64_t that)
1956 {
1957 vvp_bit4_t carry = BIT4_0;
1958 unsigned idx;
1959
1960 if (has_xz()) {
1961 vvp_vector4_t xxx (size(), BIT4_X);
1962 *this = xxx;
1963 return *this;
1964 }
1965
1966 for (idx = 0 ; idx < size() ; idx += 1) {
1967 if (that == 0 && carry==BIT4_0)
1968 break;
1969
1970 vvp_bit4_t that_bit = (that&1)? BIT4_1 : BIT4_0;
1971 that >>= 1;
1972
1973 if (that_bit==BIT4_0 && carry==BIT4_0)
1974 continue;
1975
1976 vvp_bit4_t bit = value(idx);
1977 bit = add_with_carry(bit, that_bit, carry);
1978
1979 set_bit(idx, bit);
1980 }
1981
1982 return *this;
1983 }
1984
operator <<(ostream & out,const vvp_vector4_t & that)1985 ostream& operator<< (ostream&out, const vvp_vector4_t&that)
1986 {
1987 out << that.size() << "'b";
1988 for (unsigned idx = 0 ; idx < that.size() ; idx += 1)
1989 out << that.value(that.size()-idx-1);
1990 return out;
1991 }
1992
vector4_to_value(const vvp_vector4_t & vec,INT & val,bool is_signed,bool is_arithmetic)1993 template <class INT>bool vector4_to_value(const vvp_vector4_t&vec, INT&val,
1994 bool is_signed, bool is_arithmetic)
1995 {
1996 INT res = 0;
1997 INT msk = 1;
1998 bool rc_flag = true;
1999
2000 unsigned size = vec.size();
2001 if (size > 8*sizeof(val)) size = 8*sizeof(val);
2002 for (unsigned idx = 0 ; idx < size ; idx += 1) {
2003 switch (vec.value(idx)) {
2004 case BIT4_0:
2005 break;
2006 case BIT4_1:
2007 res |= msk;
2008 break;
2009 default:
2010 if (is_arithmetic)
2011 return false;
2012 else
2013 rc_flag = false;
2014 }
2015
2016 msk <<= 1;
2017 }
2018
2019 if (is_signed && vec.value(vec.size()-1) == BIT4_1) {
2020 if (vec.size() < 8*sizeof(val))
2021 res |= static_cast<INT>(-1ULL << vec.size());
2022 }
2023
2024 val = res;
2025 return rc_flag;
2026 }
2027
2028 template bool vector4_to_value(const vvp_vector4_t&vec, int8_t&val,
2029 bool is_signed, bool is_arithmetic);
2030 template bool vector4_to_value(const vvp_vector4_t&vec, int16_t&val,
2031 bool is_signed, bool is_arithmetic);
2032 template bool vector4_to_value(const vvp_vector4_t&vec, int32_t&val,
2033 bool is_signed, bool is_arithmetic);
2034 template bool vector4_to_value(const vvp_vector4_t&vec, int64_t&val,
2035 bool is_signed, bool is_arithmetic);
2036 template bool vector4_to_value(const vvp_vector4_t&vec, uint8_t&val,
2037 bool is_signed, bool is_arithmetic);
2038 template bool vector4_to_value(const vvp_vector4_t&vec, uint16_t&val,
2039 bool is_signed, bool is_arithmetic);
2040 template bool vector4_to_value(const vvp_vector4_t&vec, uint32_t&val,
2041 bool is_signed, bool is_arithmetic);
2042 template bool vector4_to_value(const vvp_vector4_t&vec, uint64_t&val,
2043 bool is_signed, bool is_arithmetic);
2044
vector4_to_value(const vvp_vector4_t & vec,bool & overflow_flag,T & val)2045 template <class T> bool vector4_to_value(const vvp_vector4_t&vec,
2046 bool&overflow_flag, T&val)
2047 {
2048 T res = 0;
2049 T msk = 1;
2050
2051 overflow_flag = false;
2052 unsigned size = vec.size();
2053 for (unsigned idx = 0 ; idx < size ; idx += 1) {
2054 switch (vec.value(idx)) {
2055 case BIT4_0:
2056 break;
2057 case BIT4_1:
2058 if (msk == 0)
2059 overflow_flag = true;
2060 else
2061 res |= msk;
2062 break;
2063 default:
2064 return false;
2065 }
2066
2067 msk <<= static_cast<T>(1);
2068 }
2069
2070 val = res;
2071 return true;
2072 }
2073
2074 template bool vector4_to_value(const vvp_vector4_t&vec, bool&overflow_flag,
2075 unsigned long&val);
2076 #ifndef UL_AND_TIME64_SAME
2077 template bool vector4_to_value(const vvp_vector4_t&vec, bool&overflow_flag,
2078 vvp_time64_t&val);
2079 #endif
2080
vector4_to_value(const vvp_vector4_t & vec,double & val,bool signed_flag)2081 bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
2082 {
2083
2084 if (vec.size() == 0) {
2085 val = 0.0;
2086 return true;
2087 }
2088
2089 bool flag = true;
2090
2091 if (vec.value(vec.size()-1) != BIT4_1) {
2092 signed_flag = false;
2093 }
2094
2095 double res = 0.0;
2096 if (signed_flag) {
2097 vvp_bit4_t carry = BIT4_1;
2098 for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
2099 vvp_bit4_t a = ~vec.value(idx);
2100 vvp_bit4_t x = add_with_carry(a, BIT4_0, carry);
2101 switch (x) {
2102 case BIT4_0:
2103 break;
2104 case BIT4_1:
2105 res += pow(2.0, (int)idx);
2106 break;
2107 default:
2108 flag = false;
2109 }
2110 }
2111 res *= -1.0;
2112 } else {
2113 for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
2114 switch (vec.value(idx)) {
2115 case BIT4_0:
2116 break;
2117 case BIT4_1:
2118 res += pow(2.0, (int)idx);
2119 break;
2120 default:
2121 flag = false;
2122 }
2123 }
2124 }
2125 val = res;
2126 return flag;
2127 }
2128
vector2_to_value(const vvp_vector2_t & a,int32_t & val,bool is_signed)2129 bool vector2_to_value(const vvp_vector2_t&a, int32_t&val, bool is_signed)
2130 {
2131 val = 0;
2132 unsigned idx;
2133 int32_t mask;
2134 for (idx = 0, mask = 1 ; idx < a.size() && idx < 32 ; idx += 1, mask <<= 1) {
2135 if (a.value(idx)) val |= mask;
2136 }
2137
2138 if (is_signed && a.size() < 32 && a.value(a.size()-1)) {
2139 mask = -1;
2140 mask <<= a.size();
2141 val |= mask;
2142 }
2143
2144 return a.size() <= 32;
2145 }
2146
vvp_vector4array_t(unsigned width__,unsigned words__)2147 vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
2148 : width_(width__), words_(words__)
2149 {
2150 }
2151
~vvp_vector4array_t()2152 vvp_vector4array_t::~vvp_vector4array_t()
2153 {
2154 }
2155
set_word_(v4cell * cell,const vvp_vector4_t & that)2156 void vvp_vector4array_t::set_word_(v4cell*cell, const vvp_vector4_t&that)
2157 {
2158 assert(that.size_ == width_);
2159
2160 if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
2161 cell->abits_val_ = that.abits_val_;
2162 cell->bbits_val_ = that.bbits_val_;
2163 return;
2164 }
2165
2166 unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
2167
2168 if (cell->abits_ptr_ == 0) {
2169 cell->abits_ptr_ = new unsigned long[2*cnt];
2170 cell->bbits_ptr_ = cell->abits_ptr_ + cnt;
2171 }
2172
2173 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
2174 cell->abits_ptr_[idx] = that.abits_ptr_[idx];
2175 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
2176 cell->bbits_ptr_[idx] = that.bbits_ptr_[idx];
2177 }
2178
get_word_(v4cell * cell) const2179 vvp_vector4_t vvp_vector4array_t::get_word_(v4cell*cell) const
2180 {
2181 if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
2182 vvp_vector4_t res;
2183 res.size_ = width_;
2184 res.abits_val_ = cell->abits_val_;
2185 res.bbits_val_ = cell->bbits_val_;
2186 return res;
2187 }
2188
2189 vvp_vector4_t res (width_, BIT4_X);
2190 if (cell->abits_ptr_ == 0)
2191 return res;
2192
2193 unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
2194
2195 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
2196 res.abits_ptr_[idx] = cell->abits_ptr_[idx];
2197 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
2198 res.bbits_ptr_[idx] = cell->bbits_ptr_[idx];
2199
2200 return res;
2201 }
2202
vvp_vector4array_sa(unsigned width__,unsigned words__)2203 vvp_vector4array_sa::vvp_vector4array_sa(unsigned width__, unsigned words__)
2204 : vvp_vector4array_t(width__, words__)
2205 {
2206 array_ = new v4cell[words_];
2207
2208 if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
2209 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2210 array_[idx].abits_val_ = vvp_vector4_t::WORD_X_ABITS;
2211 array_[idx].bbits_val_ = vvp_vector4_t::WORD_X_BBITS;
2212 }
2213 } else {
2214 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2215 array_[idx].abits_ptr_ = 0;
2216 array_[idx].bbits_ptr_ = 0;
2217 }
2218 }
2219 }
2220
~vvp_vector4array_sa()2221 vvp_vector4array_sa::~vvp_vector4array_sa()
2222 {
2223 if (array_) {
2224 if (width_ > vvp_vector4_t::BITS_PER_WORD) {
2225 for (unsigned idx = 0 ; idx < words_ ; idx += 1)
2226 if (array_[idx].abits_ptr_)
2227 delete[]array_[idx].abits_ptr_;
2228 }
2229 delete[]array_;
2230 }
2231 }
2232
set_word(unsigned index,const vvp_vector4_t & that)2233 void vvp_vector4array_sa::set_word(unsigned index, const vvp_vector4_t&that)
2234 {
2235 assert(index < words_);
2236
2237 v4cell*cell = &array_[index];
2238
2239 set_word_(cell, that);
2240 }
2241
get_word(unsigned index) const2242 vvp_vector4_t vvp_vector4array_sa::get_word(unsigned index) const
2243 {
2244 if (index >= words_)
2245 return vvp_vector4_t(width_, BIT4_X);
2246
2247 assert(index < words_);
2248
2249 v4cell*cell = &array_[index];
2250
2251 return get_word_(cell);
2252 }
2253
vvp_vector4array_aa(unsigned width__,unsigned words__)2254 vvp_vector4array_aa::vvp_vector4array_aa(unsigned width__, unsigned words__)
2255 : vvp_vector4array_t(width__, words__)
2256 {
2257 context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
2258 }
2259
~vvp_vector4array_aa()2260 vvp_vector4array_aa::~vvp_vector4array_aa()
2261 {
2262 }
2263
alloc_instance(vvp_context_t context)2264 void vvp_vector4array_aa::alloc_instance(vvp_context_t context)
2265 {
2266 v4cell*array = new v4cell[words_];
2267
2268 if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
2269 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2270 array[idx].abits_val_ = vvp_vector4_t::WORD_X_ABITS;
2271 array[idx].bbits_val_ = vvp_vector4_t::WORD_X_BBITS;
2272 }
2273 } else {
2274 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2275 array[idx].abits_ptr_ = 0;
2276 array[idx].bbits_ptr_ = 0;
2277 }
2278 }
2279
2280 vvp_set_context_item(context, context_idx_, array);
2281 }
2282
reset_instance(vvp_context_t context)2283 void vvp_vector4array_aa::reset_instance(vvp_context_t context)
2284 {
2285 v4cell*cell = static_cast<v4cell*>
2286 (vvp_get_context_item(context, context_idx_));
2287
2288 if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
2289 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2290 cell->abits_val_ = vvp_vector4_t::WORD_X_ABITS;
2291 cell->bbits_val_ = vvp_vector4_t::WORD_X_BBITS;
2292 cell++;
2293 }
2294 } else {
2295 unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
2296 for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
2297 if (cell->abits_ptr_) {
2298 for (unsigned n = 0 ; n < cnt ; n += 1) {
2299 cell->abits_ptr_[n] = vvp_vector4_t::WORD_X_ABITS;
2300 cell->bbits_ptr_[n] = vvp_vector4_t::WORD_X_BBITS;
2301 }
2302 }
2303 cell++;
2304 }
2305 }
2306 }
2307
2308 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)2309 void vvp_vector4array_aa::free_instance(vvp_context_t context)
2310 {
2311 v4cell*cell = static_cast<v4cell*>
2312 (vvp_get_context_item(context, context_idx_));
2313 delete [] cell;
2314 }
2315 #endif
2316
set_word(unsigned index,const vvp_vector4_t & that)2317 void vvp_vector4array_aa::set_word(unsigned index, const vvp_vector4_t&that)
2318 {
2319 assert(index < words_);
2320
2321 v4cell*cell = static_cast<v4cell*>
2322 (vthread_get_wt_context_item(context_idx_)) + index;
2323
2324 set_word_(cell, that);
2325 }
2326
get_word(unsigned index) const2327 vvp_vector4_t vvp_vector4array_aa::get_word(unsigned index) const
2328 {
2329 if (index >= words_)
2330 return vvp_vector4_t(width_, BIT4_X);
2331
2332 assert(index < words_);
2333
2334 v4cell*cell = static_cast<v4cell*>
2335 (vthread_get_rd_context_item(context_idx_)) + index;
2336
2337 return get_word_(cell);
2338 }
2339
vvp_vector2_t()2340 vvp_vector2_t::vvp_vector2_t()
2341 {
2342 vec_ = 0;
2343 wid_ = 0;
2344 }
2345
vvp_vector2_t(unsigned long v,unsigned wid)2346 vvp_vector2_t::vvp_vector2_t(unsigned long v, unsigned wid)
2347 {
2348 wid_ = wid;
2349 const unsigned bits_per_word = 8 * sizeof(vec_[0]);
2350 const unsigned words = (wid_ + bits_per_word-1) / bits_per_word;
2351
2352 vec_ = new unsigned long[words];
2353 vec_[0] = v;
2354 for (unsigned idx = 1 ; idx < words ; idx += 1)
2355 vec_[idx] = 0;
2356 }
2357
vvp_vector2_t(vvp_vector2_t::fill_t fill,unsigned wid)2358 vvp_vector2_t::vvp_vector2_t(vvp_vector2_t::fill_t fill, unsigned wid)
2359 {
2360 wid_ = wid;
2361 const unsigned bits_per_word = 8 * sizeof(vec_[0]);
2362 const unsigned words = (wid_ + bits_per_word-1) / bits_per_word;
2363
2364 vec_ = new unsigned long[words];
2365 for (unsigned idx = 0 ; idx < words ; idx += 1)
2366 vec_[idx] = fill? -1 : 0;
2367 }
2368
vvp_vector2_t(const vvp_vector2_t & that,unsigned base,unsigned wid)2369 vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned base, unsigned wid)
2370 {
2371 wid_ = wid;
2372 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2373
2374 vec_ = new unsigned long[words];
2375
2376 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
2377 int bit = that.value(base+idx);
2378 if (bit == 0)
2379 continue;
2380 unsigned word = idx / BITS_PER_WORD;
2381 unsigned long mask = 1UL << (idx % BITS_PER_WORD);
2382 vec_[word] |= mask;
2383 }
2384 }
2385
copy_from_that_(const vvp_vector4_t & that)2386 void vvp_vector2_t::copy_from_that_(const vvp_vector4_t&that)
2387 {
2388 wid_ = that.size();
2389 const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD;
2390
2391 if (words == 0) {
2392 vec_ = 0;
2393 wid_ = 0;
2394 return;
2395 }
2396
2397 // Use the subarray method with the xz_to_0 flag set so that
2398 // we get values even when there are xz bits.
2399 vec_ = that.subarray(0, wid_, true);
2400 }
2401
copy_from_that_(const vvp_vector2_t & that)2402 void vvp_vector2_t::copy_from_that_(const vvp_vector2_t&that)
2403 {
2404 wid_ = that.wid_;
2405 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2406
2407 if (words == 0) {
2408 vec_ = 0;
2409 wid_ = 0;
2410 return;
2411 }
2412
2413 vec_ = new unsigned long[words];
2414 for (unsigned idx = 0 ; idx < words ; idx += 1)
2415 vec_[idx] = that.vec_[idx];
2416 }
2417
vvp_vector2_t(const vvp_vector2_t & that,unsigned newsize)2418 vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize)
2419 {
2420 wid_ = newsize;
2421 if (newsize == 0) {
2422 vec_ = 0;
2423 return;
2424 }
2425
2426 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2427 const unsigned twords = (that.wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2428
2429 vec_ = new unsigned long[words];
2430 for (unsigned idx = 0 ; idx < words ; idx += 1) {
2431 if (idx < twords)
2432 vec_[idx] = that.vec_[idx];
2433 else
2434 vec_[idx] = 0;
2435 }
2436 }
2437
operator =(const vvp_vector2_t & that)2438 vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that)
2439 {
2440 if (this == &that)
2441 return *this;
2442
2443 delete[] vec_;
2444 vec_ = 0;
2445
2446 copy_from_that_(that);
2447 return *this;
2448 }
2449
operator =(const vvp_vector4_t & that)2450 vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector4_t&that)
2451 {
2452 delete[]vec_;
2453 vec_ = 0;
2454 copy_from_that_(that);
2455 return *this;
2456 }
2457
operator <<=(unsigned int shift)2458 vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift)
2459 {
2460 if (wid_ == 0)
2461 return *this;
2462
2463 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2464
2465 // Number of words to shift
2466 const unsigned wshift = shift / BITS_PER_WORD;
2467 // bits to shift within each word.
2468 const unsigned long oshift = shift % BITS_PER_WORD;
2469
2470 // If shifting the entire value away, then return zeros.
2471 if (wshift >= words) {
2472 for (unsigned idx = 0 ; idx < words ; idx += 1)
2473 vec_[idx] = 0;
2474
2475 return *this;
2476 }
2477
2478 // Do the word shift first.
2479 if (wshift > 0) {
2480 for (unsigned idx = 0 ; idx < words-wshift ; idx += 1) {
2481 unsigned sel = words - idx - 1;
2482 vec_[sel] = vec_[sel-wshift];
2483 }
2484
2485 for (unsigned idx = 0 ; idx < wshift ; idx += 1)
2486 vec_[idx] = 0;
2487 }
2488
2489 // Do the fine shift.
2490 if (oshift != 0) {
2491 unsigned long pad = 0;
2492 for (unsigned idx = 0 ; idx < words ; idx += 1) {
2493 unsigned long next_pad = vec_[idx] >> (BITS_PER_WORD-oshift);
2494 vec_[idx] = (vec_[idx] << oshift) | pad;
2495 pad = next_pad;
2496 }
2497
2498 // Cleanup the tail bits.
2499 unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD);
2500 vec_[words-1] &= mask;
2501 }
2502
2503 return *this;
2504 }
2505
operator >>=(unsigned shift)2506 vvp_vector2_t& vvp_vector2_t::operator >>= (unsigned shift)
2507 {
2508 if (wid_ == 0)
2509 return *this;
2510
2511 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2512
2513 // Number of words to shift
2514 const unsigned wshift = shift / BITS_PER_WORD;
2515 // bits to shift within each word.
2516 const unsigned long oshift = shift % BITS_PER_WORD;
2517
2518 // If shifting the entire value away, then return zeros.
2519 if (wshift >= words) {
2520 for (unsigned idx = 0 ; idx < words ; idx += 1)
2521 vec_[idx] = 0;
2522
2523 return *this;
2524 }
2525
2526 if (wshift > 0) {
2527 for (unsigned idx = 0 ; idx < words-wshift ; idx += 1)
2528 vec_[idx] = vec_[idx+wshift];
2529
2530 for (unsigned idx = words-wshift ; idx < words ; idx += 1)
2531 vec_[idx] = 0;
2532 }
2533
2534 if (oshift > 0) {
2535 unsigned long pad = 0;
2536 for (unsigned idx = words ; idx > 0 ; idx -= 1) {
2537 unsigned long new_pad = vec_[idx-1] <<(BITS_PER_WORD-oshift);
2538 vec_[idx-1] = pad | (vec_[idx-1] >> oshift);
2539 pad = new_pad;
2540 }
2541
2542 // Cleanup the tail bits.
2543
2544 unsigned use_words = words;
2545 // Mask_shift is the number of high bits of the top word
2546 // that are to be masked off. We start with the number
2547 // of bits that are not included even in the original,
2548 // then we include the bits of the shift, that are to be
2549 // masked to zero.
2550 unsigned long mask_shift = BITS_PER_WORD - wid_%BITS_PER_WORD;
2551 mask_shift %= BITS_PER_WORD;
2552 mask_shift += oshift;
2553 while (mask_shift >= BITS_PER_WORD) {
2554 vec_[use_words-1] = 0;
2555 use_words -= 1;
2556 mask_shift -= BITS_PER_WORD;
2557 }
2558 if (mask_shift > 0) {
2559 assert(use_words > 0);
2560 unsigned long mask = -1UL >> mask_shift;
2561 vec_[use_words-1] &= mask;
2562 }
2563 }
2564
2565 return *this;
2566 }
2567
add_carry(unsigned long a,unsigned long b,unsigned long & carry)2568 static unsigned long add_carry(unsigned long a, unsigned long b,
2569 unsigned long&carry)
2570 {
2571 unsigned long out = carry;
2572 carry = 0;
2573
2574 if ((ULONG_MAX - out) < a)
2575 carry += 1;
2576 out += a;
2577
2578 if ((ULONG_MAX - out) < b)
2579 carry += 1;
2580 out += b;
2581
2582 return out;
2583 }
2584
operator +=(const vvp_vector2_t & that)2585 vvp_vector2_t& vvp_vector2_t::operator += (const vvp_vector2_t&that)
2586 {
2587 assert(wid_ == that.wid_);
2588 if (wid_ == 0)
2589 return *this;
2590
2591 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2592
2593 unsigned long carry = 0;
2594 for (unsigned idx = 0 ; idx < words ; idx += 1) {
2595 vec_[idx] = add_carry(vec_[idx], that.vec_[idx], carry);
2596 }
2597
2598
2599 // Cleanup the tail bits.
2600 unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD);
2601 vec_[words-1] &= mask;
2602
2603 return *this;
2604 }
2605
operator -=(const vvp_vector2_t & that)2606 vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that)
2607 {
2608 assert(wid_ == that.wid_);
2609 if (wid_ == 0)
2610 return *this;
2611
2612 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2613
2614 unsigned long carry = 1;
2615 for (unsigned idx = 0 ; idx < words ; idx += 1) {
2616 vec_[idx] = add_carry(vec_[idx], ~that.vec_[idx], carry);
2617 }
2618
2619 return *this;
2620 }
2621
trim()2622 void vvp_vector2_t::trim()
2623 {
2624 while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
2625 }
2626
2627 /* This is a special trim that is used on numbers we know represent a
2628 * negative signed value (they came from a negative real value). */
trim_neg()2629 void vvp_vector2_t::trim_neg()
2630 {
2631 if (value(wid_-1) == 1 && wid_ > 32) {
2632 while (value(wid_-2) == 1 && wid_ > 32) wid_ -= 1;
2633 }
2634 }
2635
value(unsigned idx) const2636 int vvp_vector2_t::value(unsigned idx) const
2637 {
2638 if (idx >= wid_)
2639 return 0;
2640
2641 const unsigned bits_per_word = 8 * sizeof(vec_[0]);
2642 unsigned addr = idx/bits_per_word;
2643 unsigned mask = idx%bits_per_word;
2644
2645 if (vec_[addr] & (1UL<<mask))
2646 return 1;
2647 else
2648 return 0;
2649 }
2650
set_bit(unsigned idx,int bit)2651 void vvp_vector2_t::set_bit(unsigned idx, int bit)
2652 {
2653 assert(idx < wid_);
2654
2655 const unsigned bits_per_word = 8 * sizeof(vec_[0]);
2656 unsigned addr = idx/bits_per_word;
2657 unsigned long mask = idx%bits_per_word;
2658
2659 if (bit)
2660 vec_[addr] |= 1UL << mask;
2661 else
2662 vec_[addr] &= ~(1UL << mask);
2663 }
2664
set_vec(unsigned adr,const vvp_vector2_t & that)2665 void vvp_vector2_t::set_vec(unsigned adr, const vvp_vector2_t&that)
2666 {
2667 assert((adr + that.wid_) <= wid_);
2668
2669 for (unsigned idx = 0 ; idx < that.wid_ ; idx += 1)
2670 set_bit(adr+idx, that.value(idx));
2671 }
2672
is_NaN() const2673 bool vvp_vector2_t::is_NaN() const
2674 {
2675 return wid_ == 0;
2676 }
2677
is_zero() const2678 bool vvp_vector2_t::is_zero() const
2679 {
2680 const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
2681
2682 for (unsigned idx = 0; idx < words; idx += 1) {
2683 if (vec_[idx] == 0) continue;
2684 return false;
2685 }
2686
2687 return true;
2688 }
2689
2690 /*
2691 * Basic idea from "Introduction to Programming using SML" by
2692 * Michael R. Hansen and Hans Rischel page 261 and "Seminumerical
2693 * Algorithms, Third Edition" by Donald E. Knuth section 4.6.3.
2694 */
pow(const vvp_vector2_t & x,vvp_vector2_t & y)2695 vvp_vector2_t pow(const vvp_vector2_t&x, vvp_vector2_t&y)
2696 {
2697 /* If we have a zero exponent just return 1. */
2698 if (y == vvp_vector2_t(0L, 1)) {
2699 return vvp_vector2_t(1L, x.size());
2700 }
2701
2702 /* Is the value odd? */
2703 if (y.value(0) == 1) {
2704 y.set_bit(0, 0); // A quick subtract by 1.
2705 vvp_vector2_t res = x * pow(x, y);
2706 return res;
2707 }
2708
2709 y >>= 1; // A fast divide by two. We know the LSB is zero.
2710 vvp_vector2_t z = pow(x, y);
2711 vvp_vector2_t res = z * z;
2712 return res;
2713 }
2714
multiply_long(unsigned long a,unsigned long b,unsigned long & low,unsigned long & high)2715 static void multiply_long(unsigned long a, unsigned long b,
2716 unsigned long&low, unsigned long&high)
2717 {
2718 assert(sizeof(unsigned long) %2 == 0);
2719
2720 const unsigned long word_mask = (1UL << 4UL*sizeof(a)) - 1UL;
2721 unsigned long tmpa;
2722 unsigned long tmpb;
2723 unsigned long res[4];
2724
2725 tmpa = a & word_mask;
2726 tmpb = b & word_mask;
2727 res[0] = tmpa * tmpb;
2728 res[1] = res[0] >> 4UL*sizeof(unsigned long);
2729 res[0] &= word_mask;
2730
2731 tmpa = (a >> 4UL*sizeof(unsigned long)) & word_mask;
2732 tmpb = b & word_mask;
2733 res[1] += tmpa * tmpb;
2734 res[2] = res[1] >> 4UL*sizeof(unsigned long);
2735 res[1] &= word_mask;
2736
2737 tmpa = a & word_mask;
2738 tmpb = (b >> 4UL*sizeof(unsigned long)) & word_mask;
2739 res[1] += tmpa * tmpb;
2740 res[2] += res[1] >> 4UL*sizeof(unsigned long);
2741 res[3] = res[2] >> 4UL*sizeof(unsigned long);
2742 res[1] &= word_mask;
2743 res[2] &= word_mask;
2744
2745 tmpa = (a >> 4UL*sizeof(unsigned long)) & word_mask;
2746 tmpb = (b >> 4UL*sizeof(unsigned long)) & word_mask;
2747 res[2] += tmpa * tmpb;
2748 res[3] += res[2] >> 4UL*sizeof(unsigned long);
2749 res[2] &= word_mask;
2750
2751 high = (res[3] << 4UL*sizeof(unsigned long)) | res[2];
2752 low = (res[1] << 4UL*sizeof(unsigned long)) | res[0];
2753 }
2754
operator *(const vvp_vector2_t & a,const vvp_vector2_t & b)2755 vvp_vector2_t operator * (const vvp_vector2_t&a, const vvp_vector2_t&b)
2756 {
2757 const unsigned bits_per_word = 8 * sizeof(a.vec_[0]);
2758
2759 // The compiler ensures that the two operands are of equal size.
2760 assert(a.size() == b.size());
2761 vvp_vector2_t r (0, a.size());
2762
2763 unsigned words = (r.wid_ + bits_per_word - 1) / bits_per_word;
2764
2765 for (unsigned bdx = 0 ; bdx < words ; bdx += 1) {
2766 unsigned long tmpb = b.vec_[bdx];
2767 if (tmpb == 0)
2768 continue;
2769
2770 for (unsigned adx = 0 ; adx < words ; adx += 1) {
2771 unsigned long tmpa = a.vec_[adx];
2772 if (tmpa == 0)
2773 continue;
2774
2775 unsigned long low, hig;
2776 multiply_long(tmpa, tmpb, low, hig);
2777
2778 unsigned long carry = 0;
2779 for (unsigned sdx = 0
2780 ; (adx+bdx+sdx) < words
2781 ; sdx += 1) {
2782
2783 r.vec_[adx+bdx+sdx] = add_carry(r.vec_[adx+bdx+sdx],
2784 low, carry);
2785 low = hig;
2786 hig = 0;
2787 }
2788 }
2789 }
2790
2791 return r;
2792 }
2793
div_mod(vvp_vector2_t dividend,vvp_vector2_t divisor,vvp_vector2_t & quotient,vvp_vector2_t & remainder)2794 static void div_mod (vvp_vector2_t dividend, vvp_vector2_t divisor,
2795 vvp_vector2_t"ient, vvp_vector2_t&remainder)
2796 {
2797
2798 quotient = vvp_vector2_t(0, dividend.size());
2799
2800 if (divisor == quotient) {
2801 cerr << "ERROR: division by zero, exiting." << endl;
2802 exit(255);
2803 }
2804
2805 if (dividend < divisor) {
2806 remainder = dividend;
2807 return;
2808 }
2809
2810 vvp_vector2_t mask (1, dividend.size());
2811
2812 // Make the dividend 1 bit larger to prevent overflow of
2813 // divtmp in startup.
2814 dividend = vvp_vector2_t(dividend, dividend.size()+1);
2815 vvp_vector2_t divtmp (divisor, dividend.size());
2816
2817 while (divtmp < dividend) {
2818 divtmp <<= 1;
2819 mask <<= 1;
2820 }
2821
2822 while (dividend >= divisor) {
2823 if (divtmp <= dividend) {
2824 dividend -= divtmp;
2825 quotient += mask;
2826 }
2827
2828 divtmp >>= 1;
2829 mask >>= 1;
2830 }
2831
2832 remainder = vvp_vector2_t(dividend, mask.size());
2833 }
2834
operator -(const vvp_vector2_t & that)2835 vvp_vector2_t operator - (const vvp_vector2_t&that)
2836 {
2837 vvp_vector2_t neg(that);
2838 if (neg.wid_ == 0) return neg;
2839
2840 const unsigned words = (neg.wid_ + neg.BITS_PER_WORD-1) /
2841 neg.BITS_PER_WORD;
2842 for (unsigned idx = 0 ; idx < words ; idx += 1) {
2843 neg.vec_[idx] = ~neg.vec_[idx];
2844 }
2845 neg += vvp_vector2_t(1, neg.wid_);
2846
2847 return neg;
2848 }
2849
operator /(const vvp_vector2_t & dividend,const vvp_vector2_t & divisor)2850 vvp_vector2_t operator / (const vvp_vector2_t÷nd,
2851 const vvp_vector2_t&divisor)
2852 {
2853 vvp_vector2_t quot, rem;
2854 div_mod(dividend, divisor, quot, rem);
2855 return quot;
2856 }
2857
operator %(const vvp_vector2_t & dividend,const vvp_vector2_t & divisor)2858 vvp_vector2_t operator % (const vvp_vector2_t÷nd,
2859 const vvp_vector2_t&divisor)
2860 {
2861 vvp_vector2_t quot, rem;
2862 div_mod(dividend, divisor, quot, rem);
2863 return rem;
2864 }
2865
operator >(const vvp_vector2_t & a,const vvp_vector2_t & b)2866 bool operator > (const vvp_vector2_t&a, const vvp_vector2_t&b)
2867 {
2868 const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2869 const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2870
2871 const unsigned words = awords > bwords? awords : bwords;
2872
2873 for (unsigned idx = words ; idx > 0 ; idx -= 1) {
2874 unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0;
2875 unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0;
2876
2877 if (aw > bw)
2878 return true;
2879 if (aw < bw)
2880 return false;
2881 }
2882
2883 // If the above loop finishes, then the vectors are equal.
2884 return false;
2885 }
2886
operator >=(const vvp_vector2_t & a,const vvp_vector2_t & b)2887 bool operator >= (const vvp_vector2_t&a, const vvp_vector2_t&b)
2888 {
2889 const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2890 const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2891
2892 const unsigned words = awords > bwords? awords : bwords;
2893
2894 for (unsigned idx = words ; idx > 0 ; idx -= 1) {
2895 unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0;
2896 unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0;
2897
2898 if (aw > bw)
2899 return true;
2900 if (aw < bw)
2901 return false;
2902 }
2903
2904 // If the above loop finishes, then the vectors are equal.
2905 return true;
2906 }
2907
operator <(const vvp_vector2_t & a,const vvp_vector2_t & b)2908 bool operator < (const vvp_vector2_t&a, const vvp_vector2_t&b)
2909 {
2910 const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2911 const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2912
2913 unsigned words = awords;
2914 if (bwords > words)
2915 words = bwords;
2916
2917 for (unsigned idx = words ; idx > 0 ; idx -= 1) {
2918 unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0;
2919 unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0;
2920
2921 if (aw < bw)
2922 return true;
2923 if (aw > bw)
2924 return false;
2925 }
2926
2927 // If the above loop finishes, then the vectors are equal.
2928 return false;
2929 }
2930
operator <=(const vvp_vector2_t & a,const vvp_vector2_t & b)2931 bool operator <= (const vvp_vector2_t&a, const vvp_vector2_t&b)
2932 {
2933 // XXXX For now, only support equal width vectors.
2934 assert(a.wid_ == b.wid_);
2935
2936 const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2937
2938 for (unsigned idx = awords ; idx > 0 ; idx -= 1) {
2939 if (a.vec_[idx-1] < b.vec_[idx-1])
2940 return true;
2941 if (a.vec_[idx-1] > b.vec_[idx-1])
2942 return false;
2943 }
2944
2945 // If the above loop finishes, then the vectors are equal.
2946 return true;
2947 }
2948
operator ==(const vvp_vector2_t & a,const vvp_vector2_t & b)2949 bool operator == (const vvp_vector2_t&a, const vvp_vector2_t&b)
2950 {
2951 const unsigned awords = (a.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2952 const unsigned bwords = (b.wid_ + vvp_vector2_t::BITS_PER_WORD-1) / vvp_vector2_t::BITS_PER_WORD;
2953
2954 const unsigned words = awords > bwords? awords : bwords;
2955
2956 for (unsigned idx = words ; idx > 0 ; idx -= 1) {
2957 unsigned long aw = (idx <= awords)? a.vec_[idx-1] : 0;
2958 unsigned long bw = (idx <= bwords)? b.vec_[idx-1] : 0;
2959
2960 if (aw > bw)
2961 return false;
2962 if (aw < bw)
2963 return false;
2964 }
2965
2966 // If the above loop finishes, then the vectors are equal.
2967 return true;
2968 }
2969
2970
vector2_to_vector4(const vvp_vector2_t & that,unsigned wid)2971 vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&that, unsigned wid)
2972 {
2973 vvp_vector4_t res (wid);
2974
2975 for (unsigned idx = 0 ; idx < res.size() ; idx += 1) {
2976 vvp_bit4_t bit = BIT4_0;
2977
2978 if (that.value(idx))
2979 bit = BIT4_1;
2980
2981 res.set_bit(idx, bit);
2982 }
2983
2984 return res;
2985 }
2986
c4string_test(const char * str)2987 bool c4string_test(const char*str)
2988 {
2989 if (strncmp(str, "C4<", 3) != 0)
2990 return false;
2991 size_t value_size = strspn(str+3, "01xz");
2992 if (str[3+value_size] != '>')
2993 return false;
2994 if (str[3+value_size+1] != 0)
2995 return false;
2996
2997 return true;
2998 }
2999
c4string_to_vector4(const char * str)3000 vvp_vector4_t c4string_to_vector4(const char*str)
3001 {
3002 assert((str[0]=='C') && (str[1]=='4') && (str[2]=='<'));
3003
3004 str += 3;
3005 const char*tp = str + strspn(str,"01xz");
3006 assert(tp[0] == '>');
3007
3008 vvp_vector4_t tmp (tp-str);
3009
3010 for (unsigned idx = 0 ; idx < tmp.size() ; idx += 1) {
3011 vvp_bit4_t bit;
3012 switch (str[idx]) {
3013 case '0':
3014 bit = BIT4_0;
3015 break;
3016 case '1':
3017 bit = BIT4_1;
3018 break;
3019 case 'x':
3020 bit = BIT4_X;
3021 break;
3022 case 'z':
3023 bit = BIT4_Z;
3024 break;
3025 default:
3026 fprintf(stderr, "Unsupported bit value %c(%d).\n", str[idx],
3027 str[idx]);
3028 assert(0);
3029 bit = BIT4_0;
3030 break;
3031 }
3032 tmp.set_bit(tmp.size()-idx-1, bit);
3033 }
3034
3035 return tmp;
3036 }
3037
operator <<(ostream & out,const vvp_vector2_t & that)3038 ostream& operator<< (ostream&out, const vvp_vector2_t&that)
3039 {
3040 if (that.is_NaN()) {
3041 out << "NaN";
3042
3043 } else {
3044 out << vector2_to_vector4(that, that.size());
3045 }
3046 return out;
3047 }
3048
vvp_vector8_t(const vvp_vector8_t & that)3049 vvp_vector8_t::vvp_vector8_t(const vvp_vector8_t&that)
3050 {
3051 size_ = that.size_;
3052 if (size_ <= sizeof(val_)) {
3053 memcpy(val_, that.val_, sizeof val_);
3054 } else {
3055 ptr_ = new unsigned char[size_];
3056 memcpy(ptr_, that.ptr_, size_);
3057 }
3058 }
3059
vvp_vector8_t(const vvp_vector4_t & that,unsigned str0,unsigned str1)3060 vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
3061 unsigned str0, unsigned str1)
3062 : size_(that.size())
3063 {
3064 if (size_ == 0)
3065 return;
3066
3067 if (size_ <= sizeof(val_)) {
3068 ptr_ = 0; // Prefill all val_ bytes
3069 for (unsigned idx = 0 ; idx < size_ ; idx += 1)
3070 val_[idx] = vvp_scalar_t(that.value(idx),str0, str1).raw();
3071 } else {
3072 ptr_ = new unsigned char[size_];
3073 for (unsigned idx = 0 ; idx < size_ ; idx += 1)
3074 ptr_[idx] = vvp_scalar_t(that.value(idx), str0, str1).raw();
3075 }
3076 }
3077
vvp_vector8_t(const vvp_vector2_t & that,unsigned str0,unsigned str1)3078 vvp_vector8_t::vvp_vector8_t(const vvp_vector2_t&that,
3079 unsigned str0, unsigned str1)
3080 : size_(that.size())
3081 {
3082 if (size_ == 0)
3083 return;
3084
3085 if (size_ <= sizeof(val_)) {
3086 ptr_ = 0;
3087 for (unsigned idx = 0 ; idx < size_ ; idx += 1)
3088 val_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
3089 } else {
3090 ptr_ = new unsigned char[size_];
3091 for (unsigned idx = 0 ; idx < size_ ; idx += 1)
3092 ptr_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
3093 }
3094 }
3095
3096 const vvp_vector8_t vvp_vector8_t::nil;
3097
operator =(const vvp_vector8_t & that)3098 vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
3099 {
3100 // Assign to self.
3101 if (this == &that)
3102 return *this;
3103
3104 if (size_ != that.size_) {
3105 if (size_ > sizeof(val_))
3106 delete[]ptr_;
3107 size_ = 0;
3108 }
3109
3110 if (that.size_ == 0) {
3111 assert(size_ == 0);
3112 return *this;
3113 }
3114
3115 if (that.size_ <= sizeof(val_)) {
3116 size_ = that.size_;
3117 memcpy(val_, that.val_, sizeof(val_));
3118 return *this;
3119 }
3120
3121 if (size_ == 0) {
3122 size_ = that.size_;
3123 ptr_ = new unsigned char[size_];
3124 }
3125
3126 memcpy(ptr_, that.ptr_, size_);
3127
3128 return *this;
3129 }
3130
subvalue(unsigned base,unsigned wid) const3131 vvp_vector8_t vvp_vector8_t::subvalue(unsigned base, unsigned wid) const
3132 {
3133 vvp_vector8_t tmp (wid);
3134
3135 unsigned char*tmp_ptr = tmp.size_ <= sizeof(val_) ? tmp.val_ : tmp.ptr_;
3136 const unsigned char*use_ptr = size_ <= sizeof(val_) ? val_ : ptr_;
3137
3138 unsigned idx = 0;
3139 while ((idx < wid) && (base+idx < size_)) {
3140 tmp_ptr[idx] = use_ptr[base+idx];
3141 idx += 1;
3142 }
3143
3144 return tmp;
3145 }
3146
set_vec(unsigned base,const vvp_vector8_t & that)3147 void vvp_vector8_t::set_vec(unsigned base, const vvp_vector8_t&that)
3148 {
3149 assert((base+that.size()) <= size());
3150 for (unsigned idx = 0 ; idx < that.size() ; idx += 1)
3151 set_bit(base+idx, that.value(idx));
3152 }
3153
part_expand(const vvp_vector8_t & that,unsigned wid,unsigned off)3154 vvp_vector8_t part_expand(const vvp_vector8_t&that, unsigned wid, unsigned off)
3155 {
3156 assert(off < wid);
3157 vvp_vector8_t tmp (wid);
3158
3159 unsigned char* tmp_ptr = tmp.size_<= sizeof(tmp.val_) ?
3160 tmp.val_ : tmp.ptr_;
3161 const unsigned char* that_ptr = that.size_<= sizeof(that.val_) ?
3162 that.val_ : that.ptr_;
3163
3164 unsigned idx = off;
3165
3166 while (idx < wid && that.size_ > (idx-off)) {
3167 tmp_ptr[idx] = that_ptr[idx-off];
3168 idx += 1;
3169 }
3170
3171 return tmp;
3172 }
3173
c8string_test(const char * str)3174 bool c8string_test(const char*str)
3175 {
3176 const char*cp;
3177 if (str[0] != 'C') return false;
3178 if (str[1] != '8') return false;
3179 if (str[2] != '<') return false;
3180
3181 cp = str+3;
3182 for (;; cp += 1) {
3183 if (cp[0] == '>' && cp[1] == 0) return true;
3184 if (cp[0] >= '0' && cp[0] <= '9') continue;
3185 if (cp[0] == 'x') continue;
3186 if (cp[0] == 'z') continue;
3187 return false;
3188 }
3189 return false;
3190 }
3191 /*
3192 * The format of a C8<> string is:
3193 * C8<aaabbbccc...>
3194 * where aaa... is a 3 character bit descriptor.
3195 */
c8string_to_vector8(const char * str)3196 vvp_vector8_t c8string_to_vector8(const char*str)
3197 {
3198 size_t vsize = strlen(str)-4;
3199 assert(vsize%3 == 0);
3200 vsize /= 3;
3201 vvp_vector8_t tmp (vsize);
3202
3203 for (size_t idx = 0 ; idx < vsize ; idx += 1) {
3204 const char*cp = str+3+3*idx;
3205 vvp_bit4_t bit = BIT4_X;
3206 unsigned dr0 = cp[0]-'0';
3207 unsigned dr1 = cp[1]-'0';
3208 switch (cp[2]) {
3209 case '0':
3210 bit = BIT4_0;
3211 break;
3212 case '1':
3213 bit = BIT4_1;
3214 break;
3215 case 'x':
3216 bit = BIT4_X;
3217 break;
3218 case 'z':
3219 bit = BIT4_Z;
3220 break;
3221 }
3222 tmp.set_bit(vsize-idx-1, vvp_scalar_t(bit, dr0, dr1));
3223 }
3224
3225 return tmp;
3226 }
3227
operator <<(ostream & out,const vvp_vector8_t & that)3228 ostream& operator<<(ostream&out, const vvp_vector8_t&that)
3229 {
3230 out << "C8<";
3231 for (unsigned idx = 0 ; idx < that.size() ; idx += 1)
3232 out << that.value(that.size()-idx-1);
3233
3234 out << ">";
3235 return out;
3236 }
3237
vvp_net_fun_t()3238 vvp_net_fun_t::vvp_net_fun_t()
3239 {
3240 count_functors += 1;
3241 }
3242
~vvp_net_fun_t()3243 vvp_net_fun_t::~vvp_net_fun_t()
3244 {
3245 }
3246
recv_vec4(vvp_net_ptr_t,const vvp_vector4_t &,vvp_context_t)3247 void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&,
3248 vvp_context_t)
3249 {
3250 fprintf(stderr, "internal error: %s: recv_vec4 not implemented\n",
3251 typeid(*this).name());
3252 assert(0);
3253 }
3254
recv_vec4_pv_(vvp_net_ptr_t p,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t)3255 void vvp_net_fun_t::recv_vec4_pv_(vvp_net_ptr_t p, const vvp_vector4_t&bit,
3256 unsigned base, unsigned wid, unsigned vwid,
3257 vvp_context_t)
3258 {
3259 // The majority of functors don't normally expect to receive part
3260 // values, because the primary operands of an expression will be
3261 // extended to the expression width. But in the case that a primary
3262 // operand is a wire that is only partly driven by a single driver,
3263 // the part value driven onto the wire propagates directly to the
3264 // inputs of any functors connected to that wire. In this case we
3265 // know that the remaining bits are undriven, so can simply build
3266 // the full width value from the part we have received.
3267 //
3268 // Note that this case is almost certainly a bug in the user's
3269 // code, but we still need to handle it correctly. See GitHub
3270 // issue #99 and br_gh99*.v in the test suite for examples.
3271
3272 assert(bit.size() == wid);
3273 assert(base + wid <= vwid);
3274
3275 vvp_vector4_t tmp(vwid, BIT4_Z);
3276 tmp.set_vec(base, bit);
3277 recv_vec4(p, tmp, 0);
3278 }
3279
recv_vec4_pv(vvp_net_ptr_t,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t)3280 void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
3281 unsigned base, unsigned wid, unsigned vwid,
3282 vvp_context_t)
3283 {
3284 cerr << "internal error: " << typeid(*this).name() << ": "
3285 << "recv_vec4_pv(" << bit << ", " << base
3286 << ", " << wid << ", " << vwid << ") not implemented" << endl;
3287 assert(0);
3288 }
3289
recv_vec8(vvp_net_ptr_t port,const vvp_vector8_t & bit)3290 void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
3291 {
3292 recv_vec4(port, reduce4(bit), 0);
3293 }
3294
recv_vec8_pv_(vvp_net_ptr_t p,const vvp_vector8_t & bit,unsigned base,unsigned wid,unsigned vwid)3295 void vvp_net_fun_t::recv_vec8_pv_(vvp_net_ptr_t p, const vvp_vector8_t&bit,
3296 unsigned base, unsigned wid, unsigned vwid)
3297 {
3298 // This is the strength-aware version of recv_vec4_pv_.
3299
3300 assert(bit.size() == wid);
3301 assert(base + wid <= vwid);
3302
3303 vvp_vector8_t tmp(vwid);
3304 tmp.set_vec(base, bit);
3305 recv_vec8(p, tmp);
3306 }
3307
recv_vec8_pv(vvp_net_ptr_t port,const vvp_vector8_t & bit,unsigned base,unsigned wid,unsigned vwid)3308 void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
3309 unsigned base, unsigned wid, unsigned vwid)
3310 {
3311 recv_vec4_pv(port, reduce4(bit), base, wid, vwid, 0);
3312 }
3313
recv_real(vvp_net_ptr_t,double bit,vvp_context_t)3314 void vvp_net_fun_t::recv_real(vvp_net_ptr_t, double bit, vvp_context_t)
3315 {
3316 fprintf(stderr, "internal error: %s: recv_real(%f) not implemented\n",
3317 typeid(*this).name(), bit);
3318 assert(0);
3319 }
3320
recv_long(vvp_net_ptr_t,long)3321 void vvp_net_fun_t::recv_long(vvp_net_ptr_t, long)
3322 {
3323 fprintf(stderr, "internal error: %s: recv_long not implemented\n",
3324 typeid(*this).name());
3325 assert(0);
3326 }
3327
recv_long_pv(vvp_net_ptr_t,long,unsigned,unsigned)3328 void vvp_net_fun_t::recv_long_pv(vvp_net_ptr_t, long, unsigned, unsigned)
3329 {
3330 fprintf(stderr, "internal error: %s: recv_long_pv not implemented\n",
3331 typeid(*this).name());
3332 assert(0);
3333 }
3334
recv_string(vvp_net_ptr_t,const std::string & bit,vvp_context_t)3335 void vvp_net_fun_t::recv_string(vvp_net_ptr_t, const std::string&bit, vvp_context_t)
3336 {
3337 fprintf(stderr, "internal error: %s: recv_string(%s) not implemented\n",
3338 typeid(*this).name(), bit.c_str());
3339 assert(0);
3340 }
3341
recv_object(vvp_net_ptr_t,vvp_object_t,vvp_context_t)3342 void vvp_net_fun_t::recv_object(vvp_net_ptr_t, vvp_object_t, vvp_context_t)
3343 {
3344 fprintf(stderr, "internal error: %s: recv_object(...) not implemented\n",
3345 typeid(*this).name());
3346 assert(0);
3347 }
3348
force_flag(bool)3349 void vvp_net_fun_t::force_flag(bool)
3350 {
3351 }
3352
3353 /* **** vvp_fun_drive methods **** */
3354
vvp_fun_drive(unsigned str0,unsigned str1)3355 vvp_fun_drive::vvp_fun_drive(unsigned str0, unsigned str1)
3356 {
3357 assert(str0 < 8);
3358 assert(str1 < 8);
3359
3360 drive0_ = str0;
3361 drive1_ = str1;
3362 }
3363
~vvp_fun_drive()3364 vvp_fun_drive::~vvp_fun_drive()
3365 {
3366 }
3367
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)3368 void vvp_fun_drive::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
3369 vvp_context_t)
3370 {
3371 assert(port.port() == 0);
3372 port.ptr()->send_vec8(vvp_vector8_t(bit, drive0_, drive1_));
3373 }
3374
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)3375 void vvp_fun_drive::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
3376 unsigned base, unsigned wid, unsigned vwid,
3377 vvp_context_t ctx)
3378 {
3379 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
3380 }
3381
3382 /* **** vvp_wide_fun_* methods **** */
3383
vvp_wide_fun_core(vvp_net_t * net,unsigned nports)3384 vvp_wide_fun_core::vvp_wide_fun_core(vvp_net_t*net, unsigned nports)
3385 {
3386 ptr_ = net;
3387 nports_ = nports;
3388 port_values_ = 0;
3389 port_rvalues_ = 0;
3390 }
3391
~vvp_wide_fun_core()3392 vvp_wide_fun_core::~vvp_wide_fun_core()
3393 {
3394 delete[] port_values_;
3395 delete[] port_rvalues_;
3396 }
3397
propagate_vec4(const vvp_vector4_t & bit,vvp_time64_t delay)3398 void vvp_wide_fun_core::propagate_vec4(const vvp_vector4_t&bit,
3399 vvp_time64_t delay)
3400 {
3401 if (delay)
3402 schedule_propagate_vector(ptr_, delay, bit);
3403 else
3404 ptr_->send_vec4(bit, 0);
3405 }
3406
propagate_real(double bit,vvp_time64_t delay)3407 void vvp_wide_fun_core::propagate_real(double bit,
3408 vvp_time64_t delay)
3409 {
3410 if (delay) {
3411 // schedule_assign_vector(ptr_->out, bit, delay);
3412 assert(0); // Need a real-value version of assign_vector.
3413 } else {
3414 ptr_->send_real(bit, 0);
3415 }
3416 }
3417
3418
port_count() const3419 unsigned vvp_wide_fun_core::port_count() const
3420 {
3421 return nports_;
3422 }
3423
value(unsigned idx)3424 vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx)
3425 {
3426 assert(idx < nports_);
3427 if (port_values_ == 0)
3428 port_values_ = new vvp_vector4_t [nports_];
3429 return port_values_[idx];
3430 }
3431
value_r(unsigned idx)3432 double vvp_wide_fun_core::value_r(unsigned idx)
3433 {
3434 assert(idx < nports_);
3435 return port_rvalues_? port_rvalues_[idx] : 0.0;
3436 }
3437
recv_real_from_inputs(unsigned)3438 void vvp_wide_fun_core::recv_real_from_inputs(unsigned)
3439 {
3440 assert(0);
3441 }
3442
dispatch_vec4_from_input_(unsigned port,vvp_vector4_t bit)3443 void vvp_wide_fun_core::dispatch_vec4_from_input_(unsigned port,
3444 vvp_vector4_t bit)
3445 {
3446 assert(port < nports_);
3447 if (port_values_ == 0) port_values_ = new vvp_vector4_t [nports_];
3448 port_values_[port] = bit;
3449 recv_vec4_from_inputs(port);
3450 }
3451
dispatch_real_from_input_(unsigned port,double bit)3452 void vvp_wide_fun_core::dispatch_real_from_input_(unsigned port,
3453 double bit)
3454 {
3455 assert(port < nports_);
3456 if (port_rvalues_ == 0) port_rvalues_ = new double[nports_];
3457 port_rvalues_[port] = bit;
3458 recv_real_from_inputs(port);
3459 }
3460
vvp_wide_fun_t(vvp_wide_fun_core * c,unsigned base)3461 vvp_wide_fun_t::vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base)
3462 : core_(c), port_base_(base)
3463 {
3464 }
3465
~vvp_wide_fun_t()3466 vvp_wide_fun_t::~vvp_wide_fun_t()
3467 {
3468 }
3469
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)3470 void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
3471 vvp_context_t)
3472 {
3473 unsigned pidx = port_base_ + port.port();
3474 core_->dispatch_vec4_from_input_(pidx, bit);
3475 }
3476
recv_vec4_pv(vvp_net_ptr_t ptr,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t ctx)3477 void vvp_wide_fun_t::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
3478 unsigned base, unsigned wid, unsigned vwid,
3479 vvp_context_t ctx)
3480 {
3481 recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
3482 }
3483
recv_real(vvp_net_ptr_t port,double bit,vvp_context_t)3484 void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit,
3485 vvp_context_t)
3486 {
3487 unsigned pidx = port_base_ + port.port();
3488 core_->dispatch_real_from_input_(pidx, bit);
3489 }
3490
3491 /* **** vvp_scalar_t methods **** */
3492
3493 /*
3494 * DRIVE STRENGTHS:
3495 *
3496 * The normal functor is not aware of strengths. It generates strength
3497 * simply by virtue of having strength specifications. The drive
3498 * strength specification includes a drive0 and drive1 strength, each
3499 * with 8 possible values (that can be represented in 3 bits) as given
3500 * in this table:
3501 *
3502 * HiZ = 0,
3503 * SMALL = 1,
3504 * MEDIUM = 2,
3505 * WEAK = 3,
3506 * LARGE = 4,
3507 * PULL = 5,
3508 * STRONG = 6,
3509 * SUPPLY = 7
3510 *
3511 * The vvp_scalar_t value, however, is a combination of value and
3512 * strength, used in strength-aware contexts.
3513 *
3514 * OUTPUT STRENGTHS:
3515 *
3516 * The strength-aware values are specified as an 8 bit value, that is
3517 * two 4 bit numbers. The value is encoded with two drive strengths (0-7)
3518 * and two drive values (0 or 1). Each nibble contains three bits of
3519 * strength and one bit of value, like so: VSSS. The high nibble has
3520 * the strength-value closest to supply1, and the low nibble has the
3521 * strength-value closest to supply0.
3522 */
3523
3524 /*
3525 * A signal value is unambiguous if the top 4 bits and the bottom 4
3526 * bits are identical. This means that the VSSSvsss bits of the 8bit
3527 * value have V==v and SSS==sss.
3528 */
3529 # define UNAMBIG(v) (((v) & 0x0f) == (((v) >> 4) & 0x0f))
3530
3531 # define STREN1(v) (((v)&0x70) >> 4)
3532 # define STREN0(v) ((v)&0x07)
3533
strength0() const3534 unsigned vvp_scalar_t::strength0() const
3535 {
3536 return STREN0(value_);
3537 }
3538
strength1() const3539 unsigned vvp_scalar_t::strength1() const
3540 {
3541 return STREN1(value_);
3542 }
3543
operator <<(ostream & out,vvp_scalar_t a)3544 ostream& operator <<(ostream&out, vvp_scalar_t a)
3545 {
3546 out << a.strength0() << a.strength1();
3547 switch (a.value()) {
3548 case BIT4_0:
3549 out << "0";
3550 break;
3551 case BIT4_1:
3552 out << "1";
3553 break;
3554 case BIT4_X:
3555 out << "X";
3556 break;
3557 case BIT4_Z:
3558 out << "Z";
3559 break;
3560 }
3561 return out;
3562 }
3563
3564 /*
3565 * This function is only called if the actual interface function rules
3566 * out some of the easy cases. If we get here, we can assume that
3567 * neither of the values is HiZ, and the values are not exactly equal.
3568 */
fully_featured_resolv_(vvp_scalar_t a,vvp_scalar_t b)3569 vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
3570 {
3571
3572 if (UNAMBIG(a.value_) && UNAMBIG(b.value_)) {
3573
3574 /* If both signals are unambiguous, simply choose
3575 the stronger. If they have the same strength
3576 but different values, then this becomes
3577 ambiguous. */
3578
3579 if ((b.value_&0x07) > (a.value_&0x07)) {
3580
3581 /* b value is stronger. Take it. */
3582 return b;
3583
3584 } else if ((b.value_&0x77) == (a.value_&0x77)) {
3585
3586 // Strengths are the same. Since we know already
3587 // that the values are not the same, Make value
3588 // into "x".
3589 vvp_scalar_t tmp (a);
3590 tmp.value_ = (tmp.value_&0x77) | 0x80;
3591 return tmp;
3592
3593 } else {
3594
3595 /* Must be "a" is the stronger one. */
3596 return a;
3597 }
3598
3599 }
3600
3601 /* If one of the signals is unambiguous, then it
3602 will sweep up the weaker parts of the ambiguous
3603 signal. The result may be ambiguous, or maybe not. */
3604
3605 if (UNAMBIG(a.value_)) {
3606 vvp_scalar_t res;
3607
3608 if ((a.value_&0x70) > (b.value_&0x70))
3609 res.value_ |= a.value_&0xf0;
3610 else
3611 res.value_ |= b.value_&0xf0;
3612
3613 if ((a.value_&0x07) > (b.value_&0x07))
3614 res.value_ |= a.value_&0x0f;
3615 else
3616 res.value_ |= b.value_&0x0f;
3617
3618 return res;
3619
3620 } else if (UNAMBIG(b.value_)) {
3621
3622 vvp_scalar_t res;
3623
3624 if ((b.value_&0x70) > (a.value_&0x70))
3625 res.value_ |= b.value_&0xf0;
3626 else
3627 res.value_ |= a.value_&0xf0;
3628
3629 if ((b.value_&0x07) > (a.value_&0x07))
3630 res.value_ |= b.value_&0x0f;
3631 else
3632 res.value_ |= a.value_&0x0f;
3633
3634 return res;
3635
3636 }
3637
3638
3639 /* If both signals are ambiguous, then the result
3640 has an even wider ambiguity. */
3641
3642 unsigned tmp = 0;
3643 int sv1a = (a.value_ & 0x80) ? STREN1(a.value_) : - STREN1(a.value_);
3644 int sv0a = (a.value_ & 0x08) ? STREN0(a.value_) : - STREN0(a.value_);
3645 int sv1b = (b.value_ & 0x80) ? STREN1(b.value_) : - STREN1(b.value_);
3646 int sv0b = (b.value_ & 0x08) ? STREN0(b.value_) : - STREN0(b.value_);
3647
3648 int sv1 = sv1a;
3649 int sv0 = sv0a;
3650
3651 if (sv0a > sv1)
3652 sv1 = sv0a;
3653 if (sv1b > sv1)
3654 sv1 = sv1b;
3655 if (sv0b > sv1)
3656 sv1 = sv0b;
3657
3658 if (sv1a < sv0)
3659 sv0 = sv1a;
3660 if (sv1b < sv0)
3661 sv0 = sv1b;
3662 if (sv0b < sv0)
3663 sv0 = sv0b;
3664
3665 if (sv1 > 0) {
3666 tmp |= 0x80;
3667 tmp |= sv1 << 4;
3668 } else {
3669 /* Set the MSB when both arguments MSBs are set. This
3670 can only happen if both one strengths are zero. */
3671 tmp |= (a.value_&b.value_)&0x80;
3672 tmp |= (-sv1) << 4;
3673 }
3674
3675 if (sv0 > 0) {
3676 tmp |= 0x08;
3677 tmp |= sv0;
3678 } else {
3679 tmp |= (-sv0);
3680 }
3681
3682 vvp_scalar_t res;
3683 res.value_ = tmp;
3684
3685 /* Canonicalize the HiZ value. */
3686 if ((res.value_&0x77) == 0)
3687 res.value_ = 0;
3688
3689 return res;
3690 }
3691
3692 unsigned vvp_switch_strength_map[2][8] = {
3693 { // non-resistive
3694 0, /* High impedance --> High impedance */
3695 1, /* Small capacitor --> Small capacitor */
3696 2, /* Medium capacitor --> Medium capacitor */
3697 3, /* Weak drive --> Weak drive */
3698 4, /* Large capacitor --> Large capacitor */
3699 5, /* Pull drive --> Pull drive */
3700 6, /* Strong drive --> Strong drive */
3701 6 /* Supply drive --> Strong drive */
3702 },
3703 { // resistive
3704 0, /* High impedance --> High impedance */
3705 1, /* Small capacitor --> Small capacitor */
3706 1, /* Medium capacitor --> Small capacitor */
3707 2, /* Weak drive --> Medium capacitor */
3708 2, /* Large capacitor --> Medium capacitor */
3709 3, /* Pull drive --> Weak drive */
3710 5, /* Strong drive --> Pull drive */
3711 5 /* Supply drive --> Pull drive */
3712 }
3713 };
3714
reduce4(const vvp_vector8_t & that)3715 vvp_vector4_t reduce4(const vvp_vector8_t&that)
3716 {
3717 vvp_vector4_t out (that.size());
3718 for (unsigned idx = 0 ; idx < out.size() ; idx += 1)
3719 out.set_bit(idx, that.value(idx).value());
3720
3721 return out;
3722 }
3723
compare_gtge(const vvp_vector4_t & lef,const vvp_vector4_t & rig,vvp_bit4_t out_if_equal)3724 vvp_bit4_t compare_gtge(const vvp_vector4_t&lef, const vvp_vector4_t&rig,
3725 vvp_bit4_t out_if_equal)
3726 {
3727 unsigned min_size = lef.size();
3728 if (rig.size() < min_size)
3729 min_size = rig.size();
3730
3731 // If one of the inputs is nil, treat is as all X values, and
3732 // that makes the result BIT4_X.
3733 if (min_size == 0)
3734 return BIT4_X;
3735
3736 // As per the IEEE1364 definition of >, >=, < and <=, if there
3737 // are any X or Z values in either of the operand vectors,
3738 // then the result of the compare is BIT4_X.
3739
3740 // Check for X/Z in the left operand
3741 if (lef.has_xz())
3742 return BIT4_X;
3743
3744 // Check for X/Z in the right operand
3745 if (rig.has_xz())
3746 return BIT4_X;
3747
3748 for (unsigned idx = lef.size() ; idx > rig.size() ; idx -= 1) {
3749 if (lef.value(idx-1) == BIT4_1)
3750 return BIT4_1;
3751 }
3752
3753 for (unsigned idx = rig.size() ; idx > lef.size() ; idx -= 1) {
3754 if (rig.value(idx-1) == BIT4_1)
3755 return BIT4_0;
3756 }
3757
3758 for (unsigned idx = min_size ; idx > 0 ; idx -= 1) {
3759 vvp_bit4_t lv = lef.value(idx-1);
3760 vvp_bit4_t rv = rig.value(idx-1);
3761
3762 if (lv == rv)
3763 continue;
3764
3765 if (lv == BIT4_1)
3766 return BIT4_1;
3767 else
3768 return BIT4_0;
3769 }
3770
3771 return out_if_equal;
3772 }
3773
compare_gtge_signed(const vvp_vector4_t & a,const vvp_vector4_t & b,vvp_bit4_t out_if_equal)3774 vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
3775 const vvp_vector4_t&b,
3776 vvp_bit4_t out_if_equal)
3777 {
3778 assert(a.size() == b.size());
3779
3780 unsigned sign_idx = a.size()-1;
3781 vvp_bit4_t a_sign = a.value(sign_idx);
3782 vvp_bit4_t b_sign = b.value(sign_idx);
3783
3784 if (bit4_is_xz(a_sign))
3785 return BIT4_X;
3786 if (bit4_is_xz(b_sign))
3787 return BIT4_X;
3788
3789 if (a_sign == b_sign)
3790 return compare_gtge(a, b, out_if_equal);
3791
3792 if (a.has_xz())
3793 return BIT4_X;
3794
3795 if (b.has_xz())
3796 return BIT4_X;
3797
3798 if(a_sign == BIT4_0)
3799 return BIT4_1;
3800 else
3801 return BIT4_0;
3802 }
3803