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.
- checksums.yaml +4 -4
- data/README.md +139 -79
- data/lib/HDLRuby/hdr_samples/constant_in_function.rb +2 -1
- data/lib/HDLRuby/hdr_samples/with_ref_expr.rb +30 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer.rb +32 -37
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +103 -69
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +10 -10
- data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +63 -0
- data/lib/HDLRuby/hdrcc.rb +1 -1
- data/lib/HDLRuby/hruby_high.rb +23 -5
- data/lib/HDLRuby/hruby_low_without_subsignals.rb +50 -11
- data/lib/HDLRuby/hruby_types.rb +5 -5
- data/lib/HDLRuby/hruby_values.rb +7 -7
- data/lib/HDLRuby/hruby_verilog.rb +101 -17
- data/lib/HDLRuby/hruby_verilog_name.rb +49 -42
- data/lib/HDLRuby/std/fsm.rb +10 -1
- data/lib/HDLRuby/std/sequencer.rb +281 -53
- data/lib/HDLRuby/std/sequencer_func.rb +533 -0
- data/lib/HDLRuby/std/std.rb +1 -0
- data/lib/HDLRuby/version.rb +1 -1
- data/tuto/tutorial_sw.md +267 -61
- metadata +5 -3
- 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
|
-
#
|
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
|
1225
|
-
# used for implementing the algorithm (shift-based sorting).
|
1364
|
+
# Declare the result signal.
|
1226
1365
|
res = nil
|
1227
1366
|
flg = nil
|
1228
|
-
|
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
|
-
#
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
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
|
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 :
|
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
|
-
|
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
|
-
|
1795
|
-
|
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
|
2042
|
+
return (0..self-1).seach(&ruby_block)
|
1815
2043
|
end
|
1816
2044
|
|
1817
2045
|
# HW upto iteration.
|