HDLRuby 3.0.0 → 3.2.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/HDLRuby.gemspec +1 -0
  3. data/README.md +149 -79
  4. data/ext/hruby_sim/hruby_rcsim_build.c +2 -0
  5. data/ext/hruby_sim/hruby_sim_calc.c +33 -6
  6. data/ext/hruby_sim/hruby_sim_tree_calc.c +111 -22
  7. data/lib/HDLRuby/hdr_samples/comparison_bench.rb +2 -2
  8. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +2 -1
  9. data/lib/HDLRuby/hdr_samples/counter_bench.rb +1 -1
  10. data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +8 -7
  11. data/lib/HDLRuby/hdr_samples/dff_properties.rb +2 -0
  12. data/lib/HDLRuby/hdr_samples/enum_as_param.rb +52 -0
  13. data/lib/HDLRuby/hdr_samples/linear_test.rb +2 -0
  14. data/lib/HDLRuby/hdr_samples/logic_bench.rb +6 -0
  15. data/lib/HDLRuby/hdr_samples/mei8.rb +6 -6
  16. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +6 -6
  17. data/lib/HDLRuby/hdr_samples/memory_test.rb +2 -0
  18. data/lib/HDLRuby/hdr_samples/named_sub.rb +9 -5
  19. data/lib/HDLRuby/hdr_samples/ram.rb +7 -6
  20. data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +2 -0
  21. data/lib/HDLRuby/hdr_samples/struct.rb +15 -3
  22. data/lib/HDLRuby/hdr_samples/with_bram.rb +1 -1
  23. data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +1 -1
  24. data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +1 -1
  25. data/lib/HDLRuby/hdr_samples/with_channel.rb +2 -0
  26. data/lib/HDLRuby/hdr_samples/with_channel_other.rb +2 -0
  27. data/lib/HDLRuby/hdr_samples/with_class.rb +3 -1
  28. data/lib/HDLRuby/hdr_samples/with_connector.rb +2 -0
  29. data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +2 -0
  30. data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +6 -0
  31. data/lib/HDLRuby/hdr_samples/with_fixpoint_adv.rb +73 -0
  32. data/lib/HDLRuby/hdr_samples/with_leftright.rb +1 -1
  33. data/lib/HDLRuby/hdr_samples/with_ref_expr.rb +30 -0
  34. data/lib/HDLRuby/hdr_samples/with_sequencer.rb +49 -37
  35. data/lib/HDLRuby/hdr_samples/with_sequencer_channel.rb +58 -0
  36. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +113 -69
  37. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +28 -14
  38. data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +63 -0
  39. data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +2 -1
  40. data/lib/HDLRuby/hdrcc.rb +13 -1
  41. data/lib/HDLRuby/hruby_high.rb +105 -31
  42. data/lib/HDLRuby/hruby_low.rb +127 -3
  43. data/lib/HDLRuby/hruby_low2programs.rb +47 -0
  44. data/lib/HDLRuby/hruby_low_resolve.rb +3 -2
  45. data/lib/HDLRuby/hruby_low_without_namespace.rb +133 -5
  46. data/lib/HDLRuby/hruby_low_without_subsignals.rb +51 -12
  47. data/lib/HDLRuby/hruby_rcsim.rb +24 -1
  48. data/lib/HDLRuby/hruby_serializer.rb +2 -1
  49. data/lib/HDLRuby/hruby_types.rb +5 -5
  50. data/lib/HDLRuby/hruby_values.rb +7 -7
  51. data/lib/HDLRuby/hruby_verilog.rb +193 -35
  52. data/lib/HDLRuby/hruby_verilog_name.rb +35 -42
  53. data/lib/HDLRuby/std/fixpoint.rb +2 -2
  54. data/lib/HDLRuby/std/fsm.rb +10 -1
  55. data/lib/HDLRuby/std/function_generator.rb +1 -1
  56. data/lib/HDLRuby/std/linear.rb +7 -7
  57. data/lib/HDLRuby/std/sequencer.rb +538 -60
  58. data/lib/HDLRuby/std/sequencer_channel.rb +90 -0
  59. data/lib/HDLRuby/std/sequencer_func.rb +546 -0
  60. data/lib/HDLRuby/std/std.rb +2 -0
  61. data/lib/HDLRuby/version.rb +1 -1
  62. data/tuto/tutorial_sw.md +267 -61
  63. metadata +25 -4
  64. data/lib/HDLRuby/hdr_samples/with_register_stack.rb +0 -150
