systemrdl 0.1.0 → 0.2.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.
@@ -25,9 +25,7 @@ module SystemRDL
25
25
  end
26
26
 
27
27
  def upper_layers(include_self: false)
28
- return [] if layer == :root
29
-
30
- layers = [*component.upper_layers, component]
28
+ layers = (layer == :root && []) || component.upper_layers(include_self: true)
31
29
  layers << self if include_self
32
30
  layers
33
31
  end
@@ -37,12 +35,9 @@ module SystemRDL
37
35
  @insts&.evaluate(instance, @parent, @id, **optargs)
38
36
  end
39
37
 
40
- def create_instances(parent_instance, inst_name, inst_values, token_range, **optargs)
41
- eval_array(inst_values) do |array_info|
42
- create_instance(
43
- parent_instance, inst_name, inst_values,
44
- array_info, token_range, **optargs
45
- )
38
+ def create_instances(parent_instance, inst_args, token_range, **optargs)
39
+ eval_array(inst_args.values) do |array_info|
40
+ create_instance(parent_instance, inst_args, array_info, token_range, **optargs)
46
41
  end
47
42
  end
48
43
 
@@ -93,8 +88,8 @@ module SystemRDL
93
88
  def check_property_exclusivity(instance, names)
94
89
  properties =
95
90
  names
96
- .map { |name| instance.property_value(name) }
97
- .select { |v| v&.value }
91
+ .map { |name| instance.property_value(name) }
92
+ .select { |v| v&.value }
98
93
  return if properties.size <= 1
99
94
 
100
95
  labels = [names[..-2].join(', '), names[-1]].join(' and ')
@@ -114,17 +109,19 @@ module SystemRDL
114
109
  yield(nil, nil)
115
110
  end
116
111
 
117
- def create_instance(parent_instance, inst_name, inst_values, array_info, token_range, **optargs)
118
- unless unique_instance?(parent_instance, inst_name, array_info)
119
- message = "duplicated instance: #{inst_name}"
112
+ def create_instance(parent_instance, inst_args, array_info, token_range, **optargs)
113
+ unless unique_instance?(parent_instance, inst_args.name, array_info)
114
+ message = "duplicated instance: #{inst_args.name}"
120
115
  raise_evaluation_error message, token_range
121
116
  end
122
117
 
123
- instance = instance_class.new(self, parent_instance, inst_name, array_info, token_range)
118
+ instance = instance_class.new(self, parent_instance, inst_args.name, token_range)
124
119
 
125
120
  init_properties(instance)
126
121
  eval_body(instance, **optargs)
127
- apply_inst_values(instance, inst_values)
122
+ apply_array(instance, array_info)
123
+ apply_inst_values(instance, inst_args.values)
124
+ apply_inst_type(instance, inst_args.type)
128
125
  post_build(instance)
129
126
  instance.validate
130
127
 
@@ -149,9 +146,9 @@ module SystemRDL
149
146
  def init_properties(instance)
150
147
  prop_defs = BuiltinProperties.properties
151
148
  prop_defs.each do |prop_def|
152
- next unless prop_def.target?(instance)
153
-
154
149
  prop = prop_def.create(instance)
150
+ next unless prop
151
+
155
152
  instance.properties << prop
156
153
  end
157
154
  end
@@ -161,9 +158,15 @@ module SystemRDL
161
158
  @elements.each { |element| element.evaluate(instance, **optargs) }
162
159
  end
163
160
 
161
+ def apply_inst_type(_instance, _inst_type)
162
+ end
163
+
164
164
  def apply_inst_values(_instance, _inst_values)
165
165
  end
166
166
 
167
+ def apply_array(_instance, _array_info)
168
+ end
169
+
167
170
  def post_build(_instance)
168
171
  end
169
172
 
@@ -20,10 +20,11 @@ module SystemRDL
20
20
  def evaluate(instance, base, id, **optargs)
21
21
  component_definition = find_component_definition(base, id, **optargs)
22
22
  check_recursive_instance(instance, component_definition)
23
+ check_inst_type(component_definition)
23
24
  check_instantiable(instance, component_definition)
24
25
 
25
26
  @insts.each do |inst|
26
- inst.evaluate(instance, component_definition, **optargs)
27
+ inst.evaluate(instance, component_definition, inst_type, **optargs)
27
28
  end
28
29
  end
29
30
 
@@ -34,7 +35,7 @@ module SystemRDL
34
35
  definition = component.definitions[id.value]
35
36
  next unless definition
36
37
 
37
- unless optargs[:test] || (definition.layer in :reg | :field)
38
+ unless optargs[:test] || instantiable_component?(definition)
38
39
  message = "#{definition.layer} instance not supported yet"
