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.
@@ -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 system to Verilog code.
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
@@ -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 addition. */
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 addition. */
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
- // printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length);
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
@@ -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
- def brancher(name,&ruby_block)
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
- # Create the branch.
608
- channelI = HDLRuby::High.channel_instance(name, &ruby_block)
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
 
@@ -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.class_eval do
20
- # Saves the former type generation method.
21
- alias_method :"_[]_fixpoint", :[]
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
- # Redefine the type generation method for supporting fixed point
24
- # type generation.
25
- def [](*args)
26
- if args.size == 1 then
27
- return self.send(:"_[]_fixpoint",*args)
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
- raise "Invalid type for generating a fixed point type: #{self.name}"
50
- end
51
- # Redefine the multiplication and division for fixed point.
52
- typ.define_operator(:*) do |left,right|
53
- (left.as([isize+fsize*2])*right) >> fsize
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
@@ -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 right value.
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(i,avs[i])
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(i,add.(avs[i],mul.(lvs[i],rv)))
181
- accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
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(i,0)
190
- accs[i].write(0)
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