HDLRuby 2.11.12 → 3.0.0

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