HDLRuby 2.5.1 → 2.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +3 -3
- 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/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 +41 -7
- data/lib/HDLRuby/hruby_decorator.rb +3 -1
- data/lib/HDLRuby/hruby_high.rb +214 -26
- 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 +25 -2
- data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +5 -1
- 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 +14 -6
- data/lib/HDLRuby/hruby_unit.rb +0 -43
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -573,10 +573,15 @@ extern void each_all_signal(void (*func)(SignalI));
|
|
573
573
|
/* Interface to the visualization engine. */
|
574
574
|
|
575
575
|
typedef struct {
|
576
|
+
/* The simulation prints. */
|
576
577
|
void (*print_time)(unsigned long long);
|
577
578
|
void (*print_name)(Object);
|
578
579
|
void (*print_value)(Value);
|
579
580
|
void (*print_signal)(SignalI);
|
581
|
+
/* The custom 'string' prints. */
|
582
|
+
void (*print_string)(const char*);
|
583
|
+
void (*print_string_name)(Object);
|
584
|
+
void (*print_string_value)(Value);
|
580
585
|
} PrinterS;
|
581
586
|
|
582
587
|
extern PrinterS printer;
|
@@ -585,11 +590,29 @@ extern PrinterS printer;
|
|
585
590
|
* @param print_time the time printer
|
586
591
|
* @param print_name the name printer
|
587
592
|
* @param print_value the value printer
|
588
|
-
* @param print_signal the signal state printer
|
593
|
+
* @param print_signal the signal state printer
|
594
|
+
* @param print_string the string printer
|
595
|
+
* @param print_string_name the string name printer
|
596
|
+
* @param print_string_value the string value printer */
|
589
597
|
extern void init_visualizer(void (*print_time)(unsigned long long),
|
590
598
|
void (*print_name)(Object),
|
591
599
|
void (*print_value)(Value),
|
592
|
-
void (*print_signal)(SignalI)
|
600
|
+
void (*print_signal)(SignalI),
|
601
|
+
void (*print_string)(const char*),
|
602
|
+
void (*print_string_name)(Object),
|
603
|
+
void (*print_string_value)(Value));
|
604
|
+
|
605
|
+
/** Prints a name (default).
|
606
|
+
* @param signal the signal to show */
|
607
|
+
extern void default_print_name(Object);
|
608
|
+
|
609
|
+
/** Prints a value (default).
|
610
|
+
* @param signal the signal to show */
|
611
|
+
extern void default_print_value(Value);
|
612
|
+
|
613
|
+
/** Prints a string (default).
|
614
|
+
* @param str the string to print. */
|
615
|
+
extern void default_print_string(const char* str);
|
593
616
|
|
594
617
|
// /** Prints the time.
|
595
618
|
// * @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. */
|
@@ -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
|
-
|
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
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "HDLRuby/hruby_high"
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
##
|
6
|
+
# Library for building unit test systems.
|
7
|
+
#
|
8
|
+
########################################################################
|
9
|
+
module HDLRuby::Unit
|
10
|
+
|
11
|
+
## The HDLRuby unit test error class.
|
12
|
+
class UnitError < ::StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
# The set of the unit systems by name.
|
16
|
+
@@unit_systems = {}
|
17
|
+
|
18
|
+
|
19
|
+
# Declares system +name+ for unit testing.
|
20
|
+
# The system is built by executing +ruby_block+.
|
21
|
+
#
|
22
|
+
# NOTE: the name of the system is not registered within the HDLRuby
|
23
|
+
# namespace since it is not meant to be used directly.
|
24
|
+
def self.system(name,&ruby_block)
|
25
|
+
# Ensure name is a symbol.
|
26
|
+
name = name.to_s.to_sym unless name.is_a?(Symbol)
|
27
|
+
# Check if the name is already used or not.
|
28
|
+
if @@unit_systems.key?(name) then
|
29
|
+
raise UnitError, "Unit test system #{name} already declared."
|
30
|
+
end
|
31
|
+
# @@unit_systems[name] = HDLRuby::High.system(&ruby_block)
|
32
|
+
@@unit_systems[name] = ruby_block
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Create a system named +test_name+ executing the unit tests given from
|
37
|
+
# +names+.
|
38
|
+
def self.test(test_name = :test, *names)
|
39
|
+
# If there is no name given, use all the test systems.
|
40
|
+
names = @@unit_systems.each_key if names.empty?
|
41
|
+
# Declare the system.
|
42
|
+
HDLRuby::High.system test_name do
|
43
|
+
|
44
|
+
# The timed block that contains the bench execurtion code.
|
45
|
+
@@tester = timed {}
|
46
|
+
|
47
|
+
# Generate the test code for each selected test units.
|
48
|
+
names.each do |name|
|
49
|
+
name = name.to_s.to_sym unless name.is_a?(Symbol)
|
50
|
+
unless @@unit_systems.key?(name) then
|
51
|
+
raise UnitError, "Unit test #{name} does not exist."
|
52
|
+
end
|
53
|
+
sub(name) do
|
54
|
+
@@myself = self
|
55
|
+
instance_exec do
|
56
|
+
# Define the test command that insert code of
|
57
|
+
# the current test unit to the tester timed block.
|
58
|
+
def test(&ruby_block)
|
59
|
+
@@tester.block.open do
|
60
|
+
# Here the signals are to be taken from
|
61
|
+
# the test unit and not the timed block.
|
62
|
+
set_this(@@myself)
|
63
|
+
ruby_block.call
|
64
|
+
# Go back to the default current this.
|
65
|
+
set_this
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
# Process the test unit.
|
70
|
+
instance_exec(&@@unit_systems[name])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|