@@ -77,20 +77,17 @@ module HDLRuby::High::Std
77
77
  this.fill_top_user(blk)
78
78
  end
79
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
80
 
89
81
  # Build the fsm.
90
82
  @fsm.build
91
83
  end
92
84
 
93
- # Get the closest loop status in the status stack.
85
+ # Gets the number of states of the underlining fsm.
86
+ def size
87
+ return @fsm.size
88
+ end
89
+
90
+ # Gets the closest loop status in the status stack.
94
91
  # NOTE: raises an exception if there are not swhile state.
95
92
  def loop_status
96
93
  i = @status.size-1
@@ -122,6 +119,25 @@ module HDLRuby::High::Std
122
119
  return st
123
120
  end
124
121
 
122
+ # Mark several steps.
123
+ def steps(num)
124
+ # Create a counter.
125
+ count = nil
126
+ zero = nil
127
+ one = nil
128
+ HDLRuby::High.cur_system.open do
129
+ if num.respond_to?(:width) then
130
+ count = [num.width].inner(HDLRuby.uniq_name(:"steps_count"))
131
+ else
132
+ count = num.to_expr.type.inner(HDLRuby.uniq_name(:"steps_count"))
133
+ end
134
+ zero = _b0
135
+ one = _b1
136
+ end
137
+ count <= num
138
+ swhile(count > zero) { count <= count - one }
139
+ end
140
+
125
141
  # Breaks current iteration.
126
142
  def sbreak
127
143
  # Mark a step.
@@ -311,9 +327,49 @@ module HDLRuby::High::Std
311
327
  end
312
328
 
313
329
 
330
+ ## Remplement make_inners of block to support declaration within sequencers.
331
+
332
+
333
+ class HDLRuby::High::Block
334
+ # Save module method (unbounded) for further call since going to
335
+ # override make_inners.
336
+ # alias_method does not seem to work in such a context, so use
337
+ # this approach.
338
+ @@old_make_inners_proc = self.instance_method(:make_inners)
339
+
340
+ def make_inners(typ,*names)
341
+ res = nil
342
+ if SequencerT.current then
343
+ unames = names.map {|name| HDLRuby.uniq_name(name) }
344
+ res = HDLRuby::High.cur_scope.make_inners(typ, *unames)
345
+ names.zip(unames).each do |name,uname|
346
+ HDLRuby::High.space_reg(name) { send(uname) }
347
+ end
348
+ else
349
+ # self.old_make_inners(typ,*names)
350
+ # Call the old make_inners.
351
+ res = @@old_make_inners_proc.bind(self).call(typ,*names)
352
+ end
353
+ return res
354
+ end
355
+ end
356
+
357
+
358
+
359
+
314
360
  # Module adding functionalities to object including the +seach+ method.
315
361
  module SEnumerable
316
-
362
+
363
+ # Iterator on each of the elements in range +rng+.
364
+ # *NOTE*:
365
+ # - Stop iteration when the end of the range is reached or when there
366
+ # are no elements left
367
+ # - This is not a method from Ruby but one specific for hardware where
368
+ # creating a array is very expensive.
369
+ def seach_range(rng,&ruby_block)
370
+ return self.seach.seach_range(rng,&ruby_block)
371
+ end
372
+
317
373
  # Tell if all the elements respect a given criterion given either
318
374
  # as +arg+ or as block.
319
375
  def sall?(arg = nil,&ruby_block)
@@ -713,8 +769,10 @@ module HDLRuby::High::Std
713
769
  # Declares the resulting vector.
714
770
  enum = self.seach
715
771
  res = nil
772
+ # size = enum.size.to_value
716
773
  HDLRuby::High.cur_system.open do
