rggen 0.7.2 → 0.8.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rggen/builtins.rb +2 -1
  3. data/lib/rggen/builtins/bit_field/type.rb +3 -5
  4. data/lib/rggen/builtins/bit_field/types/ro.rb +5 -3
  5. data/lib/rggen/builtins/bit_field/types/rw.rb +5 -3
  6. data/lib/rggen/builtins/bit_field/types/rwl_rwe.rb +5 -3
  7. data/lib/rggen/builtins/bit_field/types/w0c_w1c.erb +1 -1
  8. data/lib/rggen/builtins/bit_field/types/w0c_w1c.rb +11 -5
  9. data/lib/rggen/builtins/bit_field/types/w0s_w1s.rb +10 -6
  10. data/lib/rggen/builtins/global/array_port_format.rb +15 -0
  11. data/lib/rggen/builtins/global/unfold_sv_interface_port.rb +22 -0
  12. data/lib/rggen/builtins/register/type.rb +10 -4
  13. data/lib/rggen/builtins/register/types/external.rb +56 -5
  14. data/lib/rggen/builtins/register_block/clock_reset.rb +2 -2
  15. data/lib/rggen/builtins/register_block/host_if.rb +1 -1
  16. data/lib/rggen/builtins/register_block/host_ifs/apb.rb +44 -4
  17. data/lib/rggen/builtins/register_block/host_ifs/axi4lite.rb +76 -7
  18. data/lib/rggen/builtins/register_block/rtl_top.rb +17 -7
  19. data/lib/rggen/core_components.rb +3 -3
  20. data/lib/rggen/core_components/ral/item.rb +16 -15
  21. data/lib/rggen/core_components/rtl/component.rb +0 -4
  22. data/lib/rggen/core_components/rtl/item.rb +27 -32
  23. data/lib/rggen/core_components/verilog_utility.rb +6 -6
  24. data/lib/rggen/core_components/verilog_utility/class_definition.rb +11 -11
  25. data/lib/rggen/core_components/verilog_utility/identifier.rb +49 -17
  26. data/lib/rggen/core_components/verilog_utility/{interface_instantiation.rb → interface_instance.rb} +7 -3
  27. data/lib/rggen/core_components/verilog_utility/{interface_port_declaration.rb → interface_port.rb} +7 -3
  28. data/lib/rggen/core_components/verilog_utility/local_scope.rb +8 -4
  29. data/lib/rggen/core_components/verilog_utility/module_definition.rb +20 -9
  30. data/lib/rggen/core_components/verilog_utility/package_definition.rb +15 -23
  31. data/lib/rggen/core_components/verilog_utility/structure_definition.rb +7 -6
  32. data/lib/rggen/core_components/verilog_utility/variable.rb +115 -0
  33. data/lib/rggen/version.rb +2 -2
  34. data/rtl/compile.f +0 -3
  35. data/rtl/rggen_address_decoder.sv +2 -2
  36. data/rtl/rggen_bus_splitter.sv +2 -2
  37. data/rtl/rggen_external_register.sv +2 -2
  38. data/rtl/rggen_host_if_apb.sv +2 -2
  39. data/rtl/rggen_indirect_register.sv +3 -3
  40. data/sample/sample.json +3 -1
  41. data/sample/sample.yaml +2 -0
  42. data/sample/sample_0.sv +30 -42
  43. data/sample/sample_1.sv +13 -13
  44. data/sample/sample_setup.rb +2 -2
  45. data/setup/default.rb +2 -2
  46. metadata +7 -9
  47. data/lib/rggen/builtins/register_block/irq_controller.erb +0 -9
  48. data/lib/rggen/builtins/register_block/irq_controller.rb +0 -43
  49. data/lib/rggen/builtins/register_block/rtl_top.erb +0 -7
  50. data/lib/rggen/core_components/verilog_utility/declaration.rb +0 -76
  51. data/rtl/rggen_irq_controller.sv +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5c1f1db3a8cc427d2e94bde9851c13f2df926db959713dd2b630e7b759976b9
