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.
@@ -16,34 +16,34 @@ system :my_seqencer do
16
16
  [8].inner :res0, :res1
17
17
 
18
18
  sequencer(clk.posedge,rst) do
19
- hprint("#0\n")
19
+ # hprint("#0\n")
20
20
  res0 <= 0
21
21
  res1 <= 0
22
22
  res0 <= vals.ssum
23
23
  res1 <= res0.ssum(_h00)
24
- hprint("#1 res0=",res0," res1=",res1,"\n")
24
+ # hprint("#1 res0=",res0," res1=",res1,"\n")
25
25
  end
26
26
 
27
27
  [8].inner :res2, :res3
28
28
 
29
29
  sequencer(clk.posedge,rst) do
30
- hprint("$0\n")
30
+ # hprint("$0\n")
31
31
  res2 <= 0
32
32
  res3 <= 0
33
- res2 <= (1..5).sum
33
+ res2 <= (1..5).ssum(_h00)
34
34
  res3 <= (res3..res2).ssum
35
- hprint("$1 res2=",res2," res3=",res3,"\n")
35
+ # hprint("$1 res2=",res2," res3=",res3,"\n")
36
36
  end
37
37
 
38
38
  [8].inner :res4, :res5
39
39
 
40
40
  sequencer(clk.posedge,rst) do
41
- hprint("!0\n")
41
+ # hprint("!0\n")
42
42
  res4 <= 0
43
43
  res5 <= 0
44
44
  res4 <= [_h01,_h02,_h03,_h04].ssum
45
- res5 <= [1,2,3,4,5].ssum
46
- hprint("!1 res4=",res4," res5=",res5,"\n")
45
+ res5 <= [1,2,3,4,5].ssum(_h00)
46
+ # hprint("!1 res4=",res4," res5=",res5,"\n")
47
47
  end
48
48
 
49
49
  bit[8][-8].inner mem: [ _h01, _h02, _h03, _h04, _h30, _h30, _h30, _h30 ]
@@ -59,10 +59,10 @@ system :my_seqencer do
59
59
  end
60
60
 
61
61
  sequencer(clk.posedge,rst) do
62
- hprint("~0\n")
62
+ # hprint("~0\n")
63
63
  res6 <= 0
64
64
  res6 <= mem_enum.ssum
65
- hprint("~1 res6=",res6,"\n")
65
+ # hprint("~1 res6=",res6,"\n")
66
66
  end
67
67
 
68
68
 
@@ -0,0 +1,63 @@
1
+ require 'std/sequencer_func.rb'
2
+
3
+ include HDLRuby::High::Std
4
+
5
+
6
+ # A factorial with default stack depth.
7
+ sdef(:fact) do |n|
8
+ hprint("n=",n,"\n")
9
+ sif(n > 1) { sreturn(n*fact(n-1,20)) } #Recurse setting the stack depth to 20
10
+ selse { sreturn(1) }
11
+ end
12
+
13
+ # A factiorial with very low stack depth for checking overflow.
14
+ sdef(:fact_over,2,proc { stack_overflow_error <= 1 }) do |n|
15
+ hprint("n2=",n,"\n")
16
+ sif(n > 1) { sreturn(n*fact_over(n-1)) }
17
+ selse { sreturn(1) }
18
+ end
19
+
20
+ # Checking the usage of sequencers functions.
21
+ system :my_seqencer do
22
+
23
+ inner :clk,:rst
24
+
25
+ [16].inner :val
26
+ [16].inner :res
27
+
28
+ inner stack_overflow_error: 0
29
+
30
+ sequencer(clk.posedge,rst) do
31
+ 5.stimes do |i|
32
+ val <= i
33
+ res <= fact(val)
34
+ end
35
+ hprint("Going to overflow...\n")
36
+ 4.stimes do |i|
37
+ val <= i
38
+ res <= fact_over(val)
39
+ end
40
+ hprint("stack_overflow_error=",stack_overflow_error,"\n")
41
+ end
42
+
43
+ timed do
44
+ clk <= 0
45
+ rst <= 0
46
+ !10.ns
47
+ clk <= 1
48
+ !10.ns
49
+ clk <= 0
50
+ rst <= 1
51
+ !10.ns
52
+ clk <= 1
53
+ !10.ns
54
+ clk <= 0
55
+ rst <= 0
56
+ !10.ns
57
+ clk <= 1
58
+ repeat(500) do
59
+ !10.ns
60
+ clk <= ~clk
61
+ end
62
+ end
63
+ end
data/lib/HDLRuby/hdrcc.rb CHANGED
@@ -821,7 +821,7 @@ elsif $options[:verilog] then
821
821
  $top_system.each_systemT_deep do |systemT|