717
- res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"to_a_res"))
774
+ # res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"to_a_res"))
775
+ res = enum.type[-enum.size.to_i].inner(HDLRuby.uniq_name(:"to_a_res"))
718
776
  end
719
777
  # Fills it.
720
778
  self.seach_with_index do |elem,i|
@@ -1217,54 +1275,174 @@ module HDLRuby::High::Std
1217
1275
  raise "sslice_before is not supported yet."
1218
1276
  end
1219
1277
 
1278
+ # # HW implementation of the Ruby sort.
1279
+ # def ssort(&ruby_block)
1280
+ # enum = self.seach
1281
+ # n = enum.size
1282
+ # # Declare the result signal the flag and the result array size index
1283
+ # # used for implementing the algorithm (shift-based sorting).
1284
+ # res = nil
1285
+ # flg = nil
1286
+ # idx = nil
1287
+ # HDLRuby::High.cur_system.open do
1288
+ # res = enum.type[-n].inner(HDLRuby.uniq_name(:"sort_res"))
1289
+ # flg = bit.inner(HDLRuby.uniq_name(:"sort_flg"))
1290
+ # idx = bit[n.width].inner(HDLRuby.uniq_name(:"sort_idx"))
1291
+ # end
1292
+ # # Performs the sort using a shift-based algorithm (also used in
1293
+ # # smin).
1294
+ # enum.srewind
1295
+ # # Do the iteration.
1296
+ # idx <= 0
1297
+ # SequencerT.current.swhile(enum.snext?) do
1298
+ # # Multiple min case.
1299
+ # SequencerT.current.sif(enum.snext?) do
1300
+ # elem = enum.snext
1301
+ # flg <= 1
1302
+ # n.times do |i|
1303
+ # # Compute the comparison between the result element at i
1304
+ # # and the enum element.
1305
+ # if ruby_block then
1306
+ # cond = ruby_block.call(res[i],elem) > 0
1307
+ # else
1308
+ # cond = res[i] > elem
1309
+ # end
1310
+ # # If flg is 0, elem is already set as min, skip.
1311
+ # # If the result array size index is equal to i, then
1312
+ # # put the element whatever the comparison is since the
1313
+ # # place is still empty.
1314
+ # hif(flg & (cond | (idx == i))) do
1315
+ # # A new min is found, shift res from i.
1316
+ # ((i+1)..(n-1)).reverse_each { |j| res[j] <= res[j-1] }
1317
+ # # An set the new min in current position.
1318
+ # res[i] <= elem
1319
+ # # For now skip.
1320
+ # flg <= 0
1321
+ # end
1322
+ # end
1323
+ # idx <= idx + 1
1324
+ # end
1325
+ # end
1326
+ # return res
1327
+ # end
1328
+
1329
+ # Merge two arrays in order, for ssort only.
1330
+ def ssort_merge(arI, arO, first, middle, last, &ruby_block)
1331
+ # puts "first=#{first} middle=#{middle} last=#{last}"
1332
+ # Declare and initialize the indexes and
1333
+ # the ending flag.
1334
+ idF = nil; idM = nil; idO = nil
1335
+ flg = nil
1336
+ HDLRuby::High.cur_system.open do
1337
+ typ = [(last+1).width]
1338
+ idF = typ.inner(HDLRuby.uniq_name(:"sort_idF"))
1339
+ idM = typ.inner(HDLRuby.uniq_name(:"sort_idM"))
1340
+ idO = typ.inner(HDLRuby.uniq_name(:"sort_idO"))
1341
+ flg = inner(HDLRuby.uniq_name(:"sort_flg"))
1342
+ end
1343
+ idF <= first; idM <= middle; idO <= first
1344
+ flg <= 0
1345
+ SequencerT.current.swhile((flg == 0) & (idO < middle*2)) do
1346
+ if ruby_block then
1347
+ cond = ruby_block.call(arI[idF],arI[idM]) < 0
1348
+ else
1349
+ cond = arI[idF] < arI[idM]
1350
+ end
1351
+ hif((idF >= middle) & (idM > last)) { flg <= 1 }
1352
+ helsif (idF >= middle) do
1353
+ arO[idO] <= arI[idM]
1354
+ idM <= idM + 1
1355
+ end
1356
+ helsif(idM > last) do
1357
+ arO[idO] <= arI[idF]
1358
+ idF <= idF + 1
1359
+ end
1360
+ helsif(cond) do
1361
+ arO[idO] <= arI[idF]
1362
+ idF <= idF + 1
1363
+ end
1364
+ helse do
1365
+ arO[idO] <= arI[idM]
1366
+ idM <= idM + 1
1367
+ end
1368
+ idO <= idO + 1
1369
+ end
1370
+ end
1371
+
1220
1372
  # HW implementation of the Ruby sort.
