rggen-systemverilog 0.17.0 → 0.21.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +2 -2
  4. data/lib/rggen/systemverilog/common.rb +2 -2
  5. data/lib/rggen/systemverilog/common/component.rb +2 -6
  6. data/lib/rggen/systemverilog/common/feature.rb +39 -26
  7. data/lib/rggen/systemverilog/common/utility.rb +6 -2
  8. data/lib/rggen/systemverilog/common/utility/data_object.rb +2 -2
  9. data/lib/rggen/systemverilog/common/utility/interface_instance.rb +2 -2
  10. data/lib/rggen/systemverilog/common/utility/interface_port.rb +9 -5
  11. data/lib/rggen/systemverilog/common/utility/local_scope.rb +2 -2
  12. data/lib/rggen/systemverilog/common/utility/structure_definition.rb +3 -5
  13. data/lib/rggen/systemverilog/ral.rb +4 -1
  14. data/lib/rggen/systemverilog/ral/bit_field/type.rb +15 -10
  15. data/lib/rggen/systemverilog/ral/bit_field/type/rwe_rwl.rb +1 -11
  16. data/lib/rggen/systemverilog/ral/feature.rb +5 -7
  17. data/lib/rggen/systemverilog/ral/register/type.rb +10 -52
  18. data/lib/rggen/systemverilog/ral/register/type/default.erb +1 -1
  19. data/lib/rggen/systemverilog/ral/register/type/external.rb +6 -10
  20. data/lib/rggen/systemverilog/ral/register/type/indirect.erb +3 -3
  21. data/lib/rggen/systemverilog/ral/register/type/indirect.rb +5 -2
  22. data/lib/rggen/systemverilog/ral/register_block/sv_ral_model.erb +8 -0
  23. data/lib/rggen/systemverilog/ral/register_block/sv_ral_model.rb +36 -0
  24. data/lib/rggen/systemverilog/ral/register_block/sv_ral_package.rb +1 -32
  25. data/lib/rggen/systemverilog/ral/register_common.rb +46 -0
  26. data/lib/rggen/systemverilog/ral/register_file/sv_ral_model.erb +8 -0
  27. data/lib/rggen/systemverilog/ral/register_file/sv_ral_model.rb +57 -0
  28. data/lib/rggen/systemverilog/ral/setup.rb +2 -1
  29. data/lib/rggen/systemverilog/rtl.rb +5 -2
  30. data/lib/rggen/systemverilog/rtl/bit_field/sv_rtl_top.rb +34 -19
  31. data/lib/rggen/systemverilog/rtl/bit_field/type.rb +1 -5
  32. data/lib/rggen/systemverilog/rtl/bit_field/type/rc_w0c_w1c.rb +3 -3
  33. data/lib/rggen/systemverilog/rtl/bit_field/type/ro.rb +1 -1
  34. data/lib/rggen/systemverilog/rtl/bit_field/type/rs_w0s_w1s.rb +2 -2
  35. data/lib/rggen/systemverilog/rtl/bit_field/type/{rw_wo.erb → rw_w1_wo_wo1.erb} +4 -2
  36. data/lib/rggen/systemverilog/rtl/bit_field/type/rw_w1_wo_wo1.rb +24 -0
  37. data/lib/rggen/systemverilog/rtl/bit_field/type/rwc.rb +2 -2
  38. data/lib/rggen/systemverilog/rtl/bit_field/type/rwe.rb +2 -2
  39. data/lib/rggen/systemverilog/rtl/bit_field/type/rwl.rb +2 -2
  40. data/lib/rggen/systemverilog/rtl/bit_field/type/rws.rb +3 -3
  41. data/lib/rggen/systemverilog/rtl/bit_field/type/w0crs_w1crs.rb +1 -1
  42. data/lib/rggen/systemverilog/rtl/bit_field/type/w0src_w1src.rb +1 -1
  43. data/lib/rggen/systemverilog/rtl/bit_field/type/w0trg_w1trg.rb +1 -1
  44. data/lib/rggen/systemverilog/rtl/feature.rb +12 -16
  45. data/lib/rggen/systemverilog/rtl/partial_sum.rb +29 -0
  46. data/lib/rggen/systemverilog/rtl/register/sv_rtl_top.rb +10 -47
  47. data/lib/rggen/systemverilog/rtl/register/type.rb +25 -1
  48. data/lib/rggen/systemverilog/rtl/register/type/external.rb +15 -15
  49. data/lib/rggen/systemverilog/rtl/register/type/indirect.rb +3 -3
  50. data/lib/rggen/systemverilog/rtl/register_block/protocol.rb +17 -7
  51. data/lib/rggen/systemverilog/rtl/register_block/protocol/apb.erb +9 -5
  52. data/lib/rggen/systemverilog/rtl/register_block/protocol/apb.rb +14 -15
  53. data/lib/rggen/systemverilog/rtl/register_block/protocol/axi4lite.erb +11 -6
  54. data/lib/rggen/systemverilog/rtl/register_block/protocol/axi4lite.rb +53 -30
  55. data/lib/rggen/systemverilog/rtl/register_block/sv_rtl_top.rb +11 -13
  56. data/lib/rggen/systemverilog/rtl/register_file/sv_rtl_top.rb +30 -0
  57. data/lib/rggen/systemverilog/rtl/register_index.rb +112 -0
  58. data/lib/rggen/systemverilog/rtl/setup.rb +1 -0
  59. data/lib/rggen/systemverilog/version.rb +1 -1
  60. metadata +16 -9
  61. data/lib/rggen/systemverilog/ral/register_block/sv_ral_block_model.erb +0 -11
  62. data/lib/rggen/systemverilog/rtl/bit_field/type/rw_wo.rb +0 -14