4
- data.tar.gz: 722aa640d20ca719816965d83b16f5b67fafc26597c8f7b2083986e1ba24ee6e
3
+ metadata.gz: 1ae419a5f6e280921fc5527d3e697856fdda719cb7b381a59f34cbb23cb6bcab
4
+ data.tar.gz: ca6ea865dd6abef639b4f171bba9899132a56ddaa3eeacffa43d003ded1e801a
5
5
  SHA512:
6
- metadata.gz: 4c2a82e29f6dfc122ed6e29f84f5730b6cdfe2c27151734f811717ea131d46ab8753e9d59a01823525bf3ef5bd67fa78dc22e9dcad868a88585a756353fd8c4e
7
- data.tar.gz: fc5ae08031cc4057fb74f09642bb5d636b599598bff26eb79f4a0fea0314711c7d65aeb0e598147d7569cde0b6da2aaa0f82eb9f5b34961f3e55ef7ae5830ef5
6
+ metadata.gz: 5e064c1d08c1dd8edc12253eecfd963b4b10da727741d66f56299732e3ac902ef35ecbdeed4b7d462e6ecdb983ee18ab237d1c7ebf5dde5fa98e326c7ee6a932
7
+ data.tar.gz: 99b98435e35e3c9b06ba268a623768ad70588dbecd16ccc9a6dd738933302cd72f36b57abbb89e547719ba3e875b0cd09c017d650bb95e38a31df0d639edb885
@@ -6,6 +6,8 @@ require_relative 'builtins/loaders/register_map/xlsx_ods_loader'
6
6
 
7
7
  require_relative 'builtins/global/address_width'
8
8
  require_relative 'builtins/global/data_width'
9
+ require_relative 'builtins/global/array_port_format'
10
+ require_relative 'builtins/global/unfold_sv_interface_port'
9
11
 
10
12
  require_relative 'builtins/bit_field/bit_assignment'
11
13
  require_relative 'builtins/bit_field/field_model'
@@ -47,7 +49,6 @@ require_relative 'builtins/register_block/default_map_creator'
47
49
  require_relative 'builtins/register_block/host_if'
48
50
  require_relative 'builtins/register_block/host_ifs/apb'
49
51
  require_relative 'builtins/register_block/host_ifs/axi4lite'
50
- require_relative 'builtins/register_block/irq_controller'
51
52
  require_relative 'builtins/register_block/name'
52
53
  require_relative 'builtins/register_block/ral_package'
53
54
  require_relative 'builtins/register_block/rtl_top'
@@ -70,10 +70,6 @@ list_item :bit_field, :type do
70
70
  def same_width
71
71
  :same_width
72
72
  end
73
-
74
- def irq?(&body)
75
- define_method(:irq?, &body)
76
- end
77
73
  end
78
74
 
79
75
  field :type
@@ -82,7 +78,6 @@ list_item :bit_field, :type do
82
78
  field :read_only? , forward_to_helper: true
83
79
  field :write_only?, forward_to_helper: true
84
80
  field :reserved? , forward_to_helper: true
85
- field :irq? , default: false
86
81
 
87
82
  class_delegator :full_width
88
83
  class_delegator :need_initial_value?
@@ -174,6 +169,9 @@ list_item :bit_field, :type do
174
169
  delegate [
175
170
  :dimensions, :index, :local_index, :loop_variables
176
171
  ] => :register
172
+ delegate [
173
+ :array_port_format
174
+ ] => :configuration
177
175
 
178
176
  available? { !bit_field.reserved? }
179
177
 
@@ -6,9 +6,11 @@ list_item :bit_field, :type, :ro do
6
6
  rtl do
7
7
  build do
8
8
  input :register_block, :value_in,
9
- name: "i_#{bit_field.name}",
10
- width: width,
11
- dimensions: dimensions
9
+ name: "i_#{bit_field.name}",
10
+ data_type: :logic,
11
+ width: width,
12
+ dimensions: dimensions,
13
+ array_format: array_port_format
12
14
  end
13
15
 
14
16
  generate_code_from_template :bit_field
@@ -7,9 +7,11 @@ list_item :bit_field, :type, :rw do
7
7
  rtl do
8
8
  build do
9
9
  output :register_block, :value_out,
10
- name: "o_#{bit_field.name}",
11
- width: width,
12
- dimensions: dimensions
10
+ name: "o_#{bit_field.name}",
11
+ data_type: :logic,
12
+ width: width,
13
+ dimensions: dimensions,
14
+ array_format: array_port_format
13
15
  end
