HDLRuby 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.