HDLRuby 2.4.29 → 2.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/HDLRuby/drivers/xcd.rb +79 -0
  3. data/lib/HDLRuby/drivers/xcd/dummy.xcd +4 -0
  4. data/lib/HDLRuby/hdr_samples/adder.rb +1 -1
  5. data/lib/HDLRuby/hdr_samples/adder_bench.rb +1 -1
  6. data/lib/HDLRuby/hdr_samples/adder_gen.rb +1 -1
  7. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +27 -0
  8. data/lib/HDLRuby/hdr_samples/dff_properties.rb +19 -0
  9. data/lib/HDLRuby/hdr_samples/dff_unit.rb +54 -0
  10. data/lib/HDLRuby/hdr_samples/huge_rom.rb +25 -0
  11. data/lib/HDLRuby/hdr_samples/logic_bench.rb +21 -0
  12. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
  13. data/lib/HDLRuby/hdr_samples/multi_timed_bench.rb +54 -0
  14. data/lib/HDLRuby/hdr_samples/music.rb +79 -0
  15. data/lib/HDLRuby/hdr_samples/named_sub.rb +42 -0
  16. data/lib/HDLRuby/hdr_samples/rom.rb +16 -0
  17. data/lib/HDLRuby/hdr_samples/with_function_generator.rb +25 -0
  18. data/lib/HDLRuby/hdrcc.rb +162 -26
  19. data/lib/HDLRuby/hruby_decorator.rb +250 -0
  20. data/lib/HDLRuby/hruby_high.rb +468 -91
  21. data/lib/HDLRuby/hruby_low.rb +913 -45
  22. data/lib/HDLRuby/hruby_low2c.rb +122 -168
  23. data/lib/HDLRuby/hruby_low2hdr.rb +738 -0
  24. data/lib/HDLRuby/hruby_low2high.rb +331 -549
  25. data/lib/HDLRuby/hruby_low2vhd.rb +39 -2
  26. data/lib/HDLRuby/hruby_low_bool2select.rb +29 -0
  27. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +27 -0
  28. data/lib/HDLRuby/hruby_low_fix_types.rb +25 -0
  29. data/lib/HDLRuby/hruby_low_mutable.rb +70 -0
  30. data/lib/HDLRuby/hruby_low_resolve.rb +28 -0
  31. data/lib/HDLRuby/hruby_low_without_connection.rb +6 -3
  32. data/lib/HDLRuby/hruby_low_without_namespace.rb +7 -4
  33. data/lib/HDLRuby/hruby_low_without_select.rb +13 -0
  34. data/lib/HDLRuby/hruby_tools.rb +11 -1
  35. data/lib/HDLRuby/hruby_verilog.rb +1577 -1709
  36. data/lib/HDLRuby/sim/hruby_sim.h +29 -3
  37. data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
  38. data/lib/HDLRuby/sim/hruby_sim_core.c +24 -9
  39. data/lib/HDLRuby/sim/hruby_sim_vcd.c +5 -1
  40. data/lib/HDLRuby/sim/hruby_sim_vizualize.c +22 -6
  41. data/lib/HDLRuby/std/fixpoint.rb +9 -0
  42. data/lib/HDLRuby/std/function_generator.rb +139 -0
  43. data/lib/HDLRuby/std/hruby_unit.rb +75 -0
  44. data/lib/HDLRuby/template_expander.rb +61 -0
  45. data/lib/HDLRuby/version.rb +1 -1
  46. metadata +21 -5
@@ -451,7 +451,10 @@ typedef struct BehaviorS_ {
451
451
 
452
452
  int activated; /* Tells if the behavior is activated or not. */
453
453
 
454
- int timed; /* Tell if the behavior is timed or not. */
454
+ int timed; /* Tell if the behavior is timed or not:
455
+ - 0: not timed
456
+ - 1: timed
457
+ - 2: timed and finished. */
455
458
  unsigned long long active_time; /* The next time the behavior has to be activated. */
456
459
  pthread_t thread; /* The thread assotiated with the behavior (if any).*/
457
460
  } BehaviorS;
