HDLRuby 2.5.0 → 2.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/HDLRuby/hdr_samples/adder.rb +1 -1
- data/lib/HDLRuby/hdr_samples/adder_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/adder_gen.rb +1 -1
- data/lib/HDLRuby/hdr_samples/constant_in_function.rb +27 -0
- data/lib/HDLRuby/hdr_samples/dff_unit.rb +54 -0
- data/lib/HDLRuby/hdr_samples/huge_rom.rb +25 -0
- data/lib/HDLRuby/hdr_samples/logic_bench.rb +21 -0
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/multi_timed_bench.rb +54 -0
- data/lib/HDLRuby/hdr_samples/music.rb +79 -0
- data/lib/HDLRuby/hdr_samples/named_sub.rb +42 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +16 -0
- data/lib/HDLRuby/hdr_samples/with_function_generator.rb +25 -0
- data/lib/HDLRuby/hdrcc.rb +132 -24
- data/lib/HDLRuby/hruby_decorator.rb +3 -1
- data/lib/HDLRuby/hruby_high.rb +215 -27
- data/lib/HDLRuby/hruby_low.rb +402 -45
- data/lib/HDLRuby/hruby_low2c.rb +122 -168
- data/lib/HDLRuby/hruby_low2hdr.rb +738 -0
- data/lib/HDLRuby/hruby_low2high.rb +331 -549
- data/lib/HDLRuby/hruby_low2vhd.rb +39 -2
- data/lib/HDLRuby/hruby_low_bool2select.rb +29 -0
- data/lib/HDLRuby/hruby_low_casts_without_expression.rb +27 -0
- data/lib/HDLRuby/hruby_low_fix_types.rb +25 -0
- data/lib/HDLRuby/hruby_low_mutable.rb +70 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +28 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +6 -3
- data/lib/HDLRuby/hruby_low_without_namespace.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_select.rb +13 -0
- data/lib/HDLRuby/hruby_tools.rb +11 -1
- data/lib/HDLRuby/hruby_verilog.rb +1572 -1723
- data/lib/HDLRuby/sim/hruby_sim.h +29 -3
- data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
- data/lib/HDLRuby/sim/hruby_sim_core.c +24 -9
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +7 -3
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +22 -6
- data/lib/HDLRuby/std/fixpoint.rb +9 -0
- data/lib/HDLRuby/std/function_generator.rb +139 -0
- data/lib/HDLRuby/std/hruby_unit.rb +75 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +16 -5
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -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
|
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
|
2076
|
-
|
2077
|
-
|
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
|
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 (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
|
@@ -365,15 +366,18 @@ static void vcd_print_header() {
|
|
365
366
|
extern void init_vcd_visualizer(char* name) {
|
366
367
|
/* Open the resulting file with name: <name>.vcd */
|
367
368
|
char filename[256];
|
368
|
-
strncpy(filename,name,
|
369
|
-
strncat(filename,".vcd",
|
369
|
+
strncpy(filename,name,255);
|
370
|
+
strncat(filename,".vcd",255);
|
370
371
|
vcd_file = fopen(filename,"w");
|
371
372
|
|
372
373
|
/* Initialize the vizualizer printer engine. */
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
}
|
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -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
|