HDLRuby 2.11.12 → 3.1.0

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.html +3274 -0
  3. data/README.md +660 -128
  4. data/ext/hruby_sim/hruby_sim_calc.c +2 -0
  5. data/lib/HDLRuby/backend/hruby_allocator.rb +2 -2
  6. data/lib/HDLRuby/backend/hruby_c_allocator.rb +7 -7
  7. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +2 -1
  8. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
  9. data/lib/HDLRuby/hdr_samples/with_bram.rb +3 -3
  10. data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +105 -0
  11. data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +69 -0
  12. data/lib/HDLRuby/hdr_samples/with_ref_expr.rb +30 -0
  13. data/lib/HDLRuby/hdr_samples/with_sequencer.rb +185 -0
  14. data/lib/HDLRuby/hdr_samples/with_sequencer_deep.rb +91 -0
  15. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +439 -0
  16. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +89 -0
  17. data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +63 -0
  18. data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +120 -0
  19. data/lib/HDLRuby/hdrcc.rb +16 -3
  20. data/lib/HDLRuby/hdrlib.rb +1 -1
  21. data/lib/HDLRuby/hruby_db.rb +2 -2
  22. data/lib/HDLRuby/hruby_high.rb +61 -25
  23. data/lib/HDLRuby/hruby_high_fullname.rb +3 -1
  24. data/lib/HDLRuby/hruby_low.rb +2 -2
  25. data/lib/HDLRuby/hruby_low2c.rb +58 -43
  26. data/lib/HDLRuby/hruby_low2hdr.rb +66 -40
  27. data/lib/HDLRuby/hruby_low2high.rb +86 -44
  28. data/lib/HDLRuby/hruby_low2seq.rb +26 -18
  29. data/lib/HDLRuby/hruby_low2sym.rb +14 -13
  30. data/lib/HDLRuby/hruby_low2vhd.rb +78 -43
  31. data/lib/HDLRuby/hruby_low_bool2select.rb +61 -46
  32. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +56 -44
  33. data/lib/HDLRuby/hruby_low_cleanup.rb +18 -16
  34. data/lib/HDLRuby/hruby_low_fix_types.rb +64 -32
  35. data/lib/HDLRuby/hruby_low_mutable.rb +53 -118
  36. data/lib/HDLRuby/hruby_low_resolve.rb +26 -31
  37. data/lib/HDLRuby/hruby_low_with_bool.rb +33 -16
  38. data/lib/HDLRuby/hruby_low_with_port.rb +3 -3
  39. data/lib/HDLRuby/hruby_low_with_var.rb +23 -9
  40. data/lib/HDLRuby/hruby_low_without_concat.rb +19 -13
  41. data/lib/HDLRuby/hruby_low_without_namespace.rb +47 -32
  42. data/lib/HDLRuby/hruby_low_without_parinseq.rb +18 -12
  43. data/lib/HDLRuby/hruby_low_without_select.rb +36 -23
  44. data/lib/HDLRuby/hruby_low_without_subsignals.rb +79 -39
  45. data/lib/HDLRuby/hruby_rcsim.rb +79 -64
  46. data/lib/HDLRuby/hruby_rsim.rb +64 -15
  47. data/lib/HDLRuby/hruby_rsim_mute.rb +2 -3
  48. data/lib/HDLRuby/hruby_rsim_vcd.rb +28 -25
  49. data/lib/HDLRuby/hruby_types.rb +5 -5
  50. data/lib/HDLRuby/hruby_values.rb +19 -8
  51. data/lib/HDLRuby/hruby_verilog.rb +191 -65
  52. data/lib/HDLRuby/hruby_verilog_name.rb +49 -42
  53. data/lib/HDLRuby/soft/stacks.rb +219 -0
  54. data/lib/HDLRuby/std/bram.rb +9 -5
  55. data/lib/HDLRuby/std/clocks.rb +1 -1
  56. data/lib/HDLRuby/std/fsm.rb +39 -10
  57. data/lib/HDLRuby/std/sequencer.rb +2085 -0
  58. data/lib/HDLRuby/std/sequencer_func.rb +533 -0
  59. data/lib/HDLRuby/std/sequencer_sync.rb +400 -0
  60. data/lib/HDLRuby/std/std.rb +13 -0
  61. data/lib/HDLRuby/version.rb +1 -1
  62. data/tuto/adder_sat_flags_vcd.png +0 -0
  63. data/tuto/addsub_vcd.png +0 -0
  64. data/tuto/alu_vcd.png +0 -0
  65. data/tuto/bit_pong_vcd.png +0 -0
  66. data/tuto/checksum_vcd.png +0 -0
  67. data/tuto/circuit_hdr.odg +0 -0
  68. data/tuto/circuit_hdr.png +0 -0
  69. data/tuto/circuit_hie.odg +0 -0
  70. data/tuto/circuit_hie.png +0 -0
  71. data/tuto/circuit_view.odg +0 -0
  72. data/tuto/circuit_view.png +0 -0
  73. data/tuto/clock_counter_vcd.png +0 -0
  74. data/tuto/counter_ext_vcd.png +0 -0
  75. data/tuto/fact_vcd.png +0 -0
  76. data/tuto/hw_flow.odg +0 -0
  77. data/tuto/hw_flow.png +0 -0
  78. data/tuto/maxxer_vcd.png +0 -0
  79. data/tuto/pingpong0_vcd.png +0 -0
  80. data/tuto/pingpong1_vcd.png +0 -0
  81. data/tuto/pingpong2_vcd.png +0 -0
  82. data/tuto/ram_vcd.png +0 -0
  83. data/tuto/serializer_vcd.png +0 -0
  84. data/tuto/sw_flow.odg +0 -0
  85. data/tuto/sw_flow.png +0 -0
  86. data/tuto/the_counter_vcd.png +0 -0
  87. data/tuto/tutorial_sw.html +2359 -0
  88. data/tuto/tutorial_sw.md +2890 -0
  89. data/tuto/tutorial_sw.pdf +0 -0
  90. data/tuto/tutorial_sw_jp.md +417 -0
  91. metadata +46 -2
