HDLRuby 3.0.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HDLRuby.gemspec +1 -0
- data/README.md +149 -79
- data/ext/hruby_sim/hruby_rcsim_build.c +2 -0
- data/ext/hruby_sim/hruby_sim_calc.c +33 -6
- data/ext/hruby_sim/hruby_sim_tree_calc.c +111 -22
- data/lib/HDLRuby/hdr_samples/comparison_bench.rb +2 -2
- data/lib/HDLRuby/hdr_samples/constant_in_function.rb +2 -1
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +8 -7
- data/lib/HDLRuby/hdr_samples/dff_properties.rb +2 -0
- data/lib/HDLRuby/hdr_samples/enum_as_param.rb +52 -0
- data/lib/HDLRuby/hdr_samples/linear_test.rb +2 -0
- data/lib/HDLRuby/hdr_samples/logic_bench.rb +6 -0
- data/lib/HDLRuby/hdr_samples/mei8.rb +6 -6
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +6 -6
- data/lib/HDLRuby/hdr_samples/memory_test.rb +2 -0
- data/lib/HDLRuby/hdr_samples/named_sub.rb +9 -5
- data/lib/HDLRuby/hdr_samples/ram.rb +7 -6
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +2 -0
- data/lib/HDLRuby/hdr_samples/struct.rb +15 -3
- data/lib/HDLRuby/hdr_samples/with_bram.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_channel.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_channel_other.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_class.rb +3 -1
- data/lib/HDLRuby/hdr_samples/with_connector.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +6 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint_adv.rb +73 -0
- data/lib/HDLRuby/hdr_samples/with_leftright.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_ref_expr.rb +30 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer.rb +49 -37
- data/lib/HDLRuby/hdr_samples/with_sequencer_channel.rb +58 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +113 -69
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +28 -14
- data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +63 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +2 -1
- data/lib/HDLRuby/hdrcc.rb +13 -1
- data/lib/HDLRuby/hruby_high.rb +105 -31
- data/lib/HDLRuby/hruby_low.rb +127 -3
- data/lib/HDLRuby/hruby_low2programs.rb +47 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +3 -2
- data/lib/HDLRuby/hruby_low_without_namespace.rb +133 -5
- data/lib/HDLRuby/hruby_low_without_subsignals.rb +51 -12
- data/lib/HDLRuby/hruby_rcsim.rb +24 -1
- data/lib/HDLRuby/hruby_serializer.rb +2 -1
- data/lib/HDLRuby/hruby_types.rb +5 -5
- data/lib/HDLRuby/hruby_values.rb +7 -7
- data/lib/HDLRuby/hruby_verilog.rb +193 -35
- data/lib/HDLRuby/hruby_verilog_name.rb +35 -42
- data/lib/HDLRuby/std/fixpoint.rb +2 -2
- data/lib/HDLRuby/std/fsm.rb +10 -1
- data/lib/HDLRuby/std/function_generator.rb +1 -1
- data/lib/HDLRuby/std/linear.rb +7 -7
- data/lib/HDLRuby/std/sequencer.rb +538 -60
- data/lib/HDLRuby/std/sequencer_channel.rb +90 -0
- data/lib/HDLRuby/std/sequencer_func.rb +546 -0
- data/lib/HDLRuby/std/std.rb +2 -0
- data/lib/HDLRuby/version.rb +1 -1
- data/tuto/tutorial_sw.md +267 -61
- metadata +25 -4
- 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,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
|
1225
|
-
# used for implementing the algorithm (shift-based sorting).
|
1376
|
+
# Declare the result signal.
|
1226
1377
|
res = nil
|
1227
1378
|
flg = nil
|
1228
|
-
|
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
|
-
#
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
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
|
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
|
-
#
|
1746
|
+
# Reinitialize the iteration.
|
1520
1747
|
this.srewind
|
1521
|
-
#
|
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 @
|
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 :
|
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
|
-
|
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
|
-
|
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
|
-
|
1795
|
-
|
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
|
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
|