@@ -573,10 +576,15 @@ extern void each_all_signal(void (*func)(SignalI));
573
576
  /* Interface to the visualization engine. */
574
577
 
575
578
  typedef struct {
579
+ /* The simulation prints. */
576
580
  void (*print_time)(unsigned long long);
577
581
  void (*print_name)(Object);
578
582
  void (*print_value)(Value);
579
583
  void (*print_signal)(SignalI);
584
+ /* The custom 'string' prints. */
585
+ void (*print_string)(const char*);
586
+ void (*print_string_name)(Object);
587
+ void (*print_string_value)(Value);
580
588
  } PrinterS;
581
589
 
582
590
  extern PrinterS printer;
@@ -585,11 +593,29 @@ extern PrinterS printer;
585
593
  * @param print_time the time printer
586
594
  * @param print_name the name printer
587
595
  * @param print_value the value printer
588
- * @param print_signal the signal state printer. */
596
+ * @param print_signal the signal state printer
597
+ * @param print_string the string printer
598
+ * @param print_string_name the string name printer
599
+ * @param print_string_value the string value printer */
589
600
  extern void init_visualizer(void (*print_time)(unsigned long long),
590
601
  void (*print_name)(Object),
591
602
  void (*print_value)(Value),
592
- void (*print_signal)(SignalI));
603
+ void (*print_signal)(SignalI),
604
+ void (*print_string)(const char*),
605
+ void (*print_string_name)(Object),
606
+ void (*print_string_value)(Value));
607
+
608
+ /** Prints a name (default).
609
+ * @param signal the signal to show */
610
+ extern void default_print_name(Object);
611
+
612
+ /** Prints a value (default).
613
+ * @param signal the signal to show */
614
+ extern void default_print_value(Value);
615
+
616
+ /** Prints a string (default).
617
+ * @param str the string to print. */
618
+ extern void default_print_string(const char* str);
593
619
 
594
620
  // /** Prints the time.
595
621
  // * @param time the time to show. */
@@ -325,6 +325,9 @@ Value copy_value(Value src, Value dst) {
325
325
  /* Declared afterward. */
326
326
  static Value set_bitstring_value(Value src, Value dst);
327
327
 
328
+ /* Declared afterward. */
329
+ static Value set_numeric_value(Value src, Value dst);
330
+
328
331
  /** Copies a value to another but without overwritting with Z, the type of
329
332
  * the destination is preserved.
330
333
  * @param src the source value
@@ -393,6 +396,35 @@ static Value set_bitstring_value(Value src, Value dst) {
393
396
  return dst;
394
397
  }
395
398
 
399
+ /** Creates a numeric value from a bitstring value.
400
+ * @param src the bitstring source value
401
+ * @param dst the numeric destination value
402
+ * @return dst. */
403
+ static Value set_numeric_value(Value src, Value dst) {
404
+ /* Compute the width in bits of the source. */
405
+ unsigned long long width = type_width(src->type);
406
+ unsigned long long i;
407
+ /* Set the type and size of the destination from the type of the source.*/
408
+ dst->type = src->type;
409
+ dst->numeric = 1;
410
+
411
+ /* Access the data of the source and the destination. */
412
+ char* data_str = src->data_str;
413
+ unsigned long long data_int = 0;
414
+
415
+ /* Make the conversion. */
416
+ for(i=0; i < width; ++i) {
417
+ /* Get the bit from the source. */
418
+ unsigned long long bit = data_str[i] - '0';
419
+ /* And write it. */
420
+ data_int |= bit << i;
421
+ }
422
+ /* Update the destination. */
423
+ dst->data_int = data_int;
424
+ /* Return the destination. */
425
+ return dst;
426
+ }
427
+
396
428
 
397
429
  /** Sets a value to undefined.
398
430
  * @param dst the destination value
@@ -1620,7 +1652,7 @@ static Value not_value_numeric(Value src, Value dst) {
1620
1652
  dst->numeric = 1;
1621
1653
 
1622
1654
  /* Perform the not. */
1623
- dst->data_int = fix_numeric_type(dst->type,!src->data_int);
1655
+ dst->data_int = fix_numeric_type(dst->type,~src->data_int);
1624
1656
  return dst;
1625
1657
  }