39
40
  raise_evaluation_error message, token_range
40
41
  end
@@ -45,6 +46,10 @@ module SystemRDL
45
46
  raise_evaluation_error "undefined component: #{id.value}", token_range
46
47
  end
47
48
 
49
+ def instantiable_component?(definition)
50
+ definition.layer in :addrmap | :regfile | :mem | :reg | :field
51
+ end
52
+
48
53
  def check_recursive_instance(instance, component_definition)
49
54
  components = instance.definition.upper_layers(include_self: true)
50
55
  return if components.none? { |component| component.equal?(component_definition) }
@@ -53,6 +58,21 @@ module SystemRDL
53
58
  raise_evaluation_error message, token_range
54
59
  end
55
60
 
61
+ def check_inst_type(component_definition)
62
+ return if component_definition.support_inst_type?(inst_type)
63
+
64
+ message =
65
+ if inst_type
66
+ "#{component_definition.layer} instance with #{inst_type} not allowed"
67
+ else
68
+ "#{component_definition.layer} instance without instance type not allowed"
69
+ end
70
+ raise_evaluation_error message, token_range
71
+ end
72
+
73
+ def inst_type
74
+ end
75
+
56
76
  def check_instantiable(instance, component_definition)
57
77
  return if instance.instantiable?(component_definition)
58
78
 
@@ -61,6 +81,24 @@ module SystemRDL
61
81
  end
62
82
  end
63
83
 
84
+ class InternalComponentInsts < ComponentInsts
85
+ private
86
+
87
+ def inst_type
88
+ :internal
89
+ end
90
+ end
91
+
92
+ class ExternalComponentInsts < ComponentInsts
93
+ private
94
+
95
+ def inst_type
96
+ :external
97
+ end
98
+ end
99
+
100
+ InstArgs = Data.define(:name, :type, :values)
101
+
64
102
  class ComponentInst
65
103
  include Common
66
104
 
@@ -72,9 +110,10 @@ module SystemRDL
72
110
 
73
111
  attr_reader :inst_id
74
112
 
75
- def evaluate(instance, component_definition, **optargs)
113
+ def evaluate(instance, component_definition, inst_type, **optargs)
76
114
  inst_values = eval_inst_values(instance, **optargs)
77
- component_definition.create_instances(instance, @inst_id.value, inst_values, @token_range, **optargs)
115
+ args = InstArgs.new(@inst_id.value, inst_type, inst_values)
116
+ component_definition.create_instances(instance, args, @token_range, **optargs)
78
117
  end
79
118
 
80
119
  private
@@ -32,6 +32,10 @@ module SystemRDL
32
32
  :field
33
33
  end
34
34
 
35
+ def support_inst_type?(inst_type)
36
+ inst_type.nil?
37
+ end
38
+
35
39
  private
36
40
 
37
41
  def instance_class
@@ -39,33 +43,30 @@ module SystemRDL
39
43
  end
40
44
 
41
45
  def apply_inst_values(instance, inst_values)
42
- assign_bit_pos(instance, inst_values)
46
+ assign_bit_range(instance, inst_values)
43
47
  apply_reset_value(instance, inst_values)
44
48
  check_address_allocation_operator(inst_values)
45
49
  end
46
50
 
47
- def assign_bit_pos(instance, inst_values)
48
- msb, lsb =
49
- if (range = inst_values[:range])
50
- range.elements
51
- else
52
- calc_bit_pos(instance, inst_values)
53
- end
54
- instance.msb = msb
55
- instance.lsb = lsb
56
- end
57
-
58
- def calc_bit_pos(instance, inst_values)
59
- width = calc_bit_width(instance, inst_values)
60
- last_msb = instance.parent.instances.last&.msb
61
- lsb = (last_msb&.value || -1) + 1
62
- msb = lsb + (width&.value || 1) - 1
63
- [msb, lsb].map { |pos| Value.new(pos, :bit, 64, width&.token_range) }
51
+ def assign_bit_range(instance, inst_values)
52
+ if (range = inst_values[:range])
53
+ msb, lsb = range.elements
54
+ instance.msb = msb
55
+ instance.lsb = lsb
56
+ else
57
+ instance.width = bit_width(instance, inst_values)
58
+ end
64
59
  end
65
60
 
66
- def calc_bit_width(instance, inst_values)
61
+ def bit_width(instance, inst_values)
67
62
  size = inst_values[:array]
68
- return instance.property_value(:fieldwidth) unless size
63
+ unless size
64
+ if (fieldwidth = instance.property_value(:fieldwidth))
65
+ return fieldwidth
66
+ else
67
+ return Value.new(1, :bit, 64, nil)
68
+ end
69
+ end
69
70
 
