HDLRuby 2.2.15 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|