1221
1373
  def ssort(&ruby_block)
1222
1374
  enum = self.seach
1223
1375
  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).
1376
+ # Declare the result signal.
1226
1377
  res = nil
1227
1378
  flg = nil
1228
- idx = nil
1379
+ siz = nil
1229
1380
  HDLRuby::High.cur_system.open do
1230
1381
  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
1382
  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
1383
+ # Only one element?
1384
+ if n == 1 then
1385
+ # Just copy to the result and end here.
1386
+ res[0] <= enum.snext
1387
+ return res
1388
+ end
1389
+ tmp = []
1390
+ idxF = nil; idxM = nil; idxO = nil
1391
+ HDLRuby::High.cur_system.open do
1392
+ # More elements, need to declare intermediate arrays.
1393
+ ((n-1).width).times do
1394
+ tmp << enum.type[-n].inner(HDLRuby.uniq_name(:"sort_tmp"))
1395
+ end
1396
+ # The result will be the last of the intermediate arrays.
1397
+ tmp << res
1398
+ end
1399
+ # Fills the first temporary array.
1400
+ enum.seach_with_index { |e,i| tmp[0][i] <= e }
1401
+ # Is there only 2 elements?
1402
+ if n == 2 then
1403
+ if ruby_block then
1404
+ cond = ruby_block.call(tmp[0][0],tmp[0][1]) < 0
1405
+ else
1406
+ cond = tmp[0][0] < tmp[0][1]
1407
+ end
1408
+ # Just look for the min and the max.
1409
+ hif(cond) do
1410
+ res[0] <= tmp[0][0]
1411
+ res[1] <= tmp[0][1]
1266
1412
  end
1413
+ helse do
1414
+ res[1] <= tmp[0][0]
1415
+ res[0] <= tmp[0][1]
1416
+ end
1417
+ return res
1267
1418
  end
1419
+ # Performs the sort using a merge-based algorithm.
1420
+ breadth = 1; i = 0
1421
+ # while(breadth*2 < n)
1422
+ while(breadth < n)
1423
+ pos = 0; last = 0
1424
+ while(pos+breadth < n)
1425
+ last = [n-1,pos+breadth*2-1].min
1426
+ ssort_merge(tmp[i], tmp[i+1], pos, pos+breadth,last,&ruby_block)
1427
+ pos = pos + breadth * 2
1428
+ end
1429
+ # Copy the remaining elements if any
1430
+ # puts "n=#{n} breadth=#{breadth} last=#{last} n-last-1=#{n-last-1}"
1431
+ if last < n-1 then
1432
+ (n-last-1).stimes do |j|
1433
+ tmp[i+1][last+1+j] <= tmp[i][last+1+j]
1434
+ end
1435
+ end
1436
+ # Next step
1437
+ # SequencerT.current.step
1438
+ breadth = breadth * 2
1439
+ i += 1
1440
+ end
1441
+ # # Last merge if the array size was not a power of 2.
1442
+ # if (breadth*2 != n) then
1443
+ # ssort_merge(tmp[-2],tmp[-1],0,breadth,n-1,&ruby_block)
1444
+ # # SequencerT.current.step
1445
+ # end
1268
1446
  return res
1269
1447
  end
1270
1448
 
@@ -1302,7 +1480,7 @@ module HDLRuby::High::Std
1302
1480
  # There is a ruby block, use it to process the element first.
1303
1481
  res <= res + ruby_block.call(enum.snext)
1304
1482
  else
1305
- # No ruby block, just do the su,
1483
+ # No ruby block, just do the sum
1306
1484
  res <= res + enum.snext
