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.
@@ -4,6 +4,7 @@ module SystemRDL
4
4
  module Evaluator
5
5
  class RegDefinition < ComponentDefinition
6
6
  include AddressOperation
7
+ include InstTypeAwareComponent
7
8
  include ArrayComponent
8
9
  include ContainerComponent
9
10
 
@@ -11,7 +12,6 @@ module SystemRDL
11
12
  check_structural_component_instances(instance)
12
13
  check_regwidth(instance)
13
14
  check_accesswidth(instance)
14
- check_overlapping_fields(instance)
15
15
  check_fields_out_of_register(instance)
16
16
  check_fields_spanning_sub_word_boundary(instance)
17
17
  check_address_operations(instance)
@@ -23,10 +23,22 @@ module SystemRDL
23
23
  check_address_operations(instance)
24
24
  end
25
25
 
26
+ def finalize(instance)
27
+ check_field_ordering(instance)
28
+ allocate_bits(instance)
29
+ check_overlapping_fields(instance)
30
+ check_fields_out_of_register(instance)
31
+ check_fields_spanning_sub_word_boundary(instance)
32
+ end
33
+
26
34
  def layer
27
35
  :reg
28
36
  end
29
37
 
38
+ def support_inst_type?(_inst_type)
39
+ true
40
+ end
41
+
30
42
  private
31
43
 
32
44
  def instance_class
@@ -65,6 +77,73 @@ module SystemRDL
65
77
  raise_evaluation_error message, accesswidth.token_range, regwidth.token_range
66
78
  end
67
79
 
80
+ def check_field_ordering(instance)
81
+ mode = bit_allocation_mode(instance)
82
+ instance.instances.each do |field|
83
+ next unless field.msb
84
+
85
+ msb = field.msb
86
+ lsb = field.lsb
87
+ next if valid_field_ordering?(mode, msb, lsb)
88
+
89
+ message = "invalid field ordering: bit range [#{msb}:#{lsb}] mode #{mode}"
90
+ raise_evaluation_error message, msb.token_range, lsb.token_range
91
+ end
92
+ end
93
+
94
+ def bit_allocation_mode(instance)
95
+ (instance.find_addrmap.property_value(:msb0).value && :msb0) || :lsb0
96
+ end
97
+
98
+ def valid_field_ordering?(mode, msb, lsb)
99
+ mode == :lsb0 ? msb.value >= lsb.value : msb.value <= lsb.value
100
+ end
101
+
102
+ def allocate_bits(instance)
103
+ mode = bit_allocation_mode(instance)
104
+ instance.instances.inject(nil) do |previous_field, field|
105
+ unless field.msb
106
+ msb, lsb = allocate_field_bits(mode, instance, previous_field, field)
107
+ field.msb = msb
108
+ field.lsb = lsb
109
+ end
110
+
111
+ field
112
+ end
113
+ end
114
+
115
+ def allocate_field_bits(mode, instance, previous_field, field)
116
+ msb, lsb =
117
+ if mode == :lsb0
118
+ allocate_field_bits_lsb0(previous_field, field)
119
+ else
120
+ allocate_field_bits_msb0(instance, previous_field, field)
121
+ end
122
+ [msb, lsb].map { |pos| Value.new(pos, :bit, 64, field.width.token_range) }
123
+ end
124
+
125
+ def allocate_field_bits_lsb0(previous_field, field)
126
+ lsb =
127
+ if previous_field
128
+ previous_field.msb.value + 1
129
+ else
130
+ 0
131
+ end
132
+ msb = lsb + field.width.value - 1
133
+ [msb, lsb]
134
+ end
135
+
136
+ def allocate_field_bits_msb0(instance, previous_field, field)
137
+ lsb =
138
+ if previous_field
139
+ previous_field.msb.value - 1
140
+ else
141
+ instance.property_value(:regwidth).value - 1
142
+ end
143
+ msb = lsb - field.width.value + 1
144
+ [msb, lsb]
145
+ end
146
+
68
147
  def check_overlapping_fields(instance)
69
148
  instance.instances.combination(2).each do |(field_a, field_b)|
70
149
  next unless overlapping_field_pair?(field_a, field_b)
@@ -75,8 +154,8 @@ module SystemRDL
75
154
  end
76
155
 
77
156
  def overlapping_field_pair?(field_a, field_b)
