diff --git a/lib/rggen/veryl.rb b/lib/rggen/veryl.rb index c95bb38..ed5ec77 100644 --- a/lib/rggen/veryl.rb +++ b/lib/rggen/veryl.rb @@ -22,6 +22,18 @@ end plugin.files [ + 'veryl/register_block/veryl_top', + 'veryl/register_block/protocol', + 'veryl/register_block/protocol/apb', + 'veryl/register_block/protocol/axi4lite', + 'veryl/register_block/protocol/wishbone', + 'veryl/register_file/veryl_top', + 'veryl/register/veryl_top', + 'veryl/register/type', + 'veryl/register/type/external', + 'veryl/register/type/indirect', + 'veryl/register/type/rw', + 'veryl/bit_field/veryl_top', 'veryl/bit_field/type', 'veryl/bit_field/type/custom', 'veryl/bit_field/type/rc_w0c_w1c_wc_woc', @@ -40,18 +52,6 @@ 'veryl/bit_field/type/w0t_w1t', 'veryl/bit_field/type/w0trg_w1trg', 'veryl/bit_field/type/wo_wo1_wotrg', - 'veryl/bit_field/type/wrc_wrs', - 'veryl/bit_field/veryl_top', - 'veryl/register/type', - 'veryl/register/type/external', - 'veryl/register/type/indirect', - 'veryl/register/type/rw', - 'veryl/register/veryl_top', - 'veryl/register_file/veryl_top', - 'veryl/register_block/protocol', - 'veryl/register_block/protocol/apb', - 'veryl/register_block/protocol/axi4lite', - 'veryl/register_block/protocol/wishbone', - 'veryl/register_block/veryl_top' + 'veryl/bit_field/type/wrc_wrs' ] end diff --git a/lib/rggen/veryl/bit_field/type/rws.erb b/lib/rggen/veryl/bit_field/type/rws.erb index 3f8710a..206a1cf 100644 --- a/lib/rggen/veryl/bit_field/type/rws.erb +++ b/lib/rggen/veryl/bit_field/type/rws.erb @@ -2,7 +2,7 @@ inst u_bit_field: rggen_bit_field #( WIDTH: <%= width %>, INITIAL_VALUE: <%= initial_value %>, HW_SET_WIDTH: 1 -) u_bit_field ( +)( i_clk: <%= clock %>, i_rst: <%= reset %>, bit_field_if: <%= bit_field_if %>, diff --git a/lib/rggen/veryl/register_block/protocol.rb b/lib/rggen/veryl/register_block/protocol.rb index 4dd3c12..840cf76 100644 --- a/lib/rggen/veryl/register_block/protocol.rb +++ b/lib/rggen/veryl/register_block/protocol.rb @@ -13,13 +13,13 @@ name: 'PRE_DECODE', type: :bit, default: 0 } param :base_address, { - name: 'BASE_ADDRESS', type: :bit, width: address_width, default: 0 + name: 'BASE_ADDRESS', type: :bit, width: address_width, default: all_bits_0 } param :error_status, { name: 'ERROR_STATUS', type: :bit, default: 0 } param :default_read_data, { - name: 'DEFAULT_READ_DATA', type: :bit, width: bus_width, default: 0 + name: 'DEFAULT_READ_DATA', type: :bit, width: bus_width, default: all_bits_0 } param :insert_slicer, { name: 'INSERT_SLICER', type: :bit, default: 0 diff --git a/lib/rggen/veryl/register_block/veryl_top.rb b/lib/rggen/veryl/register_block/veryl_top.rb index d43204a..ffcc062 100644 --- a/lib/rggen/veryl/register_block/veryl_top.rb +++ b/lib/rggen/veryl/register_block/veryl_top.rb @@ -20,6 +20,18 @@ register_block.files_and_registers.sum(&:count) end + write_file '<%= register_block.name %>.veryl' do |f| + f.body do |code| + code << module_definition(register_block.name) do |m| + m.package_imports packages + m.params params + m.ports ports + m.variables variables + m.body { |c| body_code(c) } + end + end + end + private def param_values @@ -33,5 +45,27 @@ def address_width def bus_width configuration.bus_width end + + def packages + ['rggen_rtl_pkg', *register_block.package_imports(:register_block)] + end + + def params + register_block.declarations[:parameter] + end + + def ports + register_block.declarations[:port] + end + + def variables + register_block.declarations[:variable] + end + + def body_code(code) + { register_block: nil, register_file: 1 }.each do |kind, depth| + register_block.generate_code(code, kind, :top_down, depth) + end + end end end diff --git a/lib/rggen/veryl/utility/data_object.rb b/lib/rggen/veryl/utility/data_object.rb index 34d7ecf..cd43d44 100644 --- a/lib/rggen/veryl/utility/data_object.rb +++ b/lib/rggen/veryl/utility/data_object.rb @@ -53,13 +53,23 @@ def direction_keyword end def type_declaration - if width || array_size - "#{type}<#{[*array_size, width].compact.join(', ')}>" + if emit_width? || array_size + "#{type}<#{array_dimensions.join(', ')}>" else type end end + def emit_width? + width && (!width.is_a?(Integer) || width >= 2) + end + + def array_dimensions + dimensions = Array(array_size) + dimensions << width if emit_width? + dimensions + end + def default_value "= #{default}" if @object_type in :param | :const end diff --git a/lib/rggen/veryl/utility/modport.rb b/lib/rggen/veryl/utility/modport.rb index 27567e4..c902196 100644 --- a/lib/rggen/veryl/utility/modport.rb +++ b/lib/rggen/veryl/utility/modport.rb @@ -6,8 +6,8 @@ module Utility class Modport < SystemVerilog::Common::Utility::InterfacePort def declaration [ - 'modport', "#{name}:", + 'modport', port_type ].join(' ') end diff --git a/spec/rggen/veryl/bit_field/type/rws_spec.rb b/spec/rggen/veryl/bit_field/type/rws_spec.rb index 3ec1daa..db43fee 100644 --- a/spec/rggen/veryl/bit_field/type/rws_spec.rb +++ b/spec/rggen/veryl/bit_field/type/rws_spec.rb @@ -294,7 +294,7 @@ WIDTH: 1, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -317,7 +317,7 @@ WIDTH: 1, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -340,7 +340,7 @@ WIDTH: 2, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -363,7 +363,7 @@ WIDTH: 2, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -386,7 +386,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -409,7 +409,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -432,7 +432,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -455,7 +455,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -478,7 +478,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -501,7 +501,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -524,7 +524,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, @@ -547,7 +547,7 @@ WIDTH: 4, INITIAL_VALUE: INITIAL_VALUE, HW_SET_WIDTH: 1 - ) u_bit_field ( + )( i_clk: i_clk, i_rst: i_rst, bit_field_if: bit_field_sub_if, diff --git a/spec/rggen/veryl/bit_field/veryl_top_spec.rb b/spec/rggen/veryl/bit_field/veryl_top_spec.rb index d770d6e..0a3db66 100644 --- a/spec/rggen/veryl/bit_field/veryl_top_spec.rb +++ b/spec/rggen/veryl/bit_field/veryl_top_spec.rb @@ -369,7 +369,7 @@ def create_bit_fields(&body) expect(bit_fields[0]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -442,7 +442,7 @@ def create_bit_fields(&body) expect(bit_fields[2]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_2 { for i in 0..2 :g { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -554,7 +554,7 @@ def create_bit_fields(&body) expect(bit_fields[5]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -627,7 +627,7 @@ def create_bit_fields(&body) expect(bit_fields[7]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_2 { for j in 0..2 :g { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -739,7 +739,7 @@ def create_bit_fields(&body) expect(bit_fields[10]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -812,7 +812,7 @@ def create_bit_fields(&body) expect(bit_fields[12]).to generate_code(:register, :top_down, <<~'VERYL') :g_bit_field_2 { for k in 0..2 :g { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; diff --git a/spec/rggen/veryl/register/veryl_top_spec.rb b/spec/rggen/veryl/register/veryl_top_spec.rb index d779250..39b890a 100644 --- a/spec/rggen/veryl/register/veryl_top_spec.rb +++ b/spec/rggen/veryl/register/veryl_top_spec.rb @@ -486,8 +486,8 @@ def create_registers(&body) :g_register_4 { for i in 0..2 :g { for j in 0..2 :g { - var indirect_match: logic<2>; inst bit_field_if: rggen_bit_field_if#(WIDTH: 32); + var indirect_match: logic<2>; assign indirect_match[0] = register_if[0].value[0+:2] == (i as 2); assign indirect_match[1] = register_if[0].value[8+:2] == (j as 2); inst u_register: rggen_indirect_register #( diff --git a/spec/rggen/veryl/register_block/protocol_spec.rb b/spec/rggen/veryl/register_block/protocol_spec.rb index 43c42c4..45adf8e 100644 --- a/spec/rggen/veryl/register_block/protocol_spec.rb +++ b/spec/rggen/veryl/register_block/protocol_spec.rb @@ -48,7 +48,7 @@ expect(veryl) .to have_param( :base_address, - name: 'BASE_ADDRESS', type: :bit, width: 'ADDRESS_WIDTH', default: 0 + name: 'BASE_ADDRESS', type: :bit, width: 'ADDRESS_WIDTH', default: "'0" ) expect(veryl) .to have_param( @@ -58,7 +58,7 @@ expect(veryl) .to have_param( :default_read_data, - name: 'DEFAULT_READ_DATA', type: :bit, width: bus_width, default: 0 + name: 'DEFAULT_READ_DATA', type: :bit, width: bus_width, default: "'0" ) expect(veryl) .to have_param( diff --git a/spec/rggen/veryl/register_block/veryl_top_spec.rb b/spec/rggen/veryl/register_block/veryl_top_spec.rb index 0edb5e0..23f84ac 100644 --- a/spec/rggen/veryl/register_block/veryl_top_spec.rb +++ b/spec/rggen/veryl/register_block/veryl_top_spec.rb @@ -162,4 +162,44 @@ def create_register_block(&body) expect(register_block.register_if[0].value).to match_identifier('register_if[0].value') end end + + describe '#write_file' do + before do + allow(FileUtils).to receive(:mkpath) + end + + let(:configuration) do + file = ['config.json', 'config.toml', 'config.yml'].sample + path = File.join(RGGEN_SAMPLE_DIRECTORY, file) + build_configuration_factory(RgGen.builder, false).create([path]) + end + + let(:register_map) do + file_0 = ['block_0.rb', 'block_0.toml', 'block_0.yml'].sample + file_1 = ['block_1.rb', 'block_1.toml', 'block_1.yml'].sample + path = [file_0, file_1].map { |file| File.join(RGGEN_SAMPLE_DIRECTORY, file) } + build_register_map_factory(RgGen.builder, false).create(configuration, path) + end + + let(:register_blocks) do + build_veryl_factory(RgGen.builder).create(configuration, register_map).register_blocks + end + + let(:expected_code) do + [ + File.join(RGGEN_SAMPLE_DIRECTORY, 'block_0.veryl'), + File.join(RGGEN_SAMPLE_DIRECTORY, 'block_1.veryl') + ].map { |path| File.binread(path) } + end + + it 'RTLのソースファイルを書き出す' do + expect { + register_blocks[0].write_file('foo') + }.to write_file match_string('foo/block_0.veryl'), expected_code[0] + + expect { + register_blocks[1].write_file('bar') + }.to write_file match_string('bar/block_1.veryl'), expected_code[1] + end + end end diff --git a/spec/rggen/veryl/register_file/veryl_top_spec.rb b/spec/rggen/veryl/register_file/veryl_top_spec.rb index 6e1f66b..87e714e 100644 --- a/spec/rggen/veryl/register_file/veryl_top_spec.rb +++ b/spec/rggen/veryl/register_file/veryl_top_spec.rb @@ -124,7 +124,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -175,7 +175,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -232,7 +232,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -284,7 +284,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -345,7 +345,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -401,7 +401,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -464,7 +464,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; @@ -518,7 +518,7 @@ def create_register_files(&body) bit_field_if: bit_field_if ); :g_bit_field_0 { - const INITIAL_VALUE: bit<1> = 1'h0; + const INITIAL_VALUE: bit = 1'h0; inst bit_field_sub_if: rggen_bit_field_if#(WIDTH: 1); always_comb { bit_field_sub_if.valid = bit_field_if.valid; diff --git a/spec/rggen/veryl/utility/data_object_spec.rb b/spec/rggen/veryl/utility/data_object_spec.rb index be24965..23f5934 100644 --- a/spec/rggen/veryl/utility/data_object_spec.rb +++ b/spec/rggen/veryl/utility/data_object_spec.rb @@ -30,6 +30,7 @@ def data_object(name, &block) context '変数の場合' do it '変数宣言を返す' do expect(var('foo')).to match_declaration('var foo: logic') + expect(var('foo') { |o| o.width 1 }).to match_declaration('var foo: logic') expect(var('foo') { |o| o.width 2 }).to match_declaration('var foo: logic<2>') expect(var('foo') { |o| o.width 'WIDTH' }).to match_declaration('var foo: logic') diff --git a/spec/rggen/veryl/utility/modport_spec.rb b/spec/rggen/veryl/utility/modport_spec.rb index 7ca3058..2e425b7 100644 --- a/spec/rggen/veryl/utility/modport_spec.rb +++ b/spec/rggen/veryl/utility/modport_spec.rb @@ -12,17 +12,17 @@ def modport(if_type, name, attributes = {}, &block) describe '#declaration' do it 'modportの宣言を返す' do expect(modport(:foo_if, :foo, modport: :slave)) - .to match_declaration('modport foo: foo_if::slave') + .to match_declaration('foo: modport foo_if::slave') expect(modport(:foo_if, :foo, modport: [:slave, :bar, :baz])) - .to match_declaration('modport foo: foo_if::slave') + .to match_declaration('foo: modport foo_if::slave') expect(modport(:foo_if, :foo, modport: :slave, array_size: [2])) - .to match_declaration('modport foo: foo_if::slave[2]') + .to match_declaration('foo: modport foo_if::slave[2]') expect(modport(:foo_if, :foo, modport: [:slave, :bar, :baz], array_size: [2])) - .to match_declaration('modport foo: foo_if::slave[2]') + .to match_declaration('foo: modport foo_if::slave[2]') expect(modport(:foo_if, :foo, modport: :slave, array_size: [2, 3])) - .to match_declaration('modport foo: foo_if::slave[2, 3]') + .to match_declaration('foo: modport foo_if::slave[2, 3]') expect(modport(:foo_if, :foo, modport: [:slave, :bar, :baz], array_size: [2, 3])) - .to match_declaration('modport foo: foo_if::slave[2, 3]') + .to match_declaration('foo: modport foo_if::slave[2, 3]') end end end