822
822
  HDLRuby.show? "signal2subs step..."
823
823
  # Ensure there is not implicit assign to sub signals.
824
- systemT.signal2subs!
824
+ systemT.signal2subs!(true)
825
825
  # HDLRuby.show "casts_without_expression! step..."
826
826
  # systemT.casts_without_expression!
827
827
  # HDLRuby.show Time.now
@@ -2198,29 +2198,48 @@ module HDLRuby::High
2198
2198
  #
2199
2199
  # NOTE: a function is a short-cut for a method that creates a scope.
2200
2200
  def function(name, &ruby_block)
2201
+ warn("Construct 'function' is deprecated, use 'hdef' instead.")
2201
2202
  # Ensure there is a block.
2202
2203
  ruby_block = proc {} unless block_given?
2203
2204
  if HDLRuby::High.in_system? then
2204
2205
  define_singleton_method(name.to_sym) do |*args,&other_block|
2205
- # sub do
2206
2206
  sub(HDLRuby.uniq_name(name)) do
2207
2207
  HDLRuby::High.top_user.instance_exec(*args,*other_block,
2208
2208
  &ruby_block)
2209
- # ruby_block.call(*args)
2210
2209
  end
2211
2210
  end
2212
2211
  else
2213
2212
  define_method(name.to_sym) do |*args,&other_block|
2214
- # sub do
2215
2213
  sub(HDLRuby.uniq_name(name)) do
2216
2214
  HDLRuby::High.top_user.instance_exec(*args,*other_block,
2217
2215
  &ruby_block)
2218
- # ruby_block.call(*args,*other_block)
2219
2216
  end
2220
2217
  end
2221
2218
  end
2222
2219
  end
2223
2220
 
2221
+ # Declares a function named +name+ using +ruby_block+ as body.
2222
+ #
2223
+ # NOTE: a function is a short-cut for a method that creates a scope.
2224
+ def hdef(name, &ruby_block)
2225
+ # Ensure there is a block.
2226
+ ruby_block = proc {} unless block_given?
2227
+ if HDLRuby::High.in_system? then
2228
+ define_singleton_method(name.to_sym) do |*args,&other_block|
2229
+ sub(HDLRuby.uniq_name(name)) do
2230
+ HDLRuby::High.top_user.instance_exec(*args,*other_block,
2231
+ &ruby_block)
2232
+ end
2233
+ end
2234
+ else
2235
+ define_method(name.to_sym) do |*args,&other_block|
2236
+ sub(HDLRuby.uniq_name(name)) do
2237
+ HDLRuby::High.top_user.instance_exec(*args,*other_block,
2238
+ &ruby_block)
2239
+ end
2240
+ end
2241
+ end
2242
+ end
2224
2243
 
2225
2244
 
2226
2245
 
@@ -3134,7 +3153,6 @@ module HDLRuby::High
3134
3153
 
3135
3154
  # Converts the unary expression to HDLRuby::Low.
3136
3155
  def to_low
3137
- # return HDLRuby::Low::Cast.new(self.type.to_low,self.child.to_low)
3138
3156
  castL =HDLRuby::Low::Cast.new(self.type.to_low,self.child.to_low)
3139
3157
  # # For debugging: set the source high object
3140
3158
  # castL.properties[:low2high] = self.hdr_id
@@ -18,10 +18,24 @@ module HDLRuby::Low
18
18
  ## Extends the SystemT class with functionality for decomposing the
19
19
  # hierachical signals in the statements.
20
20
 
21
+ # # Decompose the hierarchical signals in the statements.
22
+ # def signal2subs!
23
+ # self.scope.signal2subs!
24
+ # end
25
+
21
26
  # Decompose the hierarchical signals in the statements.