70
71
  if size.size >= 2
71
72
  message = 'multidimensional size specification not allowed for field'
@@ -90,13 +91,21 @@ module SystemRDL
90
91
  raise_evaluation_error message, fieldwidth.token_range
91
92
  end
92
93
 
93
- msb = instance.msb
94
- lsb = instance.lsb
95
- width = msb.value - lsb.value + 1
94
+ width, width_token_range = extract_width(instance)
96
95
  return if width == fieldwidth.value
97
96
 
98
97
  message = "bit width mismatch: instance width #{width} fieldwidth property #{fieldwidth}"
99
- raise_evaluation_error message, msb.token_range, lsb.token_range
98
+ raise_evaluation_error message, *width_token_range
99
+ end
100
+
101
+ def extract_width(instance)
102
+ if instance.msb
103
+ pos = [instance.msb.value, instance.lsb.value].sort
104
+ width = pos[1] - pos[0] + 1
105
+ [width, [instance.msb.token_range, instance.lsb.token_range]]
106
+ else
107
+ [instance.width.value, [instance.width.token_range].compact]
108
+ end
100
109
  end
101
110
 
102
111
  def apply_reset_value(instance, inst_values)
@@ -120,7 +129,7 @@ module SystemRDL
120
129
  end
121
130
 
122
131
  def check_reset_value(instance, reset_value)
123
- width = instance.msb.value - instance.lsb.value + 1
132
+ width, _ = extract_width(instance)
124
133
  range = 0..((2**width) - 1)
125
134
  return if range.include?(reset_value.value)
126
135
 
@@ -224,6 +233,11 @@ module SystemRDL
224
233
  class FieldInstance < Instance
225
234
  attr_accessor :msb
226
235
  attr_accessor :lsb
236
+ attr_accessor :width
237
+
238
+ def virtual_field?
239
+ parent.virtual_reg?
240
+ end
227
241
 
228
242
  def definable?(_definition)
229
243
  false
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SystemRDL
4
+ module Evaluator
5
+ module InstTypeAwareComponent
6
+ private
7
+
8
+ def apply_inst_type(instance, inst_type)
9
+ instance.external = inst_type == :external
10
+ end
11
+ end
12
+
13
+ module InstTypeAwareInstance
14
+ attr_accessor :external
15
+ end
16
+ end
17
+ end
@@ -3,11 +3,10 @@
3
3
  module SystemRDL
4
4
  module Evaluator
5
5
  class Instance
6
- def initialize(definition, parent, name, array_info, token_range)
6
+ def initialize(definition, parent, name, token_range)
7
7
  @definition = definition
8
8
  @parent = parent
9
9
  @name = name
10
- @array_info = array_info
11
10
  @token_range = token_range
12
11
  @properties = []
13
12
  @instances = []
@@ -35,14 +34,13 @@ module SystemRDL
35
34
  end
36
35
 
37
36
  def full_name
38
- elements = [self]
39
- current = parent
40
- until current.root?
41
- elements.unshift(current)
42
- current = current.parent
43
- end
37
+ upper_instances(include_root: false, include_self: true).map(&:element_name).join('.')
38
+ end
44
39
 
45
- elements.map(&:element_name).join('.')
40
+ def upper_instances(include_root: false, include_self: false)
41
+ instances = (root? && []) || parent.upper_instances(include_root:, include_self: true)
42
+ instances << self if (root? && include_root) || (!root? && include_self)
43
+ instances
46
44
  end
47
45
 
48
46
  def layer
@@ -61,6 +59,10 @@ module SystemRDL
61
59
  layer == :regfile
62
60
  end
63
61
 
62
+ def mem?
63
+ layer == :mem
64
+ end
65
+
64
66
  def reg?
65
67
  layer == :reg
66
68
  end
@@ -70,27 +72,19 @@ module SystemRDL
70
72
  end
71
73
 
72
74
  def structural_component?
73
- addrmap? || regfile? || reg? || field?
75
+ addrmap? || regfile? || mem? || reg? || field?
74
76
  end
75
77
 
76
- def array?
77
- !array_info.nil?
78
- end
79
-
80
- def array_indices
81
- array_info&.indices
82
- end
83
-
84
- def array_sizes
85
- array_info&.sizes
86
- end
87
-
88
- def first_element?
89
- !array? || array_info.first
78
+ def find_addrmap
79
+ if RUBY_VERSION >= '4.0'
80
+ upper_instances(include_root: false, include_self: true).rfind(&:addrmap?)
81
+ else
82
+ upper_instances(include_root: false, include_self: true).reverse_each.find(&:addrmap?)
83
+ end
90
84
  end
