1 #if HAVE_ALLOCA_H
2 #include <alloca.h>
3 #endif
4 #if HAVE_MALLOC_H
5 #include <malloc.h>
6 #endif
7 #include <string.h>
8 #include <fstream>
9 #include <sstream>
10 #include <map>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <sys/types.h>
14 #if HAVE_SOCKET
15 #include <sys/socket.h>
16 #endif
17 
18 extern "C" {
19 #include <regex.h>
20 }
21 
22 #define KERNEL
23 #include <freehdl/kernel-acl.hh>
24 #include <freehdl/kernel-flags.hh>
25 #include <freehdl/kernel-kernel-class.hh>
26 #include <freehdl/kernel-name-stack.hh>
27 #include <freehdl/kernel-map-list.hh>
28 #include <freehdl/kernel-sig-info.hh>
29 #include <freehdl/kernel-register.hh>
30 #include <freehdl/kernel-persistent-dump.hh>
31 #include <freehdl/kernel-persistent-cdfg-dump.hh>
32 #include <freehdl/kernel-dump.hh>
33 #include <freehdl/kernel-db.hh>
34 #include <freehdl/kernel-error.hh>
35 #include <freehdl/kernel-fhdl-stream.hh>
36 
37 #ifdef PERFMON_STATISTICS
38 #include "pcounter.hh"
39 #endif
40 
41 
42 // The kernel. Note, there is only a single instantiation of
43 // the kernel_class
44 kernel_class kernel;
45 
46 //global variables:
47 #define BUFSIZE (sizeof(long)*8 + 1)
48 #define LIMIT_SIZE 200000
49 #define STOCK_TIME_BUFFER_SIZE 29
50 char stock_time[STOCK_TIME_BUFFER_SIZE];
51 fstream file;
52 string timescale_unit = "ns";
53 int timescale = 1;
54 int coef_str_length = 7;
55 bool quiet = false;
56 
57 buffer_stream dump_buffer;
58 buffer_stream file_buffer;
59 FILE* info_file = NULL;
60 FILE* index_file = NULL;
61 FILE* string_file = NULL;
62 extern void write_info_file(list<Xinfo_data_descriptor*> &xinfo_desc, FILE* info_file,
63 			    FILE* index_file, FILE* string_file);
64 
65 
66 // Time calculation
print_sim_time(fhdl_ostream_t & outp)67 void print_sim_time(fhdl_ostream_t &outp)
68 {
69   outp << "Simulation time = " << time_to_string (kernel.get_sim_time ())
70        << " + " << kernel.get_delta () << "d\n";
71 }
72 
73 
74 // writes the content of file_buffer in the VCD file
75 // then cleans it.
write_in_file(buffer_stream & file_buffer)76 void write_in_file(buffer_stream &file_buffer)
77 {
78   file << file_buffer.str();
79   file_buffer.clean();
80 }
81 
82 
83 // vcd_mapping_table: opens file and reads user_defined translation table
84 Tmap
get_map_list(char * fileTranslation)85 get_map_list( char* fileTranslation)
86 {
87   char ch;
88   int j = 0;
89   int i = 0;
90   char buf[80];
91   string value;
92   string instance_name;
93   ifstream g(fileTranslation);
94   Tmap table;
95   while( !(g.eof()))
96     {
97       g.get(ch);
98       if (ch == '#') {
99 	while (ch != '\n') g.get(ch);
100 	j = 0;
101 	i = 0;
102       } else if (ch == '(' ){
103 	do {
104 	  g.get(ch);
105 	  if (ch != '\'' && ch != ' ' && ch != ',')  buf[j++] = ch;
106 	}
107 	while( ch != ')');
108 	buf[j-1] = '\0';
109 	value = buf;
110 	table[instance_name] = strdup(value.c_str());
111       } else if (ch == ')'){
112       } else if (ch == '\n'){
113       } else {
114 	do {
115 	  buf[i++] = ch;
116 	  g.get(ch);
117 	}
118 	while(ch != ' ');
119 	buf[i] = '\0';
120 	instance_name = buf;
121       }
122     }
123   g.close();
124 
125  return table;
126 }
127 
128 
129 // This function verfies the alpha-numeric of file names. Returns false
130 // if d is not a valid file name
131 bool
char_verifier(const char * d)132 char_verifier(const char* d)
133 {
134   const static char* test_table = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
135 
136   if (d == NULL) return false;
137 
138   while (*d != '\0') {
139     const char *test_char = test_table;
140     while (*test_char != '\0')
141       if (*test_char == *d)
142 	break;
143       else
144 	test_char++;
145     if (*test_char == '\0')
146       return false;
147     d++;
148   }
149 
150   return true;
151 }
152 
153 
154 // creates the dumped signal lists
155 
156 void
create_dumper_processes(sig_info_base * sinfo,type_info_interface * info,name_stack & nstack,acl * a)157 create_dumper_processes(sig_info_base *sinfo, type_info_interface *info,
158 			name_stack &nstack, acl *a)
159 {
160   switch (info->id) {
161   case ARRAY:
162     {
163       array_info &ainfo = *(array_info*)info;
164 
165       if (ainfo.element_type->id == ENUM)
166 	break;
167 
168       const int lb = ainfo.left_bound;
169       const int rb = ainfo.right_bound;
170 
171       // Create a new acl with size 1 greater than acl a and copy
172       // content of a to new acl
173       const int new_acl_size = (a == NULL? 0 : a->get_size()) + 1;
174       acl *new_acl = new(new_acl_size) acl;
175       if (a != NULL)
176 	*new_acl = *a;
177       // Add a dummy element so that the current size of new_acl is set
178       // appropriately
179       *new_acl << -1;
180 
181       // For each element of the array call create_dumper_process
182       // recursively
183       if (lb <= rb)
184 	{
185 	  for (int i = lb; i <= rb; i++)
186 	    {
187 	      new_acl->set(new_acl_size - 1, i);
188 	      create_dumper_processes(sinfo, ainfo.element_type, nstack, new_acl);
189 	    }
190 	} else {
191 	  for (int i = lb; i >= rb; i--)
192 	    {
193 	      new_acl->set(new_acl_size - 1, i);
194 	      create_dumper_processes(sinfo, ainfo.element_type, nstack, new_acl);
195 	    }
196 	}
197 
198       delete new_acl;
199       return; // We're done, so return
200       break;
201     }
202 
203   case RECORD:
204     {
205       record_info &rinfo = *(record_info*)info;
206       const int length = rinfo.record_size;
207       // Create a new acl with size 1 greater than acl a and copy
208       // content of a to new acl
209       const int new_acl_size = (a == NULL? 0 : a->get_size()) + 1;
210       acl *new_acl = new(new_acl_size) acl;
211       if (a != NULL)
212 	*new_acl = *a;
213       // Add a dummy element so that the current size of new_acl is set
214       // appropriately
215       *new_acl << -1;
216 
217       // For each element of the array call create_dumper_process
218       // recursively
219       for (int i = 0; i < length; i++)
220 	{
221 	  new_acl->set(new_acl_size - 1, i);
222 	  create_dumper_processes(sinfo, rinfo.element_types [i], nstack, new_acl);
223 	}
224 
225       delete new_acl;
226       return; // We're done, so return
227       break;
228     }
229 
230   default:
231     break;
232   }
233 
234   // Create a dumper process for the entire instance
235   nstack.push(signal_dump_process_list.size() + 1);
236   signal_dump* dumper_proc = new signal_dump(nstack, sinfo, a);
237   signal_dump_process_list.push_back(dumper_proc);
238   //and finally pops the name stack and deletes the acces code list
239   nstack.pop();
240 }
241 
242 
243 const char* command_table[]={
244   "q", "quit", "n", "next", "c", "cycle", "r", "run", "dump", "d",
245   "don", "doff", "dc", "ds", "ds_view", "nds", "s", "show", "dv", "wdd",
246   "wddl", "h", "help", "db_view", NULL
247 };
248 
249 // This function validates the input command
250 bool
nu_clear(string & d)251 nu_clear(string &d)
252  {
253    int i = 0;
254    const char* regex_n = d.c_str();
255    while (true)
256      {
257        const char* regex_i = command_table[i++];
258        if (regex_i == NULL)
259 	 return false;
260        if (strcmp(regex_i, regex_n) == 0)
261 	 return true;
262      }
263 
264    return false;
265  }
266 
267 
268 // time conversion  function
269 char*
time_conversion(const lint & tval,const int & coef_str_length)270 time_conversion(const lint &tval, const int &coef_str_length )
271 {
272   // store the time value in fs the tmp_time_buffer
273   char *cursor = stock_time + STOCK_TIME_BUFFER_SIZE - 1;
274   char *pos_end_cursor =  stock_time + STOCK_TIME_BUFFER_SIZE - 1;
275   lint l = tval;
276   *(cursor--) = '\0';
277   while (l > 0) {
278     lint new_l = l / 10;
279     int diff = l - (new_l << 3) - (new_l << 1);
280     *(cursor--) = (char)diff + '0';
281     l = new_l;
282   }
283   const int str_len = (int)(pos_end_cursor-cursor);
284   // calculates the difference between the string lengths
285   const int diff =  str_len - coef_str_length;
286   // if this difference is positiv(i.e: time value is greater
287   // than coefficient time, which actually presents timescale
288   if (diff > 0) {
289     strcpy(stock_time,(cursor+1));
290     stock_time[diff] = '\0';
291   } else if(diff == 0) {
292     // the case occurs when the time grid (timescale + timeunit) is too
293     // small to represent the change of the signal
294     stock_time[0] = '0';
295     stock_time[1] = '\0';
296   } else if(diff < 0) {
297     stock_time[0] = '0';
298     stock_time[1] = '\0';
299   }
300   return  stock_time;
301 }
302 
303 // time unit conversion function: converts the time unit to the given unit
304 
time_unit_conversion(string & tsu)305 int time_unit_conversion(string &tsu)
306 {
307   lint coef_conversion = 1000000;
308   dump_buffer.clean();
309 
310   if (tsu == "s")
311     coef_conversion = 1000000000000000LL;
312   else if (tsu == "ms")
313     coef_conversion = 100000000000LL;
314   else if (tsu == "us")
315     coef_conversion = 1000000000LL;
316   else if (tsu == "ns")
317     coef_conversion = 1000000LL;
318   else if (tsu == "ps")
319     coef_conversion = 1000LL;
320   else if (tsu == "fs")
321     coef_conversion = 1LL;
322 
323   coef_conversion = coef_conversion * timescale;
324   dump_buffer  << coef_conversion ;
325   coef_str_length = dump_buffer.str_len();
326 
327   return  coef_str_length;
328 }
329 
330 
331 //f_log2 function used to determine the size of each signal type
f_log2(lint x)332 int f_log2(lint x)
333 {
334   int log = 0;
335   do
336     {
337       x = x/2;
338       log++;
339     }
340   while(x != 0);
341   return log;
342 }
343 
344 
345 // vcd_file function
346 
vcd_file(char * fileName,string & cmd)347 void vcd_file (char* fileName, string &cmd)
348 {
349 
350   // store the time in the vcd_file
351    lint tval = kernel.get_sim_time();
352    //if tval >= 0 call time_conversion function to convert time
353    // then write it in the file
354    if (tval >= 0 )
355    file_buffer << '#' << time_conversion(tval, coef_str_length) << '\n';
356    // switch the dump cases and store  the informtion in vcd_file
357    // dump and dump on  case
358    if (cmd == "d" || cmd == "dump" || cmd == "don" )
359      {
360        if (cmd == "d" || cmd == "dump") {file_buffer << "$dumpvars" << '\n';}
361        else {file_buffer << "$dumpon" <<'\n';}
362        int count = 0;
363        list<signal_dump*>::iterator ig = signal_dump_process_list.begin();
364        for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
365 	    it != signal_dump_process_list.end(); it++)
366 	 {
367 	   if ((*it)->sname != (*ig)->sname)
368 	       //delete dump_buffer to alow a new storage
369 	       dump_buffer.clean();
370 	   // call the vcd_print function into calling write_value function
371 	   (*it)->write_value();
372 	   ig = it;
373 	 }
374      }
375    // dump off case
376    else if (cmd == "doff")
377      {
378        file_buffer << "$dumpoff" << '\n';
379        const char* dump_pointer = dump_buffer.str();
380        for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
381 	    it != signal_dump_process_list.end(); it++)
382 	 {
383 	   // call the vcd_print function
384 	   (*it)->type->vcd_print(dump_buffer, (*it)->reader_pointer,(*it)->translation_table, false);
385 	   // all signals are assigned to 'x' or 'bx' then written in the file
386 	   if (dump_pointer[0] == 'b')
387 	     file_buffer <<"bx" << ' ' << (*it)->vcd_signal_identifier << '\n';
388 	   else
389 	     file_buffer <<'x'<< ' ' << (*it)->vcd_signal_identifier << '\n';
390 	 }
391      }
392    file_buffer << "$end" <<'\n' ;
393 }
394 
395 //chooses the right vcd_signal_identifier
choose_identifier(char * tab)396 char* choose_identifier(char *tab)
397 {
398   int index = 0;
399   while(1)
400     {
401       if (tab[index] == 0)
402 	tab[index] = 33;
403       else
404 	tab[index]++;
405       if(tab[index] > 126)
406 	{
407 	  tab[index] = 33;
408 	  index++;
409 	}
410       else break;
411     }
412 
413   return  tab;
414 }
415 
416 
417 
418 //file get_size_range: writes size of signal and range of array in file
419 int
get_size_range(fhdl_ostream_t & outp,list<signal_dump * >::iterator it,ostringstream & range,int & size)420 get_size_range(fhdl_ostream_t &outp, list<signal_dump*>::iterator it, ostringstream &range, int &size)
421 {
422   array_info *ainfo = ((array_info*)(*it)->type);
423   array_info *element_ainfo = (array_info*)(ainfo->element_type);
424 
425   // *****************************************************************
426   // first, tests the element type( case array)
427   // *****************************************************************
428   if (ainfo->id == ARRAY) {
429 
430     //****************************************************************
431     // test of the direction (case to):
432     //****************************************************************
433     if (ainfo->index_direction == to) {
434       // tests the subelement type. If it is an array or integer:
435       if (ainfo->element_type->id == ARRAY ||ainfo->element_type->id == INTEGER)
436 	{
437 	  //*****************************
438 	  // if it's an array:
439 	  //****************************
440 	  if (ainfo->element_type->id == ARRAY){
441 
442 	    //**********************************************
443 	    // tests the subelement direction( to or downto)
444 	    //**********************************************
445 	    if (element_ainfo->index_direction == downto)
446 	      // if downto then defines the range from left to right:
447 	      range << "[" << element_ainfo->left_bound << ":"
448 		    << element_ainfo->right_bound << "]";
449 	    else
450 	      // else(if to) then defines the range from right to left:
451 	      range <<"["<< element_ainfo->right_bound <<":"
452 		    << element_ainfo->left_bound << "]";
453 	    //then determes the size of this array:
454 	    size = element_ainfo->length;
455 	    //else: i.e if the subelement is integer type
456 	  } else {
457 	    //then calculates the difference between its right and left bounds
458 	    lint x = (lint)element_ainfo->right_bound - (lint)element_ainfo->left_bound ;
459 	    x = x < 0? -x : x;
460 	    // then uses the function f_log2 to determine the binary size of this element:
461 	    size = f_log2(x);
462 	    range << "";
463 	  }
464 	  // else if the subelement is neither an array nor an integer(i.e: enum or real)
465 	} else {
466 	  // then the range is determined from right to left of the array element
467 	  range  << "[" << ainfo->right_bound << ":" <<ainfo->left_bound << "]";
468 	  // and the size is the length of this array
469 	  size = ainfo->length;
470 	}
471 
472       //diplays a warning on the screen indicating the inversion range of this array.
473       //This will be done if quiet si true:
474       if (!quiet)
475 	outp <<"warning: Direction of signal " << (*it)->instance_name.c_str()
476 	     <<"["<<ainfo->left_bound<< " to " << ainfo->right_bound <<"]"
477 	     << "  will be converted to "<<"["<<ainfo->right_bound
478 	     <<" downto "<<ainfo->left_bound<<"]"<<" in  VCD file\n";
479 
480       // *****************************************************************
481       // case downto of direction test:
482       // *****************************************************************
483     }else if (ainfo->index_direction == downto) {
484 
485       //*******************************************************
486       // tests the subelement type when it is array or integer:
487       //*******************************************************
488       if (ainfo->element_type->id == ARRAY || ainfo->element_type->id == INTEGER)
489 	{
490 
491 	  //*********************
492 	  // if it's an array:
493 	  //********************
494 	  if (ainfo->element_type->id == ARRAY){
495 
496 	    //**********************************************
497 	    // tests subelements direction (may be "to" or "downto")
498 	    //**********************************************
499 	    if (element_ainfo->index_direction == downto)
500 	      // if downto then defines the range from left to right:
501 	      range << "["<< element_ainfo->left_bound
502 			  <<":"<<element_ainfo->right_bound <<"]";
503 	    else
504 	      // else(if to) then defines the range from right to left:
505 	      range <<"[" << element_ainfo->right_bound
506 			  <<":"<<element_ainfo->left_bound << "]";
507 	    //then calculates the difference between its right and left bounds
508 	    size = element_ainfo->length;
509 	    //else: i.e if the subelement is integer type
510 	  } else {
511 	    //then calculates the difference between its right and left bounds
512 	    lint x = (lint)element_ainfo->right_bound - (lint)element_ainfo->left_bound ;
513 	    // then uses the function f_log2 to determine the binary size of this element:
514 	    size = f_log2(x < 0? -x : x);
515 	    range << "";
516 	  }
517 	  // else if the subelement is neither array nor integer(i.e: enum or real)
518 	}else {
519 	  // then the range is determined from right to left of the array element
520 	  range << "[" <<ainfo->left_bound << ":" <<ainfo->right_bound << "]";
521 	  // and the size is the length of this array
522 	  size = ((array_info*)(*it)->type)->length;
523 	}
524     }
525 
526     // *****************************************************************
527     // now test the element type (integer case)
528     // *****************************************************************
529   } else if ((*it)->type->id == INTEGER) {
530     integer_info_base *iinfo = ((integer_info_base*)(*it)->type);
531     // then calculate the difference between its right and left bounds to determine the range
532     lint x = (lint)(iinfo->left_bound) - (lint)(iinfo->right_bound);
533     // and use f_log2 function to determine the binary size of this element
534     size = f_log2(x < 0? -x : x);
535     range <<"";
536     // if the element is neither integer nor array:
537   } else {
538     // then the element size is determined...
539     size = (*it)->type->size;
540     range <<"";
541   }
542 
543   return size;
544 }
545 
546 
547 
548 // decides the case of up and/or down scope and writes module name.
hierarchy(int & n_count,int & o_count,char * stock_var,string & old_value)549 void hierarchy (int &n_count, int &o_count, char* stock_var, string &old_value)
550 {
551   /***********************************************************/
552   /* This rountine copies the module names in array stock_mod*/
553   /***********************************************************/
554   const int len = strlen(stock_var);
555 #ifdef HAVE_ALLOCA
556   char *stock_var_cpy = (char*)alloca((len+1) * sizeof(char));
557   char **stock_mod = (char**)alloca(n_count * sizeof(char*));
558 #else
559   char *stock_var_cpy = (char*)malloc((len+1) * sizeof(char));
560   char **stock_mod = (char**)malloc(n_count * sizeof(char*));
561 #endif
562   strcpy(stock_var_cpy,stock_var);
563   int i = 1;
564   for (int h = len; h >= 0; h--) {
565     // every module is referenced with ':' in the instance name
566     if (stock_var_cpy[h] == ':') {
567       stock_mod[n_count-(i++)] = &stock_var_cpy[h+1];
568       stock_var_cpy[h] = '\0';
569     }
570   }
571 
572   // i should NEVER be greater than (n_count+1)!
573   v_assert(i > (n_count + 1), "i > n_count");
574 
575   regex_t preg;// used in regular expression function
576   const char *regex_i = old_value.c_str();// used in
577   // regular expression function
578   const char *regex_n = stock_mod[0];// used in regular
579   // expression function.
580   //Calculates the difference between the new count and the last count
581   const int diff = n_count - o_count;
582   // if this difference is positiv(i.e: that we go down in the module
583   // hierarchies)
584   if ( diff > 0){
585     // write in the file the new modules names until the last one
586     for(int i = o_count; i < n_count; i++)
587       file << "$scope module  "<< stock_mod[i]<<"  $end" <<endl;
588     // if not(i.e: that we go up in the module hierarchies)
589   } else if(diff < 0) {
590     int j = 0;
591     for (int i = 0; i < n_count; i++){
592       // and the regex_n to new module name in the stock module name
593       regex_n = stock_mod[i];
594       // then we find the existence of this module using regular
595       // expression function
596       regcomp(&preg, regex_n, REG_NOSUB);
597       int h = regexec(&preg,  regex_i, 0, NULL, REG_NOTEOL);
598       // if the new name dont exist, the boucle will be breaked
599       if (h != 0)
600 	break;
601       // else we go down in the stocked module names
602       else
603 	j++;
604     }
605     //then writes the new module names in the file
606     for (int i = j; i <= (j - diff); i++)
607       file <<"$upscope " <<"  " << "$end" << endl;
608     for (int i = j; i < n_count; i++)
609       file <<"$scope module  " <<stock_mod[i] <<"  " << "$end" << endl;
610 
611     // if the differnce is equal to zero(i.e: we are in the same
612     // hierarchy)
613   }else if (diff == 0){
614     int j = 0;
615     for (int i = 0; i < n_count; i++){
616       // and the regex_n to new module name in the stock module name
617       regex_n = stock_mod[i];
618       // then we find the existence of this module using regular
619       // expression function
620       regcomp(&preg, regex_n, REG_NOSUB);
621       int h = regexec(&preg,  regex_i, 0, NULL, REG_NOTEOL);
622       // if the new name dont exist, the boucle will be breaked
623       if (h != 0)
624 	break;
625       // else we go down in the stocked module names
626       else
627 	j++;
628     }
629     //then writes the new module names in the file
630     for ( int i = j;i < n_count; i++)
631       file <<"$upscope " <<"  " << "$end" << endl;
632     for ( int i = j;i < n_count; i++)
633       file <<"$scope module  " <<stock_mod[i] <<"  " << "$end" << endl;
634 
635   }
636 #ifndef HAVE_ALLOCA
637   free (stock_var_cpy);
638   free (stock_mod);
639 #endif
640 }
641 
642 
643 // Separates instance strings like ":addcomp:test:a" into sections (":" are removed)
644 inline vector<string>
split(const string & path)645 split (const string &path)
646 {
647   vector<string> result;
648   for (unsigned int i = 0; i < path.size (); i++)
649     if (path [i] == ':')
650       result.push_back ("");
651     else
652       result.back () += path [i];
653 
654   return result;
655 }
656 
657 
658 // Searches for the first element (strating from the beginning) that
659 // are not equal. Returns the number of element that is not equal.
660 inline int
find_different_element(const vector<string> & str1,const vector<string> & str2)661 find_different_element (const vector<string> &str1, const vector<string> &str2)
662 {
663   for (unsigned int i = 0; i < min (str1.size (), str2.size ()); i++)
664     if (str1 [i] != str2 [i])
665       return i;
666 
667   return min (str1.size (), str2.size ());
668 }
669 
670 
671 //Initial_values function:
672 
write_header(fhdl_ostream_t & outp,char * fileName)673 void write_header(fhdl_ostream_t &outp, char* fileName)
674 {
675   // { ???, INTEGER, ENUM, FLOAT, PHYSICAL, RECORD, ARRAY, ACCESS, VHDLFILE};
676   static const char *id_str_table[] = { "???", "integer", "trireg",
677 					"real", "time", "???", "reg", "???", "???" };
678   char tab[5] = "\0\0\0\0";// used to calculate signal identifiers
679   // (each character is in range 33 to 126)
680   int size = 0;// size of signal(for array its length)
681   string old_value; //used to store
682   //the last instance name, which is executed
683   int o_count = 0;// used to count how many ':' in old_value
684 
685   //write in file, date, version and timescale
686   file << "$date" << endl;
687   file << "     " << __DATE__<<"  "<<__TIME__<<endl;
688   file << "$end" << endl;
689   file << "$version" << endl;
690   file << "    " << "FREEHDL " PACKAGE_VERSION << endl;
691   file << "$end" << endl;
692   file << "$timescale" << endl;
693   file << "    " << timescale<<" "<<timescale_unit<< endl;
694   file <<"$end" << endl;
695 
696   vector<string> current_path;
697 
698   // presents the dumped signal lists to define the modules and variables and write them in the file
699   for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
700        it != signal_dump_process_list.end(); it++)
701     {
702       ostringstream range;
703       //call get_size_range function
704       get_size_range(outp, it, range, size);
705 
706       // get path name vector for current signal
707       vector<string> path_vec = split ((*it)->instance_name);
708       path_vec.pop_back ();
709 
710       // get first element that is not equal
711       const unsigned int diff = find_different_element (path_vec, current_path);
712 
713       while (diff < current_path.size ())
714 	{
715 	  file <<"$upscope $end" << endl;
716 	  current_path.pop_back ();
717 	}
718 
719       for (unsigned int i = diff; i < path_vec.size (); i++)
720 	{
721 	  file << "$scope module " << path_vec [i] << " $end" << endl;
722 	  current_path.push_back (path_vec [i]);
723 	}
724 
725       // Check whether a space must be inserted between the value and
726       // the signal identifier and print indentifier. No space is
727       // inserted for bit enumeration types (bit, boolean, std_logic,
728       // std_ulogic).
729       if ((*it)->translation_table != NULL &&
730 	  (*it)->type->id == ENUM)
731 	strcpy((*it)->vcd_signal_identifier, choose_identifier(tab));
732       else {
733 	strcpy((*it)->vcd_signal_identifier + 1, choose_identifier(tab));
734 	(*it)->vcd_signal_identifier[0] = ' ';
735       }
736       // and finally writes in file signal value, name and identifier
737       file << "$var " << "  " << id_str_table[int((*it)->type->id)] << " "
738 	   << size << " " << tab << " " << (*it)->name.c_str()+1 << range.str()
739 	   << " " << "$end" << endl;
740     }
741 
742   while (current_path.size () > 0)
743     {
744       file << "$upscope $end" << endl;
745       current_path.pop_back ();
746     }
747   file <<"$enddefinitions"<<" "<<"$end" << endl;
748 }
749 
750 
751 // Print-help
752 
print_help(fhdl_ostream_t & outp)753 void print_help(fhdl_ostream_t &outp)
754 {
755   outp << "Available commands:\n";
756   outp << "  h          : prints list of available commands\n";
757   outp << "  c <number> : execute cycles = execute <number> simulation cycles\n";
758   outp << "  n          : next = execute next simulation cycle\n";
759   outp << "  q          : quit = quit simulation\n";
760   outp << "  r <time>   : run = execute simulation for <time>\n";
761   outp << "  d          : dump = dump signals\n";
762   outp << "  doff       : dump off = stop dumping signals\n";
763   outp << "  don        : dump on = continue dumping signals\n";
764   outp << "  s          : show = show signal values\n";
765   outp << "  dv         : dump var  = dump a signal from the signal lists\n";
766   outp << "  ds         : dump show  = shows the list of dumped signals\n";
767   outp << "  nds        : number  show  = shows the number  of dumped signals\n";
768   outp << "  wdd        : write binary design info\n";
769   outp << "  wddl       : write design info using a CDFG style syntax\n";
770   outp << "  db_view    : print kernel database\n";
771   outp << "  dc [-f <filename>] [-t <timescale> <time unit>] [-cfg <translation file>] [-q] :"
772           "control waveform dumping\n";
773 #ifdef EVENT_PROFILE
774   outp << "  p <file>   : event profile information write to <file>\n";
775 #endif
776 }
777 
778 // scc function: presents the kernel function
779 
scc(fhdl_istream_t & inp,fhdl_ostream_t & outp)780 void scc(fhdl_istream_t &inp, fhdl_ostream_t &outp) {
781 
782   //Declaration of needed parameters
783   bool header_written = true;
784   bool dump_done = false;
785   bool open_file = true;
786   char fileName[80] = "wave.dmp";
787   string cmd;
788 
789   //file_buffer initialisation
790   file_buffer.clean();
791   // print help on the screen
792   if (!quiet) print_help(outp);
793 
794   // Print the current simulation time
795   if (!quiet) print_sim_time(outp);
796 
797 
798   while (true) {
799 
800     if (!inp.eof()) {
801       // Output prompt
802       if (!quiet) outp << "> "; outp.flush();
803       // Read next command to excute
804       inp >> cmd;
805 
806     } else
807       cmd = "q";
808 
809     // Quit simulation
810     if (cmd == "q" || cmd == "quit"){
811 
812        //Writing the file buffer in the waveform file
813        write_in_file(file_buffer);
814        return;
815 
816       // Print help screen
817     } else if (cmd == "h" || cmd == "help") {
818       print_help(outp);
819 
820       // Simulate the next cycle
821     } else if (cmd == "n" || cmd == "next") {
822 
823       //call initial_values function
824       if (header_written && dump_done){
825 	file.open(fileName, ios::out);
826 	write_header(outp, fileName);
827 	header_written = false;
828       }
829       // Execute next simulation cycle
830       kernel.next_cycle();
831       // Print simulation time
832       if (!quiet) print_sim_time(outp);
833 
834     // Cycle
835     } else if (cmd == "c" || cmd == "cycle") {
836       STATISTICS(int counter_start = kernel.executed_processes_counter;);
837       STATISTICS(int transactions_counter = kernel.created_transactions_counter;);
838       //call write_header function
839       if ( header_written && dump_done){
840 	file.open(fileName, ios::out);
841 	write_header(outp, fileName);
842 	header_written = false;
843       }
844       if (!quiet) outp << "Number of cycles to execute? "; outp.flush();
845       int cycles;
846       inp >> cycles;
847       if (!quiet) outp << "Executing " << cycles << " simulation cycles.\n";
848       while (cycles--) {
849 	// Execute next simulation cycle
850 	kernel.next_cycle();
851       }
852       // Print simulation time
853       if (!quiet) {
854 	print_sim_time(outp);
855 	outp << "\n";
856 	STATISTICS(outp << kernel.executed_processes_counter - counter_start
857 		   << " processes were executed.\n";);
858 	STATISTICS(outp << kernel.created_transactions_counter -  transactions_counter
859 		   << " transaction were created.\n";);
860       }
861 
862     // Run
863     } else if (cmd == "r" || cmd == "run") {
864       if (!quiet)
865 	outp << "Run simulation for which time span? "; outp.flush();
866       int val, i;
867       inp >> val;
868       string time_unit;
869       inp >> time_unit;
870       if (!quiet)
871 	outp << "\n";
872 
873       for (i=0; i < L3std_Q8standard_I4time::unit_count; i++)
874 	if (!strcmp(time_unit.c_str(), L3std_Q8standard_I4time::units[i])) break;
875       if (i == L3std_Q8standard_I4time::unit_count) {
876 	kernel_error_stream << "Unknown time unit " << time_unit << "\n";
877 	continue;
878       }
879        //call initial_values function
880       if ( header_written && dump_done){
881 	file.open(fileName, ios::out);
882 	write_header(outp, fileName);
883 	header_written = false;
884       }
885       STATISTICS(int counter_start = kernel.executed_processes_counter;);
886       STATISTICS(int transactions_counter = kernel.created_transactions_counter;);
887 
888       lint time_value = kernel.get_sim_time();
889       time_value = time_value + L3std_Q8standard_I4time::scale[i] * (lint)val;
890       if (!quiet) {
891 	outp << "Simulating model to time " << val << " " << time_unit << "\n";
892       }
893 
894 #ifdef PERFMON_STATISTICS
895       start_pcounter(main_argc, main_argv);
896 #endif
897 
898       // Perform simulation
899       kernel.do_sim(time_value);
900 
901 #ifdef PERFMON_STATISTICS
902       end_pcounter();
903 #endif
904 
905       // Print simulation time
906       if (!quiet) {
907 	print_sim_time(outp);
908 	outp << "\n";
909 	STATISTICS(outp << kernel.executed_processes_counter - counter_start <<
910 		   " processes were executed.\n";);
911 	STATISTICS(outp << kernel.created_transactions_counter - transactions_counter
912 		   << " transaction were created.\n";);
913       }
914 
915     // Print all signals
916     } else if (cmd == "s" || cmd == "show") {
917       // Setup connection to the kernel data base
918       db_explorer<db_key_type::sig_info_base_p, db_entry_type::sig_info_extension> sig_info_ext (kernel_db);
919 
920       for (signal_map_t::iterator iter = signal_name_table.begin (); iter != signal_name_table.end (); iter++)
921 	{
922 	  sig_info_base *sig = iter->second;
923 
924 	  buffer_stream s;
925 	  s.clean();
926 	  outp << sig_info_ext.get (sig).instance_name << " = ";
927 	  sig->type->print(s, (sig)->reader_pointer, VHDL_PRINT_MODE);
928 	  outp << s.str() << "\n";
929 	}
930 
931       // dump a set of signal
932     } else if (cmd == "dv"){
933       // Setup connection to the kernel data base and get entry
934       // associated with the current sig info pointer.
935       db_explorer<db_key_type::sig_info_base_p, db_entry_type::sig_info_extension> sig_info_ext (kernel_db);
936 
937       // read signal name
938       inp >> cmd;
939       name_stack nstack;
940       nstack.push("Dumper");
941       regex_t preg;
942       regcomp(&preg, cmd.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE);
943 
944       for (signal_map_t::iterator iter = signal_name_table.begin (); iter != signal_name_table.end (); iter++)
945 	{
946 	  sig_info_base *sig = iter->second;
947 
948 	  int h = regexec(&preg, sig_info_ext.get (sig).instance_name.c_str(), 0, NULL, 0);
949 	  if (h == 0 &&
950 	      !(sig_info_ext.get (sig).kernel_flags & IS_DUMPED)) {
951 	    // call signal_dump creation function
952 	    create_dumper_processes(sig, sig->type, nstack, NULL);
953 	    sig_info_ext.get (sig).kernel_flags |= IS_DUMPED;
954 	  }
955 	}
956       dump_done = true;
957 
958       // Optimize wait_elements in order to save memory and runtime
959       kernel.compact_wait_elements();
960 
961       // dump all signals
962     } else if (cmd == "d" || cmd == "dump") {
963       // Setup connection to the kernel data base
964       db_explorer<db_key_type::sig_info_base_p, db_entry_type::sig_info_extension> sig_info_ext (kernel_db);
965 
966       name_stack nstack;
967       nstack.push("dumper");
968 
969       for (signal_map_t::iterator iter = signal_name_table.begin (); iter != signal_name_table.end (); iter++)
970 	{
971 	  sig_info_base *sig = iter->second;
972 
973 	  // call signal_dump list creation function
974 	  if (!(sig_info_ext.get (sig).kernel_flags & IS_DUMPED)) {
975 	    create_dumper_processes(sig, sig->type, nstack, NULL);
976 	    sig_info_ext.get (sig).kernel_flags |= IS_DUMPED;
977 	  }
978 	}
979 
980       nstack.pop();
981       dump_done = true;
982 
983       // Optimize wait_elements in order to save memory and runtime
984       kernel.compact_wait_elements();
985 
986       //call initial_values function
987       if (header_written && dump_done){
988 	file.open(fileName, ios::out);
989 	write_header(outp, fileName);
990 	header_written = false;
991       }
992       //calling the vcd_file function
993       vcd_file(fileName, cmd);
994 
995       // Continue dumping signals
996     } else if (cmd == "don") {
997       for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
998 	   it != signal_dump_process_list.end(); it++)
999 	(*it)->dump_on();
1000       vcd_file(fileName, cmd);
1001 
1002     // Stop dumping signals
1003     } else if (cmd == "doff") {
1004       for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
1005 	   it != signal_dump_process_list.end(); it++)
1006 	(*it)->dump_off();
1007       vcd_file(fileName, cmd);
1008 
1009       // Print  dumped signal lists
1010     } else if (cmd == "ds" || cmd == "ds_view") {
1011       outp <<"Dumped signal lists is: " << "\n";
1012       for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
1013 	   it != signal_dump_process_list.end(); it++)
1014 	{
1015 	  dump_buffer.clean();
1016 	  outp << (*it)->instance_name << " = ";
1017 	  (*it)->type->vcd_print(dump_buffer, (*it)->reader_pointer,(*it)->translation_table, false);
1018 	  outp << dump_buffer.str() << "\n";
1019 	}
1020 
1021       // Print  number of dumped signals:
1022     } else if (cmd == "nds" ) {
1023       int j = 0;
1024 
1025       for (list<signal_dump*>::iterator it = signal_dump_process_list.begin();
1026 	   it != signal_dump_process_list.end(); it++) j++;
1027       outp <<"The number of dumped signals is: "<<  j  << "\n";
1028 
1029       //Dump process configuration
1030     } else if (cmd == "dc" ) {
1031 
1032       char buffer[1000];
1033       inp.get(buffer, 1000, '\n');
1034       stringstream sub_cmd;
1035       sub_cmd << buffer;
1036 
1037       while (!sub_cmd.eof()) {
1038 	// Read command parameter
1039 	sub_cmd >> cmd;
1040 	if (cmd =="-f"){
1041 	  char test_fileName[1000];
1042 	  sub_cmd >> test_fileName;
1043 	  // valid file name?
1044 	  if (!char_verifier(test_fileName))
1045 	    kernel_error_stream << "'" << test_fileName << "' is not a valid file name! Output file name is set to 'wave.dmp'!\n";
1046 	  else
1047 	    strcpy(fileName, test_fileName);
1048 
1049 	} else if (cmd =="-t"){
1050 	  sub_cmd >> timescale;
1051 	  sub_cmd >> timescale_unit;
1052 	  // call the time_unit_conversion function to convert time
1053 	  time_unit_conversion(timescale_unit);
1054 	} else if (cmd == "-q"){
1055 	  // assign quiet to false dont allow a display on screen of comments
1056 	  quiet = true;
1057 	} else if (cmd == "-cfg") {
1058 	  // name of the file containing translation table
1059 	  char fileTranslation[1000];
1060 	  // read file contenent translation table of each user_defined type
1061 	  sub_cmd >> fileTranslation;
1062 	  // valid file name?
1063 	  if (!char_verifier(fileTranslation))
1064 	    kernel_error_stream << "'" << fileTranslation << "' is not a valid file name!\n";
1065 	  else
1066 	    // call the reading file to get user defined translation table
1067 	    mapping_translation_table = get_map_list( fileTranslation);
1068 	} else
1069 	  break;
1070       }
1071 
1072       // Writes design database in binary mode
1073     } else if (cmd == "wdd" ) {
1074       //Opening the corresponding files to write in
1075       buffer_stream file_name;
1076       file_name.clean();
1077       file_name << kernel.executable_name << ".data";
1078       info_file   = fopen(file_name.str(),"wb");// data file
1079       file_name.clean();
1080       file_name << kernel.executable_name << ".index";
1081       index_file  = fopen(file_name.str(),"wb");// Index file
1082       file_name.clean();
1083       file_name << kernel.executable_name <<".string";
1084       string_file = fopen(file_name.str(),"wb"); // string file
1085       //call the funtion to write in files
1086       write_info_file(Xinfo_descriptors, info_file, index_file, string_file);
1087       //Close files
1088       fclose(info_file);
1089       fclose(index_file);
1090       fclose(string_file);
1091 
1092       // Write design database in cdfg style
1093     } else if (cmd == "wddl" ) {
1094       string ddbl_file_name = string(kernel.executable_name) + ".ddb.lsp";
1095       ofstream ddbl_stream(ddbl_file_name.c_str());
1096       //call the funtion to write design database
1097       write_cdfg_info_file(Xinfo_descriptors, ddbl_stream);
1098       //Close files
1099       ddbl_stream.close();
1100 
1101       // Print content of kernel database
1102      } else if (cmd == "db_view") {
1103 
1104       for (db::key_iterator iter = kernel_db.begin (); iter != kernel_db.end (); iter++)
1105 	{
1106 	  db_base::db_key_entry_pair &entry = kernel_db.find (*iter);
1107 	  outp << entry.first->get_name () << "(" << (int)((long)(*iter).value) << ") :";
1108 	  for (unsigned int i = 0; i < entry.second.size (); i++)
1109 	    if (entry.second [i] != NULL)
1110 	      outp << " " << entry.second [i]->get_name ();
1111 
1112 	  outp << "\n";
1113 	}
1114      }
1115 
1116 #ifdef EVENT_PROFILE
1117      else if (cmd == "p" || cmd == "profile") {
1118       if (!quiet) outp << "Print into file: "; outp.flush();
1119       char filename[80];
1120       inp >> filename;
1121       if (!quiet) outp << "\n";
1122       kernel.event_report(filename);
1123     }
1124 #endif
1125      else {
1126     // Check for valid command
1127        kernel_error_stream << "Unknown command '" << cmd << "'. Type h for help.\n";
1128        kernel_error_stream.flush();
1129      }
1130   }
1131 }
1132 
1133 // main program
1134 int
kernel_main(int argc,char * argv[],handle_info * hinfo)1135 kernel_main (int argc, char *argv[], handle_info *hinfo) {
1136 
1137   // Savely initialize the 'free_acl' memory
1138   memset (free_acl, 0, sizeof(acl*)*(MAX_ACL_DEPTH+1));
1139 
1140   // Store command line arguments
1141   main_argc = argc;
1142   main_argv = argv;
1143   // Set executable name
1144   kernel.executable_name = argv[0];
1145 
1146   // First, associate in/out streams with default streams
1147   kernel_error_stream.bind_to_stream(cerr);
1148   kernel_output_stream.bind_to_stream(cout);
1149   model_output_stream.bind_to_stream(cout);
1150   input_stream.bind_to_stream(cin);
1151 
1152   // Assue that the commands are read from stdin
1153   bool cmd_param = false;
1154   // Command buffer for command passed over as a command line
1155   // parameter
1156   stringstream cmd_stream;
1157   // Analyze command line parameters
1158   int i = 0;
1159   while (++i < argc) {
1160     if (!strcmp(argv[i], "-cmd")) {
1161       // Commands to execute are specified as a string. Each command
1162       // is separated by ';'
1163       cmd_param = true; // Store that commands are read from parameter
1164       // string. Split up the commands given in the command line string.
1165       i++;
1166       string cmds = string (i < argc? argv[i] : "");
1167       string cmd;
1168       for (unsigned int s = 0; s < cmds.size (); s++)
1169 	{
1170 	  // Search for ';' or end of string
1171 	  if (cmds [s] == ';')
1172 	    {
1173 	      if (cmd != "")
1174 		{
1175 		  cmd_stream << cmd << endl;
1176 		  cmd = "";
1177 		}
1178 	    }
1179 	  else
1180 	    cmd += cmds [s];
1181 	}
1182       if (cmd != "")
1183 	cmd_stream << cmd << endl;
1184 
1185     } else if (!strcmp(argv[i], "-FHDLgui")) {
1186 #ifdef HAVE_SOCKET
1187       // The simulator communicates with its environment via 4 socket
1188       // connections. The socket file base name is defined by the
1189       // command line parameter. The actual socket file names are
1190       // derived by appending 0, 1, 2 or 3 to the base name. 0 is
1191       // associated with a kernel error socket (to print messages
1192       // generated by the kernel (e.g., caused by an illegal simulator
1193       // command)), 1 represents the normal kernel output channel
1194       // (e.g., to list signal values), 2 is the model output channel
1195       // (e.g., to print assert messages) and 3 is the input channel.
1196       string FHDLgui_socket_base = argv[++i];
1197 
1198       int                     sockfd;
1199 
1200       // **********************************************
1201       // First, bind kernel error socket
1202       // **********************************************
1203       bzero((char *) &serv_addr_kernel_error, sizeof(serv_addr_kernel_error));
1204       serv_addr_kernel_error.sun_family = AF_UNIX;
1205       strcpy(serv_addr_kernel_error.sun_path, FHDLgui_socket_base.c_str());
1206       strcat(serv_addr_kernel_error.sun_path, "0");
1207       sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1208       sockfd = 0; // if sockets are not supported, then
1209       if (connect(sockfd, (struct sockaddr *) &serv_addr_kernel_error,
1210 		  strlen(serv_addr_kernel_error.sun_path) + sizeof(serv_addr_kernel_error.sun_family)))
1211 	kernel_error_stream << "could not open socket '" << serv_addr_kernel_error.sun_path << "\n";
1212       else
1213 	kernel_error_stream.bind_to_socket(sockfd);
1214 
1215       // **********************************************
1216       // Bind kernel output socket
1217       // **********************************************
1218       bzero((char *) &serv_addr_kernel_output, sizeof(serv_addr_kernel_output));
1219       serv_addr_kernel_output.sun_family = AF_UNIX;
1220       strcpy(serv_addr_kernel_output.sun_path, FHDLgui_socket_base.c_str());
1221       strcat(serv_addr_kernel_output.sun_path, "1");
1222       sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1223       if (connect(sockfd, (struct sockaddr *) &serv_addr_kernel_output,
1224 		  strlen(serv_addr_kernel_output.sun_path) + sizeof(serv_addr_kernel_output.sun_family)))
1225 	kernel_error_stream << "could not open socket '" << serv_addr_kernel_output.sun_path << "\n";
1226       else
1227 	kernel_output_stream.bind_to_socket(sockfd);
1228 
1229       // **********************************************
1230       // Bind model output socket
1231       // **********************************************
1232       bzero((char *) &serv_addr_model_output, sizeof(serv_addr_model_output));
1233       serv_addr_model_output.sun_family = AF_UNIX;
1234       strcpy(serv_addr_model_output.sun_path, FHDLgui_socket_base.c_str());
1235       strcat(serv_addr_model_output.sun_path, "2");
1236       sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1237       if (connect(sockfd, (struct sockaddr *) &serv_addr_model_output,
1238 		  strlen(serv_addr_model_output.sun_path) + sizeof(serv_addr_model_output.sun_family)))
1239 	kernel_error_stream << "could not open socket '" << serv_addr_model_output.sun_path << "\n";
1240       else
1241 	model_output_stream.bind_to_socket(sockfd);
1242 
1243 
1244       // **********************************************
1245       // Bind input socket
1246       // **********************************************
1247       bzero((char *) &serv_addr_input, sizeof(serv_addr_input));
1248       serv_addr_input.sun_family = AF_UNIX;
1249       strcpy(serv_addr_input.sun_path, FHDLgui_socket_base.c_str());
1250       strcat(serv_addr_input.sun_path, "3");
1251       sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1252       if (connect(sockfd, (struct sockaddr *) &serv_addr_input,
1253 		  strlen(serv_addr_input.sun_path) + sizeof(serv_addr_input.sun_family)))
1254 	kernel_error_stream << "could not open socket '" << serv_addr_input.sun_path << "\n";
1255       else
1256 	input_stream.bind_to_socket(sockfd);
1257 
1258 #else
1259       kernel_error_stream << "error: system does not have socket support!\n";
1260 #endif
1261 
1262     } else if (!strcmp(argv[i], "-q")) {
1263       quiet = true;
1264     } else {
1265       kernel_error_stream << "Unkown command line argument '" << argv[i] << "'. Simulation run aborted!\n";
1266       exit(1);
1267     }
1268   }
1269 
1270   if (cmd_param)
1271     input_stream.bind_to_stream((istream&)cmd_stream);
1272 
1273   // Call initialization functions. Note this does not inlcude the
1274   // init functions of the corresponding design units.
1275   run_init_funcs ();
1276 
1277   // Initialize default translation table for printing VCD dumps
1278   mapping_translation_table = signal_dump::get_default_translation_table();
1279   // Elaborate the VHDL model: instantiate all components, signals
1280   // and processes
1281   kernel.elaborate_model (hinfo);
1282   // Optimize wait_elements in order to save memory and runtime
1283   kernel.compact_wait_elements();
1284   // Execute processe the first time.
1285   kernel.execute_processes();
1286   // Read in command and execute them
1287   scc(input_stream, kernel_output_stream);
1288   // Close waveform file
1289   file.close();
1290 
1291   return 0;
1292 }
1293 
1294 
1295 int
ttt(int j)1296 ttt(int j)
1297 {
1298   for (int i = 0; i < j; i++)
1299     delete[] new char[i];
1300   return 0;
1301 }
1302