From 22229c23511eb0c357d85cb6c0c13146c2d47d22 Mon Sep 17 00:00:00 2001 From: Taichi Ishitani Date: Fri, 22 Nov 2024 13:06:04 +0900 Subject: [PATCH] change indirect index logic (refs: rggen/rggen#224) --- lib/rggen/systemverilog/rtl/indirect_index.rb | 42 ++++++-- .../rtl/register/type/indirect.erb | 5 +- .../rtl/register/type/indirect.rb | 4 +- .../rtl/register/sv_rtl_top_spec.rb | 10 +- .../rtl/register/type/indirect_spec.rb | 98 +++++++++---------- 5 files changed, 93 insertions(+), 66 deletions(-) diff --git a/lib/rggen/systemverilog/rtl/indirect_index.rb b/lib/rggen/systemverilog/rtl/indirect_index.rb index 896de12..8defcec 100644 --- a/lib/rggen/systemverilog/rtl/indirect_index.rb +++ b/lib/rggen/systemverilog/rtl/indirect_index.rb @@ -8,26 +8,54 @@ module IndirectIndex def index_fields @index_fields ||= - register.collect_index_fields(register_block.bit_fields) + register + .collect_index_fields(register_block.bit_fields) end - def index_width - @index_width ||= index_fields.sum(&:width) + def index_match_width + index_fields.size end def index_values + @index_values ||= collect_index_values + end + + def collect_index_values loop_variables = register.local_loop_variables register.index_entries.zip(index_fields).map do |entry, field| if entry.array_index? - loop_variables.shift[0, field.width] + array_index_value(loop_variables.shift, field.width) else - hex(entry.value, field.width) + fixed_index_value(entry.value, field.width) end end end - def indirect_index_assignment - assign(indirect_index, concat(index_fields.map(&:value))) + def array_index_value(value, width) + "#{width}'(#{value})" + end + + def fixed_index_value(value, width) + hex(value, width) + end + + def indirect_index_matches(code) + index_fields.each_with_index do |field, i| + code << assign(index_match_rhs(i), index_match_lhs(field.value, index_values[i])) + code << nl + end + end + + def index_match_rhs(index) + if index_match_width == 1 + indirect_match + else + indirect_match[index] + end + end + + def index_match_lhs(field, value) + "#{field} == #{value}" end end end diff --git a/lib/rggen/systemverilog/rtl/register/type/indirect.erb b/lib/rggen/systemverilog/rtl/register/type/indirect.erb index 3c2ec5a..f1efe1e 100644 --- a/lib/rggen/systemverilog/rtl/register/type/indirect.erb +++ b/lib/rggen/systemverilog/rtl/register/type/indirect.erb @@ -6,12 +6,11 @@ rggen_indirect_register #( .BUS_WIDTH (<%= bus_width %>), .DATA_WIDTH (<%= width %>), .VALUE_WIDTH (<%= value_width %>), - .INDIRECT_INDEX_WIDTH (<%= index_width %>), - .INDIRECT_INDEX_VALUE (<%= concat(index_values) %>) + .INDIRECT_MATCH_WIDTH (<%= index_match_width %>) ) u_register ( .i_clk (<%= register_block.clock %>), .i_rst_n (<%= register_block.reset %>), .register_if (<%= register_if %>), - .i_indirect_index (<%= indirect_index %>), + .i_indirect_match (<%= indirect_match %>), .bit_field_if (<%= bit_field_if %>) ); diff --git a/lib/rggen/systemverilog/rtl/register/type/indirect.rb b/lib/rggen/systemverilog/rtl/register/type/indirect.rb index f3bf716..73fd558 100644 --- a/lib/rggen/systemverilog/rtl/register/type/indirect.rb +++ b/lib/rggen/systemverilog/rtl/register/type/indirect.rb @@ -5,11 +5,11 @@ include RgGen::SystemVerilog::RTL::IndirectIndex build do - logic :indirect_index, { width: index_width } + logic :indirect_match, { width: index_match_width } end main_code :register do |code| - code << indirect_index_assignment << nl + indirect_index_matches(code) code << process_template end end diff --git a/spec/rggen/systemverilog/rtl/register/sv_rtl_top_spec.rb b/spec/rggen/systemverilog/rtl/register/sv_rtl_top_spec.rb index 35a9692..00e877d 100644 --- a/spec/rggen/systemverilog/rtl/register/sv_rtl_top_spec.rb +++ b/spec/rggen/systemverilog/rtl/register/sv_rtl_top_spec.rb @@ -453,10 +453,11 @@ def create_registers(&body) genvar j; for (i = 0;i < 2;++i) begin : g for (j = 0;j < 2;++j) begin : g - logic [3:0] indirect_index; + logic [1:0] indirect_match; rggen_bit_field_if #(32) bit_field_if(); `rggen_tie_off_unused_signals(32, 32'h00000303, bit_field_if) - assign indirect_index = {register_if[0].value[0+:2], register_if[0].value[8+:2]}; + assign indirect_match[0] = register_if[0].value[0+:2] == 2'(i); + assign indirect_match[1] = register_if[0].value[8+:2] == 2'(j); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -465,13 +466,12 @@ def create_registers(&body) .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (4), - .INDIRECT_INDEX_VALUE ({i[0+:2], j[0+:2]}) + .INDIRECT_MATCH_WIDTH (2) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[8+2*i+j]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); if (1) begin : g_bit_field_0 diff --git a/spec/rggen/systemverilog/rtl/register/type/indirect_spec.rb b/spec/rggen/systemverilog/rtl/register/type/indirect_spec.rb index 7eaad34..3218e93 100644 --- a/spec/rggen/systemverilog/rtl/register/type/indirect_spec.rb +++ b/spec/rggen/systemverilog/rtl/register/type/indirect_spec.rb @@ -159,25 +159,25 @@ sv_rtl.registers end - it 'logic変数#indirect_indexを持つ' do + it 'logic変数#indirect_matchを持つ' do expect(registers[4]).to have_variable( - :indirect_index, - name: 'indirect_index', data_type: :logic, width: 1 + :indirect_match, + name: 'indirect_match', data_type: :logic, width: 1 ) expect(registers[5]).to have_variable( - :indirect_index, - name: 'indirect_index', data_type: :logic, width: 2 + :indirect_match, + name: 'indirect_match', data_type: :logic, width: 1 ) expect(registers[6]).to have_variable( - :indirect_index, - name: 'indirect_index', data_type: :logic, width: 6 + :indirect_match, + name: 'indirect_match', data_type: :logic, width: 2 ) expect(registers[7]).to have_variable( - :indirect_index, - name: 'indirect_index', data_type: :logic, width: 7 + :indirect_match, + name: 'indirect_match', data_type: :logic, width: 3 ) end @@ -185,7 +185,7 @@ it 'rggen_indirect_registerをインスタンスするコードを出力する' do expect(registers[4]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[0+:1]}; + assign indirect_match = register_if[0].value[0+:1] == 1'h1; rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -194,20 +194,19 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (1), - .INDIRECT_INDEX_VALUE ({1'h1}) + .INDIRECT_MATCH_WIDTH (1) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[4]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[5]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[8+:2]}; + assign indirect_match = register_if[0].value[8+:2] == 2'(i); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -216,20 +215,20 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (2), - .INDIRECT_INDEX_VALUE ({i[0+:2]}) + .INDIRECT_MATCH_WIDTH (1) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[5+i]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[6]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[8+:2], register_if[0].value[16+:4]}; + assign indirect_match[0] = register_if[0].value[8+:2] == 2'(i); + assign indirect_match[1] = register_if[0].value[16+:4] == 4'(j); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -238,20 +237,21 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (6), - .INDIRECT_INDEX_VALUE ({i[0+:2], j[0+:4]}) + .INDIRECT_MATCH_WIDTH (2) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[7+4*i+j]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[7]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[0+:1], register_if[0].value[8+:2], register_if[0].value[16+:4]}; + assign indirect_match[0] = register_if[0].value[0+:1] == 1'h0; + assign indirect_match[1] = register_if[0].value[8+:2] == 2'(i); + assign indirect_match[2] = register_if[0].value[16+:4] == 4'(j); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -260,20 +260,19 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (7), - .INDIRECT_INDEX_VALUE ({1'h0, i[0+:2], j[0+:4]}) + .INDIRECT_MATCH_WIDTH (3) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[15+4*i+j]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[8]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[0+:1]}; + assign indirect_match = register_if[0].value[0+:1] == 1'h0; rggen_indirect_register #( .READABLE (1), .WRITABLE (0), @@ -282,20 +281,19 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (1), - .INDIRECT_INDEX_VALUE ({1'h0}) + .INDIRECT_MATCH_WIDTH (1) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[23]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[9]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[0+:1]}; + assign indirect_match = register_if[0].value[0+:1] == 1'h0; rggen_indirect_register #( .READABLE (0), .WRITABLE (1), @@ -304,20 +302,20 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (1), - .INDIRECT_INDEX_VALUE ({1'h0}) + .INDIRECT_MATCH_WIDTH (1) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[24]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[10]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[1].value[0+:2], register_if[2].value[0+:2]}; + assign indirect_match[0] = register_if[1].value[0+:2] == 2'(i); + assign indirect_match[1] = register_if[2].value[0+:2] == 2'h0; rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -326,20 +324,21 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (4), - .INDIRECT_INDEX_VALUE ({i[0+:2], 2'h0}) + .INDIRECT_MATCH_WIDTH (2) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[25+i]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[11]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[3].value[0+:1], register_if[3].value[8+:2], register_if[3].value[16+:4]}; + assign indirect_match[0] = register_if[3].value[0+:1] == 1'h0; + assign indirect_match[1] = register_if[3].value[8+:2] == 2'(i); + assign indirect_match[2] = register_if[3].value[16+:4] == 4'(j); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -348,20 +347,21 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (7), - .INDIRECT_INDEX_VALUE ({1'h0, i[0+:2], j[0+:4]}) + .INDIRECT_MATCH_WIDTH (3) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[27+4*i+j]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[12]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[0].value[0+:1], register_if[0].value[8+:2], register_if[0].value[16+:4]}; + assign indirect_match[0] = register_if[0].value[0+:1] == 1'h0; + assign indirect_match[1] = register_if[0].value[8+:2] == 2'(k); + assign indirect_match[2] = register_if[0].value[16+:4] == 4'(l); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -370,20 +370,21 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (7), - .INDIRECT_INDEX_VALUE ({1'h0, k[0+:2], l[0+:4]}) + .INDIRECT_MATCH_WIDTH (3) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[35+16*(2*i+j)+4*k+l]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE expect(registers[13]).to generate_code(:register, :top_down, <<~'CODE') `rggen_tie_off_unused_signals(32, 32'h00000001, bit_field_if) - assign indirect_index = {register_if[3].value[0+:1], register_if[3].value[8+:2], register_if[3].value[16+:4]}; + assign indirect_match[0] = register_if[3].value[0+:1] == 1'h0; + assign indirect_match[1] = register_if[3].value[8+:2] == 2'(k); + assign indirect_match[2] = register_if[3].value[16+:4] == 4'(l); rggen_indirect_register #( .READABLE (1), .WRITABLE (1), @@ -392,13 +393,12 @@ .BUS_WIDTH (32), .DATA_WIDTH (32), .VALUE_WIDTH (32), - .INDIRECT_INDEX_WIDTH (7), - .INDIRECT_INDEX_VALUE ({1'h0, k[0+:2], l[0+:4]}) + .INDIRECT_MATCH_WIDTH (3) ) u_register ( .i_clk (i_clk), .i_rst_n (i_rst_n), .register_if (register_if[35+16*(2*i+j)+8+4*k+l]), - .i_indirect_index (indirect_index), + .i_indirect_match (indirect_match), .bit_field_if (bit_field_if) ); CODE