HDLRuby 2.2.15 → 2.3.2
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/README.md +14 -8
- data/lib/HDLRuby/hdr_samples/linear_test.rb +30 -2
- data/lib/HDLRuby/hdr_samples/rom.rb +2 -2
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +3 -2
- data/lib/HDLRuby/hdr_samples/with_linear.rb +4 -1
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hdrcc.rb +3 -6
- data/lib/HDLRuby/hruby_check.rb +25 -1
- data/lib/HDLRuby/hruby_high.rb +12 -4
- data/lib/HDLRuby/hruby_low.rb +24 -9
- data/lib/HDLRuby/hruby_low2c.rb +10 -5
- data/lib/HDLRuby/hruby_low2high.rb +1 -1
- data/lib/HDLRuby/hruby_low2vhd.rb +63 -48
- data/lib/HDLRuby/hruby_low_fix_types.rb +6 -2
- data/lib/HDLRuby/hruby_low_resolve.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/hruby_verilog.rb +9 -1
- data/lib/HDLRuby/sim/hruby_sim.h +7 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +83 -6
- data/lib/HDLRuby/std/channel.rb +39 -16
- data/lib/HDLRuby/std/fixpoint.rb +50 -39
- data/lib/HDLRuby/std/linear.rb +131 -11
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1000 -30
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +6 -2
@@ -1630,12 +1630,20 @@ end
|
|
1630
1630
|
# If it is signed, it outputs signed.
|
1631
1631
|
# Enhance Type with generation of verilog code.
|
1632
1632
|
class Type
|
1633
|
-
# Converts the
|
1633
|
+
# Converts the type to Verilog code.
|
1634
1634
|
def to_verilog
|
1635
1635
|
return self.name == :signed ? "#{self.name.to_s} " : ""
|
1636
1636
|
end
|
1637
1637
|
end
|
1638
1638
|
|
1639
|
+
# Replace type by refered type.
|
1640
|
+
class TypeDef
|
1641
|
+
# Converts the type to verilog code.
|
1642
|
+
def to_verilog
|
1643
|
+
return self.def.to_verilog
|
1644
|
+
end
|
1645
|
+
end
|
1646
|
+
|
1639
1647
|
# Use it when collecting.
|
1640
1648
|
class Concat
|
1641
1649
|
def to_verilog
|
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -157,6 +157,13 @@ extern Value mul_value(Value src0, Value src1, Value dst);
|
|
157
157
|
* @return dst */
|
158
158
|
extern Value div_value(Value src0, Value src1, Value dst);
|
159
159
|
|
160
|
+
/** Computes the modulo of two general values.
|
161
|
+
* @param src0 the first source value of the addition
|
162
|
+
* @param src1 the second source value of the addition
|
163
|
+
* @param dst the destination value
|
164
|
+
* @return dst */
|
165
|
+
extern Value mod_value(Value src0, Value src1, Value dst);
|
166
|
+
|
160
167
|
/** Computes the not of a value.
|
161
168
|
* @param src the source value of the not
|
162
169
|
* @param dst the destination value
|
@@ -5,6 +5,10 @@
|
|
5
5
|
#include <limits.h>
|
6
6
|
#include "hruby_sim.h"
|
7
7
|
|
8
|
+
#ifndef alloca
|
9
|
+
#define alloca(x) __builtin_alloca(x)
|
10
|
+
#endif
|
11
|
+
|
8
12
|
|
9
13
|
/**
|
10
14
|
* The HDLRuby simulation calculation engine, to be used with C code
|
@@ -393,6 +397,9 @@ static Value set_undefined_bitstring(Value dst) {
|
|
393
397
|
|
394
398
|
/* set the type and size of the destination. */
|
395
399
|
dst->numeric = 0;
|
400
|
+
/* Ensures the buffer of dst has the write size (in cas it was a fromer
|
401
|
+
* numeric for example). */
|
402
|
+
resize_value(dst,width);
|
396
403
|
|
397
404
|
/* Get access to the destination data. */
|
398
405
|
char* dst_data = dst->data_str;
|
@@ -600,7 +607,7 @@ static Value mul_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
|
600
607
|
dst->type = src0->type;
|
601
608
|
dst->numeric = 1;
|
602
609
|
|
603
|
-
/* Perform the
|
610
|
+
/* Perform the multiplication. */
|
604
611
|
dst->data_int = value2integer(src0) * value2integer(src1);
|
605
612
|
return dst;
|
606
613
|
}
|
@@ -616,12 +623,29 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
|
616
623
|
dst->type = src0->type;
|
617
624
|
dst->numeric = 1;
|
618
625
|
|
619
|
-
/* Perform the
|
626
|
+
/* Perform the division. */
|
620
627
|
dst->data_int = value2integer(src0) / value2integer(src1);
|
621
628
|
return dst;
|
622
629
|
}
|
623
630
|
|
624
631
|
|
632
|
+
/** Computes the modulo of two defined bitstring values.
|
633
|
+
* @param src0 the first source value of the addition
|
634
|
+
* @param src1 the second source value of the addition
|
635
|
+
* @param dst the destination value
|
636
|
+
* @return dst */
|
637
|
+
static Value mod_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
638
|
+
/* Sets state of the destination using the first source. */
|
639
|
+
dst->type = src0->type;
|
640
|
+
dst->numeric = 1;
|
641
|
+
|
642
|
+
/* Perform the modulo. */
|
643
|
+
// printf("modulo with src0=%lld src1=%lld, result=%lld\n",value2integer(src0),value2integer(src1),value2integer(src0) % value2integer(src1));
|
644
|
+
dst->data_int = value2integer(src0) % value2integer(src1);
|
645
|
+
return dst;
|
646
|
+
}
|
647
|
+
|
648
|
+
|
625
649
|
/** Computes the lesser comparision of two defined bitstring values.
|
626
650
|
* @param src0 the first source value of the addition
|
627
651
|
* @param src1 the second source value of the addition
|
@@ -1411,7 +1435,10 @@ fix_numeric_type(Type type, unsigned long long val) {
|
|
1411
1435
|
/* Get the width of the type. */
|
1412
1436
|
int width = type_width(type);
|
1413
1437
|
/* Compute the base mask. */
|
1414
|
-
unsigned long long mask = ((unsigned long long)(-1)) << width;
|
1438
|
+
// unsigned long long mask = ((unsigned long long)(-1)) << width;
|
1439
|
+
/* NOTE: (ull)-1 << 64 becomes (ull)-1 on Intel processors, this is
|
1440
|
+
* totally not what I expected (I expected 0). */
|
1441
|
+
unsigned long long mask = width == 64 ? 0 : ((unsigned long long)(-1)) << width;
|
1415
1442
|
// printf("width=%i val=%llu mask=%llx\n",width,val,mask);
|
1416
1443
|
|
1417
1444
|
/* Is the type signed? */
|
@@ -1512,6 +1539,23 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
|
|
1512
1539
|
}
|
1513
1540
|
|
1514
1541
|
|
1542
|
+
/** Computes the modulo of two numeric values.
|
1543
|
+
* @param src0 the first source value of the addition
|
1544
|
+
* @param src1 the second source value of the addition
|
1545
|
+
* @param dst the destination value
|
1546
|
+
* @return dst */
|
1547
|
+
static Value mod_value_numeric(Value src0, Value src1, Value dst) {
|
1548
|
+
/* Sets state of the destination using the first source. */
|
1549
|
+
dst->type = src0->type;
|
1550
|
+
dst->numeric = 1;
|
1551
|
+
|
1552
|
+
/* Perform the division. */
|
1553
|
+
// printf("modulo numeric with src0=%lld src1=%lld, result=%lld\n",src0->data_int, src1->data_int,src0->data_int % src1->data_int);
|
1554
|
+
dst->data_int = fix_numeric_type(dst->type, src0->data_int % src1->data_int);
|
1555
|
+
return dst;
|
1556
|
+
}
|
1557
|
+
|
1558
|
+
|
1515
1559
|
/** Computes the NOT of a numeric value.
|
1516
1560
|
* @param src the source value of the not
|
1517
1561
|
* @param dst the destination value
|
@@ -1686,7 +1730,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1686
1730
|
unsigned int i,pos;
|
1687
1731
|
/* Compute the bit width of the destination. */
|
1688
1732
|
unsigned int width = 0;
|
1689
|
-
// printf("concat_value_numeric with dir=%d\n",dir);
|
1733
|
+
// printf("concat_value_numeric with dir=%d and width=%llu\n",dir,type_width(args[0]->type));
|
1690
1734
|
for(i=0; i<num; ++i) width += type_width(args[i]->type);
|
1691
1735
|
|
1692
1736
|
/* Sets state of the destination using the bit width. */
|
@@ -1710,6 +1754,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1710
1754
|
pos += arg_width;
|
1711
1755
|
}
|
1712
1756
|
/* Return the destination. */
|
1757
|
+
// printf("Result is dst=%llx\n",dst->data_int);
|
1713
1758
|
return dst;
|
1714
1759
|
}
|
1715
1760
|
|
@@ -1720,6 +1765,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1720
1765
|
* @param dst the destination value
|
1721
1766
|
* @return dst */
|
1722
1767
|
static Value cast_value_numeric(Value src, Type type, Value dst) {
|
1768
|
+
// printf("cast_value_numeric with src=%llx",src->data_int);
|
1723
1769
|
/* Copy the source to the destination. */
|
1724
1770
|
dst->data_int = src->data_int;
|
1725
1771
|
/* Update the destination type to the cast. */
|
@@ -1779,6 +1825,7 @@ static int same_content_value_range_numeric(Value value0,
|
|
1779
1825
|
* @return dst */
|
1780
1826
|
Value read_range_numeric(Value value, long long first, long long last,
|
1781
1827
|
Type base, Value dst) {
|
1828
|
+
/* printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last); */
|
1782
1829
|
/* Ensure first is the smaller. */
|
1783
1830
|
if (first > last) {
|
1784
1831
|
long long tmp = last;
|
@@ -1791,15 +1838,18 @@ Value read_range_numeric(Value value, long long first, long long last,
|
|
1791
1838
|
unsigned long long bw = type_width(base);
|
1792
1839
|
/* Scale the range according to the base type. */
|
1793
1840
|
first *= bw;
|
1841
|
+
last *= bw;
|
1794
1842
|
length *= bw;
|
1795
|
-
|
1843
|
+
/* printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
|
1796
1844
|
|
1797
1845
|
/* Set the type and size of the destination from the type of the source.*/
|
1798
1846
|
dst->type = make_type_vector(get_type_bit(),length);
|
1799
1847
|
dst->numeric = 1;
|
1800
1848
|
|
1801
1849
|
/* Compute the read mask. */
|
1802
|
-
unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
|
1850
|
+
// unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
|
1851
|
+
/* NOTE: once again, << 64 does not work like expected. */
|
1852
|
+
unsigned long long mask = mask+bw < 64 ? (~((-1LL) << (last+bw))) : -1LL;
|
1803
1853
|
/* Performs the read. */
|
1804
1854
|
unsigned long long data = (value->data_int & mask) >> first;
|
1805
1855
|
/* Write it to the destination. */
|
@@ -1995,6 +2045,33 @@ Value div_value(Value src0, Value src1, Value dst) {
|
|
1995
2045
|
}
|
1996
2046
|
|
1997
2047
|
|
2048
|
+
/** Computes the modulo of two general values.
|
2049
|
+
* @param src0 the first source value of the addition
|
2050
|
+
* @param src1 the second source value of the addition
|
2051
|
+
* @param dst the destination value
|
2052
|
+
* @return dst */
|
2053
|
+
Value mod_value(Value src0, Value src1, Value dst) {
|
2054
|
+
/* Might allocate a new value so save the current pool state. */
|
2055
|
+
unsigned int pos = get_value_pos();
|
2056
|
+
/* Do a numeric computation if possible, otherwise fallback to bitstring
|
2057
|
+
* computation. */
|
2058
|
+
if (src0->numeric && src1->numeric) {
|
2059
|
+
/* Both sources are numeric. */
|
2060
|
+
return mod_value_numeric(src0,src1,dst);
|
2061
|
+
} else if (is_defined_value(src0) && is_defined_value(src1)) {
|
2062
|
+
/* Both sources can be converted to numeric values. */
|
2063
|
+
return mod_value_defined_bitstring(src0,src1,dst);
|
2064
|
+
} else {
|
2065
|
+
/* Cannot compute (for now), simply undefines the destination. */
|
2066
|
+
/* First ensure dst has the right shape. */
|
2067
|
+
copy_value(src0,dst);
|
2068
|
+
/* Then make it undefined. */
|
2069
|
+
set_undefined_bitstring(dst);
|
2070
|
+
}
|
2071
|
+
return dst;
|
2072
|
+
}
|
2073
|
+
|
2074
|
+
|
1998
2075
|
/** Computes the NOT of a general value.
|
1999
2076
|
* @param src the source value of the not
|
2000
2077
|
* @param dst the destination value
|
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -81,9 +81,17 @@ module HDLRuby::High::Std
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
-
##
|
85
|
-
# Module for wrapping channel ports.
|
86
|
-
module ChannelPortWrapping
|
84
|
+
# ##
|
85
|
+
# # Module for wrapping channel ports.
|
86
|
+
# module ChannelPortWrapping
|
87
|
+
# # Wrap with +args+ arguments.
|
88
|
+
# def wrap(*args)
|
89
|
+
# return ChannelPortB.new(self,*args)
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
|
93
|
+
## Describes a channel port.
|
94
|
+
class ChannelPort
|
87
95
|
# Wrap with +args+ arguments.
|
88
96
|
def wrap(*args)
|
89
97
|
return ChannelPortB.new(self,*args)
|
@@ -93,8 +101,8 @@ module HDLRuby::High::Std
|
|
93
101
|
|
94
102
|
##
|
95
103
|
# Describes a read port to a channel.
|
96
|
-
class ChannelPortR
|
97
|
-
include ChannelPortWrapping
|
104
|
+
class ChannelPortR < ChannelPort
|
105
|
+
# include ChannelPortWrapping
|
98
106
|
|
99
107
|
# Creates a new channel reader running in +namespace+ and
|
100
108
|
# reading using +reader_proc+ and reseting using +reseter_proc+.
|
@@ -137,8 +145,8 @@ module HDLRuby::High::Std
|
|
137
145
|
|
138
146
|
##
|
139
147
|
# Describes a writer port to a channel.
|
140
|
-
class ChannelPortW
|
141
|
-
include ChannelPortWrapping
|
148
|
+
class ChannelPortW < ChannelPort
|
149
|
+
# include ChannelPortWrapping
|
142
150
|
|
143
151
|
# Creates a new channel writer running in +namespace+ and
|
144
152
|
# writing using +writer_proc+ and reseting using +reseter_proc+.
|
@@ -181,8 +189,8 @@ module HDLRuby::High::Std
|
|
181
189
|
|
182
190
|
##
|
183
191
|
# Describes an access port to a channel.
|
184
|
-
class ChannelPortA
|
185
|
-
include ChannelPortWrapping
|
192
|
+
class ChannelPortA < ChannelPort
|
193
|
+
# include ChannelPortWrapping
|
186
194
|
|
187
195
|
# Creates a new channel accesser running in +namespace+
|
188
196
|
# and reading using +reader_proc+, writing using +writer_proc+,
|
@@ -243,8 +251,8 @@ module HDLRuby::High::Std
|
|
243
251
|
|
244
252
|
##
|
245
253
|
# Describes port wrapper (Box) for fixing arugments.
|
246
|
-
class ChannelPortB
|
247
|
-
include ChannelPortWrapping
|
254
|
+
class ChannelPortB < ChannelPort
|
255
|
+
# include ChannelPortWrapping
|
248
256
|
|
249
257
|
# Creates a new channel box over channel port +port+ fixing +args+
|
250
258
|
# as arguments.
|
@@ -600,13 +608,23 @@ module HDLRuby::High::Std
|
|
600
608
|
|
601
609
|
# Defines a branch in the channel named +name+ built executing
|
602
610
|
# +ruby_block+.
|
603
|
-
|
611
|
+
# Alternatively, a ready channel instance can be passed as argument
|
612
|
+
# as +channelI+.
|
613
|
+
def brancher(name,channelI = nil,&ruby_block)
|
604
614
|
# Ensure name is a symbol.
|
605
615
|
name = name.to_s unless name.respond_to?(:to_sym)
|
606
616
|
name = name.to_sym
|
607
|
-
#
|
608
|
-
channelI
|
617
|
+
# Is there a ready channel instance.
|
618
|
+
if channelI then
|
619
|
+
# Yes, use it directly.
|
620
|
+
@branches[name] = channelI
|
621
|
+
return self
|
622
|
+
end
|
623
|
+
# No, create the branch.
|
624
|
+
# channelI = HDLRuby::High.channel_instance(name, &ruby_block)
|
625
|
+
channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
|
609
626
|
@branches[name] = channelI
|
627
|
+
return self
|
610
628
|
end
|
611
629
|
|
612
630
|
|
@@ -619,6 +637,7 @@ module HDLRuby::High::Std
|
|
619
637
|
name = name.to_s unless name.respond_to?(:to_sym)
|
620
638
|
name = name.to_sym
|
621
639
|
# Get the branch.
|
640
|
+
channelI = @branches[name]
|
622
641
|
return @branches[name]
|
623
642
|
end
|
624
643
|
|
@@ -902,7 +921,7 @@ module HDLRuby::High::Std
|
|
902
921
|
|
903
922
|
|
904
923
|
# Wrapper to make an object run like a channel port.
|
905
|
-
class ChannelPortObject
|
924
|
+
class ChannelPortObject < ChannelPort
|
906
925
|
# Create a new object wrapper for +obj+.
|
907
926
|
def initialize(obj)
|
908
927
|
@obj = obj
|
@@ -946,9 +965,13 @@ module HDLRuby::High::Std
|
|
946
965
|
|
947
966
|
|
948
967
|
# Wrap object +obj+ to act like a channel port.
|
949
|
-
def channel_port(obj)
|
968
|
+
def self.channel_port(obj)
|
969
|
+
return obj if obj.is_a?(ChannelPort) # No need to wrap.
|
950
970
|
return ChannelPortObject.new(obj)
|
951
971
|
end
|
972
|
+
def channel_port(obj)
|
973
|
+
return HDLRuby::High::Std.channel_port(obj)
|
974
|
+
end
|
952
975
|
end
|
953
976
|
|
954
977
|
|
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -15,53 +15,64 @@ module HDLRuby::High::Std
|
|
15
15
|
def self.included(base)
|
16
16
|
# Performs the previous included
|
17
17
|
res = self.send(:_included_fixpoint,base)
|
18
|
-
# Now modify the Type class
|
19
|
-
::HDLRuby::High::Type.
|
20
|
-
|
21
|
-
|
18
|
+
# Now modify the Type class if not already modified.
|
19
|
+
unless ::HDLRuby::High::Type.instance_methods.include?(:"_[]_fixpoint") then
|
20
|
+
::HDLRuby::High::Type.class_eval do
|
21
|
+
# Saves the former type generation method.
|
22
|
+
alias_method :"_[]_fixpoint", :[]
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
# Handle the arguments.
|
30
|
-
arg0,arg1 = *args
|
31
|
-
if arg0.respond_to?(:to_i) then
|
32
|
-
arg0 = (arg0.to_i.abs-1)..0
|
33
|
-
end
|
34
|
-
if arg1.respond_to?(:to_i) then
|
35
|
-
arg1 = (arg1.to_i.abs-1)..0
|
36
|
-
end
|
37
|
-
# Compute the fix point sizes.
|
38
|
-
isize = (arg0.first-arg0.last).abs+1
|
39
|
-
fsize = (arg1.first-arg1.last).abs+1
|
40
|
-
# Build the type.
|
41
|
-
case(self.name)
|
42
|
-
when :bit
|
43
|
-
typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
|
44
|
-
when :unsigned
|
45
|
-
typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
|
46
|
-
when :signed
|
47
|
-
typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
|
24
|
+
# Redefine the type generation method for supporting fixed point
|
25
|
+
# type generation.
|
26
|
+
def [](*args)
|
27
|
+
if args.size == 1 then
|
28
|
+
return self.send(:"_[]_fixpoint",*args)
|
48
29
|
else
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
30
|
+
# Handle the arguments and compute the fix point sizes.
|
31
|
+
arg0,arg1 = *args
|
32
|
+
if arg0.respond_to?(:to_i) then
|
33
|
+
isize = arg0
|
34
|
+
else
|
35
|
+
isize = (arg0.first-arg0.last).abs+1
|
36
|
+
end
|
37
|
+
if arg1.respond_to?(:to_i) then
|
38
|
+
fsize = arg1
|
39
|
+
else
|
40
|
+
fsize = (arg1.first-arg1.last).abs+1
|
41
|
+
end
|
42
|
+
# Build the type.
|
43
|
+
case(self.name)
|
44
|
+
when :bit
|
45
|
+
typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
|
46
|
+
when :unsigned
|
47
|
+
typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
|
48
|
+
when :signed
|
49
|
+
typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
|
50
|
+
else
|
51
|
+
raise "Invalid type for generating a fixed point type: #{self.name}"
|
52
|
+
end
|
53
|
+
# Redefine the multiplication and division for fixed point.
|
54
|
+
typ.define_operator(:*) do |left,right|
|
55
|
+
(left.as([isize+fsize*2])*right) >> fsize
|
56
|
+
end
|
57
|
+
typ.define_operator(:/) do |left,right|
|
58
|
+
(left.as([isize+fsize*2]) << fsize) / right
|
59
|
+
end
|
60
|
+
typ
|
54
61
|
end
|
55
|
-
typ.define_operator(:/) do |left,right|
|
56
|
-
(left.as([isize+fsize*2]) << fsize) / right
|
57
|
-
end
|
58
|
-
typ
|
59
62
|
end
|
63
|
+
return res
|
60
64
|
end
|
61
|
-
return res
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
68
|
+
# Extends the Numeric class for conversion to fixed point litteral.
|
69
|
+
class ::Numeric
|
70
|
+
# Convert to fixed point value with +dec+ digits after the decimal
|
71
|
+
# point.
|
72
|
+
def to_fix(dec)
|
73
|
+
return (self * (2**dec.to_i)).to_i
|
74
|
+
end
|
75
|
+
end
|
65
76
|
|
66
77
|
|
67
78
|
end
|
data/lib/HDLRuby/std/linear.rb
CHANGED
@@ -8,6 +8,51 @@ module HDLRuby::High::Std
|
|
8
8
|
#
|
9
9
|
########################################################################
|
10
10
|
|
11
|
+
# Controller of the linear operator.
|
12
|
+
# - +num+: the number of computation cycles.
|
13
|
+
# - +ev+: event to synchronize the controller on.
|
14
|
+
# - +req+: the request to start the linear computation.
|
15
|
+
# - +ack+: the ack signal that is set to 1 when the computation completes.
|
16
|
+
# - +ruby_block+: the code of the linear computation kernel, it takes
|
17
|
+
# as argument +ev+, and its own req and ack signals
|
18
|
+
# (resp. +req_ker+ +ack_ker+).
|
19
|
+
function :linearun do |num,ev,req,ack,ruby_block|
|
20
|
+
# Ensure ev is really an event.
|
21
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
22
|
+
|
23
|
+
# Creates the kernel.
|
24
|
+
inner :req_ker, :ack_ker
|
25
|
+
|
26
|
+
HDLRuby::High.top_user.instance_exec(ev,req_ker,ack_ker,&ruby_block)
|
27
|
+
|
28
|
+
# The computation counter.
|
29
|
+
[num.width].inner :count
|
30
|
+
# Run flag
|
31
|
+
inner :run
|
32
|
+
par(ev) do
|
33
|
+
req_ker <= 0
|
34
|
+
ack <= 0
|
35
|
+
count <= 1
|
36
|
+
run <= 0
|
37
|
+
hif(req | run) do
|
38
|
+
run <= 1
|
39
|
+
req_ker <= 1
|
40
|
+
# Is one linear computation completed?
|
41
|
+
hif(ack_ker) do
|
42
|
+
# Yes.
|
43
|
+
count <= count + 1
|
44
|
+
end
|
45
|
+
# Is the full computation completed?
|
46
|
+
hif(count == num) do
|
47
|
+
# Yes.
|
48
|
+
ack <= 1
|
49
|
+
run <= 0
|
50
|
+
req_ker <= 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
11
56
|
|
12
57
|
# Delcares a vector product by a scalar value.
|
13
58
|
#
|
@@ -111,7 +156,7 @@ module HDLRuby::High::Std
|
|
111
156
|
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
112
157
|
# Ensure ev is really an event.
|
113
158
|
ev = ev.posedge unless ev.is_a?(Event)
|
114
|
-
# Left value and
|
159
|
+
# Left value, right value and computation temp value.
|
115
160
|
typ.inner :lv, :rv, :av
|
116
161
|
# lv and rv are valid.
|
117
162
|
inner :lvok, :rvok
|
@@ -125,18 +170,21 @@ module HDLRuby::High::Std
|
|
125
170
|
# Computation request.
|
126
171
|
left.read(lv) { lvok <= 1 }
|
127
172
|
right.read(rv) { rvok <= 1 }
|
128
|
-
# ( acc <= add.(acc,mul.(lv,rv)) ).hif(lvok & rvok)
|
129
|
-
acc.read(av)
|
130
173
|
hif(lvok & rvok) do
|
131
174
|
ack <= 1
|
132
175
|
run <= 0
|
133
|
-
acc.write(add.(av,mul.(lv,rv)))
|
176
|
+
# acc.write(add.(av,mul.(lv,rv)))
|
177
|
+
seq do
|
178
|
+
av <= add.(av,mul.(lv,rv))
|
179
|
+
acc.write(av)
|
180
|
+
end
|
134
181
|
end
|
135
182
|
end
|
136
183
|
helse do
|
137
184
|
lvok <= 0
|
138
185
|
rvok <= 0
|
139
|
-
acc.write(0)
|
186
|
+
# acc.write(0)
|
187
|
+
av <= 0
|
140
188
|
end
|
141
189
|
end
|
142
190
|
end
|
@@ -172,13 +220,15 @@ module HDLRuby::High::Std
|
|
172
220
|
right.read(rv) { rvok <= 1 }
|
173
221
|
lefts.each_with_index do |left,i|
|
174
222
|
left.read(lvs[i]) { lvoks[i] <= 1 }
|
175
|
-
# accs.read(
|
176
|
-
accs[i].read(avs[i])
|
223
|
+
# accs[i].read(avs[i])
|
177
224
|
hif(lvoks[i] & rvok) do
|
178
225
|
ack <= 1
|
179
226
|
run <= 0
|
180
|
-
# accs.write(
|
181
|
-
|
227
|
+
# accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
|
228
|
+
seq do
|
229
|
+
avs[i] <= add.(avs[i],mul.(lvs[i],rv))
|
230
|
+
accs[i].write(avs[i])
|
231
|
+
end
|
182
232
|
end
|
183
233
|
end
|
184
234
|
end
|
@@ -186,12 +236,82 @@ module HDLRuby::High::Std
|
|
186
236
|
rvok <= 0
|
187
237
|
lefts.each_with_index do |left,i|
|
188
238
|
lvoks[i] <= 0
|
189
|
-
# accs.write(
|
190
|
-
|
239
|
+
# accs[i].write(0)
|
240
|
+
avs[i] <= 0
|
191
241
|
end
|
192
242
|
end
|
193
243
|
end
|
194
244
|
end
|
195
245
|
|
196
246
|
|
247
|
+
# Declares a simple pipelined multiple mac with single right data.
|
248
|
+
#
|
249
|
+
# Can be used for the product of a martix-vector product.
|
250
|
+
function :mac_np do |typ,ev,req,ack,lefts, rights, last,
|
251
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
252
|
+
# Ensure ev is really an event.
|
253
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
254
|
+
# Ensures lefts is an array.
|
255
|
+
lefts = lefts.to_a
|
256
|
+
# Ensures rights is an array.
|
257
|
+
rights = rights.to_a
|
258
|
+
# Get the size of the pipeline and ensure lefts and rights have the
|
259
|
+
# same.
|
260
|
+
size = lefts.size
|
261
|
+
if (rights.size != size) then
|
262
|
+
raise "Incompatible lefts and rights sizes: lefts size is #{size} and rights size is #{rights.size}"
|
263
|
+
end
|
264
|
+
# Declares the accumulators.
|
265
|
+
accs = size.times.map { |i| typ.inner :"acc#{i}" }
|
266
|
+
# Left value and right value.
|
267
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
268
|
+
rvs = rights.each_with_index.map { |right,i| typ.inner :"rv#{i}" }
|
269
|
+
# typ.inner :rv
|
270
|
+
# lv and rv are valid.
|
271
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
272
|
+
# inner :rvok
|
273
|
+
rvoks = rights.each_with_index.map { |right,i| inner :"rvok#{i}" }
|
274
|
+
# Run flag
|
275
|
+
inner :run
|
276
|
+
par(ev) do
|
277
|
+
ack <= 0
|
278
|
+
run <= 0
|
279
|
+
hif(req | run) do
|
280
|
+
run <= 1
|
281
|
+
# Computation request.
|
282
|
+
lefts.zip(rights).each_with_index do |(left,right),i|
|
283
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
284
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
285
|
+
hif(lvoks[i] & rvoks[i]) do
|
286
|
+
ack <= 1
|
287
|
+
run <= 0
|
288
|
+
if (i < lefts.size-1) then
|
289
|
+
if (i>0) then
|
290
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i])) +
|
291
|
+
accs[i-1]
|
292
|
+
else
|
293
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
294
|
+
end
|
295
|
+
else
|
296
|
+
# The last is reached
|
297
|
+
seq do
|
298
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
299
|
+
last.write(accs[i])
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
helse do
|
306
|
+
lefts.each_with_index do |left,i|
|
307
|
+
lvoks[i] <= 0
|
308
|
+
rvoks[i] <= 0
|
309
|
+
accs[i] <= 0
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
|
316
|
+
|
197
317
|
end
|