14
16
 
15
17
  generate_code_from_template :bit_field
@@ -8,9 +8,11 @@ list_item :bit_field, :type, [:rwl, :rwe] do
8
8
  rtl do
9
9
  build do
10
10
  output :register_block, :value_out,
11
- name: "o_#{bit_field.name}",
12
- width: width,
13
- dimensions: dimensions
11
+ name: "o_#{bit_field.name}",
12
+ data_type: :logic,
13
+ width: width,
14
+ dimensions: dimensions,
15
+ array_format: array_port_format
14
16
  end
15
17
 
16
18
  generate_code_from_template :bit_field
@@ -8,5 +8,5 @@ rggen_bit_field_w01s_w01c #(
8
8
  .rst_n (<%= register_block.reset %>),
9
9
  .i_set_or_clear (<%= set[loop_variables] %>),
10
10
  .bit_field_if (<%= bit_field_sub_if %>),
11
- .o_value ()
11
+ .o_value (<%= value_out[loop_variables] %>)
12
12
  );
@@ -2,16 +2,22 @@ list_item :bit_field, :type, [:w0c, :w1c] do
2
2
  register_map do
3
3
  read_write
4
4
  need_initial_value
5
- use_reference width: same_width
6
- irq? { bit_field.has_reference? }
7
5
  end
8
6
 
9
7
  rtl do
10
8
  build do
11
9
  input :register_block, :set,
12
- name: "i_#{name}_set",
13
- width: width,
14
- dimensions: dimensions
10
+ name: "i_#{name}_set",
11
+ data_type: :logic,
12
+ width: width,
13
+ dimensions: dimensions,
14
+ array_format: array_port_format
15
+ output :register_block, :value_out,
16
+ name: "o_#{name}",
17
+ data_type: :logic,
18
+ width: width,
19
+ dimensions: dimensions,
20
+ array_format: array_port_format
15
21
  end
16
22
 
17
23
  generate_code_from_template :bit_field
@@ -7,13 +7,17 @@ list_item :bit_field, :type, [:w0s, :w1s] do
7
7
  rtl do
8
8
  build do
9
9
  output :register_block, :value_out,
10
- name: "o_#{name}",
11
- width: width,
12
- dimensions: dimensions
10
+ name: "o_#{name}",
11
+ data_type: :logic,
12
+ width: width,
13
+ dimensions: dimensions,
14
+ array_format: array_port_format
13
15
  input :register_block, :clear,
14
- name: "i_#{name}_clear",
15
- width: width,
16
- dimensions: dimensions
16
+ name: "i_#{name}_clear",
17
+ data_type: :logic,
18
+ width: width,
19
+ dimensions: dimensions,
20
+ array_format: array_port_format
17
21
  end
18
22
 
19
23
  generate_code_from_template :bit_field
@@ -0,0 +1,15 @@
1
+ simple_item :global, :array_port_format do
2
+ configuration do
3
+ field :array_port_format, default: :unpacked
4
+
5
+ input_pattern /(unpacked|vectored)/i
6
+
7
+ build do |value|
8
+ pattern_matched? || (
9
+ error 'invalid array port format; ' \
10
+ "should be 'unpacked' or 'vectored': #{value.inspect}"
11
+ )
12
+ @array_port_format = captures.first.downcase.to_sym
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ simple_item :global, :unfold_sv_interface_port do
2
+ configuration do
3
+ field :unfold_sv_interface_port?, default: false
4
+
5
+ build do |value|
6
+ @unfold_sv_interface_port =
7
+ case value
8
+ when true, false
9
+ value
10
+ when /\Atrue|on|yes\z/i
11
+ true
12
+ when /\Afalse|nil|off|no\z/i
13
+ false
14
+ else
15
+ message =
16
+ 'non boolean value; should be true/false/nil/on/off/yes/no: ' \
17
+ "#{value.inspect}"
18
+ error message
19
+ end
20
+ end
21
+ end
22
+ end
@@ -202,15 +202,21 @@ list_item :register, :type do
202
202
  actual_bit_fields.size
203
203
  end
204
204
 