1307
1485
  end
1308
1486
  end
@@ -1493,6 +1671,55 @@ module HDLRuby::High::Std
1493
1671
  end
1494
1672
  end
1495
1673
 
1674
+ # Iterator on the +num+ next elements.
1675
+ # *NOTE*:
1676
+ # - Stop iteration when the end of the range is reached or when there
1677
+ # are no elements left
1678
+ # - This is not a method from Ruby but one specific for hardware where
1679
+ # creating a array is very expensive.
1680
+ def seach_nexts(num,&ruby_block)
1681
+ # # No block given, returns a new enumerator.
1682
+ # unless ruby_block then
1683
+ # res = SEnumeratorWrapper.new(self,:seach_nexts,num)
1684
+ # res.size = num
1685
+ # return res
1686
+ # end
1687
+ # # A block is given, iterate.
1688
+ # enum = self.seach
1689
+ # # Create a counter.
1690
+ # count = nil
1691
+ # zero = nil
1692
+ # one = nil
1693
+ # HDLRuby::High.cur_system.open do
1694
+ # if num.respond_to?(:width) then
1695
+ # count = [num.width].inner(HDLRuby.uniq_name(:"snexts_count"))
1696
+ # else
1697
+ # count = num.to_expr.type.inner(HDLRuby.uniq_name(:"snexts_count"))
1698
+ # end
1699
+ # zero = _b0
1700
+ # one = _b1
1701
+ # end
1702
+ # count <= num
1703
+ # SequencerT.current.swhile(count > zero) do
1704
+ # ruby_block.call(enum.snext)
1705
+ # count <= count - one
1706
+ # end
1707
+ zero = nil
1708
+ one = nil
1709
+ HDLRuby::High.cur_system.open do
1710
+ zero = _b0.as(num.to_expr.type)
1711
+ one = _b1.as(num.to_expr.type)
1712
+ end
1713
+ subE = SEnumeratorSub.new(self,zero..num-one)
1714
+ if ruby_block then
1715
+ # A block is given, iterate immediatly.
1716
+ subE.seach(&ruby_block)
1717
+ else
1718
+ # No block given, return the new sub iterator.
1719
+ return subE
1720
+ end
1721
+ end
1722
+
1496
1723
  end
1497
1724
 
1498
1725
 
@@ -1516,10 +1743,30 @@ module HDLRuby::High::Std
1516
1743
  return self unless ruby_block
1517
1744
  # A block is given, iterate.
1518
1745
  this = self
1519
- # Reitialize the iteration.
1746
+ # Reinitialize the iteration.
1520
1747
  this.srewind
1521
- # Performs the iteration.
1748
+ # Perform the iteration.
1522
1749
  SequencerT.current.swhile(self.index < self.size) do
1750
+ # ruby_block.call(this.snext)
1751
+ HDLRuby::High.top_user.instance_exec(this.snext,&ruby_block)
1752
+ end
1753
+ end
1754
+
1755
+ # Iterator on each of the elements in range +rng+.
1756
+ # *NOTE*:
1757
+ # - Stop iteration when the end of the range is reached or when there
1758
+ # are no elements left
1759
+ # - This is not a method from Ruby but one specific for hardware where
1760
+ # creating a array is very expensive.
1761
+ def seach_range(rng,&ruby_block)
1762
+ # No block given, returns a new enumerator.
1763
+ return SEnumeratorWrapper.new(self,:seach_range) unless ruby_block
1764
+ # A block is given, iterate.
1765
+ this = self
1766
+ # Perform the iteration.
1767
+ self.index <= rng.first
1768
+ SequencerT.current.swhile((self.index < self.size) &
1769
+ (self.index <= rng.last) ) do
1523
1770
  ruby_block.call(this.snext)
1524
1771
  end
1525
1772
  end
@@ -1604,7 +1851,7 @@ module HDLRuby::High::Std
1604
1851
 
1605
1852
  # The directly delegate methods.
1606
1853
  def size
1607
- return @enumerator.size
1854
+ return @enumertor.size
1608
1855
  end
1609
1856
 
1610
1857
  def type
