HDLRuby 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,6 +327,34 @@ 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
+ if SequencerT.current then
342
+ unames = names.map {|name| HDLRuby.uniq_name(name) }
343
+ HDLRuby::High.cur_scope.make_inners(typ, *unames)
344
+ names.zip(unames).each do |name,uname|
345
+ HDLRuby::High.space_reg(name) { send(uname) }
346
+ end
347
+ else
348
+ # self.old_make_inners(typ,*names)
349
+ # Call the old make_inners.
350
+ @@old_make_inners_proc.bind(self).call(typ,*names)
351
+ end
352
+ end
353
+ end
354
+
355
+
356
+
357
+
314
358
  # Module adding functionalities to object including the +seach+ method.
315
359
  module SEnumerable
316
360
 
@@ -713,8 +757,10 @@ module HDLRuby::High::Std
713
757
  # Declares the resulting vector.
714
758
  enum = self.seach
715
759
  res = nil
760
+ # size = enum.size.to_value
716
761
  HDLRuby::High.cur_system.open do
717
- res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"to_a_res"))
762
+ # res = enum.type[-enum.size].inner(HDLRuby.uniq_name(:"to_a_res"))
763
+ res = enum.type[-enum.size.to_i].inner(HDLRuby.uniq_name(:"to_a_res"))
718
764
  end
719
765
  # Fills it.
720
766
  self.seach_with_index do |elem,i|
@@ -1217,54 +1263,174 @@ module HDLRuby::High::Std
1217
1263
  raise "sslice_before is not supported yet."
1218
1264
  end
1219
1265
 
1266
+ # # HW implementation of the Ruby sort.
1267
+ # def ssort(&ruby_block)
1268
+ # enum = self.seach
1269
+ # n = enum.size
1270
+ # # Declare the result signal the flag and the result array size index
1271
+ # # used for implementing the algorithm (shift-based sorting).
1272
+ # res = nil
1273
+ # flg = nil
1274
+ # idx = nil
1275
+ # HDLRuby::High.cur_system.open do
1276
+ # res = enum.type[-n].inner(HDLRuby.uniq_name(:"sort_res"))
1277
+ # flg = bit.inner(HDLRuby.uniq_name(:"sort_flg"))
1278
+ # idx = bit[n.width].inner(HDLRuby.uniq_name(:"sort_idx"))
1279
+ # end
1280
+ # # Performs the sort using a shift-based algorithm (also used in
1281
+ # # smin).
1282
+ # enum.srewind
1283
+ # # Do the iteration.
1284
+ # idx <= 0
1285
+ # SequencerT.current.swhile(enum.snext?) do
1286
+ # # Multiple min case.
1287
+ # SequencerT.current.sif(enum.snext?) do
1288
+ # elem = enum.snext
1289
+ # flg <= 1
1290
+ # n.times do |i|
1291
+ # # Compute the comparison between the result element at i
1292
+ # # and the enum element.
1293
+ # if ruby_block then
1294
+ # cond = ruby_block.call(res[i],elem) > 0
1295
+ # else
1296
+ # cond = res[i] > elem
1297
+ # end
1298
+ # # If flg is 0, elem is already set as min, skip.
1299
+ # # If the result array size index is equal to i, then
1300
+ # # put the element whatever the comparison is since the
1301
+ # # place is still empty.
1302
+ # hif(flg & (cond | (idx == i))) do
1303
+ # # A new min is found, shift res from i.
1304
+ # ((i+1)..(n-1)).reverse_each { |j| res[j] <= res[j-1] }
1305
+ # # An set the new min in current position.
1306
+ # res[i] <= elem
1307
+ # # For now skip.
1308
+ # flg <= 0
1309
+ # end
1310
+ # end
1311
+ # idx <= idx + 1
1312
+ # end
1313
+ # end
1314
+ # return res
1315
+ # end
1316
+
1317
+ # Merge two arrays in order, for ssort only.
1318
+ def ssort_merge(arI, arO, first, middle, last, &ruby_block)
1319
+ # puts "first=#{first} middle=#{middle} last=#{last}"
1320
+ # Declare and initialize the indexes and
1321
+ # the ending flag.
1322
+ idF = nil; idM = nil; idO = nil
1323
+ flg = nil
1324
+ HDLRuby::High.cur_system.open do
1325
+ typ = [(last+1).width]
1326
+ idF = typ.inner(HDLRuby.uniq_name(:"sort_idF"))
1327
+ idM = typ.inner(HDLRuby.uniq_name(:"sort_idM"))
1328
+ idO = typ.inner(HDLRuby.uniq_name(:"sort_idO"))
1329
+ flg = inner(HDLRuby.uniq_name(:"sort_flg"))
1330
+ end
1331
+ idF <= first; idM <= middle; idO <= first
1332
+ flg <= 0
1333
+ SequencerT.current.swhile((flg == 0) & (idO < middle*2)) do
1334
+ if ruby_block then
1335
+ cond = ruby_block.call(arI[idF],arI[idM]) < 0
1336
+ else
1337
+ cond = arI[idF] < arI[idM]
1338
+ end
1339
+ hif((idF >= middle) & (idM > last)) { flg <= 1 }
1340
+ helsif (idF >= middle) do
1341
+ arO[idO] <= arI[idM]
1342
+ idM <= idM + 1
1343
+ end
1344
+ helsif(idM > last) do
1345
+ arO[idO] <= arI[idF]
1346
+ idF <= idF + 1
1347
+ end
1348
+ helsif(cond) do
1349
+ arO[idO] <= arI[idF]
1350
+ idF <= idF + 1
1351
+ end
1352
+ helse do
1353
+ arO[idO] <= arI[idM]
1354
+ idM <= idM + 1
1355
+ end
1356
+ idO <= idO + 1
1357
+ end
1358
+ end
1359
+
1220
1360
  # HW implementation of the Ruby sort.
