1 #ifndef FREEHDL_STD_VHDL_TYPES_H
2 #define FREEHDL_STD_VHDL_TYPES_H
3
4 #include <stdio.h>
5 #include <limits.h>
6 #include <float.h>
7 #include <math.h>
8 #include <iostream>
9 #include <string.h>
10
11 #include <freehdl/std-memory.hh>
12 #include <freehdl/kernel-error.hh>
13 #include <freehdl/kernel-acl.hh>
14
15 using namespace std;
16
17 typedef long long int lint;
18 const int BUFFER_STREAM_SIZE_INCREMENT = 1024;
19
20 // replaces ostrstream in order to speedup simulation. Furhter, this
21 // stream can also handle raw binary data, i.e., data which may
22 // contain 0 as an element!
23 class buffer_stream
24 {
25 public:
26 char* buffer;
27 char* end_of_buffer;
28 char* pos_cursor;
29
resize()30 void resize()
31 {
32 int size = end_of_buffer - buffer;
33 int fill_count = pos_cursor - buffer;
34 buffer = (char*)realloc(buffer, size + BUFFER_STREAM_SIZE_INCREMENT);
35 end_of_buffer = buffer + size + BUFFER_STREAM_SIZE_INCREMENT;
36 pos_cursor = buffer + fill_count;
37 }
38
39 //constructor
buffer_stream()40 buffer_stream(){
41 buffer = end_of_buffer = pos_cursor = NULL;
42 resize();
43 buffer [0] = '\0';
44 }
45
46 //desconstructor
~buffer_stream()47 ~buffer_stream()
48 {
49 if (buffer != NULL)
50 free (buffer);
51 }
52
53 // Write binary data to stream. Note that after writing binary data
54 // to the stream the buffer usually is NOT ended with 0 !
binary_write(const void * src,const int len)55 buffer_stream& binary_write(const void *src, const int len) {
56 while (pos_cursor + len >= end_of_buffer)
57 resize();
58 memcpy(pos_cursor, src, len);
59 pos_cursor += len;
60 return *this;
61 }
62
63 // output operator
operator <<(const char * c)64 buffer_stream& operator<<(const char* c) {
65 const int len = strlen(c);
66 if (pos_cursor + len >= end_of_buffer)
67 resize();
68 strcpy(pos_cursor, c);
69 pos_cursor += len;
70 return *this;
71 }
72
operator <<(const char c)73 buffer_stream& operator<<(const char c) {
74 if (c != '\0') {
75 if (pos_cursor + 2 >= end_of_buffer)
76 resize();
77 *(pos_cursor++) = c;
78 }
79 *pos_cursor = '\0';
80 return *this;
81 }
82
operator <<(const int i)83 buffer_stream& operator<<(const int i) {
84 // An int converted to decimal will never have more than 12
85 // characters
86 char ibuffer[13];
87 char *cursor = ibuffer + 12;
88 int l;
89 *(cursor--) = '\0';
90 if (i > 0) {
91 l = i;
92 while (l > 0) {
93 int new_l = l / 10;
94 int diff = l - (new_l << 3) - (new_l << 1);
95 *(cursor--) = (char)diff + '0';
96 l = new_l;
97 }
98 } else if (i < 0) {
99 l = -i;
100 while (l > 0) {
101 int new_l = l / 10;
102 int diff = l - (new_l << 3) - (new_l << 1);
103 *(cursor--) = (char)diff + '0';
104 l = new_l;
105 }
106 *(cursor--) = '-';
107 } else
108 *(cursor--) = '0';
109
110 if (pos_cursor + 30 >= end_of_buffer)
111 resize();
112 strcpy(pos_cursor, cursor+1);
113 pos_cursor += ibuffer + 12 - cursor - 1;
114
115 return *this;
116 }
117
operator <<(const lint i)118 buffer_stream& operator<<(const lint i) {
119 // An lint converted to decimal will never have more than 30
120 // characters
121 char ibuffer[31];
122 char *cursor = ibuffer + 30;
123 lint l;
124 *(cursor--) = '\0';
125 if (i > 0) {
126 l = i;
127 while (l > 0) {
128 lint new_l = l / 10;
129 lint diff = l - (new_l << 3) - (new_l << 1);
130 *(cursor--) = (char)diff + '0';
131 l = new_l;
132 }
133 } else if (i < 0) {
134 l = -i;
135 while (l > 0) {
136 lint new_l = l / 10;
137 lint diff = l - (new_l << 3) - (new_l << 1);
138 *(cursor--) = (char)diff + '0';
139 l = new_l;
140 }
141 *(cursor--) = '-';
142 } else
143 *(cursor--) = '0';
144
145 if (pos_cursor + 30 >= end_of_buffer)
146 resize();
147 strcpy(pos_cursor, cursor+1);
148 pos_cursor += ibuffer + 30 - cursor - 1;
149
150 return *this;
151 }
152
operator <<(string & s)153 buffer_stream& operator<<(string& s) {
154 return *this << s.c_str();
155 }
156
operator <<(const double i)157 buffer_stream& operator<<(const double i) {
158 char ibuffer[40];
159 sprintf(ibuffer,"%e",i);
160 return *this << ibuffer;
161 }
162
str_len()163 int str_len() {
164 return (int)(pos_cursor - buffer);
165 }
166
init(char * pos_cursor)167 void init(char* pos_cursor){
168 if(pos_cursor == end_of_buffer)
169 buffer =(char*)realloc((void*)buffer, 1024);
170 }
171
172 //clean function
clean()173 void clean(){ pos_cursor = buffer; };
reinit()174 void reinit() {
175 if (buffer != NULL)
176 free (buffer);
177 end_of_buffer = buffer = pos_cursor = NULL;
178 resize();
179 }
str()180 char *str() { return buffer; }
181 };
182
183
184
185 /* *************************************************************
186 * Type-Ids for the different VHDL type groups
187 * ************************************************************* */
188 typedef unsigned char type_id;
189 #define INTEGER 1
190 #define ENUM 2
191 #define FLOAT 3
192 #define PHYSICAL 4
193 #define RECORD 5
194 #define ARRAY 6
195 #define ACCESS 7
196 #define VHDLFILE 8
197
scalar(type_id id)198 inline bool scalar(type_id id)
199 {
200 switch (id) {
201 case RECORD:
202 case ARRAY:
203 return false;
204 default:
205 return true;
206 }
207 }
208
209 /* *************************************************************
210 * Typedefs
211 * ************************************************************* */
212 typedef long long int lint;
213 typedef unsigned char uchar;
214
215
216 /* *************************************************************
217 * Logartihmus dualis of the sizes of VHDL types (in Bytes)
218 * ************************************************************* */
219 #define INTEGER_SIZE sizeof(integer)
220 #define ENUM_SIZE sizeof(enumeration)
221 #define FLOAT_SIZE sizeof(floatingpoint)
222 #define PHYSICAL_SIZE sizeof(physical)
223 /* HACK: see below */
224 #define RECORD_SIZE (2*sizeof(void*))
225 /* HACK: an array instance actually consists of two pointers (not
226 * including memory for info and data instances). We cannot use
227 * sizeof(array_base) here as array_base will be defined at the end of
228 * this file while ARRAY_SIZE is used before! */
229 #define ARRAY_SIZE (2*sizeof(void*))
230 #define ACCESS_SIZE sizeof(void*)
231 #define VHDLFILE_SIZE sizeof(iostream*)
232
233 #define INTEGER_SIZE_LD 32
234
235
236 /* *************************************************************
237 * All VHDL integer types are actually C ints
238 * ************************************************************* */
239 typedef int integer;
240
241 /* Always returns the id of the type. The parameter is actually not
242 * needed but used to select the appropriate function id. */
id(integer * d)243 inline type_id id(integer *d) { return INTEGER; }
244
245 /* Actually does nothing */
cleanup(integer * d)246 inline void cleanup(integer *d) { };
247
248 /* mod operator */
op_mod(const integer a,const integer b)249 inline integer op_mod(const integer a, const integer b) {
250 register int tmp = a % b;
251 return ((b^tmp) < 0)? tmp + b : tmp;
252 }
253
254 /* power operator */
op_power(const integer a,const integer b)255 inline integer op_power(const integer a, const integer b) {
256 return (integer)pow((double)a, (double)b);
257 }
258
259 /* absolute operator */
op_abs(const integer a)260 inline integer op_abs (const integer a) { return abs (a); }
261
262 /* *************************************************************
263 * All VHDL access type are actually void pointer
264 * ************************************************************* */
265 typedef void * vhdlaccess;
266
267 /* Always returns the id of the type. The parameter is actually not
268 * needed but used to select the appropriate function id. */
id(vhdlaccess * d)269 inline type_id id(vhdlaccess *d) { return ACCESS; }
270
271 /* Actually does nothing */
cleanup(vhdlaccess * d)272 inline void cleanup(vhdlaccess *d) { };
273
274
275 /* *************************************************************
276 * All VHDL enumeration types are actually C chars
277 * ************************************************************* */
278 typedef unsigned char enumeration;
279
280 /* Always returns the id of the type. The parameter is actually not
281 * needed but used to select the appropriate function id. */
id(enumeration * d)282 inline type_id id(enumeration *d) { return ENUM; }
283
284 /* Actually does nothing */
cleanup(enumeration * d)285 inline void cleanup(enumeration *d) { };
286
287
288 /* *************************************************************
289 * All VHDL floating point types are actually C doubles
290 * ************************************************************* */
291 typedef double floatingpoint;
292
293 /* Always returns the id of the type. The parameter is actually not
294 * needed but used to select the appropriate function id. */
id(floatingpoint * d)295 inline type_id id(floatingpoint *d) { return FLOAT; }
296
297 /* Actually does nothing */
cleanup(floatingpoint * d)298 inline void cleanup(floatingpoint *d) { };
299
300 /* power operator */
op_power(const floatingpoint a,const integer b)301 inline floatingpoint op_power(const floatingpoint a, const integer b) {
302 return pow(a, (double)b);
303 }
304
305 /* absolute operator */
op_abs(const floatingpoint a)306 inline floatingpoint op_abs (const floatingpoint a) {
307 return (floatingpoint)fabs (a);
308 }
309
310 /* *************************************************************
311 * All VHDL physical types are actually long long ints (64 bit)
312 * ************************************************************* */
313 typedef lint physical;
314
315 /* Always returns the id of the type. The parameter is actually not
316 * needed but used to select the appropriate function id. */
id(physical * d)317 inline type_id id(physical *d) { return PHYSICAL; }
318
319 /* Actually does nothing */
cleanup(physical * d)320 inline void cleanup(physical *d) { };
321
322 /* absolute operator */
op_abs(const physical a)323 inline physical op_abs (const physical a) {
324 return (a >= 0)? a : -a;
325 }
326
327
328 /* *************************************************************
329 * VHDL file types
330 * ************************************************************* */
331 struct vhdlfile {
332 bool do_close; // Is true if the stream must be closed manually
333 istream *in_stream;
334 ostream *out_stream;
vhdlfilevhdlfile335 vhdlfile() { in_stream = NULL; out_stream = NULL; do_close = false; }
~vhdlfilevhdlfile336 ~vhdlfile() {
337 if (do_close) return;
338 if (in_stream != NULL) delete in_stream;
339 if (out_stream != NULL) delete out_stream;
340 in_stream = NULL;
341 out_stream = NULL;
342 }
343 };
344
345 /* Always returns the id of the type. The parameter is actually not
346 * needed but used to select the appropriate function id. */
id(vhdlfile * d)347 inline type_id id(vhdlfile *d) { return VHDLFILE; }
348
349 /* Actually does nothing */
cleanup(vhdlfile * d)350 inline void cleanup(vhdlfile *d) { };
351
352
353
354 /* *************************************************************
355 * Some functions for composite types
356 * ************************************************************* */
357
358 /* Function to call the cleanup operator of the appropriate array
359 instance */
360 template<class A>
cleanup(A * p)361 void cleanup(A *p) { p->cleanup_instance(); }
362
363
364 /* *************************************************************
365 * Some operators
366 * ************************************************************* */
367
368 /* not operator */
op_not(const enumeration a)369 inline enumeration op_not(const enumeration a) {
370 return a ? 0 : 1;
371 }
372
373 /* nand operator */
op_nand(const enumeration a,const enumeration b)374 inline enumeration op_nand(const enumeration a, const enumeration b) {
375 return op_not(a & b);
376 }
377
378 /* xor operator */
op_xor(const enumeration a,const enumeration b)379 inline enumeration op_xor(const enumeration a, const enumeration b) {
380 return a ^ b;
381 }
382
383 /* xnor operator */
op_xnor(const enumeration a,const enumeration b)384 inline enumeration op_xnor(const enumeration a, const enumeration b) {
385 return op_not(op_xor(a, b));
386 }
387
388 /* nor operator */
op_nor(const enumeration a,const enumeration b)389 inline enumeration op_nor(const enumeration a, const enumeration b) {
390 return a | b ? 0 : 1;
391 }
392
393
394 /* *************************************************************
395 * Some functions of global interest
396 * ************************************************************* */
397
398 /* Returns true if value is in between left and right */
399 template<class T>
check_bounds(const T & left,const T & right,const T & value)400 inline bool check_bounds(const T &left, const T &right, const T &value) {
401 if (left <= right)
402 return left <= value && value <= right;
403 else
404 return left >= value && value >= right;
405 }
406
407 #if !(!defined __GNUC__ || __GNUC__ != 2)
408 template<class T>
min(const T old_value,const T new_value)409 inline T min(const T old_value, const T new_value) {
410 return new_value < old_value? new_value : old_value;
411 }
412
413 template<class T>
max(const T old_value,const T new_value)414 inline T max(const T old_value, const T new_value) {
415 return new_value > old_value? new_value : old_value;
416 }
417 #endif
418
419 /* Determine length of range */
420 template<class T>
421 inline T
range_to_length(T le,range_direction r,T ri)422 range_to_length(T le, range_direction r, T ri)
423 {
424 if (r == to)
425 return le <= ri? (ri - le + (T)1) : (T)0;
426 else
427 return ri <= le? (le - ri + (T)1) : (T)0;
428 }
429
430
431 template<class T>
432 inline T
up_range_to_length(T le,T ri)433 up_range_to_length(T le, T ri)
434 {
435 return le <= ri? (ri - le + (T)1) : (T)0;
436 }
437
438
439 template<class T>
440 inline T
down_range_to_length(T le,T ri)441 down_range_to_length(T le, T ri)
442 {
443 return ri <= le? (le - ri + (T)1) : (T)0;
444 }
445
446
447 /* Rotate left value by count bits. Should be mapped to the
448 * corresponding rotate left machine instruction by the C++ compiler! */
449 inline unsigned int
rotate_left(unsigned int value,int count)450 rotate_left(unsigned int value, int count)
451 {
452 return (value << count) | (value >> (sizeof(unsigned int) * 8 - count));
453 }
454
455
456 /* This function is used to select an appropriate alternative of an
457 * VHDL case statement where the selection expression is an array of
458 * characters */
459 inline int
do_case_select(const int size,const int key_count,const unsigned int key,const unsigned int * const sel,const unsigned int * const keys,const int * const key_to_lit,const enumeration ** const lit_tab,const int * const actions)460 do_case_select(const int size, const int key_count, const unsigned int key,
461 const unsigned int* const sel, const unsigned int* const keys,
462 const int* const key_to_lit, const enumeration** const lit_tab,
463 const int* const actions)
464 {
465 // Try to find a key in the key table which matches the key value
466 // calculated from the selection expression
467 for (int i = 0; i < key_count; i++)
468 if (key == keys[i]) {
469 // If a key was found then we use the index number of the key to
470 // access a table which stores for each key a list of pointer to
471 // array literals. Note that all these array literals are
472 // associated with the *same* key.
473 i = key_to_lit[i];
474 do {
475 // Compare the current selection array litaral with all those
476 // literals associated with the specific key (note that there
477 // may be more than one literal). If a match is found then use
478 // the index number to access an action table which stores the
479 // corresponding action number. Return the action number.
480 if (!memcmp(sel, lit_tab[i], size * sizeof(enumeration)))
481 return actions[i];
482 } while (lit_tab[++i] != 0);
483 break;
484 }
485
486 // If no match was found then return the default action number
487 return -1;
488 }
489
490
491 /* Returns address of object passed over as a parameter */
492 template<class T>
493 inline const void *
const_pointer(const T & a)494 const_pointer(const T &a) { return &a; }
495
496
497 /* Casts void pointer to type T and derefs it */
498 template<class T>
499 inline T
deref(void * p)500 deref(void *p) { return *(T*)p; }
501
502
503 /* *************************************************************
504 * Definitions required for signal resolution
505 * ************************************************************* */
506
507 // resolver_handler_p is a pointer type to a function which will be
508 // called by the kernel ro perform signal reolution. The first
509 // parameter points to a object which shall take the result of a
510 // resolving operation while the second parameter points to array
511 // containing the driver values to be resolved. The last parameter
512 // points to the unconstrained array_info.
513 class array_base;
514 class array_info;
515 class driver_info;
516 typedef void (*resolver_handler_p)(void*, driver_info*, array_base*, array_info*);
517
518
519
520 /* *************************************************************
521 * The type info interface class is te base class for all
522 * derived type info classes
523 * ************************************************************* */
524 class type_info_interface {
525 public:
526 const type_id id;
527 const uchar size; /* size of an object that corresponds with the
528 * type_info_instance */
529 bool resolved; /* set to true if the type is resolved. Note that the
530 * type_infos do NOT store any further information to
531 * support the resolving mechanism as these infos are
532 * used by the kernel only. Instead, the kernel
533 * collects and stores all necessary information. */
534
type_info_interface(const type_id i,const uchar s)535 type_info_interface(const type_id i, const uchar s) :
536 id(i), size(s), resolved(false) {};
~type_info_interface()537 virtual ~type_info_interface() {};
538 // Returns true if the current info instance describes a scalar type
539 inline bool scalar();
540
541 // Prints value of instance (src is pointing to) into a char
542 // buffer and returns a pointer to the buffer. Note, the buffer
543 // is static! Hence, each call to str uses the SAME buffer!
544 char *str(const void *src);
545
546 // Copy the content of src to dest. Note can be used
547 // for scalar VHDL objects only!
548 inline void *fast_copy(void *dest, const void *src);
549 // Compare the content of src and dest. Note: can be used
550 // for scalar VHDL objects only!
551 inline bool fast_compare(const void *dest, const void *src);
552 // Assigns the content of src and dest. Note: can be used
553 // for scalar VHDL objects only! Returns true if the new
554 // value differs from the old one.
555 inline bool fast_assign(void *dest, const void *src);
556
557 // Gets left and right bounds of an enumeration, integer or array
558 // type and returns 0. Returns -1 if type is no enumeration, integer
559 // or array type.
560 int get_bounds(int &left, range_direction &range, int &right);
561
562 // Create a new object. Memory is allocated by malloc
563 virtual void *create() = 0;
564 // Clone a object. Memory is allocated by malloc
565 virtual void *clone(const void *src) = 0;
566 // Copy the content of src to dest
567 virtual void *copy(void *dest, const void *src) = 0;
568 // Initiliazes an instance
569 virtual void init(void *src) = 0;
570 // Frees additional memory occupied by an object.
clear(void * src)571 virtual void clear(void *src) {};
572 // Compare src1 with src2. Returns true if they are equal
573 virtual bool compare(const void *src1, const void *src2) = 0;
574 // Copy the content of src to dest. Returns true if the new
575 // value differs from the old one
576 virtual bool assign(void *dest, const void *src) = 0;
577 // Removes an object (frees memory)
578 virtual void remove(void *src) = 0;
579 // This method does nothing for scalar types. For non-scalar types
580 // it assumes that src points to allocated memory that contains
581 // garbage. Hence, the method does *not* try to read the conent
582 // stored in *src.
583 void reset (void *src);
584 // Returns the address of an appropriate subelement of the current
585 // object. acl is the "path" to the subelement. Note that element
586 // returns the address of the left element in case of a "range"
587 // (slice) is applied onto an array.
element(void * src,acl * a)588 virtual void *element(void *src, acl *a) { return src; }
589 // Returns the address of an appropriate subelement of
590 // the current object. i is the index number of the subelment.
591 void *element(void *src, int i);
592 // Convert acl to index start and end. Returns start value
593 int acl_to_index(acl *a, int &start, int &end) const;
594 // Convert acl to index start
595 int acl_to_index(acl *a) const;
596 // Get info instance of scalar element with index i
597 type_info_interface *get_info(int i) const;
598 // Return info instance of element determined by acl a. src is an
599 // optional pointer to an object.
600 type_info_interface *get_info(void *src, acl *a) const;
601 // Returns the number of scalar elements of the current object
element_count()602 virtual int element_count() { return 1; }
603 // Prints the content of src into an string stream
604 virtual void print(buffer_stream &str, const void *src, int mode) = 0;
605 // Reads a value from a string and stores it into *dest. Further, in
606 // case of an error the function returns a pointer to the character
607 // which caused the failure or NULL otherwise.
608 virtual const char *read(void *dest, const char *str) = 0;
609 // Prints the content of src into an string stream in VCD format
610 virtual void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure) = 0;
611 // Prints value into binary stream. Note that only the raw data but
612 // no type info objects are written! The method returns the number
613 // of bytes written to the stream.
614 int binary_print(buffer_stream &str, const void *src);
615 // Reads value from memory (str) and puts the values into dest. The
616 // sequence of the data values must be the same as generated by
617 // binary_print. Note that only the raw data but no type info objects
618 // are read! Hence, the dest pointer must point to valid object of the
619 // appropriate size! Returns the number of bytes read or -1 if the
620 // read operation was not successfull.
621 int binary_read(void *dest, void *src);
622 // Usualy increments/decrements reference counter of type_info
623 // instances. However, as these instances are static for all
624 // but composite types both function actually do noting. Note
625 // that the corresponding methods are overloaded by the array_info
626 // and record_info classes.
add_ref()627 virtual void add_ref() { };
remove_ref()628 virtual void remove_ref() { };
629 // Add a resolver handler (required by the kernel to perform signal
630 // resolution) to a type. Returns a reference to the current info
631 // instance. handler points to a function which is used by the
632 // kernel to perform the resolution mechanism. ainfo points to a
633 // corresponding array_info instance describing the driver
634 // array. The last parameter stated whether the resolver function
635 // must not be called for a single source (ideal = true).
636 type_info_interface &add_resolver(resolver_handler_p handler, type_info_interface *ainfo, bool ideal);
637 // Register a type
638 void register_type(const char *sln, const char *ln, const char *n, void *sr);
639 };
640
641
642 /******************************************************
643 * Some definitions which are used by the kernel only
644 ******************************************************/
645 #ifdef KERNEL // This is only required when the kernel is compiled
646
647 // Constants to control printing of values via the
648 // type_info_interface::print method
649 #define VHDL_PRINT_MODE 0
650 #define CDFG_PRINT_MODE 1
651
652 // Copy the content of src to dest. Note, this method can be used for
653 // scalar VHDL objects only!
654 inline void *
fast_copy(void * dest,const void * src)655 type_info_interface::fast_copy(void *dest, const void *src)
656 {
657 switch (id) {
658 case ENUM:
659 *(enumeration*)dest = *(enumeration*)src;
660 break;
661 case INTEGER:
662 *(integer*)dest = *(integer*)src;
663 break;
664 case FLOAT:
665 case PHYSICAL:
666 *(physical*)dest = *(physical*)src;
667 break;
668 }
669 return dest;
670 }
671
672 // Compare the content of src and dest. Note: can be used
673 // for scalar VHDL objects only!
674 inline bool
fast_compare(const void * dest,const void * src)675 type_info_interface::fast_compare(const void *dest, const void *src)
676 {
677 switch (id) {
678 case ENUM:
679 return *(enumeration*)dest == *(enumeration*)src;
680 break;
681 case INTEGER:
682 return *(integer*)dest == *(integer*)src;
683 break;
684 case FLOAT:
685 case PHYSICAL:
686 return *(physical*)dest == *(physical*)src;
687 break;
688 }
689 return false;
690 }
691
692
693 // Assigns the content of src and dest. Note: can be used
694 // for scalar VHDL objects only! Returns true if the new
695 // value differs from the old one
696 inline bool
fast_assign(void * dest,const void * src)697 type_info_interface::fast_assign(void *dest, const void *src)
698 {
699 switch (id) {
700 case ENUM:
701 {
702 enumeration src_val = *(enumeration*)src, dest_val = *(enumeration*)dest;
703 if (src_val != dest_val) {
704 *(enumeration*)dest = src_val;
705 return true;
706 } else return false;
707 }
708 case INTEGER:
709 {
710 integer src_val = *(integer*)src, dest_val = *(integer*)dest;
711 if (src_val != dest_val) {
712 *(integer*)dest = src_val;
713 return true;
714 } else return false;
715 }
716 case FLOAT:
717 case PHYSICAL:
718 {
719 physical src_val = *(physical*)src, dest_val = *(physical*)dest;
720 if (src_val != dest_val) {
721 *(physical*)dest = src_val;
722 return true;
723 } else return false;
724 }
725 }
726 return false;
727 }
728
729
730 inline bool
scalar()731 type_info_interface::scalar()
732 {
733 switch (id) {
734 case RECORD:
735 case ARRAY:
736 return false;
737 default:
738 return true;
739 }
740 }
741
742
743 // Returns whether info is or includes array types which are not
744 // constrained. Returns true if no such type or element type was
745 // found.
746 bool
747 is_constrained(type_info_interface *info);
748
749 // Create a type instance based on a reference info rinfo and an acl
750 // a. The acl stores all information which are not included within the
751 // reference info. E.g., if the reference info is an unconstrained
752 // array then the acl stores the actual bounds of the array. Note that
753 // information which can be derived from the reference info is NOT
754 // stored in the acl!
755 type_info_interface *
756 setup_type_info_interface(type_info_interface *rinfo, pacl a);
757
758
759 /******************************************************
760 * End of internal kernel definitions
761 ******************************************************/
762 #endif
763
764
765 /* *************************************************************
766 * Integer info base class
767 * ************************************************************* */
768 class integer_info_base : public type_info_interface {
769 public:
770 integer left_bound, right_bound, low_bound, high_bound;
771
772 integer_info_base();
773
774 integer_info_base(const integer le, const integer ri,
775 const integer lo, const integer hi);
776
777 integer_info_base &set(integer_info_base *src);
778 integer_info_base &set(const integer le, const integer ri,
779 const integer lo, const integer hi);
780 void *create();
781 void *clone(const void *src);
782 void *copy(void *dest, const void *src);
783 void init(void *src);
784 bool compare(const void *src1, const void *src2);
785 bool assign(void *dest, const void *src);
786 void remove(void *src);
787 void print(buffer_stream &str, const void *src, int mode);
788 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure);
789 const char *read(void *dest, const char *str);
790
check(integer value)791 integer check(integer value) {
792 if (value >= low_bound && value <= high_bound)
793 return value;
794 else
795 error(ERROR_SCALAR_OUT_OF_BOUNDS, this, &value);
796 return 0;
797 }
798 };
799
800
801
802
803 /* *************************************************************
804 * Access info base class
805 * ************************************************************* */
806 class access_info_base : public type_info_interface {
807 public:
808 type_info_interface *designated_type_info;
809
810 access_info_base();
811
812 access_info_base(type_info_interface *d_info);
813
814 access_info_base &set(type_info_interface *d_info);
815
816 void *create();
817 void *clone(const void *src);
818 void *copy(void *dest, const void *src);
819 void init(void *src);
820 bool compare(const void *src1, const void *src2);
821 bool assign(void *dest, const void *src);
822 void remove(void *src);
823 void print(buffer_stream &str, const void *src, int mode);
vcd_print(buffer_stream & str,const void * src,char * translation_table,bool pure)824 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure) {};
825 const char *read(void *dest, const char *str);
826 };
827
828
829
830
831 /* *************************************************************
832 * File info base class
833 * ************************************************************* */
834 class vhdlfile_info_base : public type_info_interface {
835 public:
836 type_info_interface *type_info;
837
838 vhdlfile_info_base();
839
840 vhdlfile_info_base(type_info_interface *f_info);
841
842 vhdlfile_info_base &set(type_info_interface *f_info);
843
844 void *create();
845 void *clone(const void *src);
846 void *copy(void *dest, const void *src);
847 void init(void *src);
848 bool compare(const void *src1, const void *src2);
849 bool assign(void *dest, const void *src);
850 void remove(void *src);
print(buffer_stream & str,const void * src,int mode)851 void print(buffer_stream &str, const void *src, int mode) {};
vcd_print(buffer_stream & str,const void * src,char * translation_table,bool pure)852 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure) {};
853 const char *read(void *dest, const char *str);
854 };
855
856
857
858
859 /* *************************************************************
860 * Float info base class
861 * ************************************************************* */
862 class float_info_base : public type_info_interface {
863 public:
864 floatingpoint left_bound, right_bound, low_bound, high_bound;
865
866 float_info_base();
867
868 float_info_base(const floatingpoint le, const floatingpoint ri,
869 const floatingpoint lo, const floatingpoint hi);
870
871 float_info_base &set(const floatingpoint le, const floatingpoint ri,
872 const floatingpoint lo, const floatingpoint hi);
873 float_info_base &set(float_info_base *src);
874 void *create();
875 void *clone(const void *src);
876 void *copy(void *dest, const void *src);
877 void init(void *src);
878 bool compare(const void *src1, const void *src2);
879 bool assign(void *dest, const void *src);
880 void remove(void *src);
881 void print(buffer_stream &str, const void *src, int mode);
882 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure);
883 const char *read(void *dest, const char *str);
884
check(floatingpoint value)885 floatingpoint check(floatingpoint value) {
886 if (value >= low_bound && value <= high_bound)
887 return value;
888 else
889 error(ERROR_SCALAR_OUT_OF_BOUNDS, this, &value);
890 return 0;
891 }
892 };
893
894
895 /* *************************************************************
896 * Enum info base class
897 * ************************************************************* */
898 class enum_info_base : public type_info_interface {
899 public:
900 int left_bound, right_bound, length;
901 const char **values;
902
903 enum_info_base();
904
905 enum_info_base(const int le, const int ri, const char **val);
906
907 enum_info_base &set(const int le, const int ri, const char **val);
908 enum_info_base &set(enum_info_base *src);
909 void *create();
910 void *clone(const void *src);
911 void *copy(void *dest, const void *src);
912 void init(void *src);
913 bool compare(const void *src1, const void *src2);
914 bool assign(void *dest, const void *src);
915 void remove(void *src);
916 void print(buffer_stream &str, const void *src, int mode);
917 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure);
918 const char *read(void *dest, const char *str);
919
check(integer value)920 enumeration check(integer value) {
921 if (value >= left_bound && value <= right_bound)
922 return value;
923 else
924 error(ERROR_SCALAR_OUT_OF_BOUNDS, this, &value);
925 return 0;
926 }
927 };
928
929 /* *************************************************************
930 * Physical info base class
931 * ************************************************************* */
932 class physical_info_base : public type_info_interface {
933 public:
934 physical left_bound, right_bound, low_bound, high_bound;
935 const char **units;
936 const physical *scale;
937 int unit_count;
938
939 physical_info_base();
940
941 physical_info_base(const physical le, const physical ri,
942 const physical lo, const physical hi,
943 const char **un, const physical *sc, int uc);
944
945 physical_info_base &set(const physical le, const physical ri,
946 const physical lo, const physical hi,
947 const char **un, const physical *sc, int uc);
948 physical_info_base &set(physical_info_base *src);
949 void *create();
950 void *clone(const void *src);
951 void *copy(void *dest, const void *src);
952 void init(void *src);
953 bool compare(const void *src1, const void *src2);
954 bool assign(void *dest, const void *src);
955 void remove(void *src);
956 void print(buffer_stream &str, const void *src, int mode);
957 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure) ;
958 const char *read(void *dest, const char *str);
959
check(physical value)960 physical check(physical value) {
961 if (value >= low_bound && value <= high_bound)
962 return value;
963 else
964 error(ERROR_SCALAR_OUT_OF_BOUNDS, this, &value);
965 return 0;
966 }
967 };
968
969
970 /* *************************************************************
971 * Record info base class
972 * ************************************************************* */
973 class record_info : public type_info_interface {
974 public:
975 int record_size;
976 int data_size;
977 type_info_interface **element_types;
978 void *(*element_addr) (void*, int);
979 const char **element_names;
980
981 /* Counts the number of instances which are currently using this
982 * record_info object. Hence, several record instances may
983 * share a single record_info instance! */
984 int ref_counter;
985
986 /* Memory management for record_info instances. */
operator new(size_t s)987 void *operator new(size_t s) {
988 return (record_info*)internal_dynamic_alloc(sizeof(record_info));
989 }
990
operator delete(void * a)991 void operator delete(void *a) {
992 internal_dynamic_remove(a, sizeof(record_info));
993 }
994
record_info()995 record_info () : type_info_interface(RECORD, RECORD_SIZE) {
996 record_size = -1; data_size = -1; element_types = NULL; element_addr = NULL; element_names = NULL;
997 }
998 record_info (int rs, int ds, const char **en, void *(*ea)(void*, int), int rc);
set(int rs,int ds,const char ** en,void * (* ea)(void *,int),int rc)999 record_info &set(int rs, int ds, const char **en, void *(*ea)(void*, int), int rc) {
1000 record_size = rs;
1001 data_size = ds;
1002 element_names = en;
1003 element_addr = ea;
1004 element_types = (type_info_interface**)internal_dynamic_alloc(record_size * sizeof(type_info_interface*));
1005 memset(element_types, 0, record_size * sizeof(type_info_interface*));
1006 ref_counter = rc;
1007
1008 return *this;
1009 }
1010
1011 /* Initialize record info from other record info */
set(record_info * info,int rc)1012 record_info &set (record_info *info, int rc)
1013 {
1014 record_size = info->record_size;
1015 data_size = info->data_size;
1016 element_types = info->element_types;
1017 element_addr = info->element_addr;
1018 element_names = info->element_names;
1019 ref_counter = rc;
1020
1021 return *this;
1022 }
1023
1024 /* Set info pointer of index "index" to eti */
set(int index,type_info_interface * eti)1025 record_info &set(int index, type_info_interface *eti) {
1026 element_types[index] = eti;
1027 eti->add_ref();
1028 return *this;
1029 }
1030
~record_info()1031 ~record_info () {
1032
1033 /* Do not destruct permanent structs at all. Global objects can
1034 not be handled reliably since their destructors will be run in
1035 no particular order and the type_info_interface structs
1036 referenced by element_types could have been destroyed before
1037 running this destructor, for example. */
1038
1039 if (ref_counter < 0)
1040 return;
1041
1042 if (element_types)
1043 {
1044 for (int i = 0; i < record_size; i++)
1045 if (element_types[i] != NULL)
1046 element_types[i]->remove_ref();
1047
1048 internal_dynamic_remove (element_types,
1049 record_size * sizeof(type_info_interface*));
1050 }
1051 }
1052
1053 /* Returns the number of scalar elements of the current type */
element_count()1054 int element_count() {
1055 int count = 0;
1056 for (int i = 0; i < record_size; i++)
1057 count += element_types[i]->element_count();
1058 return count;
1059 }
1060 /* Returns the address of an appropriate element of the current
1061 * object. acl is the "path" to the element */
1062 void *element(void *src, acl *a);
1063
1064 /* This method must be called by each array instance which references
1065 * the current info instance */
add_ref()1066 void add_ref() {
1067 if (ref_counter >= 0) ref_counter++;
1068 }
1069 /* If rec_counter == 0 then no object uses this info instance and
1070 * it is removed. Note, there are also static info instances which
1071 * are not removed even when they are not in use. To create a
1072 * static info instance, array_info is called with parameter -1. */
remove_ref()1073 void remove_ref() {
1074 if (ref_counter > 0) {
1075 ref_counter--;
1076 if (ref_counter == 0)
1077 delete this;
1078 }
1079 }
1080
1081 void *create();
1082 void *clone(const void *src);
1083 void *copy(void *dest, const void *src);
1084 void init(void *src);
1085 void clear(void *src);
compare(const void * src1,const void * src2)1086 bool compare(const void *src1, const void *src2) { return false; };
assign(void * dest,const void * src)1087 bool assign(void *dest, const void *src) { return false; };
1088 void remove(void *src);
1089 void print(buffer_stream &str, const void *src, int mode);
1090 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure) ;
1091 const char *read(void *dest, const char *str);
1092 };
1093
1094
1095
1096
1097 /* *************************************************************
1098 * Array info class
1099 * ************************************************************* */
1100
1101 class array_info : public type_info_interface {
1102 public:
1103 /* Dimension info */
1104 range_direction index_direction; /* = "to" if index is of enumeration type */
1105 int left_bound, right_bound;
1106 int length; /* = -1 if bounds are actually not set (unconstrained array) */
1107
1108 /* Index type info */
1109 type_info_interface *index_type;
1110
1111 /* Element info */
1112 type_info_interface *element_type;
1113
1114 /* Counts the number of array instances which are currently using
1115 * this array_info_base object to define their bounds. Hence, several
1116 * array instances may share a single array_info_base instance! */
1117 int ref_counter;
1118
1119 /* Methods */
1120
1121 /* Memory management for array_info instances. */
operator new(size_t s)1122 void *operator new(size_t s) {
1123 return (array_info*)internal_dynamic_alloc(sizeof(array_info));
1124 }
1125
operator delete(void * a)1126 void operator delete(void *a) {
1127 internal_dynamic_remove(a, sizeof(array_info));
1128 }
1129
1130 /* Default constructor */
array_info()1131 array_info() : type_info_interface(ARRAY, ARRAY_SIZE)
1132 {
1133 length = -1;
1134 element_type = index_type = NULL;
1135 ref_counter = 0;
1136 }
1137 /* Destructor */
~array_info()1138 ~array_info() {
1139 /* See ~record_info for additional general comments about
1140 destructors of global objects. */
1141 if (ref_counter < 0)
1142 return;
1143 if (element_type)
1144 element_type->remove_ref();
1145 if (index_type)
1146 index_type->remove_ref();
1147 }
1148
1149 /* Constructor. If rc is set to -1 then the array_info instance
1150 * will not be removed */
1151 array_info &set(type_info_interface *et, type_info_interface *it, int rc);
1152 array_info(type_info_interface *et, type_info_interface *it, int rc);
1153 /* Constructor to create an info instance for an array subtype */
1154 /* Set the element info object and the range of the array */
set(type_info_interface * et,type_info_interface * it,int le,range_direction r,int ri,int rc=1)1155 array_info &set(type_info_interface *et, type_info_interface *it, int le, range_direction r, int ri, int rc = 1) {
1156 index_direction = r;
1157 left_bound = le;
1158 right_bound = ri;
1159 length = (ri - le) * (r == to? 1 : -1);
1160 length = length < 0? 0 : length + 1;
1161 ref_counter = rc;
1162 index_type = it;
1163 index_type->add_ref();
1164 element_type = et;
1165 element_type->add_ref();
1166 return *this;
1167 }
1168 array_info(type_info_interface *et, type_info_interface *it, int le, range_direction r, int ri, int rc);
1169 /* Constructor to create an info instance where the left bound is
1170 * determined by base and the right bound is derived from len */
1171 array_info &set(type_info_interface *et, type_info_interface *it, int len, int rc);
1172 array_info(type_info_interface *et, type_info_interface *it, int len, int rc);
1173
1174 /* Set the element info object */
set(type_info_interface * et)1175 void set(type_info_interface *et) { element_type = et; element_type->add_ref(); }
1176 /* This method must be called by each array instance which references
1177 * the current info instance */
add_ref()1178 void add_ref() {
1179 if (ref_counter >= 0) ref_counter++;
1180 }
1181 /* If rec_counter == 0 then no object uses this info instance and
1182 * it is removed. Note, there are also static info instances which
1183 * are not removed even when they are not in use. To create a
1184 * static info instance, array_info is called with parameter -1. */
remove_ref()1185 void remove_ref() {
1186 if (ref_counter > 0) {
1187 ref_counter--;
1188 if (ref_counter == 0)
1189 delete this;
1190 }
1191 }
1192
1193 // Check an array index value
check(int value)1194 int check(int value) {
1195 if (index_direction == to) {
1196 if (value >= left_bound && value <= right_bound)
1197 return value;
1198 } else
1199 if (value <= left_bound && value >= right_bound)
1200 return value;
1201 error(ERROR_ARRAY_INDEX, this, &value);
1202 }
1203
1204 /* The methods named "???_match" are used to test the bounds of the
1205 * current array_info instance. All methods return a pointer to the
1206 * current array_info instance. */
1207
1208 /* Methods to test whether an array_info instances has bounds and
1209 * direction as defined by a reference array_info instance */
1210 array_info *exact_match(type_info_interface *test_info);
1211 /* Methods to test whether an array_info instances has bounds le and
1212 * ri and direction r */
1213 array_info *exact_match(int le, range_direction r, int ri);
1214 /* Methods to test whether an array_info instances has length
1215 * len */
1216 array_info *length_match(int len);
1217
1218 /* Returns the number of scalar elements of the current type */
element_count()1219 int element_count() { return length * element_type->element_count(); }
1220 /* Returns the address of an appropriate subelement of
1221 * the current object. acl is the "path" to the subelement */
1222 void *element(void *src, acl *a);
1223
1224 void *create();
1225 void *clone(const void *src);
1226 void *copy(void *dest, const void *src);
1227 void init(void *src);
1228 void clear(void *src);
compare(const void * src1,const void * src2)1229 bool compare(const void *src1, const void *src2) { return false; };
assign(void * dest,const void * src)1230 bool assign(void *dest, const void *src) { return false; };
1231 void remove(void *src);
1232 void print(buffer_stream &str, const void *src, int mode);
1233 void vcd_print(buffer_stream &str, const void *src,char* translation_table, bool pure);
1234 const char *read(void *dest, const char *str);
1235 };
1236
1237
1238 // Function to cast an type_info_interface pointer to an array_info
1239 // pointer
parray_info(type_info_interface * t)1240 inline array_info *parray_info(type_info_interface *t) { return (array_info*)t; }
1241
1242
1243
1244 /* *************************************************************
1245 * The type classes
1246 * ************************************************************* */
1247
1248
1249 /* *************************************************************
1250 * Record type class
1251 * ************************************************************* */
1252
1253 /* Record base class */
1254 class record_base {
1255 public:
1256 record_info *info; /* Points to the object which stores information
1257 * about the current record */
1258 char *data; /* Pointer to the actual data of the record */
1259
record_base()1260 record_base() { };
1261 record_base(const record_base &a);
record_base(record_info * i)1262 record_base(record_info *i) { info = i; i->add_ref(); }
set_info(record_info * i)1263 void set_info(record_info *i) {
1264 if (info != NULL) info->remove_ref();
1265 info = i;
1266 i->add_ref();
1267 }
size()1268 static int size() { return RECORD_SIZE; }
1269 };
1270
1271 /* Always returns the id of the type. The parameter is actually not
1272 * needed but used to select the appropriate function id. */
id(record_base * d)1273 inline type_id id(record_base *d) { return RECORD; }
1274
1275
1276 /* E is a structure containing the actual record data */
1277 template<class E>
1278 class record_type : public record_base {
1279 public:
1280 typedef E E_type; /* declare a local type name which is equivalent
1281 * to the actual record type */
1282 /* Method to access record value */
value()1283 E &value() { return *(E*)data; }
1284 /* Method to access record value */
value() const1285 const E &value() const { return *(E*)data; }
1286
1287 inline void cleanup_instance();
record_type()1288 record_type() {};
1289 /* init initiliazes an record. The record elements are set to their
1290 * corresponding default values. */
init(type_info_interface * rinfo)1291 record_type &init(type_info_interface *rinfo) {
1292 info = (record_info*)rinfo;
1293 info->add_ref();
1294 data = (char*)internal_dynamic_alloc(sizeof(E));
1295 this->value().init(rinfo);
1296 return *this;
1297 }
1298 /* "p" points to an record instance. The record elements are copied
1299 * from "p". */
init(type_info_interface * rinfo,const void * p)1300 record_type &init(type_info_interface *rinfo, const void *p) {
1301 info = (record_info*)rinfo;
1302 info->add_ref();
1303 data = (char*)internal_dynamic_alloc(sizeof(E));
1304 this->value().init(rinfo, p);
1305 return *this;
1306 }
record_type(const record_type & r)1307 record_type(const record_type &r) : record_base() { init(r.info, (void*)&r); }
~record_type()1308 inline ~record_type() { cleanup_instance(); }
1309
1310 /* Methods used to build record aggregats */
1311 inline record_type &aggregate_set(int index, const void *element_value);
1312 inline record_type &aggregate_copy(int index, int copy_index);
1313
operator =(const record_type & record)1314 record_type &operator=(const record_type &record) {
1315 this->value() = record.value();
1316 return *this;
1317 }
1318
1319 // Note that only the relational operators == is directly defined in
1320 // the class as it is valid for all array classes (!= is defined by
1321 // combining ! and ==).
operator ==(const record_type & record)1322 bool operator==(const record_type &record) { return record.value() == this->value(); }
1323 };
1324
1325
1326 /* Method to cleanup a record instance, i.e. memory allocated by the
1327 * instance is freed */
1328 template<class E>
cleanup_instance()1329 inline void record_type<E>::cleanup_instance()
1330 {
1331 if (info != NULL)
1332 {
1333 record_info &rinfo = *info;
1334 for (int i = 0; i < rinfo.record_size; i++) {
1335 rinfo.element_types[i]->clear ( (*rinfo.element_addr) (data, i));
1336 rinfo.element_types[i]->remove_ref();
1337 }
1338
1339 rinfo.remove_ref();
1340 internal_dynamic_remove(data, rinfo.data_size);
1341 }
1342 }
1343
1344
1345 template<class E>
aggregate_set(int index,const void * element_value)1346 inline record_type<E> &record_type<E>::aggregate_set(int index, const void *element_value)
1347 {
1348 record_info &rinfo = *info;
1349 rinfo.element_types[index]->copy( (*rinfo.element_addr) (data, index), element_value);
1350 return *this;
1351 }
1352
1353
1354 template<class E>
aggregate_copy(int index,int copy_index)1355 inline record_type<E> &record_type<E>::aggregate_copy(int index, int copy_index)
1356 {
1357 record_info &rinfo = *info;
1358 rinfo.element_types[index]->copy( (*rinfo.element_addr) (data, index),
1359 (*rinfo.element_addr) (data, copy_index));
1360 return *this;
1361 }
1362
1363
1364
1365 /* *************************************************************
1366 * Array type class
1367 * ************************************************************* */
1368 class array_base {
1369 public:
1370 array_info *info; /* Points to the object which stores information
1371 * about the current array */
1372 char *data; /* Pointer to the actual data of the array */
1373
array_base()1374 array_base() { };
1375 array_base(const array_base &a);
array_base(array_info * i)1376 array_base(array_info *i) { info = i; i->add_ref(); }
set_info(array_info * i)1377 void set_info(array_info *i) {
1378 if (info != NULL) info->remove_ref();
1379 info = i;
1380 i->add_ref();
1381 }
1382 array_base &operator=(const array_base &a);
size()1383 static int size() { return ARRAY_SIZE; }
1384 };
1385
1386
1387 /* Always returns the id of the type. The parameter is actually not
1388 * needed but used to select the appropriate function id. */
id(array_base * d)1389 inline type_id id(array_base *d) { return ARRAY; }
1390
1391
1392 /* E is the array element type of the _unconstrained_ array range
1393 * type. */
1394 template<class E>
1395 class array_type : public array_base {
1396 public:
1397 typedef E E_type; /* declare a local type name which is
1398 * equivalent to the element type */
1399 inline void cleanup_instance();
array_type()1400 array_type() {};
1401 /* init initiliazes an array. The array elements are set to their
1402 * corresponding default values. */
1403 array_type &init(type_info_interface *ainfo);
1404 /* All elements of the array are initialized to "elem_init_value" */
1405 array_type &init(type_info_interface *ainfo, const E &elem_init_value);
1406 /* "p" points to an array instance. The array elements are copied
1407 * from "p". */
1408 array_type &init(type_info_interface *ainfo, const void *p);
init(const void * p)1409 array_type &init(const void *p) { init(((array_base*)p)->info, p); return *this; }
array_type(const array_type & a)1410 array_type(const array_type &a) : array_base() { init(a.info, (void*)&a); }
1411 array_type(array_info *ainfo, const E *iarray);
1412 array_type(array_info *ainfo, const E &val);
~array_type()1413 inline ~array_type() { cleanup_instance(); }
1414
1415 /* Methods used to build array aggregats */
1416 inline array_type &aggregate_set(int left, range_direction direction, int right, const E &value);
1417 inline array_type &aggregate_copy(int left, range_direction direction, int right, int copy_index);
1418
operator [](const int i)1419 E &operator[](const int i) {
1420 int index = (info->index_direction == to? i - info->left_bound : info->left_bound - i);
1421 if (index < 0 || index >= info->length)
1422 error(ERROR_ARRAY_INDEX);
1423 return ((E*)data)[index];
1424 }
1425
operator [](const int i) const1426 const E &operator[](const int i) const {
1427 int index = (info->index_direction == to? i - info->left_bound : info->left_bound - i);
1428 if (index < 0 || index >= info->length)
1429 error(ERROR_ARRAY_INDEX);
1430 return ((E*)data)[index];
1431 }
1432
operator ()(const int i)1433 E &operator()(const int i) { return ((E*)data)[i]; }
operator ()(const int i) const1434 const E &operator()(const int i) const { return ((E*)data)[i]; }
1435
1436 array_type &operator=(const array_type &array);
1437
1438 // Note that only the relational operators == is directly defined in
1439 // the class as it is valid for all array classes (!= is defined by
1440 // combining ! and ==).
1441 bool operator==(const array_type &array) const;
1442 };
1443
1444
1445 /* Method to cleanup an array instance, i.e. memory allocated by the
1446 instance is freed */
1447 template<class E>
cleanup_instance()1448 void array_type<E>::cleanup_instance()
1449 {
1450 if (data != NULL)
1451 {
1452 /* Note, scalar(...) can be evaluated at compile time. */
1453 if (!scalar(id((E*)NULL)))
1454 /* If the element type is not scalar then execute
1455 * cleanup() for each element in the array */
1456 for (int i = 0; i < info->length; i++)
1457 cleanup(&((E*)data)[i]);
1458
1459 if (data != NULL)
1460 internal_dynamic_remove(data, sizeof(E) * info->length); /* Remove data memory */
1461 }
1462
1463 if (info != NULL)
1464 info->remove_ref(); /* Unlink from the info instance */
1465 }
1466
1467
1468
1469
1470 /* The concat operator */
1471 template<class A, class E>
1472 A concat(array_info *ainfo, const A &a1, const A &a2)
1473 {
1474 int length = ainfo->length;
1475 // If both arrays are null arrays then return the result is the
1476 // right operand
1477 if (ainfo->length == 0)
1478 return A(a2);
1479
1480 // Create new array
1481 A new_array;
1482 new_array.info = ainfo;
1483 new_array.info->add_ref();
1484
1485 /* Allocate memory for the data */
1486 const int mem_size = length * ainfo->element_type->size;
1487 new_array.data = (char*)internal_dynamic_alloc(mem_size);
1488
1489 /* Note, scalar(...) can be evaluated at compile time. */
1490 type_info_interface *etype = ainfo->element_type;
1491 if (!scalar(id((E*)NULL))) {
1492 /* If the element type is not scalar then init the memory and
1493 * execute init(...) for each element in the array */
1494 memset(new_array.data, 0, mem_size);
1495 for (int i = 0; i < length; i++)
1496 etype->init(&((E*)new_array.data)[i]);
1497 }
1498
1499 /* Copy data */
1500 int length1 = a1.info->length1;
1501 int length2 = a2.info->length2;
1502 int i;
1503 for (i = 0; i < length1; i++)
1504 ((E*)new_array.data)[i] = ((E*)a1.data)[i];
1505 for (; i < length; i++)
1506 ((E*)new_array.data)[i] = ((E*)a2.data)[i];
1507
1508 return new_array;
1509 }
1510
1511
1512 /* Another version of the concat operator */
1513 template<class A, class E>
1514 A concat(const A &a1, const A &a2)
1515 {
1516 int length = a1.info->length + a2.info->length;
1517 // If both arrays are null arrays then return the result is the
1518 // right operand
1519 if (length == 0)
1520 return A(a2);
1521
1522 // Create new array
1523 A new_array;
1524 array_info &ref_ainfo = a1.info->length != 0? *a1.info : *a2.info;
1525
1526 new_array.info = new array_info(ref_ainfo.element_type, ref_ainfo.index_type, 0);
1527 array_info &new_info = *new_array.info;
1528 new_array.info->add_ref();
1529 int right;
1530 ref_ainfo.index_type->get_bounds(new_info.left_bound, new_info.index_direction, right);
1531 if (new_info.index_direction == to) {
1532 new_info.right_bound = new_info.left_bound + length - 1;
1533 if (new_info.right_bound > right) error(ERROR_ARRAY_INDEX_OUT_OF_BOUNDS);
1534 } else {
1535 new_info.right_bound = new_info.left_bound - length + 1;
1536 if (new_info.right_bound < right) error(ERROR_ARRAY_INDEX_OUT_OF_BOUNDS);
1537 }
1538 new_info.length = length;
1539
1540 /* Allocate memory for the data */
1541 const int mem_size = length * sizeof(E);
1542 new_array.data = (char*)internal_dynamic_alloc(mem_size);
1543
1544 /* Note, scalar(...) can be evaluated at compile time. */
1545 type_info_interface *etype = new_array.info->element_type;
1546 if (!scalar(id((E*)NULL))) {
1547 /* If the element type is not scalar then execute init(...) for
1548 * each element in the array after setting the memory to 0 */
1549 memset(new_array.data, 0, mem_size);
1550 for (int i = 0; i < length; i++)
1551 etype->init(&((E*)new_array.data)[i]);
1552 }
1553
1554 /* Copy data */
1555 int length1 = a1.info->length;
1556 int i;
1557 for (i = 0; i < length1; i++)
1558 ((E*)new_array.data)[i] = ((E*)a1.data)[i];
1559 for (int j = 0; i < length; i++, j++)
1560 ((E*)new_array.data)[i] = ((E*)a2.data)[j];
1561
1562 return new_array;
1563 }
1564
1565
1566
1567 template<class E>
array_type(array_info * ainfo,const E * iarray)1568 array_type<E>::array_type (array_info *ainfo, const E *iarray)
1569 {
1570 /* Create a new array_info instance */
1571 info = ainfo;
1572 info->add_ref();
1573
1574 /* Allocate memory for the data */
1575 int length = info->length;
1576 const int mem_size = length * sizeof(E);
1577 data = (char*)internal_dynamic_alloc(mem_size);
1578
1579 /* Note, scalar(...) can be evaluated at compile time. */
1580 type_info_interface *etype = info->element_type;
1581 if (!scalar(id((E*)NULL))) {
1582 /* If the element type is not scalar then execute init(...) for
1583 * each element in the array after initialing the memory to 0 */
1584 memset(data, 0, mem_size);
1585 for (int i = 0; i < length; i++)
1586 etype->init(&((E*)data)[i]);
1587 }
1588
1589 /* Copy data */
1590 for (int i = 0; i < length; i++)
1591 ((E*)data)[i] = iarray[i];
1592 }
1593
1594
1595 template<class E>
array_type(array_info * ainfo,const E & val)1596 array_type<E>::array_type (array_info *ainfo, const E &val)
1597 {
1598 /* Create a new array_info instance */
1599 info = ainfo;
1600 info->add_ref();
1601 int length = info->length;
1602
1603 /* Allocate memory for the data */
1604 const int mem_size = length * sizeof(E);
1605 data = (char*)internal_dynamic_alloc(mem_size);
1606
1607 /* Note, scalar(...) can be evaluated at compile time. */
1608 type_info_interface *etype = info->element_type;
1609 if (!scalar(id((E*)NULL))) {
1610 /* If the element type is not scalar then execute init(...) for
1611 * each element in the array after initialing the memory to 0 */
1612 memset(data, 0, mem_size);
1613 for (int i = 0; i < length; i++) {
1614 etype->init(&((E*)data)[i]);
1615 ((E*)data)[i] = val;
1616 }
1617
1618 } else {
1619 /* Each element of the array is set to val */
1620 const E val_copy = val; // Important for speed optimization
1621 for (int i = 0; i < length; i++)
1622 ((E*)data)[i] = val_copy;
1623 }
1624 }
1625
1626
1627 template<class E>
operator =(const array_type<E> & array)1628 array_type<E> &array_type<E>::operator=(const array_type<E> &array)
1629 {
1630 int length = info->length;
1631
1632 /* Check whether array bounds are compatible */
1633 if (info != array.info && length != array.info->length)
1634 error(ERROR_INCOMPATIBLE_ARRAYS);
1635
1636 /* Copy the data part of the arrays */
1637 if (scalar(id((E*)NULL))) {
1638 /* If the element type is not scalar then execute init(...) for
1639 * each element in the array after initialing the memory to 0 */
1640 const int mem_size = length * sizeof(E);
1641 memcpy(data, array.data, mem_size);
1642 } else
1643 for (int i = 0; i < length; i++)
1644 ((E*)data)[i] = ((E*)array.data)[i];
1645
1646 return *this;
1647 }
1648
1649
1650 template<class E>
operator ==(const array_type<E> & array) const1651 bool array_type<E>::operator==(const array_type<E> &array) const
1652 {
1653 const int length = info->length;
1654
1655 if (length != array.info->length) return false;
1656 /* Compare the data part of the arrays */
1657 for (int i = 0; i < length; i++)
1658 if ((((E*)data)[i] != ((E*)array.data)[i])) return false;
1659
1660 return true;
1661 }
1662
1663
1664 template<class E>
init(type_info_interface * ainfo,const void * p)1665 array_type<E> &array_type<E>::init(type_info_interface *ainfo, const void *p)
1666 {
1667 info = (array_info*)ainfo;
1668 info->add_ref();
1669 int length = info->length;
1670 type_info_interface *etype = info->element_type;
1671
1672 /* Allocate memory for the data */
1673 const int mem_size = length * sizeof(E);
1674 data = (char*)internal_dynamic_alloc(mem_size);
1675
1676 E *src_data = (E*)((array_base*)p)->data;
1677 /* Next, analyze element type of array */
1678 switch (id((E*)NULL)) {
1679 case ARRAY:
1680 {
1681 /* If the element type is not scalar then init memory to 0 */
1682 memset(data, 0, mem_size);
1683 /* Copy each element of the array */
1684 for (int i = 0; i < length; i++) {
1685 array_base &dest = (array_base&)((E*)data)[i];
1686 ((array_info*)etype)->init (&dest);
1687 etype->copy(&dest, &src_data[i]);
1688 }
1689 break;
1690 }
1691 case RECORD:
1692 {
1693 /* If the element type is not scalar then init memory to 0 */
1694 memset(data, 0, mem_size);
1695 /* Copy each element of the array */
1696 for (int i = 0; i < length; i++) {
1697 record_base &dest = (record_base&)((E*)data)[i];
1698 ((record_info*)etype)->init (&dest);
1699 etype->copy(&dest, &src_data[i]);
1700 }
1701 break;
1702 }
1703 default:
1704 {
1705 /* The element is a scalar simply copy the entire data region */
1706 memcpy(data, src_data, mem_size);
1707 break;
1708 }
1709 }
1710
1711 return *this;
1712 }
1713
1714
1715 template<class E>
init(type_info_interface * ainfo)1716 array_type<E> &array_type<E>::init(type_info_interface *ainfo)
1717 {
1718 info = (array_info*)ainfo;
1719 info->add_ref();
1720 int length = info->length;
1721 type_info_interface *etype = info->element_type;
1722
1723 /* Allocate memory for the data */
1724 const int mem_size = length * sizeof(E);
1725 data = (char*)internal_dynamic_alloc(mem_size);
1726
1727 if (scalar(id((E*)NULL))) {
1728 /* If the element type is scalar then create a single copy of the
1729 * element and use this copy to initialize the other array
1730 * elements */
1731 E elem_init_val;
1732 etype->init(&elem_init_val);
1733 for (int i = 0; i < length; i++)
1734 ((E*)data)[i] = elem_init_val;
1735
1736 } else {
1737 /* If the element type is not scalar then init memory to 0 */
1738 memset(data, 0, mem_size);
1739 /* Initialize each element of the array */
1740 for (int i = 0; i < length; i++)
1741 etype->init(&((E*)data)[i]);
1742 }
1743
1744 return *this;
1745 }
1746
1747
1748 template<class E>
init(type_info_interface * ainfo,const E & elem_init_value)1749 array_type<E> &array_type<E>::init(type_info_interface *ainfo, const E &elem_init_value)
1750 {
1751 info = (array_info*)ainfo;
1752 info->add_ref();
1753 int length = info->length;
1754
1755 /* Allocate memory for the data */
1756 const int mem_size = length * sizeof(E);
1757 data = (char*)internal_dynamic_alloc(mem_size);
1758
1759 /* Init data part */
1760 if (scalar(id((E*)NULL))) {
1761 // Create a local copy of the element value (important for speed
1762 // optimizations)
1763 const E elem_init_value_copy = elem_init_value;
1764 for (int i = 0; i < length; i++)
1765 ((E*)data)[i] = elem_init_value_copy;
1766
1767 } else {
1768 /* If the element type is not scalar then init memory to 0 */
1769 memset(data, 0, mem_size);
1770 type_info_interface *etype = info->element_type;
1771 for (int i = 0; i < length; i++) {
1772 etype->init(&((E*)data)[i]);
1773 ((E*)data)[i] = elem_init_value;
1774 }
1775 }
1776
1777 return *this;
1778 }
1779
1780
1781 /* Method to set array elements left to/downto right to value */
1782 template<class E>
aggregate_set(int left,range_direction direction,int right,const E & value)1783 inline array_type<E> &array_type<E>::aggregate_set(int left, range_direction direction, int right, const E &value)
1784 {
1785 if (direction == downto) {
1786 int tmp = left;
1787 left = right;
1788 right = tmp;
1789 }
1790 for (int i = left; i <= right; i++)
1791 (*this)[i] = value;
1792
1793 return *this;
1794 }
1795
1796
1797 /* Method to copys array element with index copy_index to array
1798 * elements left to/downto right to value */
1799 template<class E>
aggregate_copy(int left,range_direction direction,int right,int copy_index)1800 inline array_type<E> &array_type<E>::aggregate_copy(int left, range_direction direction, int right, int copy_index)
1801 {
1802 if (direction == downto) {
1803 int tmp = left;
1804 left = right;
1805 right = tmp;
1806 }
1807 E &value = ((E*)data)[copy_index];
1808 for (int i = left; i <= right; i++)
1809 (*this)[i] = value;
1810
1811 return *this;
1812 }
1813
1814
1815 /* *************************************************************
1816 * The relational operators <,<=, >, >= are not defined for each array
1817 * type. Hence, a separate set of template functions are defined here
1818 * which define operator < (op_array_lt) and operator <=
1819 * (op_array_le). The remaining relational operators are defined by
1820 * combining < and <= with operator ! (this is done online when the
1821 * C++ code is generated by the VHDL compiler).
1822 * ************************************************************* */
1823 template<class A, class B>
op_array_lt(const A & a1,const B & a2)1824 bool op_array_lt(const A &a1, const B &a2)
1825 {
1826 const int length1 = a1.info->length;
1827 const int length2 = a2.info->length;
1828 const int min_length = min(length1, length2);
1829
1830 /* Compare the data part of the arrays */
1831 for (int i = 0; i < min_length; i++)
1832 if (a1(i) != a2(i)) return a1(i) < a2(i);
1833
1834 return length1 < length2;
1835 }
1836
1837
1838 template<class A, class B>
op_array_le(const A & a1,const B & a2)1839 bool op_array_le(const A &a1, const B &a2)
1840 {
1841 const int length1 = a1.info->length;
1842 const int length2 = a2.info->length;
1843 const int min_length = min(length1, length2);
1844
1845 /* Compare the data part of the arrays */
1846 for (int i = 0; i < min_length; i++)
1847 if (a1(i) != a2(i)) return a1(i) < a2(i);
1848
1849 return length1 <= length2;
1850 }
1851
1852
1853 /* *************************************************************
1854 * The logical operators not, and, or, nor, xor, xnor are not defined
1855 * for each array type. Hence, a separate set of template functions
1856 * are defined.
1857 * ************************************************************* */
1858 template<class A>
op_array_not(const A & a)1859 A op_array_not (const A &a)
1860 {
1861 A result(a);
1862 const int length = a.info->length;
1863
1864 /* Compare the data part of the arrays */
1865 for (int i = 0; i < length; i++)
1866 result(i) = op_not(a(i));
1867
1868 return result;
1869 }
1870
1871 template<class A, class B>
1872 A op_array_and (const A &a1, const B &a2)
1873 {
1874 A result(a1);
1875 const int length = a1.info->length;
1876
1877 /* Check whether array bounds are compatible */
1878 if (a1.info != a2.info && length != a2.info->length)
1879 error(ERROR_INCOMPATIBLE_ARRAYS);
1880
1881 /* Handle data part of the arrays */
1882 for (int i = 0; i < length; i++)
1883 result(i) = a1(i) & a2(i);
1884
1885 return result;
1886 }
1887
1888
1889 template<class A, class B>
1890 A op_array_or (const A &a1, const B &a2)
1891 {
1892 A result(a1);
1893 const int length = a1.info->length;
1894
1895 /* Check whether array bounds are compatible */
1896 if (a1.info != a2.info && length != a2.info->length)
1897 error(ERROR_INCOMPATIBLE_ARRAYS);
1898
1899 /* Handle data part of the arrays */
1900 for (int i = 0; i < length; i++)
1901 result(i) = a1(i) | a2(i);
1902
1903 return result;
1904 }
1905
1906
1907 template<class A, class B>
1908 A op_array_nand (const A &a1, const B &a2)
1909 {
1910 A result(a1);
1911 const int length = a1.info->length;
1912
1913 /* Check whether array bounds are compatible */
1914 if (a1.info != a2.info && length != a2.info->length)
1915 error(ERROR_INCOMPATIBLE_ARRAYS);
1916
1917 /* Handle data part of the arrays */
1918 for (int i = 0; i < length; i++)
1919 result(i) = op_nand(a1(i), a2(i));
1920
1921 return result;
1922 }
1923
1924
1925 template<class A, class B>
1926 A op_array_nor (const A &a1, const B &a2)
1927 {
1928 A result(a1);
1929 const int length = a1.info->length;
1930
1931 /* Check whether array bounds are compatible */
1932 if (a1.info != a2.info && length != a2.info->length)
1933 error(ERROR_INCOMPATIBLE_ARRAYS);
1934
1935 /* Handle the data part of the arrays */
1936 for (int i = 0; i < length; i++)
1937 result(i) = op_nor(a1(i), a2(i));
1938
1939 return result;
1940 }
1941
1942
1943 template<class A, class B>
1944 A op_array_xor (const A &a1, const B &a2)
1945 {
1946 A result(a1);
1947 const int length = a1.info->length;
1948
1949 /* Check whether array bounds are compatible */
1950 if (a1.info != a2.info && length != a2.info->length)
1951 error(ERROR_INCOMPATIBLE_ARRAYS);
1952
1953 /* Handle data part of the arrays */
1954 for (int i = 0; i < length; i++)
1955 result(i) = op_xor(a1(i), a2(i));
1956
1957 return result;
1958 }
1959
1960
1961 template<class A, class B>
1962 A op_array_xnor (const A &a1, const B &a2)
1963 {
1964 A result(a1);
1965 const int length = a1.info->length;
1966
1967 /* Check whether array bounds are compatible */
1968 if (a1.info != a2.info && length != a2.info->length)
1969 error(ERROR_INCOMPATIBLE_ARRAYS);
1970
1971 /* Handle data part of the arrays */
1972 for (int i = 0; i < length; i++)
1973 result(i) = op_xnor(a1(i), a2(i));
1974
1975 return result;
1976 }
1977
1978
1979 template<class A>
op_array_sll(const A & a,integer j)1980 A op_array_sll (const A &a, integer j)
1981 {
1982 typedef typename A::E_type E;
1983 const int length = a.info->length;
1984 if (length <= 0) return a;
1985 const int shift = abs (j) % length;
1986
1987 /* Create result vector. Note that result is initialized with all
1988 * elements set to element_type'left */
1989 A result;
1990 result.init (a.info);
1991
1992 if (shift == 0) return a;
1993 else if (j > 0)
1994 /* Handle data part of the arrays */
1995 for (int i = 0; i < length - shift; i++)
1996 ((E*)result.data) [i] = ((E*)a.data) [i + shift];
1997 else
1998 for (int i = length - 1; i >= shift; i--)
1999 ((E*)result.data) [i] = ((E*)a.data) [i - shift];
2000
2001 return result;
2002 }
2003
2004
2005 template<class A>
op_array_srl(const A & a,integer j)2006 A op_array_srl (const A &a, integer j)
2007 {
2008 return op_array_sll<A> (a, -j);
2009 }
2010
2011
2012 template<class A>
op_array_sla(const A & a,integer j)2013 A op_array_sla (const A &a, integer j)
2014 {
2015 typedef typename A::E_type E;
2016 const int length = a.info->length;
2017 if (length <= 0) return a;
2018 const int shift = abs (j) % length;
2019
2020 /* Create result vector. Note that result is initialized with all
2021 * elements set to a[a'right] */
2022 A result;
2023 result.init (a.info, ((E*)a.data) [j > 0? length - 1 : 0]);
2024
2025 if (shift == 0) return a;
2026 else if (j > 0)
2027 /* Handle data part of the arrays */
2028 for (int i = 0; i < length - shift; i++)
2029 ((E*)result.data) [i] = ((E*)a.data) [i + shift];
2030 else
2031 for (int i = length - 1; i >= shift; i--)
2032 ((E*)result.data) [i] = ((E*)a.data) [i - shift];
2033
2034 return result;
2035 }
2036
2037
2038 template<class A>
op_array_sra(const A & a,integer j)2039 A op_array_sra(const A &a, integer j)
2040 {
2041 return op_array_sla (a, -j);
2042 }
2043
2044
2045 template<class A>
op_array_rol(const A & a,integer j)2046 A op_array_rol (const A &a, integer j)
2047 {
2048 typedef typename A::E_type E;
2049 const int length = a.info->length;
2050 if (length <= 0) return a;
2051 const int shift = abs (j) % length;
2052
2053 /* Create result vector */
2054 A result;
2055 result.init(a.info);
2056
2057 if (shift == 0) return a;
2058 else if (j > 0)
2059 /* Handle data part of the arrays */
2060 for (int i = 0; i < length; i++)
2061 ((E*)result.data) [i] =
2062 ((E*)a.data) [i + shift - (i + shift >= length? length : 0)];
2063 else
2064 for (int i = 0; i < length; i++)
2065 ((E*)result.data) [i] =
2066 ((E*)a.data) [i - shift + (i - shift < 0? length : 0)];
2067
2068 return result;
2069 }
2070
2071
2072 template<class A>
op_array_ror(const A & a,integer j)2073 A op_array_ror (const A &a, integer j)
2074 {
2075 return op_array_rol<A> (a, -j);
2076 }
2077
2078
2079 /* *************************************************************
2080 * Array alias type class
2081 * ************************************************************* */
2082
2083 /* array_alias class is a array class derived from an array_type class
2084 * (T). This special class is used to build array alias instances of
2085 * an array object. Basically, the alias class adds some new
2086 * constructors and a destructor. The constructors do not create a new
2087 * data array but reuse an existing array. Hence, the destructor does
2088 * not deallocate the data part of the array!
2089 *
2090 * Note that T must be an array_type class! */
2091 template<class T>
2092 class array_alias : public T {
2093 public:
array_alias()2094 array_alias(): T () {
2095 array_base &array = *(array_base*)this;
2096 array.info = NULL;
2097 array.data = NULL;
2098 }
array_alias(type_info_interface * et,type_info_interface * it,int le,range_direction dir,int ri,int rc,void * iarray)2099 array_alias(type_info_interface *et, type_info_interface *it,
2100 int le, range_direction dir, int ri, int rc, void *iarray) : T () {
2101 array_base &array = *(array_base*)this;
2102 /* Create a new array_info instance */
2103 array.info = new array_info(et, it, le, dir, ri, rc);
2104 array.data = (char*)iarray;
2105 }
2106 /* Note that here the bounds of the alias are taken from the
2107 * source array and NOT from the array base! */
array_alias(array_info * base,const array_base & abase)2108 array_alias(array_info *base, const array_base &abase) : T () {
2109 array_base &array = *(array_base*)this;
2110 const array_info &ainfo = *abase.info;
2111 array.info = new array_info(base->element_type, base->index_type, ainfo.left_bound,
2112 ainfo.index_direction, ainfo.right_bound, 1);
2113 array.data = abase.data;
2114 }
array_alias(array_info * ainfo,const void * iarray)2115 array_alias(array_info *ainfo, const void *iarray) : T () {
2116 array_base &array = *(array_base*)this;
2117 array.info = ainfo;
2118 array.info->add_ref();
2119 array.data = (char*)iarray;
2120 }
set(array_info * ainfo,void * iarray)2121 array_alias &set(array_info *ainfo, void *iarray) {
2122 array_base &array = *(array_base*)this;
2123 if (array.info != NULL)
2124 array.info->remove_ref();
2125 array.info = ainfo;
2126 array.info->add_ref();
2127 array.data = (char*)iarray;
2128 return *this;
2129 }
~array_alias()2130 ~array_alias() {
2131 /* Note that the data array is NOT deallocated as the memory has
2132 * been allocated by another array_type instance */
2133 array_base &array = *(array_base*)this;
2134 array.data = NULL; /* Set pointer to NULL so that the destructor of
2135 * class T will NOT remove the memory! */
2136 }
2137 array_alias &operator=(const T &a);
operator =(const array_alias & a)2138 array_alias &operator=(const array_alias &a) { *this = (T&)a; return *this; }
2139 };
2140
2141
2142 template<class T>
operator =(const T & a)2143 array_alias<T> &array_alias<T>::operator=(const T &a)
2144 {
2145 array_base &array = *(array_base*)this;
2146 int length = array.info->length;
2147 typedef typename T::E_type E;
2148
2149 /* Check whether array bounds are compatible */
2150 if (array.info != a.info && length != a.info->length)
2151 error(ERROR_INCOMPATIBLE_ARRAYS);
2152
2153 /* Check whether the arrays overlap */
2154 const int mem_size = length * sizeof(E);
2155
2156 if (abs((long)a.data - (long)array.data) >= mem_size) {
2157 /* Ok, arrays do NOT overlap! */
2158 /* Copy the data part of the arrays */
2159 if (scalar(id((E*)NULL)))
2160 /* If the element type is not scalar then execute init(...) for
2161 * each element in the array after initialing the memory to 0 */
2162 memcpy(array.data, a.data, mem_size);
2163 else
2164 for (int i = 0; i < length; i++)
2165 ((E*)array.data)[i] = ((E*)a.data)[i];
2166
2167 } else {
2168 /* Attention: arrays overlap! */
2169 /* Copy the data part of the arrays */
2170 if (scalar(id((E*)NULL)))
2171 /* If the element type is not scalar then execute init(...) for
2172 * each element in the array after initialing the memory to
2173 * 0. Note that twe are using memmove instead of memcpy here
2174 * because the memory ranges of source and destination
2175 * overlap. */
2176 memmove(array.data, a.data, mem_size);
2177
2178 else {
2179 /* Check out whether the lower border of the source array is
2180 * located within the destination array as this affects the
2181 * iteration direction. */
2182 if (a.data >= array.data)
2183 for (int i = 0; i < length; i++)
2184 ((E*)array.data)[i] = ((E*)a.data)[i];
2185 else
2186 for (int i = length - 1; i >= 0; i--)
2187 ((E*)array.data)[i] = ((E*)a.data)[i];
2188 }
2189 }
2190
2191 return *this;
2192 }
2193
2194
2195
2196 /* *************************************************************
2197 * Functions to implement VHDL file IO
2198 * ************************************************************* */
2199
2200 enumeration file_eof(vhdlfile &file);
2201
2202 void file_close(vhdlfile &file);
2203
2204 void file_open(vhdlfile &file, const array_type<enumeration> &name, enumeration kind);
2205 void file_open(enumeration &status, const vhdlfile &file, array_type<enumeration> &name, enumeration kind);
2206
2207 void file_read_scalar(vhdlfile &file, void *value_p, int size);
2208 void file_read_array(vhdlfile &file, void *value_p);
2209 void file_read_record(vhdlfile &file, void *value_p);
2210 void file_read_array(vhdlfile &file, void *value_p, integer &length);
2211 void file_write_scalar(vhdlfile &file, const void *value_p, int size);
2212 void file_write_array(vhdlfile &file, const void *value_p);
2213 void file_write_record(vhdlfile &file, const void *value_p);
2214
2215 /******************************************************
2216 * Some definitions which are used by the kernel only
2217 ******************************************************/
2218 #ifdef KERNEL // This is only required when the kernel is compiled
2219
2220 #include <freehdl/kernel-db.hh>
2221
2222 // Create a database key type for type_info_interface so that entries
2223 // can be associated to it.
2224 define_db_key_type (type_info_interface*, type_info_interface_p);
2225
2226 #endif
2227 #endif
2228
2229