@@ -3,7 +3,7 @@
3
3
  RgGen.define_list_item_feature(:register, :type, :indirect) do
4
4
  sv_rtl do
5
5
  build do
6
- logic :register, :indirect_index, { width: index_width }
6
+ logic :indirect_index, { width: index_width }
7
7
  end
8
8
 
9
9
  main_code :register do |code|
@@ -19,11 +19,11 @@ RgGen.define_list_item_feature(:register, :type, :indirect) do
19
19
  end
20
20
 
21
21
  def index_width
22
- @index_width ||= index_fields.map(&:width).inject(:+)
22
+ @index_width ||= index_fields.map(&:width).sum
23
23
  end
24
24
 
25
25
  def index_values
26
- loop_variables = register.loop_variables
26
+ loop_variables = register.local_loop_variables
27
27
  register.index_entries.zip(index_fields).map do |entry, field|
28
28
  if entry.array_index?
29
29
  loop_variables.shift[0, field.width]
@@ -65,21 +65,27 @@ RgGen.define_list_feature(:register_block, :protocol) do
65
65
 
66
66
  base_feature do
67
67
  build do
68
- parameter :register_block, :error_status, {
68
+ parameter :address_width, {
69
+ name: 'ADDRESS_WIDTH', data_type: :int, default: local_address_width
70
+ }
71
+ parameter :pre_decode, {
72
+ name: 'PRE_DECODE', data_type: :bit, width: 1, default: 0
73
+ }
74
+ parameter :base_address, {
75
+ name: 'BASE_ADDRESS', data_type: :bit, width: address_width,
76
+ default: all_bits_0
77
+ }
78
+ parameter :error_status, {
69
79
  name: 'ERROR_STATUS', data_type: :bit, width: 1, default: 0
70
80
  }
71
- parameter :register_block, :default_read_data, {
81
+ parameter :default_read_data, {
72
82
  name: 'DEFAULT_READ_DATA', data_type: :bit, width: bus_width,
73
- default: hex(0, bus_width)
83
+ default: all_bits_0
74
84
  }
75
85
  end
76
86
 
77
87
  private
78
88
 
79
- def address_width
80
- configuration.address_width
81
- end
82
-
83
89
  def bus_width
84
90
  configuration.bus_width
85
91
  end
@@ -96,6 +102,10 @@ RgGen.define_list_feature(:register_block, :protocol) do
96
102
  register_block.total_registers
97
103
  end
98
104
 
105
+ def byte_size
106
+ register_block.byte_size
107
+ end
108
+
99
109
  def clock
100
110
  register_block.clock
101
111
  end
@@ -1,9 +1,13 @@
1
1
  rggen_apb_adapter #(
2
- .ADDRESS_WIDTH (<%= local_address_width %>),
3
- .BUS_WIDTH (<%= bus_width %>),
4
- .REGISTERS (<%= total_registers %>),
5
- .ERROR_STATUS (<%= error_status %>),
6
- .DEFAULT_READ_DATA (<%= default_read_data %>)
2
+ .ADDRESS_WIDTH (<%= address_width %>),
3
+ .LOCAL_ADDRESS_WIDTH (<%= local_address_width %>),
4
+ .BUS_WIDTH (<%= bus_width %>),
5
+ .REGISTERS (<%= total_registers %>),
6
+ .PRE_DECODE (<%= pre_decode %>),
7
+ .BASE_ADDRESS (<%= base_address %>),
8
+ .BYTE_SIZE (<%= byte_size %>),
9
+ .ERROR_STATUS (<%= error_status %>),
10
+ .DEFAULT_READ_DATA (<%= default_read_data %>)
7
11
  ) u_adapter (
8
12
  .i_clk (<%= clock %>),
9
13
  .i_rst_n (<%= reset %>),
@@ -22,42 +22,41 @@ RgGen.define_list_item_feature(:register_block, :protocol, :apb) do
22
22
  sv_rtl do
23
23
  build do
24
24
  if configuration.fold_sv_interface_port?
25
- interface_port :register_block, :apb_if, {
25
+ interface_port :apb_if, {
26
26
  name: 'apb_if', interface_type: 'rggen_apb_if', modport: 'slave'
27
27
  }
28
28
  else
29
- input :register_block, :psel, {
29
+ input :psel, {
30
30
  name: 'i_psel', data_type: :logic, width: 1
31
31
  }
32
- input :register_block, :penable, {
32
+ input :penable, {
33
33
  name: 'i_penable', data_type: :logic, width: 1
34
34
  }
35
- input :register_block, :paddr, {
35
+ input :paddr, {
36
36
  name: 'i_paddr', data_type: :logic, width: address_width
37
37
  }
38
- input :register_block, :pprot, {
38
+ input :pprot, {
39
39
  name: 'i_pprot', data_type: :logic, width: 3
40
40
  }
41
- input :register_block, :pwrite, {
41
+ input :pwrite, {
42
42
  name: 'i_pwrite', data_type: :logic, width: 1
43
43
  }
44
- input :register_block, :pstrb, {
45
- name: 'i_pstrb', data_type: :logic,
46
- width: byte_width
44
+ input :pstrb, {
45
+ name: 'i_pstrb', data_type: :logic, width: byte_width
47
46
  }
48
- input :register_block, :pwdata, {
47
+ input :pwdata, {
49
48
  name: 'i_pwdata', data_type: :logic, width: bus_width
50
49
  }
51
- output :register_block, :pready, {
50
+ output :pready, {
52
51
  name: 'o_pready', data_type: :logic, width: 1
53
52
  }
54
- output :register_block, :prdata, {
53
+ output :prdata, {
55
54
  name: 'o_prdata', data_type: :logic, width: bus_width
56
55
  }
57
- output :register_block, :pslverr, {
56
+ output :pslverr, {
58
57
  name: 'o_pslverr', data_type: :logic, width: 1
59
58
  }
60
- interface :register_block, :apb_if, {
59
+ interface :apb_if, {
61
60
  name: 'apb_if', interface_type: 'rggen_apb_if',
62
61
  parameter_values: [address_width, bus_width],
63
62
  variables: [
@@ -82,7 +81,7 @@ RgGen.define_list_item_feature(:register_block, :protocol, :apb) do
82
81
  [pready, apb_if.pready],
83
82
  [prdata, apb_if.prdata],
84
83
  [pslverr, apb_if.pslverr]
85
- ].map { |lhs, rhs| code << assign(lhs, rhs) << nl }
84
+ ].each { |lhs, rhs| code << assign(lhs, rhs) << nl }
86
85
  end
87
86
  end
88
87
  end
@@ -1,10 +1,15 @@
1
1
  rggen_axi4lite_adapter #(
2
- .ADDRESS_WIDTH (<%= local_address_width %>),
3
- .BUS_WIDTH (<%= bus_width %>),
4
- .REGISTERS (<%= total_registers %>),
5
- .ERROR_STATUS (<%= error_status %>),
6
- .DEFAULT_READ_DATA (<%= default_read_data %>),
7
- .WRITE_FIRST (<%= write_first %>)
2
+ .ID_WIDTH (<%= id_width %>),
3
+ .ADDRESS_WIDTH (<%= address_width %>),
4
+ .LOCAL_ADDRESS_WIDTH (<%= local_address_width %>),
5
+ .BUS_WIDTH (<%= bus_width %>),
6
+ .REGISTERS (<%= total_registers %>),
7
+ .PRE_DECODE (<%= pre_decode %>),
8
+ .BASE_ADDRESS (<%= base_address %>),
9
+ .BYTE_SIZE (<%= byte_size %>),
10
+ .ERROR_STATUS (<%= error_status %>),
11
+ .DEFAULT_READ_DATA (<%= default_read_data %>),
12
+ .WRITE_FIRST (<%= write_first %>)
8
13
  ) u_adapter (
9
14
  .i_clk (<%= clock %>),
10
15
  .i_rst_n (<%= reset %>),
@@ -13,83 +13,96 @@ RgGen.define_list_item_feature(:register_block, :protocol, :axi4lite) do
13
13
 
14
14
  sv_rtl do
15
15
  build do
16
- parameter :register_block, :write_first, {
17
- name: 'WRITE_FIRST',
18
- data_type: :bit,
19
- default: 1
16
+ parameter :id_width, {
17
+ name: 'ID_WIDTH', data_type: :int, default: 0
18
+ }
19
+ parameter :write_first, {
20
+ name: 'WRITE_FIRST', data_type: :bit, default: 1
20
21
  }
21
22
  if configuration.fold_sv_interface_port?
22
- interface_port :register_block, :axi4lite_if, {
23
+ interface_port :axi4lite_if, {
23
24
  name: 'axi4lite_if',
24
25
  interface_type: 'rggen_axi4lite_if', modport: 'slave'
25
26
  }
26
27
  else
27
- input :register_block, :awvalid, {
28
+ input :awvalid, {
28
29
  name: 'i_awvalid', data_type: :logic, width: 1
29
30
  }
30
- output :register_block, :awready, {
31
+ output :awready, {
31
32
  name: 'o_awready', data_type: :logic, width: 1
32
33
  }
33
- input :register_block, :awaddr, {
34
+ input :awid, {
35
+ name: 'i_awid', data_type: :logic, width: id_port_width
36
+ }
37
+ input :awaddr, {
34
38
  name: 'i_awaddr', data_type: :logic, width: address_width
35
39
  }
36
- input :register_block, :awprot, {
40
+ input :awprot, {
37
41
  name: 'i_awprot', data_type: :logic, width: 3
38
42
  }
39
- input :register_block, :wvalid, {
43
+ input :wvalid, {
40
44
  name: 'i_wvalid', data_type: :logic, width: 1
41
45
  }
42
- output :register_block, :wready, {
46
+ output :wready, {
43
47
  name: 'o_wready', data_type: :logic, width: 1
44
48
  }
45
- input :register_block, :wdata, {
49
+ input :wdata, {
46
50
  name: 'i_wdata', data_type: :logic, width: bus_width
47
51
  }
48
- input :register_block, :wstrb, {
52
+ input :wstrb, {
49
53
  name: 'i_wstrb', data_type: :logic, width: byte_width
50
54
  }
51
- output :register_block, :bvalid, {
55
+ output :bvalid, {
52
56
  name: 'o_bvalid', data_type: :logic, width: 1
53
57
  }
54
- input :register_block, :bready, {
58
+ output :bid, {
59
+ name: 'o_bid', data_type: :logic, width: id_port_width
60
+ }
61
+ input :bready, {
55
62
  name: 'i_bready', data_type: :logic, width: 1
56
63
  }
57
- output :register_block, :bresp, {
64
+ output :bresp, {
58
65
  name: 'o_bresp', data_type: :logic, width: 2
59
66
  }
60
- input :register_block, :arvalid, {
67
+ input :arvalid, {
61
68
  name: 'i_arvalid', data_type: :logic, width: 1
62
69
  }
63
- output :register_block, :arready, {
70
+ output :arready, {
64
71
  name: 'o_arready', data_type: :logic, width: 1
65
72
  }
66
- input :register_block, :araddr, {
73
+ input :arid, {
74
+ name: 'i_arid', data_type: :logic, width: id_port_width
75
+ }
76
+ input :araddr, {
67
77
  name: 'i_araddr', data_type: :logic, width: address_width
68
78
  }
69
- input :register_block, :arprot, {
79
+ input :arprot, {
70
80
  name: 'i_arprot', data_type: :logic, width: 3
71
81
  }
72
- output :register_block, :rvalid, {
82
+ output :rvalid, {
73
83
  name: 'o_rvalid', data_type: :logic, width: 1
74
84
  }
75
- input :register_block, :rready, {
85
+ input :rready, {
76
86
  name: 'i_rready', data_type: :logic, width: 1
77
87
  }
78
- output :register_block, :rdata, {
88
+ output :rid, {
89
+ name: 'o_rid', data_type: :logic, width: id_port_width
90
+ }
91
+ output :rdata, {
79
92
  name: 'o_rdata', data_type: :logic, width: bus_width
80
93
  }
81
- output :register_block, :rresp, {
94
+ output :rresp, {
82
95
  name: 'o_rresp', data_type: :logic, width: 2
83
96
  }
84
- interface :register_block, :axi4lite_if, {
97
+ interface :axi4lite_if, {
85
98
  name: 'axi4lite_if', interface_type: 'rggen_axi4lite_if',
86
- parameter_values: [address_width, bus_width],
99
+ parameter_values: [id_width, address_width, bus_width],
87
100
  variables: [
88
- 'awvalid', 'awready', 'awaddr', 'awprot',
101
+ 'awvalid', 'awready', 'awid', 'awaddr', 'awprot',
89
102
  'wvalid', 'wready', 'wdata', 'wstrb',
90
- 'bvalid', 'bready', 'bresp',
91
- 'arvalid', 'arready', 'araddr', 'arprot',
92
- 'rvalid', 'rready', 'rdata', 'rresp'
103
+ 'bvalid', 'bready', 'bid', 'bresp',
104
+ 'arvalid', 'arready', 'arid', 'araddr', 'arprot',
105
+ 'rvalid', 'rready', 'rid', 'rdata', 'rresp'
93
106
  ]
94
107
  }
95
108
  end
@@ -101,6 +114,7 @@ RgGen.define_list_item_feature(:register_block, :protocol, :axi4lite) do
101
114
  [
102
115
  [axi4lite_if.awvalid, awvalid],
103
116
  [awready, axi4lite_if.awready],
117
+ [axi4lite_if.awid, awid],
104
118
  [axi4lite_if.awaddr, awaddr],
105
119
  [axi4lite_if.awprot, awprot],
106
120
  [axi4lite_if.wvalid, wvalid],
@@ -109,17 +123,26 @@ RgGen.define_list_item_feature(:register_block, :protocol, :axi4lite) do
109
123
  [axi4lite_if.wstrb, wstrb],
110
124
  [bvalid, axi4lite_if.bvalid],
111
125
  [axi4lite_if.bready, bready],
126
+ [bid, axi4lite_if.bid],
112
127
  [bresp, axi4lite_if.bresp],
113
128
  [axi4lite_if.arvalid, arvalid],
114
129
  [arready, axi4lite_if.arready],
130
+ [axi4lite_if.arid, arid],
115
131
  [axi4lite_if.araddr, araddr],
116
132
  [axi4lite_if.arprot, arprot],
117
133
  [rvalid, axi4lite_if.rvalid],
118
134
  [axi4lite_if.rready, rready],
135
+ [rid, axi4lite_if.rid],
119
136
  [rdata, axi4lite_if.rdata],
120
137
  [rresp, axi4lite_if.rresp]
121
138
  ].each { |lhs, rhs| code << assign(lhs, rhs) << nl }
122
139
  end
123
140
  end
141
+
142
+ private
143
+
144
+ def id_port_width
145
+ "((#{id_width}>0)?#{id_width}:1)"
146
+ end
124
147
  end
125
148
  end
@@ -5,17 +5,16 @@ RgGen.define_simple_feature(:register_block, :sv_rtl_top) do
5
5
  export :total_registers
6
6
 
7
7
  build do
8
- input :register_block, :clock, {
8
+ input :clock, {
9
9
  name: 'i_clk', data_type: :logic, width: 1
10
10
  }
11
- input :register_block, :reset, {
11
+ input :reset, {
12
12
  name: 'i_rst_n', data_type: :logic, width: 1
13
13
  }
14
- interface :register_block, :register_if, {
14
+ interface :register_if, {
15
15
  name: 'register_if', interface_type: 'rggen_register_if',
16
16
  parameter_values: [address_width, bus_width, value_width],
17
- array_size: [total_registers],
18
- variables: ['value']
17
+ array_size: [total_registers], variables: ['value']
19
18
  }
20
19
  end
21
20
 
@@ -24,10 +23,7 @@ RgGen.define_simple_feature(:register_block, :sv_rtl_top) do
24
23
  end
25
24
 
26
25
  def total_registers
27
- register_block
28
- .registers
29
- .map(&:count)
30
- .inject(:+)
26
+ register_block.files_and_registers.map(&:count).sum
31
27
  end
32
28
 
33
29
  private
@@ -68,19 +64,21 @@ RgGen.define_simple_feature(:register_block, :sv_rtl_top) do
68
64
  end
69
65
 
70
66
  def parameters
71
- register_block.declarations(:register_block, :parameter)
67
+ register_block.declarations[:parameter]
72
68
  end
73
69
 
74
70
  def ports
75
- register_block.declarations(:register_block, :port)
71
+ register_block.declarations[:port]
76
72
  end
77
73
 
78
74
  def variables
79
- register_block.declarations(:register_block, :variable)
75
+ register_block.declarations[:variable]
80
76
  end
81
77
 
82
78
  def sv_module_body(code)
83
- register_block.generate_code(:register_block, :top_down, code)
79
+ { register_block: nil, register_file: 1 }.each do |kind, depth|
80
+ register_block.generate_code(code, kind, :top_down, depth)
81
+ end
84
82
  end
85
83
  end
86
84
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_simple_feature(:register_file, :sv_rtl_top) do
4
+ sv_rtl do
5
+ include RgGen::SystemVerilog::RTL::RegisterIndex
6
+
7
+ main_code :register_file do
8
+ local_scope("g_#{register_file.name}") do |scope|
9
+ scope.top_scope top_scope?
10
+ scope.loop_size loop_size
11
+ scope.body(&method(:body_code))
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def top_scope?
18
+ register_file(:upper).nil?
19
+ end
20
+
21
+ def loop_size
22
+ (register_file.array? || nil) &&
23
+ local_loop_variables.zip(register_file.array_size).to_h
24
+ end
25
+
26
+ def body_code(code)
27
+ register_file.generate_code(code, :register_file, :top_down, 1)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RgGen
4
+ module SystemVerilog
5
+ module RTL
6
+ module RegisterIndex
7
+ include PartialSum
8
+
9
+ EXPORTED_METHODS = [
10
+ :loop_variables, :local_loop_variables,
11
+ :local_index, :local_indices,
12
+ :index, :inside_roop?
13
+ ].freeze
14
+
15
+ def self.included(feature)
16
+ feature.module_eval do
17
+ EXPORTED_METHODS.each { |m| export m }
18
+
19
+ pre_build do
20
+ @base_index = files_and_registers.sum(&:count)
21
+ end
22
+ end
23
+ end
24
+
25
+ def loop_variables
26
+ (inside_roop? || nil) &&
27
+ [*upper_register_file&.loop_variables, *local_loop_variables]
28
+ end
29
+
30
+ def local_loop_variables
31
+ (component.array? || nil) &&
32
+ begin
33
+ start_depth = (upper_register_file&.loop_variables&.size || 0) + 1
34
+ Array.new(component.array_size.size) do |i|
35
+ create_identifier(loop_index(i + start_depth))
36
+ end
37
+ end
38
+ end
39
+
40
+ def local_index
41
+ (component.array? || nil) &&
42
+ local_index_coefficients
43
+ .zip(local_loop_variables)
44
+ .map { |operands| product(operands, false) }
45
+ .join('+')
46
+ end
47
+
48
+ def local_indices
49
+ [*upper_register_file&.local_indices, local_index]
50
+ end
51
+
52
+ def index(offset_or_offsets = nil)
53
+ operands = index_operands(offset_or_offsets)
54
+ partial_indices = partial_sums(operands)
55
+ if partial_indices.empty? || partial_indices.all?(&method(:integer?))
56
+ partial_indices.sum
57
+ else
58
+ partial_indices.join('+')
59
+ end
60
+ end
61
+
62
+ def inside_roop?
63
+ component.array? || upper_register_file&.inside_roop? || false
64
+ end
65
+
66
+ private
67
+
68
+ def upper_register_file
69
+ component.register_file
70
+ end
71
+
72
+ def local_index_coefficients
73
+ coefficients = []
74
+ component.array_size.reverse.inject(1) do |total, size|
75
+ coefficients.unshift(total)
76
+ total * size
77
+ end
78
+ coefficients
79
+ end
80
+
81
+ def index_operands(offset_or_offsets)
82
+ offsets = offset_or_offsets && Array(offset_or_offsets)
83
+ [
84
+ *upper_register_file&.index(offsets&.slice(0..-2)),
85
+ @base_index,
86
+ *local_register_index(offsets&.slice(-1))
87
+ ]
88
+ end
89
+
90
+ def local_register_index(offset)
91
+ (component.array? || nil) &&
92
+ begin
93
+ operands = [component.count(false), offset || local_index]
94
+ product(operands, true)
95
+ end
96
+ end
97
+
98
+ def product(operands, need_bracket)
99
+ if operands.all?(&method(:integer?))
100
+ operands.reduce(:*)
101
+ elsif operands.first == 1
102
+ operands.last
103
+ elsif need_bracket
104
+ "#{operands.first}*(#{operands.last})"
105
+ else
106
+ operands.join('*')
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end