78
- range_a = (field_a.lsb.value..field_a.msb.value)
79
- range_b = (field_b.lsb.value..field_b.msb.value)
157
+ range_a = field_bit_range(field_a)
158
+ range_b = field_bit_range(field_b)
80
159
  return false unless range_a.include?(range_b.begin) || range_b.include?(range_a.begin)
81
160
 
82
161
  r_a = field_a.sw_readable?
@@ -86,22 +165,34 @@ module SystemRDL
86
165
  (r_a && r_b) || (w_a && w_b)
87
166
  end
88
167
 
168
+ def field_bit_range(field)
169
+ pos = [field.msb.value, field.lsb.value].sort
170
+ pos[0]..pos[1]
171
+ end
172
+
89
173
  def check_fields_out_of_register(instance)
90
174
  regwidth = instance.property_value(:regwidth).value
91
175
  instance.instances.each do |field|
92
- msb = field.msb.value
93
- lsb = field.lsb.value
94
- next if msb < regwidth
176
+ next unless field.msb
95
177
 
96
- message = "field out of register: bit position [#{msb}:#{lsb}] regwidth #{regwidth}"
178
+ msb = field.msb
179
+ lsb = field.lsb
180
+ next if inside_regwidth?(msb, lsb, regwidth)
181
+
182
+ message = "field out of register: bit range [#{msb}:#{lsb}] regwidth #{regwidth}"
97
183
  raise_evaluation_error message, field.token_range
98
184
  end
99
185
  end
100
186
 
187
+ def inside_regwidth?(msb, lsb, regwidth)
188
+ range = [msb.value, lsb.value]
189
+ range.none?(&:negative?) && range.sort[1] < regwidth
190
+ end
191
+
101
192
  def check_fields_spanning_sub_word_boundary(instance)
102
193
  accesswidth = instance.property_value(:accesswidth).value
103
194
  instance.instances.each do |field|
104
- next unless field_with_side_effect?(field)
195
+ next unless field.msb && field_with_side_effect?(field)
105
196
 
106
197
  msb = field.msb.value
107
198
  lsb = field.lsb.value
@@ -109,7 +200,7 @@ module SystemRDL
109
200
 
110
201
  message =
111
202
  'field spanning sub-word boundary not allowed: ' \
112
- "bit position [#{msb}:#{lsb}] accesswidth #{accesswidth}"
203
+ "bit range [#{msb}:#{lsb}] accesswidth #{accesswidth}"
113
204
  raise_evaluation_error message, field.token_range
114
205
  end
115
206
  end
@@ -124,10 +215,17 @@ module SystemRDL
124
215
  end
125
216
 
126
217
  class RegInstance < Instance
218
+ include ArrayInstance
219
+ include InstTypeAwareInstance
220
+
127
221
  attr_accessor :address
128
222
  attr_accessor :stride
129
223
  attr_accessor :alignment
130
224
 
225
+ def virtual_reg?
226
+ parent.mem?
227
+ end
228
+
131
229
  def definable?(definition)
132
230
  definition.layer in :field
133
231
  end
@@ -3,24 +3,44 @@
3
3
  module SystemRDL
4
4
  module Evaluator
5
5
  class RegFileDefinition < ComponentDefinition
6
- include ContainerComponent
6
+ include InstTypeAwareComponent
7
+ include BlockComponent
7
8
 
8
9
  def validate(instance)
9
10
  check_structural_component_instances(instance)
11
+ check_alignment_property(instance)
12
+ end
13
+
14
+ def finalize(instance)
15
+ allocate_addresses(instance)
16
+ check_address_operations(instance)
17
+ check_overlapping_address_ranges(instance)
10
18
  end
11
19
 
12
20
  def layer
13
21
  :regfile
14
22
  end
15
23
 
24
+ def support_inst_type?(_inst_type)
25
+ true
26
+ end
27
+
16
28
  private
17
29
 
18
30
  def instance_class
19
31
  RegFileInstance
20
32
  end
33
+
34
+ def apply_inst_values(instance, inst_values)
35
+ apply_address_operations(instance, inst_values)
36
+ check_range(inst_values)
37
+ end
21
38
  end
22
39
 
23
40
  class RegFileInstance < Instance
41
+ include InstTypeAwareInstance
42
+ include BlockInstance
43
+
24
44
  def definable?(definition)
25
45
  definition.layer in :regfile | :reg | :field
