HDLRuby 2.11.11 → 3.0.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.html +3274 -0
  3. data/README.md +608 -99
  4. data/ext/hruby_sim/hruby_rcsim_build.c +27 -0
  5. data/ext/hruby_sim/hruby_sim.h +3 -0
  6. data/ext/hruby_sim/hruby_sim_calc.c +2 -0
  7. data/ext/hruby_sim/hruby_sim_core.c +17 -5
  8. data/ext/hruby_sim/hruby_sim_stack_calc.c +1 -1
  9. data/ext/hruby_sim/hruby_sim_tree_calc.c +8 -1
  10. data/ext/hruby_sim/hruby_sim_vcd.c +24 -7
  11. data/ext/hruby_sim/hruby_sim_vizualize.c +9 -1
  12. data/lib/HDLRuby/backend/hruby_allocator.rb +2 -2
  13. data/lib/HDLRuby/backend/hruby_c_allocator.rb +7 -7
  14. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +3 -1
  15. data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +3 -1
  16. data/lib/HDLRuby/hdr_samples/huge_rom.rb +1 -1
  17. data/lib/HDLRuby/hdr_samples/mei8.rb +11 -11
  18. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +12 -12
  19. data/lib/HDLRuby/hdr_samples/neg_arith_bench.rb +4 -4
  20. data/lib/HDLRuby/hdr_samples/rom_nest.rb +1 -1
  21. data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +4 -4
  22. data/lib/HDLRuby/hdr_samples/struct.rb +44 -10
  23. data/lib/HDLRuby/hdr_samples/with_bram.rb +45 -0
  24. data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +105 -0
  25. data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +69 -0
  26. data/lib/HDLRuby/hdr_samples/with_casts.rb +3 -3
  27. data/lib/HDLRuby/hdr_samples/with_concat.rb +6 -6
  28. data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +2 -2
  29. data/lib/HDLRuby/hdr_samples/with_def.rb +10 -3
  30. data/lib/HDLRuby/hdr_samples/with_define_operator.rb +44 -0
  31. data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +12 -12
  32. data/lib/HDLRuby/hdr_samples/with_init.rb +3 -3
  33. data/lib/HDLRuby/hdr_samples/with_leftright.rb +21 -0
  34. data/lib/HDLRuby/hdr_samples/with_reduce.rb +13 -13
  35. data/lib/HDLRuby/hdr_samples/with_ref_array.rb +6 -6
  36. data/lib/HDLRuby/hdr_samples/with_register_stack.rb +150 -0
  37. data/lib/HDLRuby/hdr_samples/with_sequencer.rb +190 -0
  38. data/lib/HDLRuby/hdr_samples/with_sequencer_deep.rb +91 -0
  39. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +405 -0
  40. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +89 -0
  41. data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +120 -0
  42. data/lib/HDLRuby/hdr_samples/with_subsums.rb +3 -3
  43. data/lib/HDLRuby/hdr_samples/with_terminate.rb +3 -3
  44. data/lib/HDLRuby/hdr_samples/with_to_a.rb +10 -10
  45. data/lib/HDLRuby/hdr_samples/with_values.rb +3 -3
  46. data/lib/HDLRuby/hdrcc.rb +29 -3
  47. data/lib/HDLRuby/hdrlib.rb +1 -1
  48. data/lib/HDLRuby/hruby_bstr.rb +10 -5
  49. data/lib/HDLRuby/hruby_db.rb +2 -2
  50. data/lib/HDLRuby/hruby_high.rb +152 -47
  51. data/lib/HDLRuby/hruby_high_fullname.rb +3 -1
  52. data/lib/HDLRuby/hruby_low.rb +189 -18
  53. data/lib/HDLRuby/hruby_low2c.rb +129 -54
  54. data/lib/HDLRuby/hruby_low2hdr.rb +66 -40
  55. data/lib/HDLRuby/hruby_low2high.rb +86 -44
  56. data/lib/HDLRuby/hruby_low2seq.rb +26 -18
  57. data/lib/HDLRuby/hruby_low2sym.rb +14 -13
  58. data/lib/HDLRuby/hruby_low2vhd.rb +80 -44
  59. data/lib/HDLRuby/hruby_low_bool2select.rb +61 -46
  60. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +56 -44
  61. data/lib/HDLRuby/hruby_low_cleanup.rb +18 -16
  62. data/lib/HDLRuby/hruby_low_fix_types.rb +65 -32
  63. data/lib/HDLRuby/hruby_low_mutable.rb +83 -119
  64. data/lib/HDLRuby/hruby_low_resolve.rb +38 -30
  65. data/lib/HDLRuby/hruby_low_with_bool.rb +33 -16
  66. data/lib/HDLRuby/hruby_low_with_port.rb +3 -3
  67. data/lib/HDLRuby/hruby_low_with_var.rb +23 -9
  68. data/lib/HDLRuby/hruby_low_without_concat.rb +45 -19
  69. data/lib/HDLRuby/hruby_low_without_namespace.rb +47 -32
  70. data/lib/HDLRuby/hruby_low_without_parinseq.rb +32 -16
  71. data/lib/HDLRuby/hruby_low_without_select.rb +37 -24
  72. data/lib/HDLRuby/hruby_low_without_subsignals.rb +280 -0
  73. data/lib/HDLRuby/hruby_rcsim.rb +158 -134
  74. data/lib/HDLRuby/hruby_rsim.rb +194 -20
  75. data/lib/HDLRuby/hruby_rsim_mute.rb +2 -3
  76. data/lib/HDLRuby/hruby_rsim_vcd.rb +125 -50
  77. data/lib/HDLRuby/hruby_values.rb +48 -33
  78. data/lib/HDLRuby/hruby_verilog.rb +90 -48
  79. data/lib/HDLRuby/soft/stacks.rb +219 -0
  80. data/lib/HDLRuby/std/bram.rb +26 -0
  81. data/lib/HDLRuby/std/clocks.rb +1 -1
  82. data/lib/HDLRuby/std/fixpoint.rb +2 -2
  83. data/lib/HDLRuby/std/fsm.rb +48 -11
  84. data/lib/HDLRuby/std/function_generator.rb +2 -2
  85. data/lib/HDLRuby/std/sequencer.rb +1857 -0
  86. data/lib/HDLRuby/std/sequencer_sync.rb +400 -0
  87. data/lib/HDLRuby/std/std.rb +12 -0
  88. data/lib/HDLRuby/version.rb +1 -1
  89. data/tuto/adder_sat_flags_vcd.png +0 -0
  90. data/tuto/addsub_vcd.png +0 -0
  91. data/tuto/alu_vcd.png +0 -0
  92. data/tuto/bit_pong_vcd.png +0 -0
  93. data/tuto/checksum_vcd.png +0 -0
  94. data/tuto/circuit_hdr.odg +0 -0
  95. data/tuto/circuit_hdr.png +0 -0
  96. data/tuto/circuit_hie.odg +0 -0
  97. data/tuto/circuit_hie.png +0 -0
  98. data/tuto/circuit_view.odg +0 -0
  99. data/tuto/circuit_view.png +0 -0
  100. data/tuto/clock_counter_vcd.png +0 -0
  101. data/tuto/counter_ext_vcd.png +0 -0
  102. data/tuto/fact_vcd.png +0 -0
  103. data/tuto/hw_flow.odg +0 -0
  104. data/tuto/hw_flow.png +0 -0
  105. data/tuto/maxxer_vcd.png +0 -0
  106. data/tuto/pingpong0_vcd.png +0 -0
  107. data/tuto/pingpong1_vcd.png +0 -0
  108. data/tuto/pingpong2_vcd.png +0 -0
  109. data/tuto/ram_vcd.png +0 -0
  110. data/tuto/serializer_vcd.png +0 -0
  111. data/tuto/sw_flow.odg +0 -0
  112. data/tuto/sw_flow.png +0 -0
  113. data/tuto/the_counter_vcd.png +0 -0
  114. data/tuto/tutorial_sw.html +2359 -0
  115. data/tuto/tutorial_sw.md +2684 -0
  116. data/tuto/tutorial_sw.pdf +0 -0
  117. data/tuto/tutorial_sw_jp.md +417 -0
  118. metadata +49 -3
  119. data/lib/HDLRuby/hdr_samples/sumprod.rb +0 -29
@@ -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