22
- def signal2subs!
27
+ # If +decompose_vec2d+ is true then also decompose 2 dimension vectors
28
+ # (e.g., for Verilog HDL that does not support handling such signals
29
+ # as usual expressions).
30
+ def signal2subs!(decompose_vec2d = false)
31
+ @@decompose_vec2d = decompose_vec2d == true
23
32
  self.scope.signal2subs!
24
33
  end
34
+
35
+ ## Tell if 2d vector signals must be decomposed too.
36
+ def self.decompose_vec2d?
37
+ @@decompose_vec2d
38
+ end
25
39
  end
26
40
 
27
41
 
@@ -230,16 +244,41 @@ module HDLRuby::Low
230
244
  # from signal +sig+ and add to result to +subrefs+
231
245
  def flatten_to(sig,subrefs)
232
246
  # puts "flatten_to with sig name=#{sig.name}"
233
- # Work on the sub signals if any.
234
- sig.each_signal do |sub|
235
- # Create a reference for the sub.
236
- subref = RefName.new(sub.type,self.clone,sub.name)
237
- # Recruse on it.
238
- subref.flatten_to(sub,subrefs)
239
- # Was it a leaf?
240
- unless sub.each_signal.any? then
241
- # Yes, add its new ref to the list of subs.
242
- subrefs << subref
247
+ # Shall we decompose 2d vectors, and is the current signal
248
+ # for one of them?
249
+ if SystemT.decompose_vec2d? and sig.type.is_a?(TypeVector) and
250
+ sig.type.base.is_a?(TypeVector) then
251
+ # Is the reference used other than for a memory access?
252
+ unless self.parent.is_a?(RefIndex) then
253
+ # Yes, do the decomposition.
254
+ # Selects the direction.
255
+ rng = sig.type.range
256
+ if rng.first > rng.last then
257
+ itr = (rng.last..rng.first).each
258
+ else
259
+ itr = rng.reverse_each
260
+ end
261
+ # Iterate on each element.
262
+ itr.each do |i|
263
+ # Create a reference fo the sub.
264
+ subref = RefIndex.new(sig.type.base,self.clone,
265
+ Value.new(TypeUnsigned.new(:""),i))
266
+ # Add it.
267
+ subrefs << subref
268
+ end
269
+ end
270
+ else
271
+ # Work on the sub signals if any.
272
+ sig.each_signal do |sub|
273
+ # Create a reference for the sub.
274
+ subref = RefName.new(sub.type,self.clone,sub.name)
275
+ # Recurse on it.
276
+ subref.flatten_to(sub,subrefs)
277
+ # Was it a leaf?
278
+ unless sub.each_signal.any? then
279
+ # Yes, add its new ref to the list of subs.
280
+ subrefs << subref
281
+ end
243
282
  end
244
283
  end
245
284
  end
@@ -42,13 +42,13 @@ module HDLRuby
42
42
  elsif type.float? then
43
43
  return type
44
44
  elsif self.signed? then
45
- return self
45
+ if type.signed? then
46
+ return self.width >= type.width ? self : type
47
+ else
48
+ return self
49
+ end
46
50
  elsif type.signed? then
47
51
  return type
48
- elsif self.unsigned? then
49
- return self
50
- elsif type.unsigned? then
51
- return type
52
52
  elsif self.width >= type.width then
53
53
  return self
54
54
  else
@@ -253,6 +253,7 @@ module HDLRuby
253
253
  # Cast to +type+.
254
254
  # NOTE: nodir tells if the direction is to be ignored.
255
255
  def cast(type,nodir = false)
256
+ # puts "cast with content=#{self.content} type.signed=#{type.signed?} type.width=#{type.width}"
256
257
  # Handle the direction.
257
258
  if !nodir && type.direction != self.type.direction then
258
259
  if self.content.is_a?(Numeric) then
@@ -281,19 +282,18 @@ module HDLRuby
281
282
  res_content.positive!
282
283
  end
283
284
  end
284
- if type.signed && res_content.is_a?(Numeric) && res_content >= (1 << (type.width-1)) then
285
+ if type.signed? && res_content.is_a?(Numeric) && res_content >= (1 << (type.width-1)) then
285
286
  res_content = (-1 << type.width) + res_content
