HDLRuby 2.2.14 → 2.3.1

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.
@@ -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
 
@@ -901,29 +920,81 @@ module HDLRuby::High::Std
901
920
  end
902
921
 
903
922
 
904
- end
905
-
923
+ # Wrapper to make an object run like a channel port.
924
+ class ChannelPortObject < ChannelPort
925
+ # Create a new object wrapper for +obj+.
926
+ def initialize(obj)
927
+ @obj = obj
928
+ end
906
929
 
907
- module HDLRuby::High
930
+ # Port read with arguments +args+ executing +ruby_block+ in
931
+ # case of success.
932
+ def read(*args,&ruby_block)
933
+ # Get the target from the arguments.
934
+ target = args.pop
935
+ # Is there any argument left?
936
+ unless (args.empty?) then
937
+ # There are arguments left, perform an array access.
938
+ target <= @obj[*args]
939
+ else
940
+ # There are no argument left, perform a direct access.
941
+ target <= @obj
942
+ end
943
+ # Execute the ruby_block if any.
944
+ ruby_block.call if ruby_block
945
+ end
908
946
 
909
- ## Enhance expressions with possibility to act like a reading branch.
910
- module HExpression
911
- ## Transmits the expression to +target+ and execute +ruby_block+ if
912
- # any.
913
- def read(target,&ruby_block)
914
- target <= self
915
- ruby_block.call if ruby_block
947
+ # Port write with argumnet +Args+ executing +ruby_block+ in
948
+ # case of success.
949
+ def write(*args,&ruby_block)
950
+ # Get the value to write from the arguments.
951
+ value = args.pop
952
+ # Is there any argument left?
953
+ unless (args.empty?) then
954
+ # There are arguments left, perform an array access.
955
+ @obj[*args] <= value
956
+ else
957
+ # There are no argument left, perform a direct access.
958
+ @obj <= value
959
+ end
960
+ # Execute the ruby_block if any.
961
+ ruby_block.call if ruby_block
916
962
  end
963
+
917
964
  end
918
965
 
919
966
 
920
- ## Enhance references with possibility to act like a writing branch.
921
- module HRef
922
- ## Transmits +target+ to the reference and execute +ruby_block+ if
923
- # any.
924
- def write(target,&ruby_block)
925
- self <= target
926
- ruby_block.call if ruby_block
927
- end
967
+ # Wrap object +obj+ to act like a channel port.
968
+ def self.channel_port(obj)
969
+ return obj if obj.is_a?(ChannelPort) # No need to wrap.
970
+ return ChannelPortObject.new(obj)
971
+ end
972
+ def channel_port(obj)
973
+ return HDLRuby::High::Std.channel_port(obj)
928
974
  end
929
975
  end
976
+
977
+
978
+ # module HDLRuby::High
979
+ #
980
+ # ## Enhance expressions with possibility to act like a reading branch.
981
+ # module HExpression
982
+ # ## Transmits the expression to +target+ and execute +ruby_block+ if
983
+ # # any.
984
+ # def read(target,&ruby_block)
985
+ # target <= self
986
+ # ruby_block.call if ruby_block
987
+ # end
988
+ # end
989
+ #
990
+ #
991
+ # ## Enhance references with possibility to act like a writing branch.
992
+ # module HRef
993
+ # ## Transmits +target+ to the reference and execute +ruby_block+ if
994
+ # # any.
995
+ # def write(target,&ruby_block)
996
+ # self <= target
997
+ # ruby_block.call if ruby_block
998
+ # end
999
+ # end
1000
+ # end
@@ -26,17 +26,18 @@ module HDLRuby::High::Std
26
26
  if args.size == 1 then
27
27
  return self.send(:"_[]_fixpoint",*args)
28
28
  else
29
- # Handle the arguments.
29
+ # Handle the arguments and compute the fix point sizes.
30
30
  arg0,arg1 = *args
31
31
  if arg0.respond_to?(:to_i) then