1221
1361
  def ssort(&ruby_block)
1222
1362
  enum = self.seach
1223
1363
  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).
1364
+ # Declare the result signal.
1226
1365
  res = nil
1227
1366
  flg = nil
1228
- idx = nil
1367
+ siz = nil
1229
1368
  HDLRuby::High.cur_system.open do
1230
1369
  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
1370
  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
1371
+ # Only one element?
1372
+ if n == 1 then
1373
+ # Just copy to the result and end here.
1374
+ res[0] <= enum.snext
1375
+ return res
1376
+ end
1377
+ tmp = []
1378
+ idxF = nil; idxM = nil; idxO = nil
1379
+ HDLRuby::High.cur_system.open do
1380
+ # More elements, need to declare intermediate arrays.
1381
+ ((n-1).width).times do
1382
+ tmp << enum.type[-n].inner(HDLRuby.uniq_name(:"sort_tmp"))
1383
+ end
1384
+ # The result will be the last of the intermediate arrays.
1385
+ tmp << res
1386
+ end
1387
+ # Fills the first temporary array.
1388
+ enum.seach_with_index { |e,i| tmp[0][i] <= e }
1389
+ # Is there only 2 elements?
1390
+ if n == 2 then
1391
+ if ruby_block then
1392
+ cond = ruby_block.call(tmp[0][0],tmp[0][1]) < 0
1393
+ else
1394
+ cond = tmp[0][0] < tmp[0][1]
1266
1395
  end
1396
+ # Just look for the min and the max.
1397
+ hif(cond) do
1398
+ res[0] <= tmp[0][0]
1399
+ res[1] <= tmp[0][1]
1400
+ end
1401
+ helse do
1402
+ res[1] <= tmp[0][0]
1403
+ res[0] <= tmp[0][1]
1404
+ end
1405
+ return res
1267
1406
  end
1407
+ # Performs the sort using a merge-based algorithm.
1408
+ breadth = 1; i = 0
1409
+ # while(breadth*2 < n)
1410
+ while(breadth < n)
1411
+ pos = 0; last = 0
1412
+ while(pos+breadth < n)
1413
+ last = [n-1,pos+breadth*2-1].min
1414
+ ssort_merge(tmp[i], tmp[i+1], pos, pos+breadth,last,&ruby_block)
1415
+ pos = pos + breadth * 2
1416
+ end
1417
+ # Copy the remaining elements if any
1418
+ # puts "n=#{n} breadth=#{breadth} last=#{last} n-last-1=#{n-last-1}"
1419
+ if last < n-1 then
1420
+ (n-last-1).stimes do |j|
1421
+ tmp[i+1][last+1+j] <= tmp[i][last+1+j]
1422
+ end
1423
+ end
1424
+ # Next step
1425
+ # SequencerT.current.step
1426
+ breadth = breadth * 2
1427
+ i += 1
1428
+ end
1429
+ # # Last merge if the array size was not a power of 2.
1430
+ # if (breadth*2 != n) then
1431
+ # ssort_merge(tmp[-2],tmp[-1],0,breadth,n-1,&ruby_block)
1432
+ # # SequencerT.current.step
1433
+ # end
1268
1434
  return res
1269
1435
  end
1270
1436
 
@@ -1302,7 +1468,7 @@ module HDLRuby::High::Std
1302
1468
  # There is a ruby block, use it to process the element first.