286
287
  end
287
- # # truncs to the right size if necessary.
288
- # if res_content.is_a?(BitString) then
289
- # res_content.trunc!(type.width)
290
- # else
291
- # res_content = self.trunc(res_content,type.width)
292
- # end
293
288
  # Generate the resulting value.
289
+ # puts "res_content=#{res_content}"
294
290
  return self.class.new(type,res_content)
295
291
  end
296
292
 
293
+ def as(typ)
294
+ return self.cast(typ)
295
+ end
296
+
297
297
  # Concat the content of +vals+.
298
298
  def self.concat(*vals)
299
299
  # Compute the resulting type.
@@ -89,10 +89,10 @@ module HDLRuby::Low
89
89
  # Convert the ranges to arrays.
90
90
  rngI,rngS = self.r2a(rngI), self.r2a(rngS)
91
91
  # Generate the name.
92
- return "trunc_#{rngI[0]}_#{rngI[1]}_#{rngS[0]}_#{rngS[1]}"
92
+ return "truncer_#{rngI[0]}_#{rngI[1]}_#{rngS[0]}_#{rngS[1]}"
93
93
  end
94
94
 
95
- # Generate the truncating functionds.
95
+ # Generate the truncating functions.
96
96
  def dump
97
97
  # Ensure there is only one truncating function per range.
98
98
  @truncers.sort!.uniq!
@@ -117,6 +117,53 @@ module HDLRuby::Low
117
117
  TruncersI = Truncers.new
118
118
 
119
119
 
120
+ # Class for generating the truncating functions in verilog.
121
+ # Such function are necessary as expression cannot be truncated directly.
122
+ class Indexers
123
+ def initialize
124
+ @indexers = []
125
+ end
126
+
127
+ # Add an indexer to of expression of verilog type +typI+ returning
128
+ # verilog type +typR+.
129
+ def add(typI,typR)
130
+ # Add them
131
+ @indexers << [typI,typR]
132
+ end
133
+ alias_method :<<, :add
134
+
135
+
136
+ # Generate an indexer function name for expression of verilog type
137
+ # +typI+ returning verilog type +typR+.
138
+ def indexer_name(typI,typR)
139
+ # Generate the name.
140
+ return "indexer_#{name_to_verilog(typI)}_#{name_to_verilog(typR)}"
141
+ end
142
+
143
+ # Generate the indexing functions.
144
+ def dump
145
+ # Ensure there is only one indexing function per range.
146
+ @indexers.sort!.uniq!
147
+ # Generate the resulting code.
148
+ codeT = ""
149
+ @indexers.each do |(typI,typR)|
150
+ codeT << " function #{typR} "
151
+ codeT << self.indexer_name(typI,typR)
152
+ codeT << "(input #{typI} val, input integer idx);\n"
153
+ codeT << " " << self.indexer_name(typI,typR) << " = "
154
+ codeT << "val[idx];\n"
155
+ codeT << " endfunction\n\n"
156
+ end
157
+ # Clears the indexers.
158
+ @indexers = []
159
+ return codeT
160
+ end
161
+ end
162
+
163
+ # Declaration of the truncating function generator.
164
+ IndexersI = Indexers.new
165
+
166
+
120
167
  class Binary
121
168
  ## Enhances Binary with verilog generation.
122
169
 
@@ -1479,7 +1526,16 @@ module HDLRuby::Low
1479
1526
 
1480
1527
  # Converts the system to Verilog code.
1481
1528
  def to_verilog
1482
- return "#{self.ref.to_verilog}[#{self.index.to_verilog}]"
1529
+ # return "#{self.ref.to_verilog}[#{self.index.to_verilog}]"
1530
+ if self.ref.is_a?(RefName) then
1531
+ return "#{self.ref.to_verilog}[#{self.index.to_verilog}]"
1532
+ else
1533
+ # No a pure signal, need to use a function for accessing.
1534
+ at = self.ref.type.to_verilog
1535
+ rt = self.type.to_verilog
1536
+ IndexersI.add(at,rt)
1537
+ return "#{IndexersI.indexer_name(at,rt)}(#{self.ref.to_verilog},#{self.index.to_verilog})"
1538
+ end
1483
1539
  end