205
+ def address_range
206
+ @address_range ||=
207
+ if register.array?
208
+ register.start_address..(register.start_address + byte_width - 1)
209
+ else
210
+ register.start_address..register.end_address
211
+ end
212
+ end
213
+
205
214
  def start_address
206
215
  address_code(register.start_address)
207
216
  end
208
217
 
209
218
  def end_address
210
- return address_code(register.end_address) unless register.array?
211
- address_code(
212
- register.start_address + byte_width - 1
213
- )
219
+ address_code(address_range.last)
214
220
  end
215
221
 
216
222
  def address_code(address)
@@ -6,14 +6,65 @@ list_item :register, :type, :external do
6
6
  end
7
7
 
8
8
  rtl do
9
+ delegate [:unfold_sv_interface_port?] => :configuration
10
+ delegate [:name] => :register
11
+
9
12
  build do
10
- interface_port :register_block, :bus_if,
11
- name: "#{register.name}_bus_if",
12
- type: :rggen_bus_if,
13
- modport: :master
13
+ if unfold_sv_interface_port?
14
+ output :register_block, :request,
15
+ name: "o_#{name}_request", data_type: :logic, width: 1
16
+ output :register_block, :address,
17
+ name: "o_#{name}_address", data_type: :logic, width: address_width
18
+ output :register_block, :direction,
19
+ name: "o_#{name}_direction", data_type: :logic, width: 1
20
+ output :register_block, :write_data,
21
+ name: "o_#{name}_write_data", data_type: :logic, width: data_width
22
+ output :register_block, :strobe,
23
+ name: "o_#{name}_strobe", data_type: :logic, width: data_width / 8
24
+ input :register_block, :done,
25
+ name: "i_#{name}_done", data_type: :logic, width: 1
26
+ input :register_block, :write_done,
27
+ name: "i_#{name}_write_done", data_type: :logic, width: 1
28
+ input :register_block, :read_done,
29
+ name: "i_#{name}_read_done", data_type: :logic, width: 1
30
+ input :register_block, :read_data,
31
+ name: "i_#{name}_read_data", data_type: :logic, width: data_width
32
+ input :register_block, :status,
33
+ name: "i_#{name}_status", data_type: :logic, width: 2
34
+ interface :register, :bus_if,
35
+ type: :rggen_bus_if, parameters: [address_width, data_width]
36
+
37
+ else
38
+ interface_port :register_block, :bus_if,
39
+ name: "#{name}_bus_if", type: :rggen_bus_if, modport: :master
40
+ end
14
41
  end
15
42
 
16
- generate_code_from_template :register
43
+ def address_width
44
+ Math.clog2(address_range.end - address_range.begin + 1)
45
+ end
46
+
47
+ generate_code :register do |code|
48
+ unfold_sv_interface_port? && bus_if_assignment(code)
49
+ code << process_template
50
+ end
51
+
52
+ def bus_if_assignment(code)
53
+ code << assign(request , "#{bus_if}.request" ) << nl
54
+ code << assign(address , "#{bus_if}.address" ) << nl
55
+ code << assign(direction , "#{bus_if}.direction" ) << nl
56
+ code << assign(write_data, "#{bus_if}.write_data" ) << nl
57
+ code << assign(strobe , "#{bus_if}.write_strobe") << nl
58
+ code << assign("#{bus_if}.done" , done ) << nl
59
+ code << assign("#{bus_if}.write_done", write_done ) << nl
60
+ code << assign("#{bus_if}.read_done" , read_done ) << nl
61
+ code << assign("#{bus_if}.read_data" , read_data ) << nl
62
+ code << assign("#{bus_if}.status" , casted_status) << nl
63
+ end
64
+
65
+ def casted_status
66
+ "rggen_rtl_pkg::rggen_status'(#{status})"
67
+ end
17
68
  end
18
69
 
19
70
  c_header do
@@ -1,8 +1,8 @@
1
1
  simple_item :register_block, :clock_reset do
2
2
  rtl do
3
3
  build do
4
- input :register_block, :clock, name: 'clk' , width: 1
5
- input :register_block, :reset, name: 'rst_n', width: 1
4
+ input :register_block, :clock, name: 'clk' , data_type: :logic, width: 1
5
+ input :register_block, :reset, name: 'rst_n', data_type: :logic, width: 1
6
6
  end
