rggen 0.3.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +91 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/LICENSE.txt +21 -0
- data/README.md +31 -0
- data/bin/rggen +6 -0
- data/lib/rggen/base/component.rb +27 -0
- data/lib/rggen/base/component_factory.rb +46 -0
- data/lib/rggen/base/hierarchical_accessors.rb +87 -0
- data/lib/rggen/base/hierarchical_item_accessors.rb +79 -0
- data/lib/rggen/base/item.rb +24 -0
- data/lib/rggen/base/item_factory.rb +20 -0
- data/lib/rggen/builder/builder.rb +69 -0
- data/lib/rggen/builder/category.rb +52 -0
- data/lib/rggen/builder/component_entry.rb +50 -0
- data/lib/rggen/builder/component_store.rb +42 -0
- data/lib/rggen/builder/input_component_store.rb +25 -0
- data/lib/rggen/builder/item_store.rb +89 -0
- data/lib/rggen/builder/list_item_entry.rb +81 -0
- data/lib/rggen/builder/output_component_store.rb +13 -0
- data/lib/rggen/builder/simple_item_entry.rb +33 -0
- data/lib/rggen/builtins/bit_field/bit_assignment.rb +39 -0
- data/lib/rggen/builtins/bit_field/field_model_creation.rb +25 -0
- data/lib/rggen/builtins/bit_field/field_model_declaration.rb +9 -0
- data/lib/rggen/builtins/bit_field/initial_value.rb +36 -0
- data/lib/rggen/builtins/bit_field/name.rb +26 -0
- data/lib/rggen/builtins/bit_field/reference.rb +42 -0
- data/lib/rggen/builtins/bit_field/reserved.rb +9 -0
- data/lib/rggen/builtins/bit_field/ro.rb +19 -0
- data/lib/rggen/builtins/bit_field/rw.erb +13 -0
- data/lib/rggen/builtins/bit_field/rw.rb +25 -0
- data/lib/rggen/builtins/bit_field/type.rb +205 -0
- data/lib/rggen/builtins/bit_field/wo.rb +5 -0
- data/lib/rggen/builtins/global/address_width.rb +17 -0
- data/lib/rggen/builtins/global/data_width.rb +20 -0
- data/lib/rggen/builtins/loaders/configuration/json_loader.rb +7 -0
- data/lib/rggen/builtins/loaders/configuration/yaml_loader.rb +7 -0
- data/lib/rggen/builtins/loaders/register_map/csv_loader.rb +14 -0
- data/lib/rggen/builtins/loaders/register_map/xls_loader.rb +19 -0
- data/lib/rggen/builtins/loaders/register_map/xlsx_ods_loader.rb +24 -0
- data/lib/rggen/builtins/register/accessibility.rb +23 -0
- data/lib/rggen/builtins/register/address_decoder.erb +16 -0
- data/lib/rggen/builtins/register/address_decoder.rb +92 -0
- data/lib/rggen/builtins/register/array.rb +133 -0
- data/lib/rggen/builtins/register/field_model_creator.rb +10 -0
- data/lib/rggen/builtins/register/field_model_declarations.rb +7 -0
- data/lib/rggen/builtins/register/name.rb +26 -0
- data/lib/rggen/builtins/register/offset_address.rb +55 -0
- data/lib/rggen/builtins/register/read_data.rb +36 -0
- data/lib/rggen/builtins/register/reg_model_constructor.rb +17 -0
- data/lib/rggen/builtins/register/reg_model_creation.rb +64 -0
- data/lib/rggen/builtins/register/reg_model_declaration.rb +13 -0
- data/lib/rggen/builtins/register/reg_model_definition.rb +22 -0
- data/lib/rggen/builtins/register/shadow.rb +130 -0
- data/lib/rggen/builtins/register/shadow_index_configurator.rb +53 -0
- data/lib/rggen/builtins/register/uniqueness_validator.rb +48 -0
- data/lib/rggen/builtins/register_block/apb.erb +27 -0
- data/lib/rggen/builtins/register_block/apb.rb +20 -0
- data/lib/rggen/builtins/register_block/base_address.rb +64 -0
- data/lib/rggen/builtins/register_block/block_model_constructor.rb +14 -0
- data/lib/rggen/builtins/register_block/block_model_default_map_creator.rb +39 -0
- data/lib/rggen/builtins/register_block/block_model_definition.rb +18 -0
- data/lib/rggen/builtins/register_block/byte_size.rb +37 -0
- data/lib/rggen/builtins/register_block/clock_reset.rb +8 -0
- data/lib/rggen/builtins/register_block/host_if.rb +46 -0
- data/lib/rggen/builtins/register_block/module_definition.rb +13 -0
- data/lib/rggen/builtins/register_block/name.rb +26 -0
- data/lib/rggen/builtins/register_block/ral_package_definition.rb +19 -0
- data/lib/rggen/builtins/register_block/reg_model_creator.rb +14 -0
- data/lib/rggen/builtins/register_block/reg_model_declarations.rb +7 -0
- data/lib/rggen/builtins/register_block/response_mux.erb +14 -0
- data/lib/rggen/builtins/register_block/response_mux.rb +16 -0
- data/lib/rggen/builtins/register_block/signal_declarations.rb +9 -0
- data/lib/rggen/builtins.rb +52 -0
- data/lib/rggen/commands.rb +23 -0
- data/lib/rggen/core_components/configuration/configuration_factory.rb +23 -0
- data/lib/rggen/core_components/configuration/item_factory.rb +13 -0
- data/lib/rggen/core_components/configuration/raise_error.rb +11 -0
- data/lib/rggen/core_components/configuration/setup.rb +14 -0
- data/lib/rggen/core_components/ral/item.rb +16 -0
- data/lib/rggen/core_components/ral/setup.rb +19 -0
- data/lib/rggen/core_components/register_map/bit_field_factory.rb +11 -0
- data/lib/rggen/core_components/register_map/component.rb +12 -0
- data/lib/rggen/core_components/register_map/generic_map.rb +69 -0
- data/lib/rggen/core_components/register_map/item.rb +22 -0
- data/lib/rggen/core_components/register_map/item_factory.rb +13 -0
- data/lib/rggen/core_components/register_map/loader.rb +13 -0
- data/lib/rggen/core_components/register_map/raise_error.rb +17 -0
- data/lib/rggen/core_components/register_map/register_block_factory.rb +29 -0
- data/lib/rggen/core_components/register_map/register_factory.rb +18 -0
- data/lib/rggen/core_components/register_map/register_map_factory.rb +21 -0
- data/lib/rggen/core_components/register_map/setup.rb +33 -0
- data/lib/rggen/core_components/rtl/component.rb +28 -0
- data/lib/rggen/core_components/rtl/item.rb +83 -0
- data/lib/rggen/core_components/rtl/setup.rb +19 -0
- data/lib/rggen/core_components.rb +23 -0
- data/lib/rggen/core_extensions/facets.rb +17 -0
- data/lib/rggen/core_extensions/forwardable.rb +26 -0
- data/lib/rggen/core_extensions/integer.rb +5 -0
- data/lib/rggen/core_extensions/math.rb +7 -0
- data/lib/rggen/exceptions.rb +22 -0
- data/lib/rggen/generator.rb +185 -0
- data/lib/rggen/input_base/component.rb +19 -0
- data/lib/rggen/input_base/component_factory.rb +58 -0
- data/lib/rggen/input_base/item.rb +170 -0
- data/lib/rggen/input_base/item_factory.rb +13 -0
- data/lib/rggen/input_base/loader.rb +14 -0
- data/lib/rggen/input_base/regexp_patterns.rb +29 -0
- data/lib/rggen/output_base/code_block.rb +72 -0
- data/lib/rggen/output_base/code_utility.rb +44 -0
- data/lib/rggen/output_base/component.rb +88 -0
- data/lib/rggen/output_base/component_factory.rb +32 -0
- data/lib/rggen/output_base/item.rb +175 -0
- data/lib/rggen/output_base/item_factory.rb +6 -0
- data/lib/rggen/output_base/line.rb +28 -0
- data/lib/rggen/output_base/template_utility.rb +29 -0
- data/lib/rggen/output_base/verilog_utility/class_definition.rb +23 -0
- data/lib/rggen/output_base/verilog_utility/declaration.rb +70 -0
- data/lib/rggen/output_base/verilog_utility/identifier.rb +29 -0
- data/lib/rggen/output_base/verilog_utility/module_definition.rb +47 -0
- data/lib/rggen/output_base/verilog_utility/package_definition.rb +67 -0
- data/lib/rggen/output_base/verilog_utility/structure_definition.rb +52 -0
- data/lib/rggen/output_base/verilog_utility/subroutine_definition.rb +43 -0
- data/lib/rggen/output_base/verilog_utility.rb +66 -0
- data/lib/rggen/version.rb +6 -0
- data/lib/rggen.rb +65 -0
- data/ral/compile.f +4 -0
- data/ral/rggen_ral_block.svh +84 -0
- data/ral/rggen_ral_field.svh +47 -0
- data/ral/rggen_ral_macros.svh +22 -0
- data/ral/rggen_ral_map.svh +124 -0
- data/ral/rggen_ral_pkg.sv +14 -0
- data/ral/rggen_ral_reg.svh +52 -0
- data/ral/rggen_ral_shadow_reg.svh +188 -0
- data/rggen.gemspec +45 -0
- data/rtl/bit_field/rggen_bit_field_rw.sv +28 -0
- data/rtl/register/rggen_address_decoder.sv +49 -0
- data/rtl/register_block/rggen_host_if_apb.sv +40 -0
- data/rtl/register_block/rggen_response_mux.sv +82 -0
- data/sample/sample.csv +14 -0
- data/sample/sample.json +4 -0
- data/sample/sample.xls +0 -0
- data/sample/sample.xlsx +0 -0
- data/sample/sample.yaml +2 -0
- data/sample/sample_0.sv +285 -0
- data/sample/sample_0_ral_pkg.sv +99 -0
- data/sample/sample_1.sv +172 -0
- data/sample/sample_1_ral_pkg.sv +53 -0
- data/sample/sample_setup.rb +21 -0
- data/setup/default.rb +11 -0
- metadata +296 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
simple_item :register, :read_data do
|
|
2
|
+
rtl do
|
|
3
|
+
generate_code :module_item do |buffer|
|
|
4
|
+
buffer << assign(register_read_data, read_data) << nl
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def register_read_data
|
|
8
|
+
register_block.register_read_data[register.index]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def read_data
|
|
12
|
+
if register.readable?
|
|
13
|
+
concat(*read_data_expressions)
|
|
14
|
+
else
|
|
15
|
+
hex(0, configuration.data_width)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def read_data_expressions
|
|
20
|
+
last_lsb = configuration.data_width
|
|
21
|
+
expressions = []
|
|
22
|
+
readable_fields.each do |field|
|
|
23
|
+
padding_bits = last_lsb - field.msb - 1
|
|
24
|
+
last_lsb = field.lsb
|
|
25
|
+
expressions << hex(0, padding_bits) if padding_bits > 0
|
|
26
|
+
expressions << field.value[register.loop_variables]
|
|
27
|
+
end
|
|
28
|
+
expressions << hex(0, last_lsb) if last_lsb > 0
|
|
29
|
+
expressions
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def readable_fields
|
|
33
|
+
register.bit_fields.select(&:readable?).sort_by(&:msb).reverse
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
simple_item :register, :reg_model_constructor do
|
|
2
|
+
ral do
|
|
3
|
+
generate_code :reg_model_item do
|
|
4
|
+
function_definition :new do |f|
|
|
5
|
+
f.arguments [
|
|
6
|
+
argument(:name, data_type: :string, default: string(register.name))
|
|
7
|
+
]
|
|
8
|
+
f.body { "super.new(name, #{bits}, 0);" }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def bits
|
|
13
|
+
max_msb = register.bit_fields.map(&:msb).max
|
|
14
|
+
((max_msb + 8) / 8) * 8
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
simple_item :register, :reg_model_creation do
|
|
2
|
+
ral do
|
|
3
|
+
delegate [:byte_width] => :configuration
|
|
4
|
+
delegate [:local_address_width] => :register_block
|
|
5
|
+
delegate [:name, :dimensions, :array?, :shadow?] => :register
|
|
6
|
+
|
|
7
|
+
generate_code :reg_model_creation do |buffer|
|
|
8
|
+
foreach_header(buffer) if array?
|
|
9
|
+
model_creation(buffer)
|
|
10
|
+
foreach_footer(buffer) if array?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def foreach_header(buffer)
|
|
14
|
+
buffer << "foreach (#{name}[#{loop_varibles.join(', ')}]) begin" << nl
|
|
15
|
+
buffer.indent += 2
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def model_creation(buffer)
|
|
19
|
+
buffer << "`rggen_ral_create_reg_model(#{arguments.join(', ')})" << nl
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def foreach_footer(buffer)
|
|
23
|
+
buffer.indent -= 2
|
|
24
|
+
buffer << 'end' << nl
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def arguments
|
|
28
|
+
[handle, string(name), array_index, offset_address, rights, unmapped]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def handle
|
|
32
|
+
create_identifier(name)[loop_varibles]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def array_index
|
|
36
|
+
return '\'{}' unless array?
|
|
37
|
+
array(*loop_varibles)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def offset_address
|
|
41
|
+
base = hex(register.start_address, local_address_width)
|
|
42
|
+
if !array? || shadow?
|
|
43
|
+
base
|
|
44
|
+
else
|
|
45
|
+
"#{base} + #{byte_width} * #{loop_varibles.first}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def rights
|
|
50
|
+
return string(:RO) if register.read_only?
|
|
51
|
+
return string(:WO) if register.write_only?
|
|
52
|
+
string(:RW)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def unmapped
|
|
56
|
+
(shadow? && 1) || 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def loop_varibles
|
|
60
|
+
return nil unless array?
|
|
61
|
+
@loop_varibles ||= Array.new(dimensions.size, &method(:loop_index))
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
simple_item :register, :reg_model_declaration do
|
|
2
|
+
ral do
|
|
3
|
+
delegate [:model_name, :name, :dimensions] => :register
|
|
4
|
+
|
|
5
|
+
generate_code :reg_model_declaration do |buffer|
|
|
6
|
+
buffer << declaration << semicolon << nl
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def declaration
|
|
10
|
+
model_declaration(model_name, name, dimensions: dimensions)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
simple_item :register, :reg_model_definition do
|
|
2
|
+
ral do
|
|
3
|
+
export :model_name
|
|
4
|
+
|
|
5
|
+
generate_code :package_item do
|
|
6
|
+
class_definition model_name do |c|
|
|
7
|
+
c.base base_model
|
|
8
|
+
c.body do |buffer|
|
|
9
|
+
register.generate_code(:reg_model_item, :top_down, buffer)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def model_name
|
|
15
|
+
"#{register.name}_reg_model"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def base_model
|
|
19
|
+
(register.shadow? && :rggen_ral_shadow_reg) || :rggen_ral_reg
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
simple_item :register, :shadow do
|
|
2
|
+
register_map do
|
|
3
|
+
ShadowIndexEntry = Struct.new(:name, :value) do
|
|
4
|
+
def initialize(name, value)
|
|
5
|
+
self.name = name
|
|
6
|
+
self.value = value && Integer(value)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def ==(other)
|
|
10
|
+
return false unless name == other.name
|
|
11
|
+
return true if [value, other.value].any?(&:nil?)
|
|
12
|
+
value == other.value
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
field :shadow?
|
|
17
|
+
field :shadow_indexes
|
|
18
|
+
|
|
19
|
+
input_pattern %r{(#{variable_name})(?::(#{number}))?}
|
|
20
|
+
|
|
21
|
+
build do |cell|
|
|
22
|
+
@shadow_indexes = parse_shadow_indexes(cell)
|
|
23
|
+
@shadow = @shadow_indexes.not_nil?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
validate do
|
|
27
|
+
next unless shadow?
|
|
28
|
+
check_using_shadow_register_only
|
|
29
|
+
check_index_fields
|
|
30
|
+
check_size_of_array_index_fields
|
|
31
|
+
check_array_index_values
|
|
32
|
+
check_specific_value_index_values
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def parse_shadow_indexes(cell)
|
|
36
|
+
return nil if cell.nil? || cell.empty?
|
|
37
|
+
cell.split(/[,\n]/).map do |entry|
|
|
38
|
+
if pattern_match(entry)
|
|
39
|
+
ShadowIndexEntry.new(captures[0], captures[1])
|
|
40
|
+
else
|
|
41
|
+
error "invalid value for shadow index: #{cell.inspect}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def check_using_shadow_register_only
|
|
47
|
+
return unless register.multiple? && register.array?
|
|
48
|
+
error 'not use real array and shadow register on the same register'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def check_index_fields
|
|
52
|
+
shadow_indexes.each do |entry|
|
|
53
|
+
case
|
|
54
|
+
when use_same_index_field_more_than_once?(entry.name)
|
|
55
|
+
error "not use the same index field more than once: #{entry.name}"
|
|
56
|
+
when not_find_shadow_index_field?(entry)
|
|
57
|
+
error "no such shadow index field: #{entry.name}"
|
|
58
|
+
when use_own_bit_field?(entry)
|
|
59
|
+
error 'own bit field is specified for shadow index field:' \
|
|
60
|
+
" #{entry.name}"
|
|
61
|
+
when use_arrayed_bit_field?(entry)
|
|
62
|
+
error 'arrayed bit field is specified for shadow index field:' \
|
|
63
|
+
" #{entry.name}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def use_same_index_field_more_than_once?(name)
|
|
69
|
+
shadow_indexes.count { |entry| entry.name == name } > 1
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def not_find_shadow_index_field?(entry)
|
|
73
|
+
shadow_index_bit_field[entry.name].nil?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def use_own_bit_field?(entry)
|
|
77
|
+
register.bit_fields.map(&:name).include?(entry.name)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def use_arrayed_bit_field?(entry)
|
|
81
|
+
shadow_index_bit_field[entry.name].register.array?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def check_size_of_array_index_fields
|
|
85
|
+
return if size_of_dimensions == array_indexes.size
|
|
86
|
+
error 'not match number of array dimensions and' \
|
|
87
|
+
' number of array index fields'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def check_array_index_values
|
|
91
|
+
array_indexes.each_with_index do |entry, i|
|
|
92
|
+
next if register.dimensions[i] <= (maximum_value(entry.name) + 1)
|
|
93
|
+
error "exceeds maximum array size specified by #{entry.name}" \
|
|
94
|
+
"(#{maximum_value(entry.name) + 1}): #{register.dimensions[i]}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def check_specific_value_index_values
|
|
99
|
+
specific_value_indexes.each do |entry|
|
|
100
|
+
next if entry.value <= maximum_value(entry.name)
|
|
101
|
+
error "exceeds maximum value of #{entry.name}" \
|
|
102
|
+
"(#{maximum_value(entry.name)}): #{entry.value}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def size_of_dimensions
|
|
107
|
+
(register.array? && register.dimensions.size) || 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def array_indexes
|
|
111
|
+
shadow_indexes.select { |entry| entry.value.nil? }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def specific_value_indexes
|
|
115
|
+
shadow_indexes.select { |entry| entry.value.not_nil? }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def maximum_value(index_name)
|
|
119
|
+
2**shadow_index_bit_field[index_name].width - 1
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def shadow_index_bit_field
|
|
123
|
+
@shadow_index_bit_field ||= Hash.new do |hash, index_name|
|
|
124
|
+
hash[index_name] = register_block.bit_fields.find do |bit_field|
|
|
125
|
+
bit_field.name == index_name && !bit_field.reserved?
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
simple_item :register, :shadow_index_configurator do
|
|
2
|
+
ral do
|
|
3
|
+
generate_code :reg_model_item do
|
|
4
|
+
function_definition :configure_shadow_indexes do |f|
|
|
5
|
+
f.return_type :void
|
|
6
|
+
f.body { |code| function_body(code) }
|
|
7
|
+
end if register.shadow?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def function_body(code)
|
|
11
|
+
register.shadow_indexes.each do |shadow_index|
|
|
12
|
+
code << "set_shadow_index(#{arguments(shadow_index)});" << nl
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def arguments(shadow_index)
|
|
17
|
+
[
|
|
18
|
+
parent_name(shadow_index),
|
|
19
|
+
index_name(shadow_index),
|
|
20
|
+
index_value(shadow_index)
|
|
21
|
+
].join(', ')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def parent_name(shadow_index)
|
|
25
|
+
parent_register = fild_parent_register(shadow_index.name)
|
|
26
|
+
string(parent_register.name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fild_parent_register(index_name)
|
|
30
|
+
index_field = register_block.bit_fields.find do |bit_field|
|
|
31
|
+
bit_field.name == index_name
|
|
32
|
+
end
|
|
33
|
+
index_field.register
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def index_name(shadow_index)
|
|
37
|
+
string(shadow_index.name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def index_value(shadow_index)
|
|
41
|
+
if shadow_index.value
|
|
42
|
+
shadow_index.value
|
|
43
|
+
else
|
|
44
|
+
"indexes[#{array_index}]"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def array_index
|
|
49
|
+
@array_index ||= -1
|
|
50
|
+
@array_index += 1
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
simple_item :register, :uniqueness_validator do
|
|
2
|
+
register_map do
|
|
3
|
+
validate do
|
|
4
|
+
previous_registers.each do |previous_register|
|
|
5
|
+
validate_uniqueness(previous_register)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def previous_registers
|
|
10
|
+
register_block.registers.take_while { |r| !r.equal?(register) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def validate_uniqueness(previous_register)
|
|
14
|
+
case
|
|
15
|
+
when overlap_offset_address?(previous_register)
|
|
16
|
+
error 'offset address is not unique', error_position(:start_address)
|
|
17
|
+
when overlap_shadow_indexes?(previous_register)
|
|
18
|
+
error 'shadow indexes is not unique', error_position(:shadow_indexes)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def overlap_offset_address?(previous_register)
|
|
23
|
+
return false if [previous_register, register].all?(&:shadow?)
|
|
24
|
+
overlap_address_range?(register, previous_register)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def overlap_address_range?(lhs, rhs)
|
|
28
|
+
lhs_range = lhs.start_address..lhs.end_address
|
|
29
|
+
rhs_range = rhs.start_address..rhs.end_address
|
|
30
|
+
lhs_range.overlap?(rhs_range)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def overlap_shadow_indexes?(previous_register)
|
|
34
|
+
return false unless overlap_address_range?(register, previous_register)
|
|
35
|
+
return true unless unique_shadw_indexes?(register, previous_register)
|
|
36
|
+
return true unless unique_shadw_indexes?(previous_register, register)
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def unique_shadw_indexes?(lhs, rhs)
|
|
41
|
+
lhs.shadow_indexes.any?(&rhs.shadow_indexes.method(:exclude?))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def error_position(field)
|
|
45
|
+
register.items.find { |i| i.fields.include?(field) }.position
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
rggen_host_if_apb #(
|
|
2
|
+
.DATA_WIDTH (<%= configuration.data_width %>),
|
|
3
|
+
.HOST_ADDRESS_WIDTH (<%= configuration.address_width %>),
|
|
4
|
+
.LOCAL_ADDRESS_WIDTH (<%= register_block.local_address_width %>)
|
|
5
|
+
) u_host_if (
|
|
6
|
+
.clk (<%= register_block.clock %>),
|
|
7
|
+
.rst_n (<%= register_block.reset %>),
|
|
8
|
+
.i_paddr (<%= apb.paddr %>),
|
|
9
|
+
.i_pprot (<%= apb.pprot %>),
|
|
10
|
+
.i_psel (<%= apb.psel %>),
|
|
11
|
+
.i_penable (<%= apb.penable %>),
|
|
12
|
+
.i_pwrite (<%= apb.pwrite %>),
|
|
13
|
+
.i_pwdata (<%= apb.pwdata %>),
|
|
14
|
+
.i_pstrb (<%= apb.pstrb %>),
|
|
15
|
+
.o_pready (<%= apb.pready %>),
|
|
16
|
+
.o_prdata (<%= apb.prdata %>),
|
|
17
|
+
.o_pslverr (<%= apb.pslverr %>),
|
|
18
|
+
.o_command_valid (<%= host_if.command_valid %>),
|
|
19
|
+
.o_write (<%= host_if.write %>),
|
|
20
|
+
.o_read (<%= host_if.read %>),
|
|
21
|
+
.o_address (<%= host_if.address %>),
|
|
22
|
+
.o_write_data (<%= host_if.write_data %>),
|
|
23
|
+
.o_write_mask (<%= host_if.write_mask %>),
|
|
24
|
+
.i_response_ready (<%= host_if.response_ready %>),
|
|
25
|
+
.i_read_data (<%= host_if.read_data %>),
|
|
26
|
+
.i_status (<%= host_if.status %>)
|
|
27
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
list_item :register_block, :host_if, :apb do
|
|
2
|
+
rtl do
|
|
3
|
+
build do
|
|
4
|
+
group(:apb) do
|
|
5
|
+
input :paddr , name: 'i_paddr' , width: configuration.address_width
|
|
6
|
+
input :pprot , name: 'i_pprot' , width: 3
|
|
7
|
+
input :psel , name: 'i_psel' , width: 1
|
|
8
|
+
input :penable, name: 'i_penable', width: 1
|
|
9
|
+
input :pwrite , name: 'i_pwrite' , width: 1
|
|
10
|
+
input :pwdata , name: 'i_pwdata' , width: configuration.data_width
|
|
11
|
+
input :pstrb , name: 'i_pstrb' , width: configuration.byte_width
|
|
12
|
+
output :pready , name: 'o_pready' , width: 1
|
|
13
|
+
output :prdata , name: 'o_prdata' , width: configuration.data_width
|
|
14
|
+
output :pslverr, name: 'o_pslverr', width: 1
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
generate_code_from_template :module_item
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
simple_item :register_block, :base_address do
|
|
2
|
+
register_map do
|
|
3
|
+
field :start_address
|
|
4
|
+
field :end_address
|
|
5
|
+
field :byte_size
|
|
6
|
+
field :local_address_width
|
|
7
|
+
|
|
8
|
+
input_pattern %r{(#{number})-(#{number})}
|
|
9
|
+
|
|
10
|
+
build do |cell|
|
|
11
|
+
parse_address(cell)
|
|
12
|
+
case
|
|
13
|
+
when @start_address >= @end_address
|
|
14
|
+
error "start address is equal to or greater than end address: #{cell}"
|
|
15
|
+
when not_aligned_with_data_width?
|
|
16
|
+
error 'not aligned with data width' \
|
|
17
|
+
"(#{configuration.data_width}): #{cell}"
|
|
18
|
+
when not_aligned_with_local_address_width?
|
|
19
|
+
error 'not aligned with local address width' \
|
|
20
|
+
"(#{@local_address_width}): #{cell}"
|
|
21
|
+
when @end_address > max_address
|
|
22
|
+
error 'exceeds the maximum base address' \
|
|
23
|
+
"(0x#{max_address.to_s(16)}): #{cell}"
|
|
24
|
+
when overlapped_address?
|
|
25
|
+
error "overlapped base address: #{cell}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def parse_address(cell)
|
|
30
|
+
if pattern_matched?
|
|
31
|
+
@start_address = Integer(captures[0])
|
|
32
|
+
@end_address = Integer(captures[1])
|
|
33
|
+
@byte_size = @end_address - @start_address + 1
|
|
34
|
+
@local_address_width = Math.clog2(@byte_size) if @byte_size > 0
|
|
35
|
+
else
|
|
36
|
+
error "invalid value for base address: #{cell.inspect}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def not_aligned_with_data_width?
|
|
41
|
+
byte_width = configuration.byte_width
|
|
42
|
+
return true unless (@start_address + 0).multiple?(byte_width)
|
|
43
|
+
return true unless (@end_address + 1).multiple?(byte_width)
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def not_aligned_with_local_address_width?
|
|
48
|
+
window_size = 2**@local_address_width
|
|
49
|
+
return true unless @start_address.multiple?(window_size)
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def max_address
|
|
54
|
+
2**configuration.address_width - 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def overlapped_address?
|
|
58
|
+
own_range = @start_address..@end_address
|
|
59
|
+
register_map.register_blocks.any? do |block|
|
|
60
|
+
own_range.overlap?(block.start_address..block.end_address)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
simple_item :register_block, :block_model_constructor do
|
|
2
|
+
ral do
|
|
3
|
+
delegate [:name] => :register_block
|
|
4
|
+
|
|
5
|
+
generate_code :block_model_item do
|
|
6
|
+
function_definition :new do |f|
|
|
7
|
+
f.arguments [
|
|
8
|
+
argument(:name, data_type: :string, default: string(name))
|
|
9
|
+
]
|
|
10
|
+
f.body { 'super.new(name);' }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
simple_item :register_block, :block_model_default_map_creator do
|
|
2
|
+
ral do
|
|
3
|
+
generate_code :block_model_item do
|
|
4
|
+
function_definition :create_default_map do |f|
|
|
5
|
+
f.return_type :uvm_reg_map
|
|
6
|
+
f.body do |code|
|
|
7
|
+
code << :return
|
|
8
|
+
code << space
|
|
9
|
+
code << "create_map(#{arguments.join(', ')})"
|
|
10
|
+
code << semicolon
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def arguments
|
|
16
|
+
[name, base_address, n_bytes, endian, byte_addressing]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def name
|
|
20
|
+
string(:default_map)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def base_address
|
|
24
|
+
0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def n_bytes
|
|
28
|
+
configuration.byte_width
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def endian
|
|
32
|
+
:UVM_LITTLE_ENDIAN
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def byte_addressing
|
|
36
|
+
1
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
simple_item :register_block, :block_model_definition do
|
|
2
|
+
ral do
|
|
3
|
+
generate_code :package_item do
|
|
4
|
+
class_definition model_name do |c|
|
|
5
|
+
c.base :rggen_ral_block
|
|
6
|
+
c.body { |code| body_code(code) }
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def model_name
|
|
11
|
+
"#{register_block.name}_block_model"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def body_code(code)
|
|
15
|
+
register_block.generate_code(:block_model_item, :top_down, code)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
simple_item :register_block, :byte_size do
|
|
2
|
+
register_map do
|
|
3
|
+
field :byte_size
|
|
4
|
+
field :local_address_width
|
|
5
|
+
|
|
6
|
+
build do |cell|
|
|
7
|
+
begin
|
|
8
|
+
@byte_size = Integer(cell)
|
|
9
|
+
rescue
|
|
10
|
+
error "invalid value for byte size: #{cell.inspect}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
case
|
|
14
|
+
when @byte_size.not.positive?
|
|
15
|
+
error "zero or negative value is not allowed for byte size: #{cell}"
|
|
16
|
+
when @byte_size.not.multiple?(configuration.byte_width)
|
|
17
|
+
error 'not aligned with data width' \
|
|
18
|
+
"(#{configuration.data_width}): #{cell}"
|
|
19
|
+
when total_byte_size > upper_bound
|
|
20
|
+
error 'exceeds upper bound of total byte size' \
|
|
21
|
+
"(#{upper_bound}): #{total_byte_size}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@local_address_width = Math.clog2(@byte_size)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def upper_bound
|
|
28
|
+
2**configuration.address_width
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def total_byte_size
|
|
32
|
+
register_map.register_blocks.inject(@byte_size) do |total, block|
|
|
33
|
+
total + block.byte_size
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
list_item :register_block, :host_if do
|
|
2
|
+
shared_context do
|
|
3
|
+
attr_accessor :enabled_host_ifs
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
configuration do
|
|
7
|
+
item_class do
|
|
8
|
+
field :host_if do
|
|
9
|
+
@host_if || shared_context.enabled_host_ifs.first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
build do |value|
|
|
13
|
+
@host_if = shared_context.enabled_host_ifs.find do |host_if|
|
|
14
|
+
host_if.to_sym.casecmp(value.to_sym) == 0
|
|
15
|
+
end
|
|
16
|
+
error "unknown host interface: #{value}" if @host_if.nil?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
rtl do
|
|
22
|
+
shared_context.enabled_host_ifs = @enabled_items
|
|
23
|
+
|
|
24
|
+
item_base do
|
|
25
|
+
build do
|
|
26
|
+
group(:host_if) do
|
|
27
|
+
logic :command_valid , width: 1
|
|
28
|
+
logic :write , width: 1
|
|
29
|
+
logic :read , width: 1
|
|
30
|
+
logic :address , width: register_block.local_address_width
|
|
31
|
+
logic :write_data , width: configuration.data_width
|
|
32
|
+
logic :write_mask , width: configuration.data_width
|
|
33
|
+
logic :response_ready, width: 1
|
|
34
|
+
logic :read_data , width: configuration.data_width
|
|
35
|
+
logic :status , width: 2
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
factory do
|
|
41
|
+
def select_target_item(configuration, _register_block)
|
|
42
|
+
@target_items[configuration.host_if]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
define_simple_item :register_block, :module_definition do
|
|
2
|
+
rtl do
|
|
3
|
+
write_file '<%= register_block.name %>.sv' do
|
|
4
|
+
module_definition register_block.name do |m|
|
|
5
|
+
m.parameters register_block.parameter_declarations
|
|
6
|
+
m.ports register_block.port_declarations
|
|
7
|
+
m.body do |code|
|
|
8
|
+
register_block.generate_code(:module_item, :top_down, code)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|