@@ -1632,13 +1879,32 @@ module HDLRuby::High::Std
1632
1879
  end
1633
1880
 
1634
1881
  def snext?
1882
+ # if @size then
1883
+ # return @enumerator.index < @size
1884
+ # else
1885
+ # return @enumerator.snext?
1886
+ # end
1635
1887
  return @enumerator.snext?
1636
1888
  end
1637
1889
 
1890
+ def snext!(val)
1891
+ return @enumerator.snext!(val)
1892
+ end
1893
+
1638
1894
  def srewind
1639
1895
  return @enumerator.srewind
1640
1896
  end
1641
1897
 
1898
+ # Iterator on each of the elements in range +rng+.
1899
+ # *NOTE*:
1900
+ # - Stop iteration when the end of the range is reached or when there
1901
+ # are no elements left
1902
+ # - This is not a method from Ruby but one specific for hardware where
1903
+ # creating a array is very expensive.
1904
+ def seach_range(rng,&ruby_block)
1905
+ return @enumerator.seach_range(rng,&ruby_block)
1906
+ end
1907
+
1642
1908
  # Clones the enumerator.
1643
1909
  def clone
1644
1910
  return SEnumeratorWrapper.new(@enumerator,@iterator,*@arguments)
@@ -1654,6 +1920,92 @@ module HDLRuby::High::Std
1654
1920
  end
1655
1921
 
1656
1922
 
1923
+ # Describes a sequencer enumerator class that allows to generate HW iterations
1924
+ # over HW or SW objects within sequencers.
1925
+ # This is the sub Enumerator over an other one for interating inside the
1926
+ # enumerator.
1927
+ # This is specific the HDLRuby for avoiding creation of array which are
1928
+ # expensive in HW. Used by seach_next for example.
1929
+ # Will change the index position of the initial iterator without reseting
1930
+ # it.
1931
+ class SEnumeratorSub < SEnumerator
1932
+
1933
+ # Create a new SEnumerator wrapper over +enum+ among +rng+ indexes.
1934
+ def initialize(enum,rng,*args)
1935
+ @enumerator = enum.seach
1936
+ @range = rng.first..rng.last
1937
+ # Declare the sub index.
1938
+ idx = nil
1939
+ siz = @range.last-@range.first+1
1940
+ HDLRuby::High.cur_system.open do
1941
+ idx = [siz.width].inner({
1942
+ HDLRuby.uniq_name("sub_idx") => 0 })
1943
+ end
1944
+ @index = idx
1945
+ @size = siz
1946
+ end
1947
+
1948
+ # The directly delegate methods.
1949
+ def size
1950
+ return @size
1951
+ end
1952
+
1953
+ def type
1954
+ return @enumerator.type
1955
+ end
1956
+
1957
+ def result
1958
+ return @enumerator.result
1959
+ end
1960
+
1961
+ def index
1962
+ return @index
1963
+ end
1964
+
1965
+ def access(idx)
1966
+ return @enumerator.access(@index+@range.first)
1967
+ end
1968
+
1969
+ def speek
1970
+ return @enumerator.speek
1971
+ end
1972
+
1973
+ def snext
1974
+ @index <= @index + 1
1975
+ return @enumerator.snext
1976
+ end
1977
+
1978
+ def snext?
1979
+ return @index < self.size
1980
+ end
1981
+
1982
+ def snext!(val)
1983
+ return @enumerator.snext!(val)
1984
+ end
1985
+
1986
+ def srewind
1987
+ @index <= 0
1988
+ end
1989
+
1990
+ # Clones the enumerator.
1991
+ def clone
1992
+ return SEnumeratorSub.new(@enumerator,@range)
1993
+ end
1994
+
1995
+ # Iterate over each element.
1996
+ def seach(&ruby_block)
1997
+ # No block given, returns self.
1998
+ return self unless ruby_block
1999
+ # A block is given, iterate.
2000
+ this = self
2001
+ SequencerT.current.swhile(this.snext?) do
2002
+ ruby_block.call(this.snext)
2003
+ end
2004
+ end
2005
+ end
2006
+
2007
+
2008
+
1657
2009
  # Describes a sequencer enumerator class that allows to generate HW