91
85
 
92
- def last_element?
93
- !array? || array_info.last
86
+ def array?
87
+ false
94
88
  end
95
89
 
96
90
  def property(name)
@@ -112,8 +106,8 @@ module SystemRDL
112
106
  end
113
107
 
114
108
  def finalize
115
- @definition.finalize(self)
116
109
  @instances.each(&:finalize)
110
+ @definition.finalize(self)
117
111
  end
118
112
  end
119
113
  end
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SystemRDL
4
+ module Evaluator
5
+ class MemDefinition < ComponentDefinition
6
+ include InstTypeAwareComponent
7
+ include BlockComponent
8
+
9
+ def validate(instance)
10
+ check_positive_value(instance, :mementries)
11
+ check_memwidth(instance)
12
+ check_regwidth(instance)
13
+ check_virtual_field_sw(instance)
14
+ end
15
+
16
+ def revalidate(instance)
17
+ check_virtual_field_sw(instance)
18
+ end
19
+
20
+ def finalize(instance)
21
+ check_virtual_field_pos(instance)
22
+ allocate_addresses(instance)
23
+ check_address_operations(instance)
24
+ check_reg_size(instance)
25
+ end
26
+
27
+ def layer
28
+ :mem
29
+ end
30
+
31
+ def support_inst_type?(inst_type)
32
+ inst_type == :external
33
+ end
34
+
35
+ private
36
+
37
+ def instance_class
38
+ MemInstance
39
+ end
40
+
41
+ def apply_inst_values(instance, inst_values)
42
+ apply_address_operations(instance, inst_values)
43
+ check_range(inst_values)
44
+ end
45
+
46
+ def post_build(instance)
47
+ apply_default_memwidth(instance)
48
+ end
49
+
50
+ def apply_default_memwidth(instance)
51
+ return if no_regs?(instance)
52
+
53
+ property = instance.property(:memwidth)
54
+ return if property.value
55
+
56
+ entrywidth = Value.new(instance.entrywidth, :bit, 64, nil)
57
+ property.assign(entrywidth)
58
+ end
59
+
60
+ def check_memwidth(instance)
61
+ check_positive_value(instance, :memwidth)
62
+
63
+ memwidth = instance.property_value(:memwidth)
64
+ return if memwidth || !no_regs?(instance)
65
+
66
+ message = 'omitting memwidth without virtual regs not allowed'
67
+ raise_evaluation_error message, instance.token_range
68
+ end
69
+
70
+ def check_positive_value(instance, prop_name)
71
+ value = instance.property_value(prop_name)
72
+ return if value.nil? || value.value >= 1
73
+
74
+ message = "#{prop_name} must be positive"
75
+ raise_evaluation_error message, value.token_range
76
+ end
77
+
78
+ def check_regwidth(instance)
79
+ return if no_regs?(instance)
80
+
81
+ entrywidth = instance.entrywidth
82
+ instance.instances.each do |reg|
83
+ regwidth = reg.property_value(:regwidth).value
84
+ next if regwidth <= entrywidth
85
+
86
+ memwidth = instance.property_value(:memwidth)
87
+ message =
88
+ 'regwidth larger than entry width not allowed: ' \
89
+ "entry width #{entrywidth} (memwidth #{memwidth}) regwidth #{regwidth}"
90
+ raise_evaluation_error message, reg.token_range
91
+ end
92
+ end
93
+
94
+ def check_virtual_field_pos(instance)
95
+ return if no_regs?(instance)
96
+
97
+ memwidth = instance.property_value(:memwidth).value
98
+ instance.instances.flat_map(&:instances).each do |field|
99
+ next if valid_virtual_field_pos?(field, memwidth)
100
+
101
+ message =
102
+ 'virtual field outside memwidth not allowed: ' \
103
+ "memwidth #{memwidth} msb #{field.msb} lsb #{field.lsb}"
104
+ raise_evaluation_error message, field.token_range
105
+ end
106
+ end
107
+
108
+ def valid_virtual_field_pos?(field, memwidth)
109
+ [field.msb.value, field.lsb.value].sort[1] < memwidth
110
+ end
111
+
112
+ def check_virtual_field_sw(instance)
113
+ return if no_regs?(instance)
114
+
115
+ mem_sw = instance.property_value(:sw).value
116
+ instance.instances.flat_map(&:instances).each do |field|
117
+ field_sw = field.property_value(:sw).value
118
+ next if field_sw == mem_sw
119
+
120
+ message =
121
+ 'mismatch between mem sw and virtual field sw: ' \
122
+ "mem #{mem_sw} virtual field #{field_sw}"
123
+ raise_evaluation_error message, field.token_range
124
+ end
125
+ end
126
+
127
+ def check_reg_size(instance)
128
+ return if no_regs?(instance)
129
+
130
+ size = instance.size
131
+ instance.instances.each do |reg|
132
+ reg_addr = reg.address.value
133
+ reg_size = reg.size
134
+ next if (reg_addr + reg_size) <= size
135
+
136
+ message =
137
+ 'virtual reg outside mem area not allowed: ' \
138
+ "mem size #{size} reg address 0x#{reg_addr.to_s(16)} reg size #{reg_size}"
139
+ raise_evaluation_error message, reg.token_range
140
+ end
141
+ end
142
+
143
+ def no_regs?(instance)
144
+ instance.instances.empty?
145
+ end
146
+ end
147
+
148
+ class MemInstance < Instance
149
+ include InstTypeAwareInstance
150
+ include BlockInstance
151
+
152
+ def entrywidth
153
+ @entrywidth ||=
154
+ if (memwidth = property_value(:memwidth)&.value)
155
+ if memwidth <= 8
156
+ 8
157
+ elsif memwidth.nobits?(memwidth - 1)
158
+ memwidth
159
+ else
160
+ 2**memwidth.bit_length
161
+ end
162
+ else
163
+ instances
164
+ .map { |inst| inst.property_value(:regwidth).value }
165
+ .max
166
+ end
167
+ end
168
+
169
+ def accesswidth
170
+ (instances.empty? && entrywidth) || super
171
+ end
172
+
173
+ def size
174
+ @size ||= begin
175
+ width = entrywidth / 8
176
+ entries = property_value(:mementries).value
177
+ width * entries
178
+ end
179
+ end
180
+
181
+ def definable?(definition)
182
+ definition.layer in :reg | :field
183
+ end
184
+
185
+ def instantiable?(definition)
186
+ definition.layer in :reg
187
+ end
188
+ end
189
+ end
190
+ end
@@ -130,6 +130,16 @@ module SystemRDL
130
130
  ComponentInsts.new(insts, node.token_range)
