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