@@ -0,0 +1,2085 @@
1
+ require 'std/fsm'
2
+
3
+ module HDLRuby::High::Std
4
+
5
+ ##
6
+ # Standard HDLRuby::High library: sequencer generator.
7
+ # The idea is to be able to write sw-like sequential code.
8
+ #
9
+ ########################################################################
10
+
11
+
12
+
13
+ # Describes a sequencer block.
14
+ class SequencerT
15
+ @@current = nil # The current sequencer.
16
+
17
+ # Get the sequencer currently processing.
18
+ def self.current
19
+ @@current
20
+ end
21
+
22
+ # The start and end states values.
23
+ attr_reader :start_state_value, :end_state_value
24
+
25
+ # Create a new sequencer block synchronized on +ev+ and starting
26
+ # on +start+
27
+ def initialize(ev,start,&ruby_block)
28
+ this = self
29
+ # Process the arguments.
30
+ ev = ev.posedge unless ev.is_a?(Event)
31
+ if start.is_a?(Event) then
32
+ start = start.type == :posedge ? start.ref : ~start.ref
33
+ end
34
+ # Create the fsm from the block.
35
+ @fsm = fsm(ev,start,:seq)
36
+ # On reset (start) tell to go to the first state.
37
+ run = HDLRuby::High.cur_system.inner(HDLRuby.uniq_name(:run) => 0)
38
+ @fsm.reset do
39
+ # HDLRuby::High.top_user.instance_exec do
40
+ # next_state_sig <= this.start_state_value
41
+ # end
42
+ run <= 1
43
+ end
44
+
45
+ # The status stack of the sequencer.
46
+ @status = [ {} ]
47
+ # Creates the namespace to execute the sequencer deescription
48
+ # block in.
49
+ @namespace = Namespace.new(self)
50
+
51
+ # The end state is actually 0, allows to sequencer to be stable
52
+ # by default.
53
+ @fsm.default { run <= 0 }
54
+ @end_state = @fsm.state { }
55
+ @end_state.gotos << proc do
56
+ HDLRuby::High.top_user.instance_exec do
57
+ hif(run) { next_state_sig <= this.start_state_value }
58
+ helse { next_state_sig <= this.end_state_value }
59
+ end
60
+ end
61
+ # Record the start and end state values.
62
+ # For now, the start state is the one just following the end state.
63
+ @end_state_value = @end_state.value
64
+ @start_state_value = @end_state_value + 1
65
+ # puts "end_state_value=#{@end_state_value}"
66
+
67
+ # Process the ruby_block.
68
+ @@current = self
69
+ HDLRuby::High.space_push(@namespace)
70
+ blk = HDLRuby::High::Block.new(:seq,&ruby_block)
71
+ HDLRuby::High.space_pop
72
+
73
+ # If the block is not empty, add it as last state.
74
+ this = self
75
+ if blk.each_statement.any? then
76
+ st = @fsm.state do
77
+ this.fill_top_user(blk)
78
+ end
79
+ end
80
+
81
+ # Build the fsm.
82
+ @fsm.build
83
+ end
84
+
85
+ # Gets the number of states of the underlining fsm.
86
+ def size
87
+ return @fsm.size
88
+ end
89
+
90
+ # Gets the closest loop status in the status stack.
91
+ # NOTE: raises an exception if there are not swhile state.
92
+ def loop_status
93
+ i = @status.size-1
94
+ begin
95
+ status = @status[i -= 1]
96
+ raise "No loop for sbreak." unless status
97
+ end while(!status[:loop])
98
+ return status
99
+ end
100
+
101
+
102
+
103
+ # Mark a step.
104
+ def step
105
+ # Create a new block from all the statements in the previous block.
106
+ blk = HDLRuby::High::Block.new(:seq) {}
107
+ # Get all the statements of the builder block.
108
+ stmnts = HDLRuby::High.cur_block.instance_variable_get(:@statements)
109
+ # Add all the statements to blk.
110
+ stmnts.each { |stmnt| stmnt.parent = nil; blk.add_statement(stmnt) }
111
+ # Remove them from the builder block.
112
+ stmnts.clear
113
+
114
+ # Create a state for this block.
115
+ this = self
116
+ st = @fsm.state { this.fill_top_user(blk) }
117
+ # # Set the previous step in sequence.
118
+ # @status.last[:state] = st
119
+ return st
120
+ end
121
+
122
+ # Mark several steps.
123
+ def steps(num)
124
+ # Create a counter.
125
+ count = nil
126
+ zero = nil
127
+ one = nil
128
+ HDLRuby::High.cur_system.open do
129
+ if num.respond_to?(:width) then
130
+ count = [num.width].inner(HDLRuby.uniq_name(:"steps_count"))
131
+ else
132
+ count = num.to_expr.type.inner(HDLRuby.uniq_name(:"steps_count"))
133
+ end
134
+ zero = _b0
135
+ one = _b1
136
+ end
137
+ count <= num
138
+ swhile(count > zero) { count <= count - one }
139
+ end
140
+
141
+ # Breaks current iteration.
142
+ def sbreak
143
+ # Mark a step.
144
+ st = self.step
145
+ # Tell there is a break to process.
146
+ # Do that in the first loop status met.
147
+ status = self.loop_status
148
+ status[:sbreaks] ||= []
149
+ status[:sbreaks] << st
150
+ return st
151
+ end
152
+
153
+ # Continues current iteration.
154
+ def scontinue
155
+ # Mark a step.
156
+ st = self.step
157
+ # Go to the begining of the iteration, i.e., the first loop
158
+ # status met.
159
+ status = self.loop_status
160
+ st.gotos << proc do
161
+ HDLRuby::High.top_user.instance_exec do
162
+ next_state_sig <= status[:loop]
163
+ end
164
+ end
165
+ return st
166
+ end
167
+
168
+ # Terminates the sequencer.
169
+ def sterminate
170
+ # Mark a step.
171
+ st = self.step
172
+ # Adds a goto the ending state.
173
+ this = self
174
+ st.gotos << proc do
175
+ HDLRuby::High.top_user.instance_exec do
176
+ next_state_sig <= this.end_state_value
177
+ end
178
+ end
179
+ return st
180
+ end
181
+
182
+ # Create a sequential if statement on +cond+.
183
+ def sif(cond, &ruby_block)
184
+ # Mark a step.
185
+ st = self.step
186
+ # Remember the condition.
187
+ @status.last[:condition] = cond
188
+ # Create a state to be executed if the condition is met.
189
+ @status.push({})
190
+ yes_name = HDLRuby.uniq_name("yes")
191
+ yes_blk = HDLRuby::High::Block.new(:seq,&ruby_block)
192
+ @status.pop
193
+ this = self
194
+ yes = @fsm.state(yes_name) { this.fill_top_user(yes_blk) }
195
+ # Add a goto to the previous state.
196
+ st.gotos << proc do
197
+ HDLRuby::High.top_user.instance_exec do
198
+ hif(cond) { next_state_sig <= st.value + 1 }
199
+ helse { next_state_sig <= yes.value + 1 }
200
+ end
201
+ end
202
+ # Remeber the if yes state for being able to add else afterward.
203
+ @status.last[:sif_yes] = yes
204
+ return st
205
+ end
206
+
207
+ # Create a sequential else statement.
208
+ def selse(&ruby_block)
209
+ # Create a state to be executed if the previous condition is
210
+ # not met.
211
+ @status.push({})
212
+ no_name = HDLRuby.uniq_name("no")
213
+ no_blk = HDLRuby::High::Block.new(:seq,&ruby_block)
214
+ @status.pop
215
+ this = self
216
+ no = @fsm.state(no_name) { this.fill_top_user(no_blk) }
217
+ # Adds a goto to the previous if yes state for jumping the no state.
218
+ yes = @status.last[:sif_yes]
219
+ raise "Cannot use selse here." unless yes
220
+ cond = @status.last[:condition]
221
+ yes.gotos << proc do
222
+ HDLRuby::High.top_user.instance_exec do
223
+ next_state_sig <= no.value + 1
224
+ end
225
+ end
226
+ return no
227
+ end
228
+
229
+ # Wait a given condition.
230
+ def swait(cond)
231
+ return self.swhile(~cond)
232
+ end
233
+
234
+ # Create a sequential while statement on +cond+.
235
+ def swhile(cond,&ruby_block)
236
+ # Ensures there is a ruby block. This allows to use empty while
237
+ # statement.
238
+ ruby_block = proc { } unless ruby_block
239
+ # Mark a step.
240
+ st = self.step
241
+
242
+ # Tell we are building a while and remember the state number.
243
+ @status.last[:loop] = st.value + 1
244
+
245
+ # Create a state to be executed if the condition is met.
246
+ @status.push({})
247
+ # Build the loop sub sequence.
248
+ yes_name = HDLRuby.uniq_name("yes")
249
+ yes_blk = HDLRuby::High::Block.new(:seq,&ruby_block)
250
+ @status.pop
251
+
252
+ this = self
253
+ yes = @fsm.state(yes_name) { this.fill_top_user(yes_blk) }
254
+ # Add a goto to the previous state.
255
+ st.gotos << proc do
256
+ HDLRuby::High.top_user.instance_exec do
257
+ if cond then
258
+ # There is a condition, it is a real while loop.
259
+ hif(cond) { next_state_sig <= st.value + 1 }
260
+ helse { next_state_sig <= yes.value + 1 }
261
+ # puts("Here st: st.value+1=#{st.value+1} yes.value+1=#{yes.value+1}\n")
262
+ else
263
+ # There is no ending condition, this is an infinite loop.
264
+ next_state_sig <= st.value + 1
265
+ # puts("There st: st.value+1=#{st.value+1}\n")
266
+ end
267
+ end
268
+ end
269
+ # And to the yes state.
270
+ yes.gotos << proc do
271
+ HDLRuby::High.top_user.instance_exec do
272
+ if cond then
273
+ # There is a condition, it is a real while loop
274
+ hif(cond) { next_state_sig <= st.value + 1 }
275
+ helse { next_state_sig <= yes.value + 1 }
276
+ # puts("Here yes: st.value+1=#{st.value+1} yes.value+1=#{yes.value+1}\n")
277
+ else
278
+ # There is no ending condition, this is an infinite loop.
279
+ next_state_sig <= st.value + 1
280
+ # puts("There yes: st.value+1=#{st.value+1}\n")
281
+ end
282
+ end
283
+ end
284
+ # puts "st_value=#{st.value} yes_value=#{yes.value}"
285
+
286
+ # Where there any break?
287
+ if @status.last[:sbreaks] then
288
+ # Yes, adds them the right goto since the end of loop state
289
+ # is now defined.
290
+ @status.last[:sbreaks].each do |st_brk|
291
+ st_brk.gotos << proc do
292
+ HDLRuby::High.top_user.instance_exec do
293
+ next_state_sig <= yes.value + 1
294
+ end
295
+ end
296
+ end
297
+ # And remove them from the status to avoid reprocessing them,
298
+ @status.last.clear
299
+ end
300
+
301
+ return st
302
+ end
303
+
304
+ # Create a sequential infinite loop statement.
305
+ def sloop(&ruby_block)
306
+ self.swhile(nil,&ruby_block)
307
+ end
308
+
309
+ # Create a sequential for statement iterating over the elements
310
+ # of +expr+.
311
+ def sfor(expr,&ruby_block)
312
+ # Ensures there is a ruby block to avoid returning an enumerator
313
+ # (returning an enumerator would be confusing for a for statement).
314
+ ruby_block = proc {} unless ruby_block
315
+ expr.seach.with_index(&ruby_block)
316
+ end
317
+
318
+
319
+ # Fills the top user with the content of block +blk+.
320
+ def fill_top_user(blk)
321
+ # Fill the current block with blk content.
322
+ blk.each_statement do |stmnt|
323
+ stmnt.parent = nil
324
+ HDLRuby::High.top_user.add_statement(stmnt)
325
+ end
326
+ end
327
+ end
328
+
329
+
330
+ ## Remplement make_inners of block to support declaration within sequencers.
331
+
332
+
333
+ class HDLRuby::High::Block
334
+ # Save module method (unbounded) for further call since going to
335
+ # override make_inners.
336
+ # alias_method does not seem to work in such a context, so use
337
+ # this approach.
338
+ @@old_make_inners_proc = self.instance_method(:make_inners)
339
+
340
+ def make_inners(typ,*names)
341
+ if SequencerT.current then
342
+ unames = names.map {|name| HDLRuby.uniq_name(name) }
343
+ HDLRuby::High.cur_scope.make_inners(typ, *unames)
344
+ names.zip(unames).each do |name,uname|
345
+ HDLRuby::High.space_reg(name) { send(uname) }
346
+ end
347
+ else
348
+ # self.old_make_inners(typ,*names)
349
+ # Call the old make_inners.
350
+ @@old_make_inners_proc.bind(self).call(typ,*names)
351
+ end
352
+ end
353
+ end
354
+
355
+
356
+
357
+
358
+ # Module adding functionalities to object including the +seach+ method.
359
+ module SEnumerable
360
+
361
+ # Tell if all the elements respect a given criterion given either
362
+ # as +arg+ or as block.
363
+ def sall?(arg = nil,&ruby_block)
364
+ # Declare the result signal.
365
+ res = nil
366
+ HDLRuby::High.cur_system.open do
367
+ res = bit.inner(HDLRuby.uniq_name(:"all_cond"))
368
+ end
369
+ # Initialize the result.
370
+ res <= 1
371
+ # Performs the computation.
372
+ if arg then
373
+ # Compare elements to arg.
374
+ self.seach do |elem|
375
+ res <= res & (elem == arg)
376
+ end
377
+ elsif ruby_block then
378
+ # Use the ruby block.
379
+ self.seach do |elem|
380
+ res <= res & ruby_block.call(elem)
381
+ end
382
+ else
383
+ raise "Ruby nil does not have any meaning in HW."
384
+ end
385
+ res
386
+ end
387
+
388
+ # Tell if any of the elements respects a given criterion given either
389
+ # as +arg+ or as block.
390
+ def sany?(arg = nil,&ruby_block)
391
+ # Declare the result signal.
392
+ res = nil
393
+ HDLRuby::High.cur_system.open do
394
+ res = bit.inner(HDLRuby.uniq_name(:"any_cond"))
395
+ end
396
+ # Initialize the result.
397
+ res <= 0
398
+ # Performs the computation.
399
+ if arg then
400
+ # Compare elements to arg.
401
+ self.seach do |elem|
402
+ res <= res | (elem == arg)
403
+ end
404
+ elsif ruby_block then
405
+ # Use the ruby block.
406
+ self.seach do |elem|
407
+ res <= res | ruby_block.call(elem)
408
+ end
409
+ else
410
+ raise "Ruby nil does not have any meaning in HW."
411
+ end
412
+ res
413
+ end
414
+
415
+ # Returns an SEnumerator generated from current enumerable and +arg+
416
+ def schain(arg)
417
+ return self.seach + arg
418
+ end
419
+
420
+ # HW implementation of the Ruby chunk.
421
+ # NOTE: to do, or may be not.
422
+ def schunk(*args,&ruby_block)
423
+ raise "schunk is not supported yet."
424
+ end
425
+
426
+ # HW implementation of the Ruby chunk_while.
427
+ # NOTE: to do, or may be not.
428
+ def schunk_while(*args,&ruby_block)
429
+ raise "schunk_while is not supported yet."
430
+ end
431
+
432
+ # Returns a vector containing the execution result of the given block
433
+ # on each element. If no block is given, return an SEnumerator.
434
+ # NOTE: be carful that the resulting vector can become huge if there
435
+ # are many element.
436
+ def smap(&ruby_block)
437
+ # No block given? Generate a new wrapper enumerator for smap.
438
+ if !ruby_block then
439
+ return SEnumeratorWrapper.new(self,:smap)
440
+ end
441
+ # A block given? Fill the vector it with the computation result.
442
+ # Generate the vector to put the result in.
443
+ # The declares the resulting vector.
444
+ res = nil
445
+ enum = self.seach
446
+ HDLRuby::High.cur_system.open do
447
+ res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"map_vec"))
448
+ end
449
+ # And do the iteration.
450
+ enum.with_index do |elem,idx|
451
+ res[idx] <= ruby_block.call(elem)
452
+ end
453
+ # Return the resulting vector.
454
+ return res
455
+ end
456
+
457
+ # HW implementation of the Ruby flat_map.
458
+ # NOTE: actually due to the way HDLRuby handles vectors, should work
459
+ # like smap
460
+ def sflat_map(&ruby_block)
461
+ return smap(&ruby_block)
462
+ end
463
+
464
+ # HW implementation of the Ruby compact, but remove 0 values instead
465
+ # on nil (since nil that does not have any meaning in HW).
466
+ def scompact
467
+ # Generate the vector to put the result in.
468
+ # The declares the resulting vector and index.
469
+ res = nil
470
+ idx = nil
471
+ enum = self.seach
472
+ HDLRuby::High.cur_system.open do
473
+ res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"compact_vec"))
474
+ idx = [enum.size.width].inner(HDLRuby.uniq_name(:"compact_idx"))
475
+ end
476
+ # And do the iteration.
477
+ idx <= 0
478
+ enum.seach do |elem|
479
+ HDLRuby::High.top_user.hif(elem != 0) do
480
+ res[idx] <= elem
481
+ idx <= idx + 1
482
+ end
483
+ end
484
+ SequencerT.current.swhile(idx < enum.size) do
485
+ res[idx] <= 0
486
+ idx <= idx + 1
487
+ end
488
+ # Return the resulting vector.
489
+ return res
490
+ end
491
+
492
+
493
+ # WH implementation of the Ruby count.
494
+ def scount(obj = nil, &ruby_block)
495
+ # Generate the counter result signal.
496
+ cnt = nil
497
+ enum = self.seach
498
+ HDLRuby::High.cur_system.open do
499
+ cnt = [enum.size.width].inner(HDLRuby.uniq_name(:"count_idx"))
500
+ end
501
+ # Do the counting.
502
+ cnt <= 0
503
+ # Is obj present?
504
+ if obj then
505
+ # Yes, count the occurences of obj.
506
+ enum.seach do |elem|
507
+ HDLRuby::High.top_user.hif(obj == elem) { cnt <= cnt + 1 }
508
+ end
509
+ elsif ruby_block
510
+ # No, but there is a ruby block, use its result for counting.
511
+ enum.seach do |elem|
512
+ HDLRuby::High.top_user.hif(ruby_block.call(elem)) do
513
+ cnt <= cnt + 1
514
+ end
515
+ end
516
+ else
517
+ # No, the result is simply the number of elements.
518
+ cnt <= enum.size
519
+ end
520
+ return cnt
521
+ end
522
+
523
+ # HW implementation of the Ruby cycle.
524
+ def scycle(n = nil,&ruby_block)
525
+ # No block given? Generate a new wrapper enumerator for scycle.
526
+ if !ruby_block then
527
+ return SEnumeratorWrapper.new(self,:scycle,n)
528
+ end
529
+ this = self
530
+ # Is n nil?
531
+ if n == nil then
532
+ # Yes, infinite loop.
533
+ SequencerT.current.sloop do
534
+ this.seach(&ruby_block)
535
+ end
536
+ else
537
+ # Finite loop.
538
+ (0..(n-1)).seach do
539
+ this.seach(&ruby_block)
540
+ end
541
+ end
542
+ end
543
+
544
+ # HW implementation of the Ruby find.
545
+ # NOTE: contrary to Ruby, if_none_proc is mandatory since there is no
546
+ # nil in HW. Moreover, the argument can also be a value.
547
+ def sfind(if_none_proc, &ruby_block)
548
+ # No block given? Generate a new wrapper enumerator for sfind.
549
+ if !ruby_block then
550
+ return SEnumeratorWrapper.new(self,:sfind,if_none_proc)
551
+ end
552
+ # Generate the found result signal and flag signals.
553
+ found = nil
554
+ flag = nil
555
+ enum = self.seach
556
+ HDLRuby::High.cur_system.open do
557
+ found = enum.type.inner(HDLRuby.uniq_name(:"find_found"))
558
+ flag = bit.inner(HDLRuby.uniq_name(:"find_flag"))
559
+ end
560
+ # Look for the element.
561
+ flag <= 0
562
+ enum.srewind
563
+ SequencerT.current.swhile((flag == 0) & (enum.snext?)) do
564
+ found <= enum.snext
565
+ hif(ruby_block.call(found)) do
566
+ # Found, save the element and raise the flag.
567
+ flag <= 1
568
+ end
569
+ end
570
+ HDLRuby::High.top_user.hif(~flag) do
571
+ # Not found, execute the none block.
572
+ if if_none_proc.respond_to?(:call) then
573
+ found <= f_none_proc.call
574
+ else
575
+ found <= if_none_proc
576
+ end
577
+ end
578
+ found
579
+ end
580
+
581
+ # HW implementation of the Ruby drop.
582
+ def sdrop(n)
583
+ # Generate the vector to put the result in.
584
+ # The declares the resulting vector and index.
585
+ res = nil
586
+ idx = nil
587
+ enum = self.seach
588
+ HDLRuby::High.cur_system.open do
589
+ # res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"drop_vec"))
590
+ res = enum.type[-enum.size+n].inner(HDLRuby.uniq_name(:"drop_vec"))
591
+ # idx = [enum.size.width].inner(HDLRuby.uniq_name(:"drop_idx"))
592
+ end
593
+ # And do the iteration.
594
+ # idx <= 0
595
+ # enum.seach.with_index do |elem,i|
596
+ # HDLRuby::High.top_user.hif(i >= n) do
597
+ # res[idx] <= elem
598
+ # idx <= idx + 1
599
+ # end
600
+ # end
601
+ # SequencerT.current.swhile(idx < enum.size) do
602
+ # res[idx] <= 0
603
+ # idx <= idx + 1
604
+ # end
605
+ (enum.size-n).stimes do |i|
606
+ res[i] <= enum.access(i+n)
607
+ end
608
+ # Return the resulting vector.
609
+ return res
610
+ end
611
+
612
+ # HW implementation of the Ruby drop_while.
613
+ def sdrop_while(&ruby_block)
614
+ # No block given? Generate a new wrapper enumerator for sdrop_while.
615
+ if !ruby_block then
616
+ return SEnumeratorWrapper.new(self,:sdrop_while)
617
+ end
618
+ # A block is given.
619
+ # Generate the vector to put the result in.
620
+ # The declares the resulting vector, index and drop flag.
621
+ res = nil
622
+ idx = nil
623
+ flg = nil
624
+ enum = self.seach
625
+ HDLRuby::High.cur_system.open do
626
+ res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"drop_vec"))
627
+ idx = [enum.size.width].inner(HDLRuby.uniq_name(:"drop_idx"))
628
+ flg = bit.inner(HDLRuby.uniq_name(:"drop_flg"))
629
+ end
630
+ # And do the iteration.
631
+ # First drop and fill from current enumerable elements.
632
+ idx <= 0
633
+ flg <= 1
634
+ enum.seach.with_index do |elem,i|
635
+ HDLRuby::High.top_user.hif(flg == 1) do
636
+ HDLRuby::High.top_user.hif(ruby_block.call(elem) == 0) do
637
+ flg <= 0
638
+ end
639
+ end
640
+ HDLRuby::High.top_user.hif(flg == 0) do
641
+ res[idx] <= elem
642
+ idx <= idx + 1
643
+ end
644
+ end
645
+ # Finally, end with zeros.
646
+ SequencerT.current.swhile(idx < enum.size) do
647
+ res[idx] <= 0
648
+ idx <= idx + 1
649
+ end
650
+ # Return the resulting vector.
651
+ return res
652
+ end
653
+
654
+ # HW implementation of the Ruby each_cons
655
+ def seach_cons(n,&ruby_block)
656
+ # No block given? Generate a new wrapper enumerator for seach_cons.
657
+ if !ruby_block then
658
+ return SEnumeratorWrapper.new(self,:seach_cons)
659
+ end
660
+ # A block is given.
661
+ # Declares the indexes and the buffer for cosecutive elements.
662
+ enum = self.seach
663
+ idx = nil
664
+ buf = nil
665
+ HDLRuby::High.cur_system.open do
666
+ idx = [enum.size.width].inner(HDLRuby.uniq_name(:"each_cons_idx"))
667
+ buf = n.times.map do |i|
668
+ [enum.type].inner(HDLRuby.uniq_name(:"each_cons_buf#{i}"))
669
+ end
670
+ end
671
+ # And do the iteration.
672
+ this = self
673
+ # Initialize the buffer.
674
+ n.times do |i|
675
+ buf[i] <= enum.access(i)
676
+ SequencerT.current.step
677
+ end
678
+ # Do the first iteration.
679
+ ruby_block.call(*buf)
680
+ # Do the remaining iteration.
681
+ idx <= n
682
+ SequencerT.current.swhile(idx < enum.size) do
683
+ # Shifts the buffer (in parallel)
684
+ buf.each_cons(2) { |a0,a1| a0 <= a1 }
685
+ # Adds the new element.
686
+ buf[-1] <= enum.access(idx)
687
+ idx <= idx + 1
688
+ # Executes the block.
689
+ ruby_block.call(*buf)
690
+ end
691
+ end
692
+
693
+ # HW implementation of the Ruby each_entry.
694
+ # NOTE: to do, or may be not.
695
+ def seach_entry(*args,&ruby_block)
696
+ raise "seach_entry is not supported yet."
697
+ end
698
+
699
+ # HW implementation of the Ruby each_slice
700
+ def seach_slice(n,&ruby_block)
701
+ # No block given? Generate a new wrapper enumerator for seach_slice.
702
+ if !ruby_block then
703
+ return SEnumeratorWrapper.new(self,:seach_slice)
704
+ end
705
+ # A block is given.
706
+ # Declares the indexes and the buffer for consecutive elements.
707
+ enum = self.seach
708
+ idx = nil
709
+ buf = nil
710
+ HDLRuby::High.cur_system.open do
711
+ idx = [(enum.size+n).width].inner(HDLRuby.uniq_name(:"each_slice_idx"))
712
+ buf = n.times.map do |i|
713
+ [enum.type].inner(HDLRuby.uniq_name(:"each_slice_buf#{i}"))
714
+ end
715
+ end
716
+ # And do the iteration.
717
+ this = self
718
+ # Adjust n if too large.
719
+ n = enum.size if n > enum.size
720
+ # Initialize the buffer.
721
+ n.times do |i|
722
+ buf[i] <= enum.access(i)
723
+ SequencerT.current.step
724
+ end
725
+ # Do the first iteration.
726
+ ruby_block.call(*buf)
727
+ # Do the remaining iteration.
728
+ idx <= n
729
+ SequencerT.current.swhile(idx < enum.size) do
730
+ # Gets the new element.
731
+ n.times do |i|
732
+ sif(idx+i < enum.size) do
733
+ buf[i] <= enum.access(idx+i)
734
+ end
735
+ selse do
736
+ buf[i] <= 0
737
+ end
738
+ end
739
+ idx <= idx + n
740
+ # Executes the block.
741
+ ruby_block.call(*buf)
742
+ end
743
+ end
744
+
745
+ # HW implementation of the Ruby each_with_index.
746
+ def seach_with_index(*args,&ruby_block)
747
+ self.seach.with_index(*args,&ruby_block)
748
+ end
749
+
750
+ # HW implementation of the Ruby each_with_object.
751
+ def seach_with_object(obj,&ruby_block)
752
+ self.seach.with_object(obj,&ruby_block)
753
+ end
754
+
755
+ # HW implementation of the Ruby to_a.
756
+ def sto_a
757
+ # Declares the resulting vector.
758
+ enum = self.seach
759
+ res = nil
760
+ # size = enum.size.to_value
761
+ HDLRuby::High.cur_system.open do
762
+ # res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"to_a_res"))
763
+ res = enum.type[-enum.size.to_i].inner(HDLRuby.uniq_name(:"to_a_res"))
764
+ end
765
+ # Fills it.
766
+ self.seach_with_index do |elem,i|
767
+ res[i] <= elem
768
+ end
769
+ return res
770
+ end
771
+
772
+ # HW implementation of the Ruby select.
773
+ def sselect(&ruby_block)
774
+ # No block given? Generate a new wrapper enumerator for sselect.
775
+ if !ruby_block then
776
+ return SEnumeratorWrapper.new(self,:sselect)
777
+ end
778
+ # A block is given.
779
+ # Generate the vector to put the result in.
780
+ # The declares the resulting vector and index.
781
+ res = nil
782
+ idx = nil
783
+ enum = self.seach
784
+ HDLRuby::High.cur_system.open do
785
+ res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"select_vec"))
786
+ idx = [enum.size.width].inner(HDLRuby.uniq_name(:"select_idx"))
787
+ end
788
+ # And do the iteration.
789
+ # First select and fill from current enumerable elements.
790
+ idx <= 0
791
+ enum.seach do |elem|
792
+ HDLRuby::High.top_user.hif(ruby_block.call(elem) == 1) do
793
+ res[idx] <= elem
794
+ idx <= idx + 1
795
+ end
796
+ end
797
+ # Finally, end with zeros.
798
+ SequencerT.current.swhile(idx < enum.size) do
799
+ res[idx] <= 0
800
+ idx <= idx + 1
801
+ end
802
+ # Return the resulting vector.
803
+ return res
804
+ end
805
+
806
+ # HW implementation of the Ruby find_index.
807
+ def sfind_index(obj = nil, &ruby_block)
808
+ # No block given nor obj? Generate a new wrapper enumerator for
809
+ # sfind.
810
+ if !ruby_block && !obj then
811
+ return SEnumeratorWrapper.new(self,:sfind,if_none_proc)
812
+ end
813
+ # Generate the index result signal and flag signals.
814
+ idx = nil
815
+ flag = nil
816
+ enum = self.seach
817
+ HDLRuby::High.cur_system.open do
818
+ idx = signed[enum.size.width+1].inner(HDLRuby.uniq_name(:"find_idx"))
819
+ flag = bit.inner(HDLRuby.uniq_name(:"find_flag"))
820
+ end
821
+ # Look for the element.
822
+ flag <= 0
823
+ idx <= 0
824
+ enum.srewind
825
+ SequencerT.current.swhile((flag == 0) & (enum.snext?)) do
826
+ if (obj) then
827
+ # There is obj case.
828
+ HDLRuby::High.top_user.hif(enum.snext == obj) do
829
+ # Found, save the element and raise the flag.
830
+ flag <= 1
831
+ end
832
+ else
833
+ # There is a block case.
834
+ HDLRuby::High.top_user.hif(ruby_block.call(enum.snext)) do
835
+ # Found, save the element and raise the flag.
836
+ flag <= 1
837
+ end
838
+ end
839
+ HDLRuby::High.top_user.helse do
840
+ idx <= idx + 1
841
+ end
842
+ end
843
+ HDLRuby::High.top_user.hif(flag ==0) { idx <= -1 }
844
+ return idx
845
+ end
846
+
847
+ # HW implementation of the Ruby first.
848
+ def sfirst(n=1)
849
+ # Generate the vector to put the result in.
850
+ # The declares the resulting vector and index.
851
+ res = nil
852
+ enum = self.seach
853
+ HDLRuby::High.cur_system.open do
854
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"first_vec"))
855
+ end
856
+ # And do the iteration.
857
+ n.stimes do |i|
858
+ res[i] <= enum.access(i)
859
+ end
860
+ # Return the resulting vector.
861
+ return res
862
+ end
863
+
864
+ # HW implementation of the Ruby grep.
865
+ # NOTE: to do, or may be not.
866
+ def sgrep(*args,&ruby_block)
867
+ raise "sgrep is not supported yet."
868
+ end
869
+
870
+ # HW implementation of the Ruby grep_v.
871
+ # NOTE: to do, or may be not.
872
+ def sgrep_v(*args,&ruby_block)
873
+ raise "sgrep_v is not supported yet."
874
+ end
875
+
876
+ # HW implementation of the Ruby group_by.
877
+ # NOTE: to do, or may be not.
878
+ def sgroup_by(*args,&ruby_block)
879
+ raise "sgroup_by is not supported yet."
880
+ end
881
+
882
+ # HW implementation of the Ruby include?
883
+ def sinclude?(obj)
884
+ # Generate the result signal.
885
+ res = nil
886
+ enum = self.seach
887
+ HDLRuby::High.cur_system.open do
888
+ res = bit.inner(HDLRuby.uniq_name(:"include_res"))
889
+ end
890
+ # Look for the element.
891
+ res <= 0
892
+ enum.srewind
893
+ SequencerT.current.swhile((res == 0) & (enum.snext?)) do
894
+ # There is obj case.
895
+ HDLRuby::High.top_user.hif(enum.snext == obj) do
896
+ # Found, save the element and raise the flag.
897
+ res <= 1
898
+ end
899
+ end
900
+ return res
901
+ end
902
+
903
+ # HW implementation of the Ruby inject.
904
+ def sinject(*args,&ruby_block)
905
+ init = nil
906
+ symbol = nil
907
+ # Process the arguments.
908
+ if args.size > 2 then
909
+ raise ArgumentError.new("wrong number of arguments (given #{args.size} expected 0..2)")
910
+ elsif args.size == 2 then
911
+ # Initial value and symbol given case.
912
+ init, symbol = args
913
+ elsif args.size == 1 && ruby_block then
914
+ # Initial value and block given case.
915
+ init = args[0]
916
+ elsif args.size == 1 then
917
+ # Symbol given case.
918
+ symbol = args[0]
919
+ end
920
+ enum = self.seach
921
+ # Define the computation type: from the initial value if any,
922
+ # otherwise from the enum.
923
+ typ = init ? init.to_expr.type : enum.type
924
+ # Generate the result signal.
925
+ res = nil
926
+ HDLRuby::High.cur_system.open do
927
+ res = typ.inner(HDLRuby.uniq_name(:"inject_res"))
928
+ end
929
+ # Start the initialization
930
+ enum.srewind
931
+ # Is there an initial value?
932
+ if (init) then
933
+ # Yes, start with it.
934
+ res <= init
935
+ else
936
+ # No, start with the first element of the enumerator.
937
+ res <= 0
938
+ SequencerT.current.sif(!enum.snext?) { res <= enum.snext }
939
+ end
940
+ SequencerT.current.swhile(enum.snext?) do
941
+ # Do the accumulation.
942
+ if (symbol) then
943
+ res <= res.send(symbol,enum.snext)
944
+ else
945
+ res <= ruby_block.call(res,enum.snext)
946
+ end
947
+ end
948
+ return res
949
+ end
950
+
951
+ alias_method :sreduce, :sinject
952
+
953
+ # HW implementation of the Ruby lazy.
954
+ # NOTE: to do, or may be not.
955
+ def slazy(*args,&ruby_block)
956
+ raise "slazy is not supported yet."
957
+ end
958
+
959
+ # HW implementation of the Ruby max.
960
+ def smax(n = nil, &ruby_block)
961
+ # Process the arguments.
962
+ n = 1 unless n
963
+ enum = self.seach
964
+ # Declare the result signal the flag and the result array size index
965
+ # used for implementing the algorithm (shift-based sorting) in
966
+ # case of multiple max.
967
+ res = nil
968
+ flg = nil
969
+ idx = nil
970
+ HDLRuby::High.cur_system.open do
971
+ if n == 1 then
972
+ res = enum.type.inner(HDLRuby.uniq_name(:"max_res"))
973
+ # No flg nor idx!
974
+ else
975
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"max_res"))
976
+ flg = bit.inner(HDLRuby.uniq_name(:"max_flg"))
977
+ idx = bit[n.width].inner(HDLRuby.uniq_name(:"max_idx"))
978
+ end
979
+ end
980
+ enum.srewind
981
+ if n == 1 then
982
+ # Single max case, initialize res with the first element(s)
983
+ res <= enum.type.min
984
+ SequencerT.current.sif(enum.snext?) { res <= enum.snext }
985
+ else
986
+ # Multiple max case, initialize the resulting array size index.
987
+ idx <= 0
988
+ end
989
+ # Do the iteration.
990
+ SequencerT.current.swhile(enum.snext?) do
991
+ if n == 1 then
992
+ # Single max case.
993
+ elem = enum.snext
994
+ if ruby_block then
995
+ hif(ruby_block.call(res,elem) < 0) { res <= elem }
996
+ else
997
+ hif(res < elem) { res <= elem }
998
+ end
999
+ else
1000
+ # Multiple max case.
1001
+ SequencerT.current.sif(enum.snext?) do
1002
+ elem = enum.snext
1003
+ flg <= 1
1004
+ n.times do |i|
1005
+ # Compute the comparison between the result element
1006
+ # at i and the enum element.
1007
+ if ruby_block then
1008
+ cond = ruby_block.call(res[i],elem) < 0
1009
+ else
1010
+ cond = res[i] < elem
1011
+ end
1012
+ # If flg is 0, elem is already set as max, skip.
1013
+ # If the result array size index is equal to i, then
1014
+ # put the element whatever the comparison is since
1015
+ # the place is still empty.
1016
+ hif(flg & (cond | (idx == i))) do
1017
+ # A new max is found, shift res from i.
1018
+ ((i+1)..(n-1)).reverse_each { |j| res[j] <= res[j-1] }
1019
+ # An set the new max in current position.
1020
+ res[i] <= elem
1021
+ # For now skip.
1022
+ flg <= 0
1023
+ end
1024
+ end
1025
+ # Note: when idx >= n, the resulting array is full
1026
+ hif(idx < n) { idx <= idx + 1 }
1027
+ end
1028
+ end
1029
+ end
1030
+ return res
1031
+ end
1032
+
1033
+ # HW implementation of the Ruby max_by.
1034
+ def smax_by(n = nil, &ruby_block)
1035
+ # No block given? Generate a new wrapper enumerator for smax_by.
1036
+ if !ruby_block then
1037
+ return SEnumeratorWrapper.new(self,:smax_by,n)
1038
+ end
1039
+ # A block is given, use smax with a proc that applies ruby_block
1040
+ # before comparing.
1041
+ return smax(n) { |a,b| ruby_block.call(a) <=> ruby_block.call(b) }
1042
+ end
1043
+
1044
+ # HW implementation of the Ruby min.
1045
+ def smin(n = nil, &ruby_block)
1046
+ # Process the arguments.
1047
+ n = 1 unless n
1048
+ enum = self.seach
1049
+ # Declare the result signal the flag and the result array size index
1050
+ # used for implementing the algorithm (shift-based sorting) in
1051
+ # case of multiple min.
1052
+ res = nil
1053
+ flg = nil
1054
+ idx = nil
1055
+ HDLRuby::High.cur_system.open do
1056
+ if n == 1 then
1057
+ res = enum.type.inner(HDLRuby.uniq_name(:"min_res"))
1058
+ # No flg nor idx!
1059
+ else
1060
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"min_res"))
1061
+ flg = bit.inner(HDLRuby.uniq_name(:"min_flg"))
1062
+ idx = bit[n.width].inner(HDLRuby.uniq_name(:"min_idx"))
1063
+ end
1064
+ end
1065
+ enum.srewind
1066
+ if n == 1 then
1067
+ # Single min case, initialize res with the first element(s)
1068
+ res <= enum.type.max
1069
+ SequencerT.current.sif(enum.snext?) { res <= enum.snext }
1070
+ else
1071
+ # Multiple min case, initialize the resulting array size index.
1072
+ idx <= 0
1073
+ end
1074
+ # Do the iteration.
1075
+ SequencerT.current.swhile(enum.snext?) do
1076
+ if n == 1 then
1077
+ # Single min case.
1078
+ elem = enum.snext
1079
+ if ruby_block then
1080
+ hif(ruby_block.call(res,elem) > 0) { res <= elem }
1081
+ else
1082
+ hif(res > elem) { res <= elem }
1083
+ end
1084
+ else
1085
+ # Multiple min case.
1086
+ SequencerT.current.sif(enum.snext?) do
1087
+ elem = enum.snext
1088
+ flg <= 1
1089
+ n.times do |i|
1090
+ # Compute the comparison between the result element
1091
+ # at i and the enum element.
1092
+ if ruby_block then
1093
+ cond = ruby_block.call(res[i],elem) > 0
1094
+ else
1095
+ cond = res[i] > elem
1096
+ end
1097
+ # If flg is 0, elem is already set as min, skip.
1098
+ # If the result array size index is equal to i, then
1099
+ # put the element whatever the comparison is since
1100
+ # the place is still empty.
1101
+ hif(flg & (cond | (idx == i))) do
1102
+ # A new min is found, shift res from i.
1103
+ ((i+1)..(n-1)).reverse_each { |j| res[j] <= res[j-1] }
1104
+ # An set the new min in current position.
1105
+ res[i] <= elem
1106
+ # For now skip.
1107
+ flg <= 0
1108
+ end
1109
+ end
1110
+ # Note: when idx >= n, the resulting array is full
1111
+ hif(idx < n) { idx <= idx + 1 }
1112
+ end
1113
+ end
1114
+ end
1115
+ return res
1116
+ end
1117
+
1118
+ # HW implementation of the Ruby min_by.
1119
+ def smin_by(n = nil, &ruby_block)
1120
+ # No block given? Generate a new wrapper enumerator for smin_by.
1121
+ if !ruby_block then
1122
+ return SEnumeratorWrapper.new(self,:smin_by,n)
1123
+ end
1124
+ # A block is given, use smin with a proc that applies ruby_block
1125
+ # before comparing.
1126
+ return smin(n) { |a,b| ruby_block.call(a) <=> ruby_block.call(b) }
1127
+ end
1128
+
1129
+ # HW implementation of the Ruby minmax.
1130
+ def sminmax(&ruby_block)
1131
+ # Generate the result signal.
1132
+ res = nil
1133
+ enum = self.seach
1134
+ HDLRuby::High.cur_system.open do
1135
+ res = enum.type[2].inner(HDLRuby.uniq_name(:"minmax_res"))
1136
+ end
1137
+ # Computes the min.
1138
+ res[0] <= enum.smin(&ruby_block)
1139
+ # Computes the max.
1140
+ res[1] <= enum.smax(&ruby_block)
1141
+ # Return the result.
1142
+ return res
1143
+ end
1144
+
1145
+ # HW implementation of the Ruby minmax_by.
1146
+ def sminmax_by(&ruby_block)
1147
+ # Generate the result signal.
1148
+ res = nil
1149
+ enum = self.seach
1150
+ HDLRuby::High.cur_system.open do
1151
+ res = enum.type[2].inner(HDLRuby.uniq_name(:"minmax_res"))
1152
+ end
1153
+ # Computes the min.
1154
+ res[0] <= enum.smin_by(&ruby_block)
1155
+ # Computes the max.
1156
+ res[1] <= enum.smax_by(&ruby_block)
1157
+ # Return the result.
1158
+ return res
1159
+ end
1160
+
1161
+ # Tell if none of the elements respects a given criterion given either
1162
+ # as +arg+ or as block.
1163
+ def snone?(arg = nil,&ruby_block)
1164
+ # Declare the result signal.
1165
+ res = nil
1166
+ HDLRuby::High.cur_system.open do
1167
+ res = bit.inner(HDLRuby.uniq_name(:"none_cond"))
1168
+ end
1169
+ # Initialize the result.
1170
+ res <= 1
1171
+ # Performs the computation.
1172
+ if arg then
1173
+ # Compare elements to arg.
1174
+ self.seach do |elem|
1175
+ res <= res & (elem != arg)
1176
+ end
1177
+ elsif ruby_block then
1178
+ # Use the ruby block.
1179
+ self.seach do |elem|
1180
+ res <= res & ~ruby_block.call(elem)
1181
+ end
1182
+ else
1183
+ raise "Ruby nil does not have any meaning in HW."
1184
+ end
1185
+ res
1186
+ end
1187
+
1188
+ # Tell if one and only one of the elements respects a given criterion
1189
+ # given either as +arg+ or as block.
1190
+ def sone?(arg = nil,&ruby_block)
1191
+ # Declare the result signal.
1192
+ res = nil
1193
+ HDLRuby::High.cur_system.open do
1194
+ res = bit.inner(HDLRuby.uniq_name(:"one_cond"))
1195
+ end
1196
+ # Initialize the result.
1197
+ res <= 0
1198
+ # Performs the computation.
1199
+ if arg then
1200
+ # Compare elements to arg.
1201
+ self.seach do |elem|
1202
+ res <= res ^ (elem == arg)
1203
+ end
1204
+ elsif ruby_block then
1205
+ # Use the ruby block.
1206
+ self.seach do |elem|
1207
+ res <= res ^ ruby_block.call(elem)
1208
+ end
1209
+ else
1210
+ raise "Ruby nil does not have any meaning in HW."
1211
+ end
1212
+ res
1213
+ end
1214
+
1215
+ # HW implementation of the Ruby partition.
1216
+ # NOTE: to do, or may be not.
1217
+ def spartition(*args,&ruby_block)
1218
+ raise "spartition is not supported yet."
1219
+ end
1220
+
1221
+ # HW implementatiob of the Ruby reject.
1222
+ def sreject(&ruby_block)
1223
+ return sselect {|elem| ~ruby_block.call(elem) }
1224
+ end
1225
+
1226
+ # HW implementatiob of the Ruby reverse_each.
1227
+ def sreverse_each(*args,&ruby_block)
1228
+ # No block given? Generate a new wrapper enumerator for
1229
+ # sreverse_each.
1230
+ if !ruby_block then
1231
+ return SEnumeratorWrapper.new(self,:sreverse_each,*args)
1232
+ end
1233
+ # A block is given.
1234
+ # Declares the index.
1235
+ enum = self.seach
1236
+ idx = nil
1237
+ HDLRuby::High.cur_system.open do
1238
+ idx = bit[enum.size.width].inner(HDLRuby.uniq_name(:"reverse_idx"))
1239
+ end
1240
+ # Do the iteration.
1241
+ idx <= enum.size
1242
+ SequencerT.current.swhile(idx > 0) do
1243
+ idx <= idx - 1
1244
+ ruby_block.call(*args,enum.access(idx))
1245
+ end
1246
+ end
1247
+
1248
+ # HW implementation of the Ruby slice_after.
1249
+ # NOTE: to do, or may be not.
1250
+ def sslice_after(pattern = nil,&ruby_block)
1251
+ raise "sslice_after is not supported yet."
1252
+ end
1253
+
1254
+ # HW implementation of the Ruby slice_before.
1255
+ # NOTE: to do, or may be not.
1256
+ def sslice_before(*args,&ruby_block)
1257
+ raise "sslice_before is not supported yet."
1258
+ end
1259
+
1260
+ # HW implementation of the Ruby slice_when.
1261
+ # NOTE: to do, or may be not.
1262
+ def sslice_when(*args,&ruby_block)
1263
+ raise "sslice_before is not supported yet."
1264
+ end
1265
+
1266
+ # # HW implementation of the Ruby sort.
1267
+ # def ssort(&ruby_block)
1268
+ # enum = self.seach
1269
+ # n = enum.size
1270
+ # # Declare the result signal the flag and the result array size index
1271
+ # # used for implementing the algorithm (shift-based sorting).
1272
+ # res = nil
1273
+ # flg = nil
1274
+ # idx = nil
1275
+ # HDLRuby::High.cur_system.open do
1276
+ # res = enum.type[-n].inner(HDLRuby.uniq_name(:"sort_res"))
1277
+ # flg = bit.inner(HDLRuby.uniq_name(:"sort_flg"))
1278
+ # idx = bit[n.width].inner(HDLRuby.uniq_name(:"sort_idx"))
1279
+ # end
1280
+ # # Performs the sort using a shift-based algorithm (also used in
1281
+ # # smin).
1282
+ # enum.srewind
1283
+ # # Do the iteration.
1284
+ # idx <= 0
1285
+ # SequencerT.current.swhile(enum.snext?) do
1286
+ # # Multiple min case.
1287
+ # SequencerT.current.sif(enum.snext?) do
1288
+ # elem = enum.snext
1289
+ # flg <= 1
1290
+ # n.times do |i|
1291
+ # # Compute the comparison between the result element at i
1292
+ # # and the enum element.
1293
+ # if ruby_block then
1294
+ # cond = ruby_block.call(res[i],elem) > 0
1295
+ # else
1296
+ # cond = res[i] > elem
1297
+ # end
1298
+ # # If flg is 0, elem is already set as min, skip.
1299
+ # # If the result array size index is equal to i, then
1300
+ # # put the element whatever the comparison is since the
1301
+ # # place is still empty.
1302
+ # hif(flg & (cond | (idx == i))) do
1303
+ # # A new min is found, shift res from i.
1304
+ # ((i+1)..(n-1)).reverse_each { |j| res[j] <= res[j-1] }
1305
+ # # An set the new min in current position.
1306
+ # res[i] <= elem
1307
+ # # For now skip.
1308
+ # flg <= 0
1309
+ # end
1310
+ # end
1311
+ # idx <= idx + 1
1312
+ # end
1313
+ # end
1314
+ # return res
1315
+ # end
1316
+
1317
+ # Merge two arrays in order, for ssort only.
1318
+ def ssort_merge(arI, arO, first, middle, last, &ruby_block)
1319
+ # puts "first=#{first} middle=#{middle} last=#{last}"
1320
+ # Declare and initialize the indexes and
1321
+ # the ending flag.
1322
+ idF = nil; idM = nil; idO = nil
1323
+ flg = nil
1324
+ HDLRuby::High.cur_system.open do
1325
+ typ = [(last+1).width]
1326
+ idF = typ.inner(HDLRuby.uniq_name(:"sort_idF"))
1327
+ idM = typ.inner(HDLRuby.uniq_name(:"sort_idM"))
1328
+ idO = typ.inner(HDLRuby.uniq_name(:"sort_idO"))
1329
+ flg = inner(HDLRuby.uniq_name(:"sort_flg"))
1330
+ end
1331
+ idF <= first; idM <= middle; idO <= first
1332
+ flg <= 0
1333
+ SequencerT.current.swhile((flg == 0) & (idO < middle*2)) do
1334
+ if ruby_block then
1335
+ cond = ruby_block.call(arI[idF],arI[idM]) < 0
1336
+ else
1337
+ cond = arI[idF] < arI[idM]
1338
+ end
1339
+ hif((idF >= middle) & (idM > last)) { flg <= 1 }
1340
+ helsif (idF >= middle) do
1341
+ arO[idO] <= arI[idM]
1342
+ idM <= idM + 1
1343
+ end
1344
+ helsif(idM > last) do
1345
+ arO[idO] <= arI[idF]
1346
+ idF <= idF + 1
1347
+ end
1348
+ helsif(cond) do
1349
+ arO[idO] <= arI[idF]
1350
+ idF <= idF + 1
1351
+ end
1352
+ helse do
1353
+ arO[idO] <= arI[idM]
1354
+ idM <= idM + 1
1355
+ end
1356
+ idO <= idO + 1
1357
+ end
1358
+ end
1359
+
1360
+ # HW implementation of the Ruby sort.
1361
+ def ssort(&ruby_block)
1362
+ enum = self.seach
1363
+ n = enum.size
1364
+ # Declare the result signal.
1365
+ res = nil
1366
+ flg = nil
1367
+ siz = nil
1368
+ HDLRuby::High.cur_system.open do
1369
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"sort_res"))
1370
+ end
1371
+ # Only one element?
1372
+ if n == 1 then
1373
+ # Just copy to the result and end here.
1374
+ res[0] <= enum.snext
1375
+ return res
1376
+ end
1377
+ tmp = []
1378
+ idxF = nil; idxM = nil; idxO = nil
1379
+ HDLRuby::High.cur_system.open do
1380
+ # More elements, need to declare intermediate arrays.
1381
+ ((n-1).width).times do
1382
+ tmp << enum.type[-n].inner(HDLRuby.uniq_name(:"sort_tmp"))
1383
+ end
1384
+ # The result will be the last of the intermediate arrays.
1385
+ tmp << res
1386
+ end
1387
+ # Fills the first temporary array.
1388
+ enum.seach_with_index { |e,i| tmp[0][i] <= e }
1389
+ # Is there only 2 elements?
1390
+ if n == 2 then
1391
+ if ruby_block then
1392
+ cond = ruby_block.call(tmp[0][0],tmp[0][1]) < 0
1393
+ else
1394
+ cond = tmp[0][0] < tmp[0][1]
1395
+ end
1396
+ # Just look for the min and the max.
1397
+ hif(cond) do
1398
+ res[0] <= tmp[0][0]
1399
+ res[1] <= tmp[0][1]
1400
+ end
1401
+ helse do
1402
+ res[1] <= tmp[0][0]
1403
+ res[0] <= tmp[0][1]
1404
+ end
1405
+ return res
1406
+ end
1407
+ # Performs the sort using a merge-based algorithm.
1408
+ breadth = 1; i = 0
1409
+ # while(breadth*2 < n)
1410
+ while(breadth < n)
1411
+ pos = 0; last = 0
1412
+ while(pos+breadth < n)
1413
+ last = [n-1,pos+breadth*2-1].min
1414
+ ssort_merge(tmp[i], tmp[i+1], pos, pos+breadth,last,&ruby_block)
1415
+ pos = pos + breadth * 2
1416
+ end
1417
+ # Copy the remaining elements if any
1418
+ # puts "n=#{n} breadth=#{breadth} last=#{last} n-last-1=#{n-last-1}"
1419
+ if last < n-1 then
1420
+ (n-last-1).stimes do |j|
1421
+ tmp[i+1][last+1+j] <= tmp[i][last+1+j]
1422
+ end
1423
+ end
1424
+ # Next step
1425
+ # SequencerT.current.step
1426
+ breadth = breadth * 2
1427
+ i += 1
1428
+ end
1429
+ # # Last merge if the array size was not a power of 2.
1430
+ # if (breadth*2 != n) then
1431
+ # ssort_merge(tmp[-2],tmp[-1],0,breadth,n-1,&ruby_block)
1432
+ # # SequencerT.current.step
1433
+ # end
1434
+ return res
1435
+ end
1436
+
1437
+ # HW implementation of the Ruby sort.
1438
+ def ssort_by(&ruby_block)
1439
+ # No block given? Generate a new wrapper enumerator for smin_by.
1440
+ if !ruby_block then
1441
+ return SEnumeratorWrapper.new(self,:ssort_by,n)
1442
+ end
1443
+ # A block is given, use smin with a proc that applies ruby_block
1444
+ # before comparing.
1445
+ return ssort { |a,b| ruby_block.call(a) <=> ruby_block.call(b) }
1446
+ end
1447
+
1448
+ # HW implementation of the Ruby sum.
1449
+ def ssum(initial_value = nil,&ruby_block)
1450
+ enum = self.seach
1451
+ # Define the computation type: from the initial value if any,
1452
+ # otherwise from the enum.
1453
+ typ = initial_value ? initial_value.to_expr.type : enum.type
1454
+ # Ensures there is an initial value.
1455
+ initial_value = 0.to_expr.as(typ) unless initial_value
1456
+ # Generate the result signal.
1457
+ res = nil
1458
+ HDLRuby::High.cur_system.open do
1459
+ res = typ.inner(HDLRuby.uniq_name(:"sum_res"))
1460
+ end
1461
+ # Start the initialization
1462
+ enum.srewind
1463
+ # Yes, start with the initial value.
1464
+ res <= initial_value
1465
+ SequencerT.current.swhile(enum.snext?) do
1466
+ # Do the accumulation.
1467
+ if (ruby_block) then
1468
+ # There is a ruby block, use it to process the element first.
1469
+ res <= res + ruby_block.call(enum.snext)
1470
+ else
1471
+ # No ruby block, just do the sum
1472
+ res <= res + enum.snext
1473
+ end
1474
+ end
1475
+ return res
1476
+ end
1477
+
1478
+ # The HW implementation of the Ruby take.
1479
+ def stake(n)
1480
+ enum = self.seach
1481
+ # Generate the result signal.
1482
+ res = nil
1483
+ HDLRuby::High.cur_system.open do
1484
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"sum_res"))
1485
+ end
1486
+ # Take the n first elements.
1487
+ n.stimes do |i|
1488
+ res[i] <= enum.access(i)
1489
+ end
1490
+ return res
1491
+ end
1492
+
1493
+ # The HW implementation of the Ruby take_while.
1494
+ def stake_while(&ruby_block)
1495
+ # No block given? Generate a new wrapper enumerator for sdrop_while.
1496
+ if !ruby_block then
1497
+ return SEnumeratorWrapper.new(self,:stake_while)
1498
+ end
1499
+ # A block is given.
1500
+ # Generate the vector to put the result in.
1501
+ # The declares the resulting vector and take flag.
1502
+ res = nil
1503
+ flg = nil
1504
+ enum = self.seach
1505
+ HDLRuby::High.cur_system.open do
1506
+ res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"take_vec"))
1507
+ flg = bit.inner(HDLRuby.uniq_name(:"take_flg"))
1508
+ end
1509
+ # And do the iteration.
1510
+ # First fill from current enumerable elements.
1511
+ flg <= 1
1512
+ enum.seach.with_index do |elem,i|
1513
+ HDLRuby::High.top_user.hif(flg == 1) do
1514
+ HDLRuby::High.top_user.hif(ruby_block.call(elem) == 0) do
1515
+ flg <= 0
1516
+ end
1517
+ end
1518
+ HDLRuby::High.top_user.hif(flg == 1) do
1519
+ res[i] <= elem
1520
+ end
1521
+ HDLRuby::High.top_user.helse do
1522
+ res[i] <= 0
1523
+ end
1524
+ end
1525
+ # Return the resulting vector.
1526
+ return res
1527
+ end
1528
+
1529
+ # HW implementation of the Ruby tally.
1530
+ # NOTE: to do, or may be not.
1531
+ def stally(h = nil)
1532
+ raise "stally is not supported yet."
1533
+ end
1534
+
1535
+ # HW implementation of the Ruby to_h.
1536
+ # NOTE: to do, or may be not.
1537
+ def sto_h(h = nil)
1538
+ raise "sto_h is not supported yet."
1539
+ end
1540
+
1541
+ # HW implementation of the Ruby uniq.
1542
+ def suniq(&ruby_block)
1543
+ enum = self.seach
1544
+ n = enum.size
1545
+ # Declare the result signal the flag and the result array size index
1546
+ # used for implementing the algorithm (shift-based sorting).
1547
+ res = nil
1548
+ flg = nil
1549
+ idx = nil
1550
+ HDLRuby::High.cur_system.open do
1551
+ res = enum.type[-n].inner(HDLRuby.uniq_name(:"suniq_res"))
1552
+ flg = bit.inner(HDLRuby.uniq_name(:"suniq_flg"))
1553
+ idx = bit[n.width].inner(HDLRuby.uniq_name(:"suniq_idx"))
1554
+ end
1555
+ enum.srewind
1556
+ # Do the iteration.
1557
+ idx <= 0
1558
+ SequencerT.current.swhile(enum.snext?) do
1559
+ # Multiple min case.
1560
+ SequencerT.current.sif(enum.snext?) do
1561
+ elem = enum.snext
1562
+ flg <= 1
1563
+ n.times do |i|
1564
+ # Compute the comparison between the result element at i
1565
+ # and the enum element.
1566
+ hif(i < idx) do
1567
+ if ruby_block then
1568
+ flg <= (flg &
1569
+ (ruby_block.call(res[i]) != ruby_block.call(elem)))
1570
+ else
1571
+ flg <= (flg & (res[i] != elem))
1572
+ end
1573
+ end
1574
+ # If flg is 1 the element is new, if it is the right
1575
+ # position, add it to the result.
1576
+ hif((idx == i) & flg) do
1577
+ # An set the new min in current position.
1578
+ res[i] <= elem
1579
+ # For next position now.
1580
+ idx <= idx + 1
1581
+ # Stop here for current element.
1582
+ flg <= 0
1583
+ end
1584
+ end
1585
+ end
1586
+ end
1587
+ # Fills the remaining location with 0.
1588
+ SequencerT.current.swhile(idx < enum.size) do
1589
+ res[idx] <= 0
1590
+ idx <= idx + 1
1591
+ end
1592
+ return res
1593
+ end
1594
+
1595
+ # HW implementation of the Ruby zip.
1596
+ # NOTE: for now szip is deactivated untile tuples are properly
1597
+ # handled by HDLRuby.
1598
+ def szip(obj,&ruby_block)
1599
+ res = nil
1600
+ l0,r0,l1,r1 = nil,nil,nil,nil
1601
+ idx = nil
1602
+ enum0 = self.seach
1603
+ enum1 = obj.seach
1604
+ # Compute the minimal and maximal iteration sizes of both
1605
+ # enumerables.
1606
+ size_min = [enum0.size,enum1.size].min
1607
+ size_max = [enum0.size,enum1.size].max
1608
+ HDLRuby::High.cur_system.open do
1609
+ # If there is no ruby_block, szip generates a resulting vector
1610
+ # and its access indexes.
1611
+ unless ruby_block then
1612
+ res = bit[enum0.type.width+enum1.type.width][-size_max].inner(HDLRuby.uniq_name(:"zip_res"))
1613
+ l0 = enum0.type.width+enum1.type.width - 1
1614
+ r0 = enum1.type.width
1615
+ l1 = r0-1
1616
+ r1 = 0
1617
+ end
1618
+ # Generate the index.
1619
+ idx = [size_max.width].inner(HDLRuby.uniq_name(:"zip_idx"))
1620
+ end
1621
+ # Do the iteration.
1622
+ enum0.srewind
1623
+ enum1.srewind
1624
+ # As long as there is enough elements.
1625
+ idx <= 0
1626
+ SequencerT.current.swhile(idx < size_min) do
1627
+ # Generate the access to the elements.
1628
+ elem0 = enum0.snext
1629
+ elem1 = enum1.snext
1630
+ if ruby_block then
1631
+ # A ruby block is given, applies it directly on the elements.
1632
+ ruby_block.call(elem0,elem1)
1633
+ else
1634
+ # No ruby block, put the access results into res.
1635
+ # res[idx][l0..r0] <= elem0
1636
+ # res[idx][l1..r1] <= elem1
1637
+ res[idx] <= [elem0,elem1]
1638
+ end
1639
+ idx <= idx + 1
1640
+ end
1641
+ # For the remaining iteration use zeros for the smaller enumerable.
1642
+ SequencerT.current.swhile(idx < size_max) do
1643
+ # Generate the access to the elements.
1644
+ elem0 = enum0.size < size_max ? 0 : enum0.snext
1645
+ elem1 = enum1.size < size_max ? 0 : enum1.snext
1646
+ if ruby_block then
1647
+ # A ruby block is given, applies it directly on the elements.
1648
+ ruby_block.call(elem0,elem1)
1649
+ else
1650
+ # No ruby block, put the access results into res.
1651
+ # res[idx][l0..r0] <= elem0
1652
+ # res[idx][l1..r1] <= elem1
1653
+ res[idx] <= [elem0,elem1]
1654
+ end
1655
+ idx <= idx + 1
1656
+ end
1657
+ unless ruby_block then
1658
+ return res
1659
+ end
1660
+ end
1661
+
1662
+ end
1663
+
1664
+
1665
+ # Describes a sequencer enumerator class that allows to generate HW iteration
1666
+ # over HW or SW objects within sequencers.
1667
+ # This is the abstract Enumerator class.
1668
+ class SEnumerator
1669
+ include SEnumerable
1670
+
1671
+ # The methods that need to be defined.
1672
+ [:size, :type, :result, :index,
1673
+ :clone, :speek, :snext, :srewind].each do |name|
1674
+ define_method(:name) do
1675
+ raise "Method '#{name}' must be defined for a valid sequencer enumerator."
1676
+ end
1677
+ end
1678
+
1679
+ # Iterate on each element.
1680
+ def seach(&ruby_block)
1681
+ # No block given, returns self.
1682
+ return self unless ruby_block
1683
+ # A block is given, iterate.
1684
+ this = self
1685
+ # Reitialize the iteration.
1686
+ this.srewind
1687
+ # Performs the iteration.
1688
+ SequencerT.current.swhile(self.index < self.size) do
1689
+ ruby_block.call(this.snext)
1690
+ end
1691
+ end
1692
+
1693
+ # Iterate on each element with index.
1694
+ def seach_with_index(&ruby_block)
1695
+ return self.with_index(&ruby_block)
1696
+ end
1697
+
1698
+ # Iterate on each element with arbitrary object +obj+.
1699
+ def seach_with_object(val,&ruby_block)
1700
+ # self.seach do |elem|
1701
+ # ruby_block(elem,val)
1702
+ # end
1703
+ return self.with_object(val,&ruby_block)
1704
+ end
1705
+
1706
+ # Iterates with an index.
1707
+ def with_index(&ruby_block)
1708
+ # Is there a ruby block?
1709
+ if ruby_block then
1710
+ # Yes, iterate directly.
1711
+ idx = self.index
1712
+ return self.seach do |elem|
1713
+ ruby_block.call(elem,idx-1)
1714
+ end
1715
+ end
1716
+ # No, create a new enumerator with +with_index+ as default
1717
+ # iteration.
1718
+ return SEnumeratorWrapper.new(self,:with_index)
1719
+ end
1720
+
1721
+ # Return a new SEnumerator with an arbitrary arbitrary object +obj+.
1722
+ def with_object(obj)
1723
+ # Is there a ruby block?
1724
+ if ruby_block then
1725
+ # Yes, iterate directly.
1726
+ return self.seach do |elem|
1727
+ ruby_block.call(elem,val)
1728
+ end
1729
+ end
1730
+ # No, create a new enumerator with +with_index+ as default
1731
+ # iteration.
1732
+ return SEnumeratorWrapper.new(self,:with_object,obj)
1733
+ end
1734
+
1735
+ # Return a new SEnumerator going on iteration over enumerable +obj+
1736
+ def +(obj)
1737
+ enum = self.clone
1738
+ obj_enum = obj.seach
1739
+ res = nil
1740
+ this = self
1741
+ HDLRuby::High.cur_system.open do
1742
+ res = this.type.inner(HDLRuby.uniq_name("enum_plus"))
1743
+ end
1744
+ return SEnumeratorBase.new(this.type,this.size+obj_enum.size) do|idx|
1745
+ HDLRuby::High.top_user.hif(idx < this.size) { res <= enum.snext }
1746
+ HDLRuby::High.top_user.helse { res <= obj_enum.snext }
1747
+ res
1748
+ end
1749
+ end
1750
+ end
1751
+
1752
+
1753
+ # Describes a sequencer enumerator class that allows to generate HW iterations
1754
+ # over HW or SW objects within sequencers.
1755
+ # This is the wrapper Enumerator over an other one for applying an other
1756
+ # interation method over the first one.
1757
+ class SEnumeratorWrapper < SEnumerator
1758
+
1759
+ # Create a new SEnumerator wrapper over +enum+ with +iter+ iteration
1760
+ # method and +args+ argument.
1761
+ def initialize(enum,iter,*args)
1762
+ if enum.is_a?(SEnumerator) then
1763
+ @enumerator = enum.clone
1764
+ else
1765
+ @enumerator = enum.seach
1766
+ end
1767
+ @iterator = iter.to_sym
1768
+ @arguments = args
1769
+ end
1770
+
1771
+ # The directly delegate methods.
1772
+ def size
1773
+ return @enumerator.size
1774
+ end
1775
+
1776
+ def type
1777
+ return @enumerator.type
1778
+ end
1779
+
1780
+ def result
1781
+ return @enumerator.result
1782
+ end
1783
+
1784
+ def index
1785
+ return @enumerator.index
1786
+ end
1787
+
1788
+ def access(idx)
1789
+ return @enumerator.access(idx)
1790
+ end
1791
+
1792
+ def speek
1793
+ return @enumerator.speek
1794
+ end
1795
+
1796
+ def snext
1797
+ return @enumerator.snext
1798
+ end
1799
+
1800
+ def snext?
1801
+ return @enumerator.snext?
1802
+ end
1803
+
1804
+ def srewind
1805
+ return @enumerator.srewind
1806
+ end
1807
+
1808
+ # Clones the enumerator.
1809
+ def clone
1810
+ return SEnumeratorWrapper.new(@enumerator,@iterator,*@arguments)
1811
+ end
1812
+
1813
+ # Iterate over each element.
1814
+ def seach(&ruby_block)
1815
+ # No block given, returns self.
1816
+ return self unless ruby_block
1817
+ # A block is given, iterate.
1818
+ return @enumerator.send(@iterator,*@arguments,&ruby_block)
1819
+ end
1820
+ end
1821
+
1822
+
1823
+ # Describes a sequencer enumerator class that allows to generate HW
1824
+ # iterations over HW or SW objects within sequencers.
1825
+ # This is the base Enumerator that directly iterates.
1826
+ class SEnumeratorBase < SEnumerator
1827
+
1828
+ attr_reader :size
1829
+ attr_reader :type
1830
+ attr_reader :result
1831
+ attr_reader :index
1832
+
1833
+ # Create a new sequencer for +size+ elements as +typ+ with an HW
1834
+ # array-like accesser +access+.
1835
+ def initialize(typ,size,&access)
1836
+ # Sets the size.
1837
+ @size = size
1838
+ # Sets the type.
1839
+ @type = typ
1840
+ # Sets the accesser.
1841
+ @access = access
1842
+ # Compute the index width (default: safe 32 bits).
1843
+ width = @size.respond_to?(:width) ? @size.width :
1844
+ @size.respond_to?(:type) ? size.type.width : 32
1845
+ # puts "width=#{width}"
1846
+ # Create the index and the iteration result.
1847
+ idx = nil
1848
+ result = nil
1849
+ HDLRuby::High.cur_system.open do
1850
+ idx = [width].inner({
1851
+ HDLRuby.uniq_name("enum_idx") => 0 })
1852
+ result = typ.inner(HDLRuby.uniq_name("enum_res"))
1853
+ end
1854
+ @index = idx
1855
+ @result = result
1856
+ end
1857
+
1858
+ # Clones the enumerator.
1859
+ def clone
1860
+ return SEnumeratorBase.new(@type,@size,&@access)
1861
+ end
1862
+
1863
+ # Generates the access at +idx+
1864
+ def access(idx)
1865
+ @access.call(idx)
1866
+ end
1867
+
1868
+ # View the next element without advancing the iteration.
1869
+ def speek
1870
+ @result <= @access.call(@index)
1871
+ return @result
1872
+ end
1873
+
1874
+ # Get the next element.
1875
+ def snext
1876
+ @result <= @access.call(@index)
1877
+ @index <= @index + 1
1878
+ return @result
1879
+ end
1880
+
1881
+ # Tell if there is a next element.
1882
+ def snext?
1883
+ return @index < @size
1884
+ end
1885
+
1886
+ # Restart the iteration.
1887
+ def srewind
1888
+ @index <= 0
1889
+ end
1890
+ end
1891
+
1892
+
1893
+ module HDLRuby::High::HExpression
1894
+ # Enhance the HExpression module with sequencer iteration.
1895
+
1896
+ # HW iteration on each element.
1897
+ def seach(&ruby_block)
1898
+ # Create the hardware iterator.
1899
+ this = self
1900
+ hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx|
1901
+ this[idx]
1902
+ end
1903
+ # Is there a ruby block?
1904
+ if(ruby_block) then
1905
+ # Yes, apply it.
1906
+ return hw_enum.seach(&ruby_block)
1907
+ else
1908
+ # No, return the resulting enumerator.
1909
+ return hw_enum
1910
+ end
1911
+ end
1912
+
1913
+ # Also adds the methods of SEnumerable.
1914
+ SEnumerable.instance_methods.each do |meth|
1915
+ define_method(meth,SEnumerable.instance_method(meth))
1916
+ end
1917
+ end
1918
+
1919
+
1920
+ class HDLRuby::High::Value
1921
+ # Enhance the Value class with sequencer iterations.
1922
+
1923
+ # HW times iteration.
1924
+ def stimes(&ruby_block)
1925
+ return (0..self-1).seach(&ruby_block)
1926
+ end
1927
+
1928
+ # HW upto iteration.
1929
+ def supto(val,&ruby_block)
1930
+ return (self..val).seach(&ruby_block)
1931
+ end
1932
+
1933
+ # HW downto iteration.
1934
+ def sdownto(val,&ruby_block)
1935
+ # Create the hardware iterator.
1936
+ range = val..(self.to_i)
1937
+ hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
1938
+ range.last - idx
1939
+ end
1940
+ # Is there a ruby block?
1941
+ if(ruby_block) then
1942
+ # Yes, apply it.
1943
+ return hw_enum.seach(&ruby_block)
1944
+ else
1945
+ # No, return the resulting enumerator.
1946
+ return hw_enum
1947
+ end
1948
+ end
1949
+ end
1950
+
1951
+
1952
+ module ::Enumerable
1953
+ # Enhance the Enumerable module with sequencer iteration.
1954
+
1955
+ # HW iteration on each element.
1956
+ def seach(&ruby_block)
1957
+ # Convert the enumrable to an array for easier processing.
1958
+ ar = self.to_a
1959
+ return if ar.empty? # The array is empty, nothing to do.
1960
+ # Compute the type of the elements.
1961
+ typ = ar[0].respond_to?(:type) ? ar[0].type : signed[32]
1962
+ # Create the hardware iterator.
1963
+ hw_enum = SEnumeratorBase.new(typ,ar.size) do |idx|
1964
+ HDLRuby::High.top_user.mux(idx,*ar)
1965
+ end
1966
+ # Is there a ruby block?
1967
+ if(ruby_block) then
1968
+ # Yes, apply it.
1969
+ return hw_enum.seach(&ruby_block)
1970
+ else
1971
+ # No, return the resulting enumerator.
1972
+ return hw_enum
1973
+ end
1974
+ end
1975
+
1976
+ # Also adds the methods of SEnumerable.
1977
+ SEnumerable.instance_methods.each do |meth|
1978
+ define_method(meth,SEnumerable.instance_method(meth))
1979
+ end
1980
+ end
1981
+
1982
+
1983
+ class ::Range
1984
+ # Enhance the Range class with sequencer iteration.
1985
+ include SEnumerable
1986
+
1987
+ # HW iteration on each element.
1988
+ def seach(&ruby_block)
1989
+ # Create the iteration type.
1990
+ # if self.first < 0 || self.last < 0 then
1991
+ # fw = self.first.is_a?(Numeric) ? self.first.abs.width :
1992
+ # self.first.width
1993
+ # lw = self.last.is_a?(Numeric) ? self.last.abs.width :
1994
+ # self.last.width
1995
+ # typ = signed[[fw,lw].max]
1996
+ # else
1997
+ # typ = bit[[self.first.width,self.last.width].max]
1998
+ # end
1999
+ # Create the iteration type: selection of the larger HDLRuby type
2000
+ # between first and last. If one of first and last is a Numeric,
2001
+ # priority to the non Numeric one.
2002
+ if (self.last.is_a?(Numeric)) then
2003
+ typ = self.first.to_expr.type
2004
+ elsif (self.first.is_a?(Numeric)) then
2005
+ typ = self.last.to_expr.type
2006
+ else
2007
+ typ = self.first.type.width > self.last.type.width ?
2008
+ self.first.type : self.last.type
2009
+ end
2010
+ # Create the hardware iterator.
2011
+ this = self
2012
+ size = this.size ? this.size : this.last - this.first + 1
2013
+ # size = size.to_expr
2014
+ # if size.respond_to?(:cast) then
2015
+ # size = size.cast(typ)
2016
+ # else
2017
+ # size = size.as(typ)
2018
+ # end
2019
+ size = size.to_expr.as(typ)
2020
+ # hw_enum = SEnumeratorBase.new(signed[32],size) do |idx|
2021
+ hw_enum = SEnumeratorBase.new(typ,size) do |idx|
2022
+ # idx.as(typ) + this.first
2023
+ idx.as(typ) + this.first.to_expr.as(typ)
2024
+ end
2025
+ # Is there a ruby block?
2026
+ if(ruby_block) then
2027
+ # Yes, apply it.
2028
+ return hw_enum.seach(&ruby_block)
2029
+ else
2030
+ # No, return the resulting enumerator.
2031
+ return hw_enum
2032
+ end
2033
+ end
2034
+ end
2035
+
2036
+
2037
+ class ::Integer
2038
+ # Enhance the Integer class with sequencer iterations.
2039
+
2040
+ # HW times iteration.
2041
+ def stimes(&ruby_block)
2042
+ return (0..self-1).seach(&ruby_block)
2043
+ end
2044
+
2045
+ # HW upto iteration.
2046
+ def supto(val,&ruby_block)
2047
+ return (self..val).seach(&ruby_block)
2048
+ end
2049
+
2050
+ # HW downto iteration.
2051
+ def sdownto(val,&ruby_block)
2052
+ # Create the hardware iterator.
2053
+ range = val..self
2054
+ hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
2055
+ range.last - idx
2056
+ end
2057
+ # Is there a ruby block?
2058
+ if(ruby_block) then
2059
+ # Yes, apply it.
2060
+ return hw_enum.seach(&ruby_block)
2061
+ else
2062
+ # No, return the resulting enumerator.
2063
+ return hw_enum
2064
+ end
2065
+ end
2066
+ end
2067
+
2068
+
2069
+
2070
+ # Creates a sequencer of code synchronised of +clk+ and starting on +start+.
2071
+ def sequencer(clk,start,&ruby_block)
2072
+ return SequencerT.new(clk,start,&ruby_block)
2073
+ end
2074
+
2075
+ # Creates an sequencer enumerator using a specific block access.
2076
+ # - +typ+ is the data type of the elements.
2077
+ # - +size+ is the number of elements.
2078
+ # - +access+ is the block implementing the access method.
2079
+ def senumerator(typ,size,&access)
2080
+ return SEnumeratorBase.new(typ,size,&access)
2081
+ end
2082
+
2083
+
2084
+
2085
+ end