HDLRuby 2.2.15 → 2.3.2

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