HDLRuby 2.2.14 → 2.3.1

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