7
7
  end
8
8
  end
@@ -41,7 +41,7 @@ list_item :register_block, :host_if do
41
41
 
42
42
  item_base do
43
43
  delegate [:local_address_width, :clock, :reset] => :register_block
44
- delegate [:data_width] => :configuration
44
+ delegate [:data_width, :unfold_sv_interface_port?] => :configuration
45
45
 
46
46
  build do
47
47
  interface :register_block, :register_if,
@@ -14,11 +14,51 @@ list_item :register_block, :host_if, :apb do
14
14
 
15
15
  rtl do
16
16
  build do
17
- interface_port :register_block, :apb_if,
18
- type: :rggen_apb_if,
19
- modport: :slave
17
+ if unfold_sv_interface_port?
18
+ input :register_block, :psel,
19
+ name: 'i_psel', data_type: :logic, width: 1
20
+ input :register_block, :penable,
21
+ name: 'i_penable', data_type: :logic, width: 1
22
+ input :register_block, :paddr,
23
+ name: 'i_paddr', data_type: :logic, width: local_address_width
24
+ input :register_block, :pprot,
25
+ name: 'i_pprot', data_type: :logic, width: 3
26
+ input :register_block, :pwrite,
27
+ name: 'i_pwrite', data_type: :logic, width: 1
28
+ input :register_block, :pwdata,
29
+ name: 'i_pwdata', data_type: :logic, width: data_width
30
+ input :register_block, :pstrb,
31
+ name: 'i_pstrb', data_type: :logic, width: data_width / 8
32
+ output :register_block, :pready,
33
+ name: 'o_pready', data_type: :logic, width: 1
34
+ output :register_block, :prdata,
35
+ name: 'o_prdata', data_type: :logic, width: data_width
36
+ output :register_block, :pslverr,
37
+ name: 'o_pslverr', data_type: :logic, width: 1
38
+ interface :register_block, :apb_if,
39
+ type: :rggen_apb_if, parameters: [local_address_width, data_width]
40
+ else
41
+ interface_port :register_block, :apb_if,
42
+ type: :rggen_apb_if, modport: :slave
43
+ end
44
+ end
45
+
46
+ generate_code :register_block do |code|
47
+ unfold_sv_interface_port? && apb_if_assignment(code)
48
+ code << process_template
20
49
  end
21
50
 
22
- generate_code_from_template :register_block
51
+ def apb_if_assignment(code)
52
+ code << assign("#{apb_if}.psel" , psel ) << nl
53
+ code << assign("#{apb_if}.penable", penable) << nl
54
+ code << assign("#{apb_if}.paddr" , paddr ) << nl
55
+ code << assign("#{apb_if}.pprot" , pprot ) << nl
56
+ code << assign("#{apb_if}.pwrite" , pwrite ) << nl
57
+ code << assign("#{apb_if}.pwdata" , pwdata ) << nl
58
+ code << assign("#{apb_if}.pstrb" , pstrb ) << nl
59
+ code << assign(pready , "#{apb_if}.pready" ) << nl
60
+ code << assign(prdata , "#{apb_if}.prdata" ) << nl
61
+ code << assign(pslverr, "#{apb_if}.pslverr") << nl
62
+ end
23
63
  end
24
64
  end
@@ -11,14 +11,83 @@ list_item :register_block, :host_if, :axi4lite do
11
11
  rtl do
12
12
  build do
13
13
  parameter :register_block, :access_priority,