1484
1540
  end
1485
1541
 
@@ -1505,7 +1561,15 @@ module HDLRuby::Low
1505
1561
 
1506
1562
  # Converts the system to Verilog code.
1507
1563
  def to_verilog(unknown = false)
1508
- return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]"
1564
+ if self.ref.is_a?(RefName) then
1565
+ return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]"
1566
+ else
1567
+ # No a pure signal, need to use a function for accessing.
1568
+ sr = self.range.first.to_i..self.range.last.to_i
1569
+ cr = (self.type.width-1)..0
1570
+ TruncersI.add(cr,sr)
1571
+ return "#{TruncersI.truncer_name(cr,sr)}(#{self.ref.to_verilog})"
1572
+ end
1509
1573
  end
1510
1574
  end
1511
1575
 
@@ -1576,20 +1640,28 @@ module HDLRuby::Low
1576
1640
  # end
1577
1641
  # return "#{self.type.range.first + 1}'b#{self.content.to_verilog}"
1578
1642
  if self.content.is_a?(Numeric) then
1579
- if self.content < 0 then
1580
- # str = (2**self.type.width + self.content).to_s(2)
1581
- str = self.content.to_s(2)
1582
- str = "0" * (self.type.width-str.length+1) + str[1..-1]
1583
- return "-#{self.type.width}'b#{str}"
1643
+ if self.type.signed? then
1644
+ if self.content < 0 then
1645
+ # str = (2**self.type.width + self.content).to_s(2)
1646
+ str = self.content.to_s(2)
1647
+ str = "0" * (self.type.width-str.length+1) + str[1..-1]
1648
+ return "-#{self.type.width}'sb#{str}"
1649
+ else
1650
+ str = self.content.to_s(2)
1651
+ str = "0" * (self.type.width-str.length) + str
1652
+ return "#{self.type.width}'sb#{str}"
1653
+ end
1584
1654
  else
1585
- str = self.content.to_s(2)
1586
- str = "0" * (self.type.width-str.length) + str
1587
- return "#{self.type.width}'b#{str}"
1655
+ return "#{self.type.width}'b#{self.content.to_s(2)}"
1588
1656
  end
1589
1657
  # return "#{self.type.width}'b#{str}"
1590
1658
  else
1591
1659
  str = self.content.to_verilog
1592
- return "#{str.length}'b#{str}"
1660
+ if self.content.negative? then
1661
+ return "#{str.length}'sb#{str}"
1662
+ else
1663
+ return "#{str.length}'b#{str}"
1664
+ end
1593
1665
  end
1594
1666
  end
1595
1667
  # How to use when simply obtaining the width
@@ -1770,10 +1842,20 @@ module HDLRuby::Low
1770
1842
  cw = self.child.type.width
1771
1843
  sw = self.type.width
1772
1844
  if self.type.signed? then
1773
- if (sw>cw) then
1774
- # Need to sign extend.
1775
- return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," +
1776
- "#{self.child.to_verilog}})"
1845
+ # Need to sign extend.
1846
+ if cw == 1 then
1847
+ return "$signed({#{sw}{#{self.child.to_verilog}}})"
1848
+ elsif (sw>cw) then
1849
+ # return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})"
1850
+ if self.child.is_a?(RefName) then
1851
+ return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})"
1852
+ else
1853
+ # No a pure signal, need to use a function for accessing.
1854
+ at = self.child.type.to_verilog
1855
+ rt = bit.to_verilog
1856
+ IndexersI.add(at,rt)
1857
+ return "$signed({{#{sw-cw}{#{IndexersI.indexer_name(at,rt)}(#{self.child.to_verilog},#{cw-1})}}," + "#{self.child.to_verilog}})"
1858
+ end
1777
1859
  elsif (sw<cw) then
1778
1860
  # Need to truncate
1779
1861
  # return "$signed(#{self.child.to_verilog}[#{sw-1}:0])"
@@ -2288,6 +2370,8 @@ module HDLRuby::Low
2288
2370
 