1303
1469
  res <= res + ruby_block.call(enum.snext)
1304
1470
  else
1305
- # No ruby block, just do the su,
1471
+ # No ruby block, just do the sum
1306
1472
  res <= res + enum.snext
1307
1473
  end
1308
1474
  end
@@ -1674,7 +1840,9 @@ module HDLRuby::High::Std
1674
1840
  # Sets the accesser.
1675
1841
  @access = access
1676
1842
  # Compute the index width (default: safe 32 bits).
1677
- width = @size.respond_to?(:width) ? @size.width : 32
1843
+ width = @size.respond_to?(:width) ? @size.width :
1844
+ @size.respond_to?(:type) ? size.type.width : 32
1845
+ # puts "width=#{width}"
1678
1846
  # Create the index and the iteration result.
1679
1847
  idx = nil
1680
1848
  result = nil
@@ -1749,6 +1917,38 @@ module HDLRuby::High::Std
1749
1917
  end
1750
1918
 
1751
1919
 
1920
+ class HDLRuby::High::Value
1921
+ # Enhance the Value class with sequencer iterations.
1922
+
1923
+ # HW times iteration.
1924
+ def stimes(&ruby_block)
1925
+ return (0..self-1).seach(&ruby_block)
1926
+ end
1927
+
1928
+ # HW upto iteration.
1929
+ def supto(val,&ruby_block)
1930
+ return (self..val).seach(&ruby_block)
1931
+ end
1932
+
1933
+ # HW downto iteration.
1934
+ def sdownto(val,&ruby_block)
1935
+ # Create the hardware iterator.
1936
+ range = val..(self.to_i)
1937
+ hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
1938
+ range.last - idx
1939
+ end
1940
+ # Is there a ruby block?
1941
+ if(ruby_block) then
1942
+ # Yes, apply it.
1943
+ return hw_enum.seach(&ruby_block)
1944
+ else
1945
+ # No, return the resulting enumerator.
1946
+ return hw_enum
1947
+ end
1948
+ end
1949
+ end
1950
+
1951
+
1752
1952
  module ::Enumerable
1753
1953
  # Enhance the Enumerable module with sequencer iteration.
1754
1954
 
@@ -1787,12 +1987,40 @@ module HDLRuby::High::Std
1787
1987
  # HW iteration on each element.
1788
1988
  def seach(&ruby_block)
1789
1989
  # Create the iteration type.
1790
- typ = bit[[self.first.width,self.last.width].max]
1990
+ # if self.first < 0 || self.last < 0 then
1991
+ # fw = self.first.is_a?(Numeric) ? self.first.abs.width :
1992
+ # self.first.width
1993
+ # lw = self.last.is_a?(Numeric) ? self.last.abs.width :
1994
+ # self.last.width
1995
+ # typ = signed[[fw,lw].max]
1996
+ # else
1997
+ # typ = bit[[self.first.width,self.last.width].max]
1998
+ # end
1999
+ # Create the iteration type: selection of the larger HDLRuby type
2000
+ # between first and last. If one of first and last is a Numeric,
2001
+ # priority to the non Numeric one.
2002
+ if (self.last.is_a?(Numeric)) then
2003
+ typ = self.first.to_expr.type
2004
+ elsif (self.first.is_a?(Numeric)) then
2005
+ typ = self.last.to_expr.type
2006
+ else
2007
+ typ = self.first.type.width > self.last.type.width ?
2008
+ self.first.type : self.last.type
2009
+ end
1791
2010
  # Create the hardware iterator.
1792
2011
  this = self
1793
2012
  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
2013
+ # size = size.to_expr
2014
+ # if size.respond_to?(:cast) then
2015
+ # size = size.cast(typ)
2016
+ # else
2017
+ # size = size.as(typ)
2018
+ # end
2019
+ size = size.to_expr.as(typ)
2020
+ # hw_enum = SEnumeratorBase.new(signed[32],size) do |idx|
2021
+ hw_enum = SEnumeratorBase.new(typ,size) do |idx|
2022
+ # idx.as(typ) + this.first
2023
+ idx.as(typ) + this.first.to_expr.as(typ)
1796
2024
  end
1797
2025
  # Is there a ruby block?
1798
2026
  if(ruby_block) then
@@ -1811,7 +2039,7 @@ module HDLRuby::High::Std
1811
2039
 
1812
2040
  # HW times iteration.
1813
2041
  def stimes(&ruby_block)
1814
- return (0...self).seach(&ruby_block)
2042
+ return (0..self-1).seach(&ruby_block)
1815
2043
  end
1816
2044
 
1817
2045
  # HW upto iteration.