1658
2010
  # iterations over HW or SW objects within sequencers.
1659
2011
  # This is the base Enumerator that directly iterates.
@@ -1674,7 +2026,9 @@ module HDLRuby::High::Std
1674
2026
  # Sets the accesser.
1675
2027
  @access = access
1676
2028
  # Compute the index width (default: safe 32 bits).
1677
- width = @size.respond_to?(:width) ? @size.width : 32
2029
+ width = @size.respond_to?(:width) ? @size.width :
2030
+ @size.respond_to?(:type) ? size.type.width : 32
2031
+ # puts "width=#{width}"
1678
2032
  # Create the index and the iteration result.
1679
2033
  idx = nil
1680
2034
  result = nil
@@ -1712,9 +2066,17 @@ module HDLRuby::High::Std
1712
2066
 
1713
2067
  # Tell if there is a next element.
1714
2068
  def snext?
2069
+ # puts "@index=#{index}, @size=#{@size}"
1715
2070
  return @index < @size
1716
2071
  end
1717
2072
 
2073
+ # Set the next element.
2074
+ def snext!(val)
2075
+ @access.call(@index,val)
2076
+ @index <= @index + 1
2077
+ return val
2078
+ end
2079
+
1718
2080
  # Restart the iteration.
1719
2081
  def srewind
1720
2082
  @index <= 0
@@ -1722,6 +2084,8 @@ module HDLRuby::High::Std
1722
2084
  end
1723
2085
 
1724
2086
 
2087
+
2088
+
1725
2089
  module HDLRuby::High::HExpression
1726
2090
  # Enhance the HExpression module with sequencer iteration.
1727
2091
 
@@ -1729,8 +2093,14 @@ module HDLRuby::High::Std
1729
2093
  def seach(&ruby_block)
1730
2094
  # Create the hardware iterator.
1731
2095
  this = self
1732
- hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx|
1733
- this[idx]
2096
+ hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx,val = nil|
2097
+ if val then
2098
+ # Write access
2099
+ this[idx] <= val
2100
+ else
2101
+ # Read access
2102
+ this[idx]
2103
+ end
1734
2104
  end
1735
2105
  # Is there a ruby block?
1736
2106
  if(ruby_block) then
@@ -1749,6 +2119,42 @@ module HDLRuby::High::Std
1749
2119
  end
1750
2120
 
1751
2121
 
2122
+ # class HDLRuby::High::Value
2123
+ module HDLRuby::High::HExpression
2124
+ # Enhance the Value class with sequencer iterations.
2125
+
2126
+ # HW times iteration.
2127
+ def stimes(&ruby_block)
2128
+ # return (0..self-1).seach(&ruby_block)
2129
+ return AnyRange.new(0,self-1).seach(&ruby_block)
2130
+ end
2131
+
2132
+ # HW upto iteration.
2133
+ def supto(val,&ruby_block)
2134
+ # return (self..val).seach(&ruby_block)
2135
+ return AnyRange.new(self,val).seach(&ruby_block)
2136
+ end
2137
+
2138
+ # HW downto iteration.
2139
+ def sdownto(val,&ruby_block)
2140
+ # Create the hardware iterator.
2141
+ # range = val..(self.to_i)
2142
+ range = AnyRange.new(val,self)
2143
+ hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
2144
+ range.last - idx
2145
+ end
2146
+ # Is there a ruby block?
2147
+ if(ruby_block) then
2148
+ # Yes, apply it.
2149
+ return hw_enum.seach(&ruby_block)
2150
+ else
2151
+ # No, return the resulting enumerator.
2152
+ return hw_enum
2153
+ end
2154
+ end
2155
+ end
2156
+
2157
+
1752
2158
  module ::Enumerable
1753
2159
  # Enhance the Enumerable module with sequencer iteration.
1754
2160
 
@@ -1787,12 +2193,85 @@ module HDLRuby::High::Std
1787
2193
  # HW iteration on each element.
1788
2194
  def seach(&ruby_block)
1789
2195
  # Create the iteration type.