26
46
  end
@@ -14,7 +14,7 @@ module SystemRDL
14
14
 
15
15
  def evaluate(instance, **optargs)
16
16
  inherit(instance) if instance&.root?
17
- root = create_instance(nil, :root, nil, nil, nil, **optargs)
17
+ root = create_instance(nil, InstArgs.new(:root, nil, nil), nil, nil, **optargs)
18
18
  root.finalize
19
19
  root
20
20
  end
@@ -7,8 +7,8 @@ module SystemRDL
7
7
  @name = inst.element_name
8
8
  @layer = inst.layer
9
9
  @parent = parent
10
- @instances = build_sub_instances(inst)
11
- @properties = build_properties(inst)
10
+ @instances = build_sub_instances(inst).freeze
11
+ @properties = build_properties(inst).freeze
12
12
  @token_range = inst.token_range
13
13
  freeze
14
14
  end
@@ -17,6 +17,7 @@ module SystemRDL
17
17
  attr_reader :layer
18
18
  attr_reader :parent
19
19
  attr_reader :instances
20
+ attr_reader :properties
20
21
  attr_reader :token_range
21
22
 
22
23
  class << self
@@ -24,8 +25,8 @@ module SystemRDL
24
25
 
25
26
  private
26
27
 
27
- def def_property(property_name)
28
- (@properties ||= []) << property_name
28
+ def def_property(property_name, value_class = nil, &body)
29
+ (@properties ||= {})[property_name] = [value_class, body]
29
30
  class_eval(<<~M, __FILE__, __LINE__ + 1)
30
31
  # def display_name
31
32
  # @properties[:display_name]&.value
@@ -37,17 +38,16 @@ module SystemRDL
37
38
  end
38
39
  end
39
40
 
40
- def_property :display_name
41
- def_property :desc
42
-
43
41
  def to_s
44
42
  "#{name} (#{layer})"
45
43
  end
46
44
 
47
- def full_name
48
- elements = [self]
49
- current = @parent
45
+ def full_name(exclude_addrmap: false)
46
+ elements = []
47
+ current = self
50
48
  while current
49
+ break if exclude_addrmap && current.layer == :addrmap
50
+
51
51
  elements.unshift(current)
52
52
  current = current.parent
53
53
  end
@@ -78,6 +78,7 @@ module SystemRDL
78
78
  inst.instances.map do |sub_inst|
79
79
  case sub_inst.layer
80
80
  when :addrmap then AddrMap.new(sub_inst, self)
81
+ when :mem then Mem.new(sub_inst, self)
81
82
  when :regfile then RegFile.new(sub_inst, self)
82
83
  when :reg then Reg.new(sub_inst, self)
83
84
  when :field then Field.new(sub_inst, self)
@@ -86,80 +87,118 @@ module SystemRDL
86
87
  end
87
88
 
88
89
  def build_properties(inst)
89
- properties.to_h do |prop_name|
90
- prop_value =
91
- if prop_name == :display_name
92
- inst.property_value(:name)
93
- elsif (property = inst.property(prop_name))
94
- property.value
90
+ self.class.properties.to_h do |prop_name, (default_class, body)|
91
+ prop_value, prop_value_class, token_range =
92
+ if body
93
+ value, klass = body.call(inst)
94
+ [value, klass || Value]
95
95
  else
96
- inst.__send__(prop_name)
96
+ value = eval_prop_value(prop_name, inst)
97
+ klass = select_value_class(value, default_class)
98
+ [value&.value, klass, value&.token_range]
97
99
  end
98
- [prop_name, create_property_value(prop_name, prop_value)]
100
+ [prop_name, prop_value_class.new(prop_name.to_s, prop_value, self, token_range)]
99
101
  end
100
102
  end
101
103
 
102
- def properties
103
- klass = self.class
104
- [klass.superclass, klass].flat_map(&:properties)
104
+ def eval_prop_value(prop_name, inst)
105
+ if prop_name == :display_name
106
+ inst.property_value(:name)
107
+ elsif (property = inst.property(prop_name))
108
+ property.value
109
+ else
110
+ inst.__send__(prop_name)
111
+ end
105
112
  end
106
113
 