1626
1658
 
@@ -1731,7 +1763,8 @@ static Value equal_value_numeric(Value src0, Value src1, Value dst) {
1731
1763
  dst->numeric = 1;
1732
1764
 
1733
1765
  /* Perform the !XOR. */
1734
- dst->data_int = (src0->data_int == src1->data_int);
1766
+ // dst->data_int = (src0->data_int == src1->data_int);
1767
+ dst->data_int = ~(src0->data_int ^ src1->data_int);
1735
1768
  return dst;
1736
1769
  }
1737
1770
 
@@ -2068,15 +2101,39 @@ Value sub_value(Value src0, Value src1, Value dst) {
2068
2101
  * @param dst the destination value
2069
2102
  * @return dst */
2070
2103
  Value mul_value(Value src0, Value src1, Value dst) {
2104
+ // printf("mul_value with src0=%llx src1=%llx\n",value2integer(src0),value2integer(src1));
2105
+ // printf("src0->numeric=%d src1->numeric=%d\n",src0->numeric,src1->numeric);
2106
+ // printf("is_defined_value(src0)=%d is_defined_value(src1)=%d\n",is_defined_value(src0),is_defined_value(src1));
2071
2107
  /* Might allocate a new value so save the current pool state. */
2072
2108
  unsigned int pos = get_value_pos();
2073
2109
  /* Do a numeric computation if possible, otherwise fallback to bitstring
2074
2110
  * computation. */
2075
- if (src0->numeric && src1->numeric) {
2076
- /* Both sources are numeric. */
2077
- return mul_value_numeric(src0,src1,dst);
2111
+ if (src0->numeric) {
2112
+ if (src1->numeric) {
2113
+ /* Both sources are numeric. */
2114
+ return mul_value_numeric(src0,src1,dst);
2115
+ } else if (is_defined_value(src1)) {
2116
+ // /* src1 is a defined bitstring, convert src0 to bitstring. */
2117
+ // src0 = set_bitstring_value(src0,get_value());
2118
+ // /* And do a bitstring multiplying. */
2119
+ // return mul_value_defined_bitstring(src0,src1,dst);
2120
+ /* src1 is a defined bitstring, convert it to a numeric. */
2121
+ src1 = set_numeric_value(src1,get_value());
2122
+ /* And do a numeri multiplying. */
2123
+ return mul_value_numeric(src0,src1,dst);
2124
+ }
2125
+ } else if (src1->numeric && is_defined_value(src0)) {
2126
+ // /* src1 is numeric but src0 is a defined bitstring, convert src1 to
2127
+ // * bitstring. */
2128
+ // src1 = set_bit_string_value(src1,get_value());
2129
+ // /* And do a bitstring multiplying. */
2130
+ // return mul_value_defined_bitstring(src0,src1,dst);
2131
+ /* src0 is a defined bitstring, convert it to a numeric. */
2132
+ src0 = set_numeric_value(src0,get_value());
2133
+ /* And do a numeri multiplying. */
2134
+ return mul_value_numeric(src0,src1,dst);
2078
2135
  } else if (is_defined_value(src0) && is_defined_value(src1)) {
2079
- /* Both sources can be converted to numeric values. */
2136
+ /* Both sources are defined bitstrings. */
2080
2137
  return mul_value_defined_bitstring(src0,src1,dst);
2081
2138
  } else {
2082
2139
  /* Cannot compute (for now), simply undefines the destination. */
@@ -285,7 +285,8 @@ void hruby_sim_advance_time() {
285
285
  int i;
286
286
  for(i=0; i<num_timed_behaviors; ++i) {
287
287
  unsigned long long beh_time = timed_behaviors[i]->active_time;
288
- if (beh_time < next_time) next_time = beh_time;
288
+ if (timed_behaviors[i]->timed == 1)
289
+ if (beh_time < next_time) next_time = beh_time;
289
290
  }
290
291
  /* Sets the new activation time. */
291
292
  hruby_sim_time = next_time;
@@ -310,7 +311,9 @@ void hruby_sim_activate_behaviors_on_time() {
310
311
  /* Count the number of behaviors that will be activated. */
311
312
  for(i=0; i<num_timed_behaviors; ++i) {
312
313
  Behavior beh = timed_behaviors[i];
313
- if (beh->active_time == hruby_sim_time) {
314
+ // printf("beh->active_time=%llu\n",beh->active_time);
315
+ // if (beh->active_time == hruby_sim_time) {
316
+ if (beh->timed == 1 && beh->active_time == hruby_sim_time) {
314
317
  /* Increase the number of timed behavior to wait for. */
315
318
  num_active_behaviors ++;
316
319
  // printf("num_active_behaviors = %d\n",num_active_behaviors);
@@ -318,18 +321,19 @@ void hruby_sim_activate_behaviors_on_time() {
318
321
  }
319
322
  /* Activate the behaviors .*/
320
323
  behaviors_can_run = 1;
324
+ // printf("$2\n");
321
325
  // pthread_cond_signal(&compute_cond); /* No behaviors. */
322
- pthread_cond_signal(&hruby_beh_cond);
326
+ // pthread_cond_signal(&hruby_beh_cond);
323
327
  pthread_mutex_unlock(&hruby_sim_mutex);
324
- // printf("$2\n");
328
+ pthread_cond_broadcast(&hruby_beh_cond);
325
329
  }
326
330
 
327
331
 
328
332
  /** Wait for the active timed behaviors to advance. */
329
333
  void hruby_sim_wait_behaviors() {
330
- // printf("$3\n");
331
334
  pthread_mutex_lock(&hruby_sim_mutex);
332
335
  while(num_active_behaviors > 0) {
336
+ // printf("$3\n");
333
337
  // printf("num_active_behaviors = %d\n",num_active_behaviors);
334
338
  // pthread_cond_wait(&active_behaviors_cond, &hruby_sim_mutex);
335
339
  pthread_cond_wait(&hruby_sim_cond, &hruby_sim_mutex);
@@ -349,6 +353,7 @@ void* behavior_run(void* arg) {
349
353
  pthread_mutex_lock(&hruby_sim_mutex);
350
354
  num_active_behaviors -= 1;
351
355
  while(!behaviors_can_run) {
356
+ // printf("cannot run\n");
352
357
  // pthread_cond_wait(&compute_cond, &hruby_sim_mutex);
353
358
  pthread_cond_wait(&hruby_beh_cond, &hruby_sim_mutex);
354
359
  }
@@ -356,12 +361,17 @@ void* behavior_run(void* arg) {
356
361
  // printf("#2\n");
357
362
  /* Now can start the execution of the behavior. */
358
363
  behavior->block->function();
364
+ // printf("#3\n");
365
+ /* Now can start the execution of the behavior. */
359
366
  /* Stops the behavior. */
360
367
  pthread_mutex_lock(&hruby_sim_mutex);
361
368
  num_active_behaviors -= 1;
362
369
  num_run_behaviors -= 1;
363
- pthread_cond_signal(&hruby_sim_cond);
370
+ // printf("num_run_behaviors=%d\n",num_run_behaviors);
371
+ behavior->timed = 2;
372
+ // pthread_cond_signal(&hruby_sim_cond);
364
373
  pthread_mutex_unlock(&hruby_sim_mutex);
374
+ pthread_cond_signal(&hruby_sim_cond);
365
375
  /* End the thread. */
366
376
  pthread_exit(NULL);
367
377
  }
@@ -374,11 +384,13 @@ void hruby_sim_start_timed_behaviors() {
374
384
  pthread_mutex_lock(&hruby_sim_mutex);
375
385
  /* Sets the end flags to 0. */
376
386
  sim_end_flag = 0;
387
+ /* Tells the behavior can run. */
388
+ behaviors_can_run = 1;
377
389
  /* Create and start the threads. */
378
390
  for(i=0; i<num_timed_behaviors; ++i) {
379
391
  num_run_behaviors += 1;
380
392
  // ++num_active_behaviors;
381
- // printf("0 num_active_behaviors = %d\n",num_active_behaviors);
393
+ // printf("0 num_run_behaviors = %d\n",num_run_behaviors);
382
394
  pthread_create(&timed_behaviors[i]->thread,NULL,
383
395
  &behavior_run,timed_behaviors[i]);
384
396
  }
@@ -457,7 +469,6 @@ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
457
469
  * @param delay the delay to wait in fs.
458
470
  * @param behavior the current behavior. */
459
471
  void hw_wait(unsigned long long delay, Behavior behavior) {
460
- // printf("!1\n");
461
472
  /* Maybe the thread is to end immediatly. */
462
473
  if (sim_end_flag)
463
474
  pthread_exit(NULL);
@@ -465,16 +476,20 @@ void hw_wait(unsigned long long delay, Behavior behavior) {
465
476
  pthread_mutex_lock(&hruby_sim_mutex);
466
477
  /* Indicate the behavior finished current execution. */
467
478
  num_active_behaviors -= 1;
468
- pthread_cond_signal(&hruby_sim_cond);
479
+ // printf("!!num_active_behaviors=%d\n",num_active_behaviors);
480
+ // pthread_cond_signal(&hruby_sim_cond);
469
481
  /* Update the behavior's time. */
470
482
  behavior->active_time += delay;
471
483
  pthread_mutex_unlock(&hruby_sim_mutex);
484
+ pthread_cond_signal(&hruby_sim_cond);
472
485
  /* Wait for being reactivated. */
473
486
  while(behavior->active_time > hruby_sim_time) {
474
487
  pthread_mutex_lock(&hruby_sim_mutex);
475
488
  while(!behaviors_can_run) {
489
+ // printf("!1\n");
476
490
  // pthread_cond_wait(&compute_cond, &hruby_sim_mutex);
477
491
  pthread_cond_wait(&hruby_beh_cond, &hruby_sim_mutex);
492
+ // printf("!2\n");
478
493
  }
479
494
  pthread_mutex_unlock(&hruby_sim_mutex);
480
495
  }
@@ -357,6 +357,7 @@ static void vcd_print_header() {
357
357
  }
358
358
 
359
359
 
360
+
360
361
  /* The configuration and initialization of the vcd vizualizer. */
361
362
 
362
363
 
@@ -373,7 +374,10 @@ extern void init_vcd_visualizer(char* name) {
373
374
  init_visualizer(&vcd_print_time,
374
375
  &vcd_print_full_name,
375
376
  &vcd_print_value,
376
- &vcd_print_signal_fvalue);
377
+ &vcd_print_signal_fvalue,
378
+ &default_print_string,
379
+ &default_print_name,
380
+ &default_print_value);
377
381
 
378
382
  /* Prints the header of the vcd file. */
379
383
  vcd_print_header();
@@ -16,15 +16,22 @@ PrinterS printer;
16
16
  * @param print_time the time printer
17
17
  * @param print_name the name printer
18
18
  * @param print_value the value printer
19
- * @param print_signal the signal state printer. */
19
+ * @param print_signal the signal state printer
20
+ * @param print_string the string printer. */
20
21
  void init_visualizer(void (*print_time)(unsigned long long),
21
22
  void (*print_name)(Object),
22
23
  void (*print_value)(Value),
23
- void (*print_signal)(SignalI)) {
24
+ void (*print_signal)(SignalI),
25
+ void (*print_string)(const char*),
26
+ void (*print_string_name)(Object),
27
+ void (*print_string_value)(Value)) {
24
28
  printer.print_time = print_time;
25
29
  printer.print_name = print_name;
26
30
  printer.print_value = print_value;
27
31
  printer.print_signal = print_signal;
32
+ printer.print_string = print_string;
33
+ printer.print_string_name = print_string_name;
34
+ printer.print_string_value = print_string_value;
28
35
  }
29
36
 
30
37
 
@@ -34,7 +41,7 @@ void init_visualizer(void (*print_time)(unsigned long long),
34
41
 
35
42
  /** Prints the time.
36
43
  * @param time the time to show. */
37
- static void default_print_time(unsigned long long time) {
44
+ void default_print_time(unsigned long long time) {
38
45
  printf("# %llups",time);
39
46
  }
40
47
 
@@ -47,7 +54,7 @@ static void default_println_time(unsigned long long time) {
47
54
 
48
55
  /** Prints the name of an object.
49
56
  * @param object the object to print the name. */
50
- static void default_print_name(Object object) {
57
+ void default_print_name(Object object) {
51
58
  /* Recurse on the owner if any. */
52
59
  // printf("owner=%p\n",object->owner);
53
60
  if (object->owner != NULL) {
@@ -73,7 +80,7 @@ static void default_print_name(Object object) {
73
80
 
74
81
  /** Prints a value.
75
82
  * @param value the value to print */
76
- static void default_print_value(Value value) {
83
+ void default_print_value(Value value) {
77
84
  if (value->numeric) {
78
85
  unsigned long long width = type_width(value->type);
79
86
  unsigned long long mask = 1ULL << (width-1);
@@ -100,6 +107,12 @@ static void default_print_value(Value value) {
100
107
  }
101
108
  }
102
109
 
110
+ /** Prints a string.
111
+ * @param str the string to print. */
112
+ void default_print_string(const char* str) {
113
+ printf("%s", str);
114
+ }
115
+
103
116
  /** Prints a signal.
104
117
  * @param signal the signal to show */
105
118
  static void default_print_signal(SignalI signal) {
@@ -126,5 +139,8 @@ void init_default_visualizer(char* name) {
126
139
  init_visualizer(&default_println_time,
127
140
  &default_print_name,
128
141
  &default_print_value,
129
- &default_println_signal);
142
+ &default_println_signal,
143
+ &default_print_string,
144
+ &default_print_name,
145
+ &default_print_value);
130
146
  }
@@ -65,6 +65,15 @@ module HDLRuby::High::Std
65
65
  (left.as([isize+fsize*2]) << fsize) / right
66
66
  end
67
67
  end
68
+ # Define the removal of the point.
69
+ typ.define_singleton_method(:no_point) do
70
+ if (typ.signed?) then
71
+ signed[typ.width]
72
+ else
73
+ bit[typ.width]
74
+ end
75
+ end
76
+ # Return the resulting typ.
68
77
  typ
69
78
  end
70
79
  end
@@ -0,0 +1,139 @@
1
+ ##
2
+ # Standard HDLRuby::High library: universal generic function generator
3
+ # based on the work of Ryota Sakai from NN4H
4
+ #
5
+ ########################################################################
6
+
7
+
8
+ module HDLRuby::High::Std
9
+
10
+ # Module describing a function generator using linear approximation between
11
+ # fixed precalculated values.
12
+ # Generic parameters:
13
+ # +func+ procedure generating the discret values of the functions.
14
+ # +ityp+ the type of the input
15
+ # +otyp+ the type of the output
16
+ # +awidth+ width of the address bus for accessing the discret values
17
+ # +xrange+ the range for x values when computing the function
18
+ # +yrange+ the range for y values when computing the function
19
+ system :function_generator do |func, ityp, otyp, awidth, xrange, yrange|
20
+ # Check the generic parameters.
21
+ func = func.to_proc
22
+ ityp = ityp.to_type
23
+ otyp = otyp.to_type
24
+ awidth = awidth.to_i
25
+ xrange = xrange.first.to_f..xrange.last.to_f
26
+ yrange = yrange.first.to_f..yrange.last.to_f
27
+
28
+ # Declare the interface of the generator.
29
+ ityp.input :x
30
+ otyp.output :y
31
+
32
+ # Discrete values used for interpolating.
33
+ otyp.inner :base, :next_data
34
+
35
+ # Address
36
+ [awidth].inner :address
37
+ # Remainder
38
+ ityp.inner :remaining
39
+ x
40
+ # Compute the address and the remainder from the input.
41
+ address <= x[(ityp.width-1)..(ityp.width-awidth)]
42
+ remaining <= [[_b1b0] * awidth, x[(ityp.width-1-awidth)..0]]
43
+
44
+ # Instantiate the lut holding the discrete values.
45
+ lut(func,ityp,otyp,awidth,xrange,yrange).(:my_lut).(address,base,next_data)
46
+
47
+ # Instantiate the interpolator.
48
+ interpolator(ityp,otyp,awidth).(:my_iterpolator).(base,next_data, remaining, y)
49
+ end
50
+
51
+
52
+ # The LUT containing the discre values.
53
+ system :lut do |func,ityp, otyp, awidth, xrange, yrange|
54
+ # Check the generic arguments.
55
+ func = func.to_proc
56
+ ityp = ityp.to_type
57
+ otyp = otyp.to_type
58
+ awidth = awidth.to_i
59
+ xrange = xrange.first.to_f..xrange.last.to_f
60
+ yrange = yrange.first.to_f..yrange.last.to_f
61
+
62
+ # lut_size = 2 ** address_width
63
+ # Compute the size of the lut.
64
+ lut_size = 2 ** awidth
65
+
66
+ # Declare the input and output of the lut.
67
+ [awidth].input :address
68
+ otyp.output :base, :next_data
69
+
70
+ # Declare the lut
71
+ otyp[-lut_size].constant lut:
72
+ initialize_lut(func,otyp,awidth,xrange,yrange)
73
+
74
+ # Assign the base discret value.
75
+ base <= lut[address]
76
+
77
+ # Assign the next_data discrete value.
78
+ next_data <= lut[address+1]
79
+ end
80
+
81
+
82
+ # compute tanh
83
+ # LUTの点の間の値を計算するモジュール
84
+ # system :interpolator do |typ, integer_width, address_width|
85
+ # Module making linear interpolation between two discrete values.
86
+ # Generic parameters:
87
+ # +ityp+: the function input value type
88
+ # +otyp+: the function output value type
89
+ # +width+: the step width between discrete values
90
+ system :interpolator do |ityp,otyp,width|
91
+ # Check the generic arguments
92
+ ityp = ityp.to_type
93
+ otyp = otyp.to_type
94
+ width = width.to_i
95
+ # Compute the scale factor and convert it to a shift value.
96
+ shift_bits = ityp.width - width
97
+
98
+ # Declare the input and outputs.
99
+ otyp.input :base, :next_data
100
+ ityp.input :remaining
101
+ otyp.output :interpolated_value
102
+
103
+ if (otyp.signed?) then
104
+ signed[otyp.width+ityp.width].inner :diff
105
+ else
106
+ bit[otyp.width+ityp.width].inner :diff
107
+ end
108
+
109
+ # Make the interpolation.
110
+ diff <= (next_data-base).as(diff.type) * remaining
111
+ if(otyp.signed?) then
112
+ interpolated_value <= base +
113
+ ([[diff[diff.type.width-1]]*shift_bits,
114
+ diff[diff.type.width-1..shift_bits]]).to_expr
115
+ else
116
+ interpolated_value <= base + (diff >> shift_bits)
117
+ end
118
+ end
119
+
120
+ # Make an array consists of a point of any activation function.
121
+ # @param [Integer] lut_size the lut_size of LUT
122
+ # @return [Array] table an array consists of a point of tanh
123
+ def initialize_lut(func, otyp, awidth, xrange, yrange)
124
+ # Compute the x step between discret values.
125
+ xstep = (xrange.last-xrange.first)/(2 ** awidth)
126
+
127
+ # Generate the discrete set of x values.
128
+ x_values = xrange.step(xstep)
129
+ # Generate the table.
130
+ table = x_values.map do |x_value|
131
+ ((func.call(x_value)-yrange.first)/(yrange.last-yrange.first)*
132
+ 2**otyp.width).to_i.to_expr.as(otyp)
133
+ end
134
+
135
+ return table
136
+ end
137
+
138
+
139
+ end