131
131
  end
132
132
 
133
+ def on_internal_component_insts(node)
134
+ insts = process_all(node.children)
135
+ InternalComponentInsts.new(insts, node.token_range)
136
+ end
137
+
138
+ def on_external_component_insts(node)
139
+ insts = process_all(node.children)
140
+ ExternalComponentInsts.new(insts, node.token_range)
141
+ end
142
+
133
143
  def on_explicit_component_inst(node)
134
144
  id = process(node.children[0])
135
145
  insts = process(node.children[1])
@@ -157,6 +167,7 @@ module SystemRDL
157
167
  case node.children[0].to_sym
158
168
  when :addrmap then AddrMapDefinition
159
169
  when :regfile then RegFileDefinition
170
+ when :mem then MemDefinition
160
171
  when :reg then RegDefinition
161
172
  when :field then FieldDefinition
162
173
  end
@@ -69,25 +69,36 @@ module SystemRDL
69
69
 
70
70
  attr_reader :name
71
71
  attr_accessor :targets
72
+ attr_accessor :exist
72
73
  attr_accessor :types
73
74
  attr_accessor :ref_target
74
75
  attr_accessor :dynamic_assign
75
76
  attr_accessor :per_element_assign
76
77
  attr_accessor :default_value
77
78
 
79
+ def create(instance)
80
+ return unless target?(instance) && exist?(instance)
81
+
82
+ value = eval_value(instance)
83
+ Property.new(instance, self, value)
84
+ end
85
+
86
+ private
87
+
78
88
  def target?(instance)
79
89
  return false if instance.root?
80
90
 
81
91
  targets.nil? || targets.include?(instance.layer)
82
92
  end
83
93
 
84
- def create(instance)
85
- value = eval_value(instance)
86
- Property.new(instance, self, value)
94
+ def exist?(instance)
95
+ if @exist.is_a?(Proc)
96
+ @exist.call(instance)
97
+ else
98
+ @exist
99
+ end
87
100
  end
88
101
 
89
- private
90
-
91
102
  def eval_value(instance)
92
103
  value = instance.definition.find_default_property(name)
93
104
  return value if value
@@ -101,7 +112,7 @@ module SystemRDL
101
112
 
102
113
  return if value.nil?
103
114
 
104
- create_value(value)
115
+ value.is_a?(Value) ? value : create_value(value)
105
116
  end
106
117
 
107
118
  def create_value(value)