107
- def create_property_value(name, value)
108
- klass =
109
- if reference_value?(value)
110
- ReferenceValue
111
- elsif hex_value?(name, value)
112
- HexValue
113
- else
114
- Value
115
- end
116
- klass.new(name.to_s, value&.value, self, value&.token_range)
114
+ def select_value_class(value, default_class)
115
+ if reference_value?(value)
116
+ ReferenceValue
117
+ elsif default_class && value&.value
118
+ default_class
119
+ else
120
+ Value
121
+ end
117
122
  end
118
123
 
119
124
  def reference_value?(value)
120
- return false unless value
125
+ return false unless value.respond_to?(:type)
121
126
 
122
127
  value.type in :property_reference | :field_reference
123
128
  end
124
-
125
- def hex_value?(_name, _value)
126
- false
127
- end
128
129
  end
129
130
 
130
131
  class AddrMap < Instance
132
+ def_property :display_name
133
+ def_property :desc
134
+ def_property :address, HexValue
135
+ def_property :size, &:size
136
+ def_property :accesswidth, &:accesswidth
131
137
  def_property :sharedextbus
132
138
  def_property :errextbus
133
139
  def_property :bigendian
134
140
  def_property :littleendian
135
141
  def_property :rsvdset
136
142
  def_property :rsvdsetX
143
+ def_property :msb0
144
+
145
+ alias_method :regs, :instances
146
+ end
147
+
148
+ class Mem < Instance
149
+ def_property :display_name
150
+ def_property :desc
151
+ def_property :address, HexValue
152
+ def_property :size, &:size
153
+ def_property :accesswidth, &:accesswidth
154
+ def_property :entrywidth, &:entrywidth
155
+ def_property :memwidth
156
+ def_property :mementries
157
+ def_property :sw
158
+
159
+ alias_method :regs, :instances
160
+ end
161
+
162
+ class RegFile < Instance
163
+ def_property :display_name
164
+ def_property :desc
165
+ def_property :external, &:external
166
+ def_property :address, HexValue
167
+ def_property :size, &:size
168
+ def_property :accesswidth, &:accesswidth
169
+ def_property :sharedextbus
170
+ def_property :errextbus
137
171
 
138
172
  alias_method :regs, :instances
139
173
  end
140
174
 
141
175
  class Reg < Instance
142
- def_property :address
176
+ def_property :display_name
177
+ def_property :desc
178
+ def_property :external, &:external
179
+ def_property :address, HexValue
180
+ def_property :size, &:size
143
181
  def_property :accesswidth
144
182
  def_property :errextbus
145
183
  def_property :shared
146
184
 
147
185
  alias_method :fields, :instances
148
-
149
- private
150
-
151
- def hex_value?(name, _value)
152
- name == :address
153
- end
154
186
  end
155
187
 
156
188
  class Field < Instance
189
+ def_property :display_name
190
+ def_property :desc
157
191
  def_property :msb
158
192
  def_property :lsb
193
+ def_property :width do |inst|
194
+ msb = inst.msb.value
195
+ lsb = inst.lsb.value
196
+ msb - lsb + 1
197
+ end
159
198
  def_property :hw
160
199
  def_property :sw
161
200
  def_property :next
162
- def_property :reset
201
+ def_property :reset, HexValue
163
202
  def_property :resetsignal
164
203
  def_property :rclr
165
204
  def_property :rset
@@ -183,12 +222,6 @@ module SystemRDL
183
222
  def_property :hwmask
184
223
  def_property :precedence
185
224
  def_property :paritycheck
186
-
187
- private
188
-
189
- def hex_value?(name, value)
190
- name == :reset && value&.type == :bit
191
- end
192
225
  end
193
226
  end
194
227
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  module SystemRDL
4
4
  module Model
5
- Value = Data.define(:name, :value, :instance, :token_range) do
6
- def full_name
7
- "#{instance.full_name}.#{name}"
5
+ Value = Struct.new(:name, :value, :instance, :token_range) do
6
+ def full_name(exclude_addrmap: false)
7
+ [instance.full_name(exclude_addrmap:), name].reject(&:empty?).join('.')
8
8
  end
9
9
 
10
10
  def to_s
@@ -20,6 +20,18 @@ module SystemRDL
20
20
  pp_value(pp)
21
21
  end
22
22
 
23
+ def value?
24
+ true
25
+ end
26
+
27
+ def instance_ref?
28
+ false
29
+ end
30
+
31
+ def property_ref?
32
+ false
33
+ end
34
+
23
35
  private