1790
- typ = bit[[self.first.width,self.last.width].max]
2196
+ # if self.first < 0 || self.last < 0 then
2197
+ # fw = self.first.is_a?(Numeric) ? self.first.abs.width :
2198
+ # self.first.width
2199
+ # lw = self.last.is_a?(Numeric) ? self.last.abs.width :
2200
+ # self.last.width
2201
+ # typ = signed[[fw,lw].max]
2202
+ # else
2203
+ # typ = bit[[self.first.width,self.last.width].max]
2204
+ # end
2205
+ # Create the iteration type: selection of the larger HDLRuby type
2206
+ # between first and last. If one of first and last is a Numeric,
2207
+ # priority to the non Numeric one.
2208
+ if (self.last.is_a?(Numeric)) then
2209
+ typ = self.first.to_expr.type
2210
+ elsif (self.first.is_a?(Numeric)) then
2211
+ typ = self.last.to_expr.type
2212
+ else
2213
+ typ = self.first.type.width > self.last.type.width ?
2214
+ self.first.type : self.last.type
2215
+ end
1791
2216
  # Create the hardware iterator.
1792
2217
  this = self
1793
2218
  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
2219
+ # size = size.to_expr
2220
+ # if size.respond_to?(:cast) then
2221
+ # size = size.cast(typ)
2222
+ # else
2223
+ # size = size.as(typ)
2224
+ # end
2225
+ size = size.to_expr.as(typ)
2226
+ # hw_enum = SEnumeratorBase.new(signed[32],size) do |idx|
2227
+ hw_enum = SEnumeratorBase.new(typ,size) do |idx|
2228
+ # idx.as(typ) + this.first
2229
+ idx.as(typ) + this.first.to_expr.as(typ)
2230
+ end
2231
+ # Is there a ruby block?
2232
+ if(ruby_block) then
2233
+ # Yes, apply it.
2234
+ return hw_enum.seach(&ruby_block)
2235
+ else
2236
+ # No, return the resulting enumerator.
2237
+ return hw_enum
2238
+ end
2239
+ end
2240
+ end
2241
+
2242
+
2243
+ # Range substitute class for sequencers that supports any kind of bounds.
2244
+ class AnyRange
2245
+ # Enhance the AnyRange class with sequencer iteration.
2246
+ include SEnumerable
2247
+
2248
+ attr_reader :first, :last
2249
+
2250
+ def initialize(first,last)
2251
+ @first = first
2252
+ @last = last
2253
+ end
2254
+
2255
+ # HW iteration on each element.
2256
+ def seach(&ruby_block)
2257
+ # Create the iteration type: selection of the larger HDLRuby type
2258
+ # between first and last. If one of first and last is a Numeric,
2259
+ # priority to the non Numeric one.
2260
+ if (self.last.is_a?(Numeric)) then
2261
+ typ = self.first.to_expr.type
2262
+ elsif (self.first.is_a?(Numeric)) then
2263
+ typ = self.last.to_expr.type
2264
+ else
2265
+ typ = self.first.type.width > self.last.type.width ?
2266
+ self.first.type : self.last.type
2267
+ end
2268
+ # Create the hardware iterator.
2269
+ this = self
2270
+ # size = this.size ? this.size : this.last - this.first + 1
2271
+ size = this.last - this.first + 1
2272
+ size = size.to_expr.as(typ)
2273
+ hw_enum = SEnumeratorBase.new(typ,size) do |idx|
2274
+ idx.as(typ) + this.first.to_expr.as(typ)
1796
2275
  end
1797
2276
  # Is there a ruby block?
1798
2277
  if(ruby_block) then
@@ -1811,7 +2290,7 @@ module HDLRuby::High::Std
1811
2290
 
1812
2291
  # HW times iteration.
1813
2292
  def stimes(&ruby_block)
1814
- return (0...self).seach(&ruby_block)
2293
+ return (0..self-1).seach(&ruby_block)
1815
2294
  end
1816
2295
 
1817
2296
  # HW upto iteration.
@@ -1853,5 +2332,4 @@ module HDLRuby::High::Std
1853
2332
  end
1854
2333
 
1855
2334
 
1856
-
1857
2335
  end