32
- arg0 = (arg0.to_i.abs-1)..0
32
+ isize = arg0
33
+ else
34
+ isize = (arg0.first-arg0.last).abs+1
33
35
  end
34
36
  if arg1.respond_to?(:to_i) then
35
- arg1 = (arg1.to_i.abs-1)..0
37
+ fsize = arg1
38
+ else
39
+ fsize = (arg1.first-arg1.last).abs+1
36
40
  end
37
- # Compute the fix point sizes.
38
- isize = (arg0.first-arg0.last).abs+1
39
- fsize = (arg1.first-arg1.last).abs+1
40
41
  # Build the type.
41
42
  case(self.name)
42
43
  when :bit
@@ -62,6 +63,14 @@ module HDLRuby::High::Std
62
63
  end
63
64
  end
64
65
 
66
+ # Extends the Numeric class for conversion to fixed point litteral.
67
+ class ::Numeric
68
+ # Convert to fixed point value with +dec+ digits after the decimal
69
+ # point.
70
+ def to_fix(dec)
71
+ return (self * (2**dec.to_i)).to_i
72
+ end
73
+ end
65
74
 
66
75
 
67
76
  end
@@ -0,0 +1,317 @@
1
+ module HDLRuby::High::Std
2
+
3
+
4
+ ##
5
+ # Standard HDLRuby::High library: linear algebra functions.
6
+ #
7
+ # NOTE: require channel-like interface.
8
+ #
9
+ ########################################################################
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
+
56
+
57
+ # Delcares a vector product by a scalar value.
58
+ #
59
+ # Can be used for scaling a vector.
60
+ function :scale do |typ,ev,req,ack,left,rights,prods,
61
+ mul = proc { |x,y| x*y }|
62
+ # Ensure ev is really an event.
63
+ ev = ev.posedge unless ev.is_a?(Event)
64
+ # Ensures rights and prods are arrays.
65
+ rights = rights.to_a
66
+ prods = prods.to_a
67
+ # Left value (the scale) and right value.
68
+ typ.inner :lv
69
+ rvs = rights.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
70
+ # lv and rv are valid.
71
+ inner :lvok
72
+ rvoks = rights.each_with_index.map { |left,i| inner :"rvok#{i}" }
73
+ # Run flag
74
+ inner :run
75
+ par(ev) do
76
+ ack <= 0
77
+ run <= 0
78
+ hif(req | run) do
79
+ run <= 1
80
+ # Computation request.
81
+ left.read(lv) { lvok <= 1 }
82
+ rights.each_with_index do |right,i|
83
+ right.read(rvs[i]) { rvoks[i] <= 1 }
84
+ hif(lvok & rvoks[i]) do
85
+ ack <= 1
86
+ run <= 0
87
+ prods[i].write(mul.(lv,rvs[i]))
88
+ end
89
+ end
90
+ end
91
+ helse do
92
+ lvok <= 0
93
+ rights.each_with_index do |right,i|
94
+ rvoks[i] <= 0
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ # Declares a 1-dimension vector adder.
102
+ #
103
+ # Can be used for the sum of two vectors.
104
+ function :add_n do |typ,ev,req,ack,lefts, rights, sums,
105
+ add = proc { |x,y| x+y }|
106
+ # Ensure ev is really an event.
107
+ ev = ev.posedge unless ev.is_a?(Event)
108
+ # Ensures lefts and rights and sums are arrays.
109
+ lefts = lefts.to_a
110
+ rights = rights.to_a
111
+ sums = sums.to_a
112
+ # Left value and right value.
113
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
114
+ rvs = lefts.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
115
+ # lv and rv are valid.
116
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
117
+ rvoks = lefts.each_with_index.map { |left,i| inner :"rvok#{i}" }
118
+ # Run flag.
119
+ inner :run
120
+ par(ev) do
121
+ ack <= 0
122
+ run <= 0
123
+ hif(req | run) do
124
+ run <= 1
125
+ # Computation request.
126
+ lefts.zip(rights).each_with_index do |(left,right),i|
127
+ left.read(lvs[i]) { lvoks[i] <= 1 }
128
+ right.read(rvs[i]) { rvoks[i] <= 1 }
129
+ hif(lvoks[i] & rvoks[i]) do
130
+ run <= 0
131
+ ack <= 1
132
+ sums[i].write(add.(lvs[i],rvs[i]))
133
+ end
134
+ end
135
+ end
136
+ helse do
137
+ lefts.each_with_index do |left,i|
138
+ lvoks[i] <= 0
139
+ rvoks[i] <= 0
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # Declares a 1-dimension vector element-wise multiplier.
146
+ function :mul_n do |typ,ev,req,ack,lefts, rights, prods,
147
+ mul = proc { |x,y| x*y }|
148
+ add_n(typ,ev,req,ack,lefts,rights,prods,mul)
149
+ end
150
+
151
+
152
+ # Declares a simple multiplier accumulator.
153
+ #
154
+ # Can be used for the scalar product of two vectors.
155
+ function :mac do |typ,ev,req,ack,left, right, acc,
156
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
157
+ # Ensure ev is really an event.
158
+ ev = ev.posedge unless ev.is_a?(Event)
159
+ # Left value, right value and computation temp value.
160
+ typ.inner :lv, :rv, :av
161
+ # lv and rv are valid.
162
+ inner :lvok, :rvok
163
+ # Run flag
164
+ inner :run
165
+ par(ev) do
166
+ ack <= 0
167
+ run <= 0
168
+ hif(req | run) do
169
+ run <= 1
170
+ # Computation request.
171
+ left.read(lv) { lvok <= 1 }
172
+ right.read(rv) { rvok <= 1 }
173
+ hif(lvok & rvok) do
174
+ ack <= 1
175
+ run <= 0
176
+ # acc.write(add.(av,mul.(lv,rv)))
177
+ seq do
178
+ av <= add.(av,mul.(lv,rv))
179
+ acc.write(av)
180
+ end
181
+ end
182
+ end
183
+ helse do
184
+ lvok <= 0
185
+ rvok <= 0
186
+ # acc.write(0)
187
+ av <= 0
188
+ end
189
+ end
190
+ end
191
+
192
+
193
+ # Declares a simple multiple mac with single right data.
194
+ #
195
+ # Can be used for the product of a martix-vector product.
196
+ function :mac_n1 do |typ,ev,req,ack,lefts, right, accs,
197
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
198
+ # Ensure ev is really an event.
199
+ ev = ev.posedge unless ev.is_a?(Event)
200
+ # Ensures lefts is an array.
201
+ lefts = lefts.to_a
202
+ # Ensures accs is an array.
203
+ accs = accs.to_a
204
+ # Left value and right value.
205
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
206
+ # Accumutated values.
207
+ avs = lefts.each_with_index.map { |left,i| typ.inner :"av#{i}" }
208
+ typ.inner :rv
209
+ # lv and rv are valid.
210
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
211
+ inner :rvok
212
+ # Run flag
213
+ inner :run
214
+ par(ev) do
215
+ ack <= 0
216
+ run <= 0
217
+ hif(req | run) do
218
+ run <= 1
219
+ # Computation request.
220
+ right.read(rv) { rvok <= 1 }
221
+ lefts.each_with_index do |left,i|
222
+ left.read(lvs[i]) { lvoks[i] <= 1 }
223
+ # accs[i].read(avs[i])
224
+ hif(lvoks[i] & rvok) do
225
+ ack <= 1
226
+ run <= 0
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
232
+ end
233
+ end
234
+ end
235
+ helse do
236
+ rvok <= 0
237
+ lefts.each_with_index do |left,i|
238
+ lvoks[i] <= 0
239
+ # accs[i].write(0)
240
+ avs[i] <= 0
241
+ end
242
+ end
243
+ end
244
+ end
245
+
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
+
317
+ end