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