24
36
 
25
37
  def pp_value(pp)
@@ -32,6 +44,18 @@ module SystemRDL
32
44
  full_name
33
45
  end
34
46
 
47
+ def value?
48
+ false
49
+ end
50
+
51
+ def instance_ref?
52
+ value.is_a?(Instance)
53
+ end
54
+
55
+ def property_ref?
56
+ value.is_a?(Value)
57
+ end
58
+
35
59
  private
36
60
 
37
61
  def pp_value(pp)
@@ -2,9 +2,45 @@
2
2
 
3
3
  module SystemRDL
4
4
  module Model
5
- def self.build(root)
6
- root.instances.map do |addrmap|
7
- AddrMap.new(addrmap, nil)
5
+ class << self
6
+ def build(root)
7
+ models = root.instances.map do |addrmap|
8
+ AddrMap.new(addrmap, nil)
9
+ end
10
+
11
+ finalize(models)
12
+ models
13
+ end
14
+
15
+ private
16
+
17
+ def finalize(models)
18
+ instances = models.flat_map { |model| collect_instances(model) }
19
+ properties = instances.flat_map { |inst| inst.properties.values }
20
+
21
+ properties.each do |property|
22
+ resolve_reference(property, instances, properties)
23
+ property.freeze
24
+ end
25
+ end
26
+
27
+ def collect_instances(model)
28
+ model.instances.flat_map { |inst| [inst, *collect_instances(inst)] }
29
+ end
30
+
31
+ def resolve_reference(property, instances, properties)
32
+ return if property.value?
33
+
34
+ path = property.value.full_name
35
+
36
+ if (ref = instances.find { |inst| inst.full_name == path })
37
+ property.value = ref
38
+ return
39
+ end
40
+
41
+ if (ref = properties.find { |prop| prop.full_name == path })
42
+ property.value = ref
43
+ end
8
44
  end
9
45
  end
10
46
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SystemRDL
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/systemrdl.rb CHANGED
@@ -25,11 +25,14 @@ require_relative 'systemrdl/evaluator/component_insts'
25
25
  require_relative 'systemrdl/evaluator/component_definition'
26
26
  require_relative 'systemrdl/evaluator/address_operation'
27
27
  require_relative 'systemrdl/evaluator/address_allocation'
28
+ require_relative 'systemrdl/evaluator/inst_type_aware_component'
28
29
  require_relative 'systemrdl/evaluator/array_component'
29
30
  require_relative 'systemrdl/evaluator/container_component'
31
+ require_relative 'systemrdl/evaluator/block_component'
30
32
  require_relative 'systemrdl/evaluator/field'
31
33
  require_relative 'systemrdl/evaluator/reg'
32
34
  require_relative 'systemrdl/evaluator/regfile'
35
+ require_relative 'systemrdl/evaluator/mem'
33
36
  require_relative 'systemrdl/evaluator/addrmap'
34
37
  require_relative 'systemrdl/evaluator/root'
35
38
  require_relative 'systemrdl/evaluator/processor'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: systemrdl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taichi Ishitani
@@ -39,15 +39,18 @@ files:
39
39
  - lib/systemrdl/evaluator/address_operation.rb
40
40
  - lib/systemrdl/evaluator/addrmap.rb
41
41
  - lib/systemrdl/evaluator/array_component.rb
42
+ - lib/systemrdl/evaluator/block_component.rb
42
43
  - lib/systemrdl/evaluator/builtin_properties.rb
43
44
  - lib/systemrdl/evaluator/common.rb
44
45
  - lib/systemrdl/evaluator/component_definition.rb
45
46
  - lib/systemrdl/evaluator/component_insts.rb
46
47
  - lib/systemrdl/evaluator/container_component.rb
47
48
  - lib/systemrdl/evaluator/field.rb
49
+ - lib/systemrdl/evaluator/inst_type_aware_component.rb
48
50
  - lib/systemrdl/evaluator/instance.rb
49
51
  - lib/systemrdl/evaluator/list.rb
50
52
  - lib/systemrdl/evaluator/literal.rb
53
+ - lib/systemrdl/evaluator/mem.rb
51
54
  - lib/systemrdl/evaluator/operation.rb
52
55
  - lib/systemrdl/evaluator/processor.rb
53
56
  - lib/systemrdl/evaluator/property.rb