2289
2371
  # Adds the truncing functions.
2290
2372
  code << TruncersI.dump
2373
+ # Adds the indexing functions.
2374
+ code << IndexersI.dump
2291
2375
  # Adds the content code.
2292
2376
  code << codeC
2293
2377
  return code
@@ -1,42 +1,49 @@
1
- # Program with inverse conversion
2
- # last update 2019 01 29
3
-
4
- module HDLRuby::Verilog
5
-
6
- # This is sample.
7
- # n = "abc_ABC_いろは"
8
- # puts n
9
- # name = n.split("")
10
-
11
- @@hdr2verilog = {}
12
-
13
- # Since it is possible to use $ and numbers other than the beginning of the character string, it is divided.
14
- def name_to_verilog(name)
15
- # name = name.to_s
16
- # # Convert special characters.
17
- # name = name.each_char.map do |c|
18
- # if c=~ /[a-z0-9]/ then
19
- # c
20
- # elsif c == "_" then
21
- # "__"
22
- # else
23
- # "_" + c.ord.to_s
24
- # end
25
- # end.join
26
- # # First character: only letter is possible.
27
- # unless name[0] =~ /[a-z_]/ then
28
- # name = "_" + name
29
- # end
30
- # return name
31
- name = name.to_s
32
- vname = @@hdr2verilog[name]
33
- unless vname then
34
- vname = "_v#{@@hdr2verilog.size}_#{name.split(/[^a-zA-Z_0-9]/)[-1]}"
35
- @@hdr2verilog[name] = vname
36
- end
37
- return vname
38
- end
39
-
40
- #puts ref
41
-
42
- end
1
+ # Program with inverse conversion
2
+ # last update 2019 01 29
3
+
4
+ module HDLRuby::Verilog
5
+
6
+ # This is sample.
7
+ # n = "abc_ABC_いろは"
8
+ # puts n
9
+ # name = n.split("")
10
+
11
+ @@hdr2verilog = {}
12
+
13
+ # Since it is possible to use $ and numbers other than the beginning of the character string, it is divided.
14
+ def name_to_verilog(name)
15
+ # name = name.to_s
16
+ # # Convert special characters.
17
+ # name = name.each_char.map do |c|
18
+ # if c=~ /[a-z0-9]/ then
19
+ # c
20
+ # elsif c == "_" then
21
+ # "__"
22
+ # else
23
+ # "_" + c.ord.to_s
24
+ # end
25
+ # end.join
26
+ # # First character: only letter is possible.
27
+ # unless name[0] =~ /[a-z_]/ then
28
+ # name = "_" + name
29
+ # end
30
+ # return name
31
+ name = name.to_s
32
+ vname = @@hdr2verilog[name]
33
+ unless vname then
34
+ # Shall we change the string?
35
+ if name.match?(/^[_a-zA-Z][_a-zA-Z0-9]*$/) then
36
+ # No, just clone
37
+ vname = name.clone
38
+ else
39
+ # Yes, ensure it is a verilog-compatible name.
40
+ vname = "_v#{@@hdr2verilog.size}_#{name.split(/[^a-zA-Z_0-9]/)[-1]}"
41
+ end
42
+ @@hdr2verilog[name] = vname
43
+ end
44
+ return vname
45
+ end
46
+
47
+ #puts ref
48
+
49
+ end
@@ -219,7 +219,11 @@ module HDLRuby::High::Std
219
219
  # The default code.
220
220
  default_codes.each(&:call)
221
221
  # Depending on the state.
222
- hcase(this.cur_state_sig)
222
+ if (type == :sync) then
223
+ hcase(this.next_state_sig)
224
+ else
225
+ hcase(this.cur_state_sig)
226
+ end
223
227
  states.each do |st|
224
228
  # Register the working state (for the gotos)
225
229
  this.work_state = st
@@ -345,6 +349,11 @@ module HDLRuby::High::Std
345
349
 
346
350
 
347
351
  ## The interface for building the fsm
352
+
353
+ # Gets the current number of states.
354
+ def size
355
+ @states.size
356
+ end
348
357
 
349
358
  # Sets the event synchronizing the fsm.
350
359
  def for_event(event = nil,&ruby_block)