14
- name: 'ACCESS_PRIORITY',
15
- data_type: :'rggen_rtl_pkg::rggen_direction',
16
- default: :'rggen_rtl_pkg::RGGEN_WRITE'
17
- interface_port :register_block, :axi4lite_if,
18
- type: :rggen_axi4lite_if,
19
- modport: :slave
14
+ name: 'ACCESS_PRIORITY',
15
+ data_type: :'rggen_rtl_pkg::rggen_direction',
16
+ default: :'rggen_rtl_pkg::RGGEN_WRITE'
17
+ if unfold_sv_interface_port?
18
+ input :register_block, :awvalid,
19
+ name: 'i_awvalid', data_type: :logic, width: 1
20
+ output :register_block, :awready,
21
+ name: 'o_awready', data_type: :logic, width: 1
22
+ input :register_block, :awaddr,
23
+ name: 'i_awaddr', data_type: :logic, width: local_address_width
24
+ input :register_block, :awprot,
25
+ name: 'i_awprot', data_type: :logic, width: 3
26
+ input :register_block, :wvalid,
27
+ name: 'i_wvalid', data_type: :logic, width: 1
28
+ output :register_block, :wready,
29
+ name: 'o_wready', data_type: :logic, width: 1
30
+ input :register_block, :wdata,
31
+ name: 'i_wdata', data_type: :logic, width: data_width
32
+ input :register_block, :wstrb,
33
+ name: 'i_wstrb', data_type: :logic, width: data_width / 8
34
+ output :register_block, :bvalid,
35
+ name: 'o_bvalid', data_type: :logic, width: 1
36
+ input :register_block, :bready,
37
+ name: 'i_bready', data_type: :logic, width: 1
38
+ output :register_block, :bresp,
39
+ name: 'o_bresp', data_type: :logic, width: 2
40
+ input :register_block, :arvalid,
41
+ name: 'i_arvalid', data_type: :logic, width: 1
42
+ output :register_block, :arready,
43
+ name: 'o_arready', data_type: :logic, width: 1
44
+ input :register_block, :araddr,
45
+ name: 'i_araddr', data_type: :logic, width: local_address_width
46
+ input :register_block, :arprot,
47
+ name: 'i_arprot', data_type: :logic, width: 3
48
+ output :register_block, :rvalid,
49
+ name: 'o_rvalid', data_type: :logic, width: 1
50
+ input :register_block, :rready,
51
+ name: 'i_rready', data_type: :logic, width: 1
52
+ output :register_block, :rdata,
53
+ name: 'o_rdata', data_type: :logic, width: data_width
54
+ output :register_block, :rresp,
55
+ name: 'o_rresp', data_type: :logic, width: 2
56
+ interface :register_block, :axi4lite_if,
57
+ type: :rggen_axi4lite_if,
58
+ parameters: [local_address_width, data_width]
59
+ else
60
+ interface_port :register_block, :axi4lite_if,
61
+ type: :rggen_axi4lite_if,
62
+ modport: :slave
63
+ end
64
+ end
65
+
66
+ generate_code :register_block do |code|
67
+ unfold_sv_interface_port? && axi4lite_if_assignment(code)
68
+ code << process_template
20
69
  end
21
70
 
22
- generate_code_from_template :register_block
71
+ def axi4lite_if_assignment(code)
72
+ code << assign("#{axi4lite_if}.awvalid", awvalid) << nl
73
+ code << assign(awready, "#{axi4lite_if}.awready") << nl
74
+ code << assign("#{axi4lite_if}.awaddr" , awaddr ) << nl
75
+ code << assign("#{axi4lite_if}.awprot" , awprot ) << nl
76
+ code << assign("#{axi4lite_if}.wvalid" , wvalid ) << nl
77
+ code << assign(wready , "#{axi4lite_if}.wready" ) << nl
78
+ code << assign("#{axi4lite_if}.wdata" , wdata ) << nl
79
+ code << assign("#{axi4lite_if}.wstrb" , wstrb ) << nl
80
+ code << assign(bvalid , "#{axi4lite_if}.bvalid" ) << nl
81
+ code << assign("#{axi4lite_if}.bready" , bready ) << nl
82
+ code << assign(bresp , "#{axi4lite_if}.bresp" ) << nl
83
+ code << assign("#{axi4lite_if}.arvalid", arvalid) << nl
84
+ code << assign(arready, "#{axi4lite_if}.arready") << nl
85
+ code << assign("#{axi4lite_if}.araddr" , araddr ) << nl
86
+ code << assign("#{axi4lite_if}.arprot" , arprot ) << nl
87
+ code << assign(rvalid , "#{axi4lite_if}.rvalid" ) << nl
88
+ code << assign("#{axi4lite_if}.rready" , rready ) << nl
89
+ code << assign(rdata , "#{axi4lite_if}.rdata" ) << nl
90
+ code << assign(rresp , "#{axi4lite_if}.rresp" ) << nl
91
+ end
23
92
  end
24
93
  end