systemrdl 0.1.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +127 -0
  4. data/lib/systemrdl/error.rb +55 -0
  5. data/lib/systemrdl/evaluator/address_allocation.rb +126 -0
  6. data/lib/systemrdl/evaluator/address_operation.rb +103 -0
  7. data/lib/systemrdl/evaluator/addrmap.rb +67 -0
  8. data/lib/systemrdl/evaluator/array_component.rb +42 -0
  9. data/lib/systemrdl/evaluator/builtin_properties.rb +400 -0
  10. data/lib/systemrdl/evaluator/common.rb +22 -0
  11. data/lib/systemrdl/evaluator/component_definition.rb +185 -0
  12. data/lib/systemrdl/evaluator/component_insts.rb +106 -0
  13. data/lib/systemrdl/evaluator/container_component.rb +16 -0
  14. data/lib/systemrdl/evaluator/field.rb +245 -0
  15. data/lib/systemrdl/evaluator/instance.rb +120 -0
  16. data/lib/systemrdl/evaluator/list.rb +26 -0
  17. data/lib/systemrdl/evaluator/literal.rb +173 -0
  18. data/lib/systemrdl/evaluator/operation.rb +241 -0
  19. data/lib/systemrdl/evaluator/processor.rb +166 -0
  20. data/lib/systemrdl/evaluator/property.rb +116 -0
  21. data/lib/systemrdl/evaluator/property_assignment.rb +220 -0
  22. data/lib/systemrdl/evaluator/reference.rb +135 -0
  23. data/lib/systemrdl/evaluator/reg.rb +156 -0
  24. data/lib/systemrdl/evaluator/regfile.rb +33 -0
  25. data/lib/systemrdl/evaluator/root.rb +39 -0
  26. data/lib/systemrdl/evaluator/value.rb +13 -0
  27. data/lib/systemrdl/evaluator.rb +14 -0
  28. data/lib/systemrdl/model/instance.rb +194 -0
  29. data/lib/systemrdl/model/value.rb +54 -0
  30. data/lib/systemrdl/model.rb +11 -0
  31. data/lib/systemrdl/parser/generated_parser.rb +2808 -0
  32. data/lib/systemrdl/parser/node.rb +17 -0
  33. data/lib/systemrdl/parser/parser.rb +86 -0
  34. data/lib/systemrdl/parser/scanner.rb +251 -0
  35. data/lib/systemrdl/parser/systemrdl.y +448 -0
  36. data/lib/systemrdl/parser/token.rb +58 -0
  37. data/lib/systemrdl/parser.rb +11 -0
  38. data/lib/systemrdl/version.rb +5 -0
  39. data/lib/systemrdl.rb +90 -0
  40. metadata +96 -0
@@ -0,0 +1,241 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SystemRDL
4
+ module Evaluator
5
+ class Operation
6
+ include Common
7
+
8
+ attr_reader :token_range
9
+
10
+ def evaluate(instance, width: nil, **_optargs)
11
+ value, type, width = eval_operation(instance, width)
12
+ Value.new(value, type, width, token_range)
13
+ end
14
+
15
+ private
16
+
17
+ def integral_operand?(operand)
18
+ [:bit, :boolean].include?(operand.type)
19
+ end
20
+
21
+ def check_integral_operand(operand)
22
+ return if integral_operand?(operand)
23
+
24
+ message = "non integral operand is given: #{operand.type}"
25
+ raise_evaluation_error message, token_range
26
+ end
27
+
28
+ def to_boolean(instance, operand)
29
+ operand = eval_operand(instance, operand, nil, check: true)
30
+
31
+ if operand.type == :boolean
32
+ operand.value
33
+ else
34
+ operand.value != 0
35
+ end
36
+ end
37
+
38
+ def to_int(instance, operand, width = nil, evaluation: true)
39
+ operand = eval_operand(instance, operand, width, check: true) if evaluation
40
+
41
+ if operand.type == :boolean
42
+ [(operand.value && 1) || 0, 1]
43
+ else
44
+ [operand.value, width || operand.width]
45
+ end
46
+ end
47
+
48
+ def eval_operand(instance, operand, width, check:)
49
+ result = operand.evaluate(instance, width:)
50
+ check_integral_operand(result) if check
51
+ result
52
+ end
53
+
54
+ def mask(value, width)
55
+ value & ((1 << width) - 1)
56
+ end
57
+ end
58
+
59
+ class UnaryOperation < Operation
60
+ def initialize(operator, operand, token_range)
61
+ @operator = operator
62
+ @operand = operand
63
+ super(token_range)
64
+ end
65
+
66
+ def connect(parent, component)
67
+ super
68
+ @operand.connect(self, component)
69
+ end
70
+
71
+ def expression_width
72
+ if [:~, :+, :-].include?(@operator)
73
+ @operand.expression_width
74
+ else
75
+ 1
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def eval_operation(instance, width)
82
+ case @operator
83
+ when :! then logical_negation(instance)
84
+ when :+, :-, :~ then general_op(instance, width)
85
+ when :&, :|, :^ then reduction(instance, @operator, false)
86
+ when :'~&' then reduction(instance, :&, true)
87
+ when :'~|' then reduction(instance, :|, true)
88
+ when :'~^', :'^~' then reduction(instance, :^, true)
89
+ end
90
+ end
91
+
92
+ def logical_negation(instance)
93
+ value = to_boolean(instance, @operand)
94
+ [!value, :boolean]
95
+ end
96
+
97
+ def reduction(instance, operator, negate)
98
+ value, width = to_int(instance, @operand)
99
+
100
+ init_value = { '&': 1, '|': 0, '^': 0 }[operator]
101
+ result = width.times.inject(init_value) do |r, i|
102
+ r.__send__(operator, value[i])
103
+ end
104
+
105
+ if negate
106
+ [mask(~result, 1), :bit, 1]
107
+ else
108
+ [result, :bit, 1]
109
+ end
110
+ end
111
+
112
+ def general_op(instance, width)
113
+ width ||= @operand.expression_width
114
+ value, _ = to_int(instance, @operand, width)
115
+
116
+ op = { '+': :+@, '-': :-@, '~': :~ }[@operator]
117
+ result = value.__send__(op)
118
+ [mask(result, width), :bit, width]
119
+ end
120
+ end
121
+
122
+ class BinaryOperation < Operation
123
+ def initialize(operator, l_operand, r_operand, token_range)
124
+ @operator = operator
125
+ @l_operand = l_operand
126
+ @r_operand = r_operand
127
+ super(token_range)
128
+ end
129
+
130
+ def connect(parent, component)
131
+ super
132
+ @l_operand.connect(self, component)
133
+ @r_operand.connect(self, component)
134
+ end
135
+
136
+ def expression_width
137
+ if [:'&&', :'||', :==, :!=, :<, :>, :<=, :>=].include?(@operator)
138
+ 1
139
+ else
140
+ eval_expression_width
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def eval_expression_width
147
+ lhs_width = @l_operand.expression_width
148
+ return lhs_width if [:<<, :>>, :**].include?(@operator)
149
+
150
+ rhs_width = @r_operand.expression_width
151
+
152
+ if lhs_width && rhs_width
153
+ [lhs_width, rhs_width].max
154
+ else
155
+ lhs_width || rhs_width
156
+ end
157
+ end
158
+
159
+ def eval_operation(instance, width)
160
+ case @operator
161
+ when :'&&', :'||' then logical_op(instance)
162
+ when :==, :!= then equality_op(instance)
163
+ when :<, :>, :<=, :>= then relational_op(instance)
164
+ when :<<, :>>, :** then shift_power_op(instance, width)
165
+ when :'~^', :'^~' then general_op(instance, :^, width, true)
166
+ else general_op(instance, @operator, width, false)
167
+ end
168
+ end
169
+
170
+ def logical_op(instance)
171
+ lhs = to_boolean(instance, @l_operand)
172
+ rhs = to_boolean(instance, @r_operand)
173
+ if @operator == :'&&'
174
+ [lhs && rhs, :boolean]
175
+ else
176
+ [lhs || rhs, :boolean]
177
+ end
178
+ end
179
+
180
+ def equality_op(instance)
181
+ lhs, rhs = eval_eq_operands(instance)
182
+ [lhs.__send__(@operator, rhs), :boolean]
183
+ end
184
+
185
+ def eval_eq_operands(instance)
186
+ width = eval_expression_width
187
+ l_operand = eval_operand(instance, @l_operand, width, check: false)
188
+ r_operand = eval_operand(instance, @r_operand, width, check: false)
189
+
190
+ if [l_operand, r_operand].all? { integral_operand?(_1) }
191
+ lhs, _ = to_int(instance, l_operand, evaluation: false)
192
+ rhs, _ = to_int(instance, r_operand, evaluation: false)
193
+ [lhs, rhs]
194
+ elsif l_operand.type == r_operand.type
195
+ [l_operand.value, r_operand.value]
196
+ else
197
+ message = "#{r_operand.type} type is not compatible with #{l_operand.type} type"
198
+ raise_evaluation_error message, @r_operand.token_range
199
+ end
200
+ end
201
+
202
+ def relational_op(instance)
203
+ lhs, rhs, _ = integral_operands(instance, nil)
204
+ [lhs.__send__(@operator, rhs), :boolean]
205
+ end
206
+
207
+ def shift_power_op(instance, width)
208
+ width ||= eval_expression_width
209
+ lhs, _ = to_int(instance, @l_operand, width)
210
+ rhs, _ = to_int(instance, @r_operand)
211
+
212
+ result = lhs.__send__(@operator, rhs)
213
+ [mask(result, width), :bit, width]
214
+ end
215
+
216
+ def general_op(instance, operator, width, negate)
217
+ lhs, rhs, width = integral_operands(instance, width)
218
+
219
+ if div_by_0?(rhs)
220
+ message = 'divisor should be non zero value'
221
+ raise_evaluation_error message, @r_operand.token_range
222
+ end
223
+
224
+ result = lhs.__send__(operator, rhs)
225
+ result = ~result if negate
226
+ [mask(result, width), :bit, width]
227
+ end
228
+
229
+ def div_by_0?(rhs)
230
+ [:/, :%].include?(@operator) && rhs == 0
231
+ end
232
+
233
+ def integral_operands(instance, width)
234
+ width ||= eval_expression_width
235
+ lhs, _ = to_int(instance, @l_operand, width)
236
+ rhs, _ = to_int(instance, @r_operand, width)
237
+ [lhs, rhs, width]
238
+ end
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SystemRDL
4
+ module Evaluator
5
+ class Processor < AST::Processor
6
+ def on_id(node)
7
+ id = node.children[0].to_sym
8
+ Value.new(id, nil, nil, node.token_range)
9
+ end
10
+
11
+ def on_boolean(node)
12
+ Boolean.new(node)
13
+ end
14
+
15
+ def on_number(node)
16
+ Number.new(node)
17
+ end
18
+
19
+ def on_verilog_number(node)
20
+ VerilogNumber.new(node)
21
+ end
22
+
23
+ def on_string(node)
24
+ String.new(node)
25
+ end
26
+
27
+ def on_accesstype(node)
28
+ AccessType.new(node)
29
+ end
30
+
31
+ def on_onreadtype(node)
32
+ OnReadType.new(node)
33
+ end
34
+
35
+ def on_onwritetype(node)
36
+ OnWriteType.new(node)
37
+ end
38
+
39
+ def on_addressingtype(node)
40
+ AddressingType.new(node)
41
+ end
42
+
43
+ def on_precedencetype(node)
44
+ PrecedenceType.new(node)
45
+ end
46
+
47
+ def on_unary_operation(node)
48
+ operator = node.children[0].to_sym
49
+ operand = process(node.children[1])
50
+ UnaryOperation.new(operator, operand, node.token_range)
51
+ end
52
+
53
+ def on_binary_operation(node)
54
+ operator = node.children[0].to_sym
55
+ l_operand = process(node.children[1])
56
+ r_operand = process(node.children[2])
57
+ BinaryOperation.new(operator, l_operand, r_operand, node.token_range)
58
+ end
59
+
60
+ def on_array(node)
61
+ elements = process_all(node.children)
62
+ List.new(elements, node.token_range)
63
+ end
64
+
65
+ def on_range(node)
66
+ elements = process_all(node.children)
67
+ List.new(elements, node.token_range)
68
+ end
69
+
70
+ def on_instance_ref_element(node)
71
+ id = process(node.children[0])
72
+ array = process(node.children[1])
73
+ InstanceRefElement.new(id, array, node.token_range)
74
+ end
75
+
76
+ def on_instance_ref(node)
77
+ elements = process_all(node.children)
78
+ InstanceRef.new(elements, node.token_range)
79
+ end
80
+
81
+ def on_prop_ref(node)
82
+ instance_ref = process(node.children[0])
83
+ prop = process(node.children[1])
84
+ PropRef.new(instance_ref, prop, node.token_range)
85
+ end
86
+
87
+ def on_default_prop_assignment(node)
88
+ prop_name, value = process_all(node.children)
89
+ DefaultPropertyAssignment.new(prop_name, value, node.token_range)
90
+ end
91
+
92
+ def on_prop_assignment(node)
93
+ id, value = process_all(node.children)
94
+ prop_ref = PropRef.new(nil, id, node.children[0].token_range)
95
+ PropertyAssignment.new(prop_ref, value, node.token_range)
96
+ end
97
+
98
+ def on_post_prop_assignment(node)
99
+ prop_ref, value = process_all(node.children)
100
+ PostPropertyAssignment.new(prop_ref, value, node.token_range)
101
+ end
102
+
103
+ def on_reset_value(node)
104
+ process(node.children[0])
105
+ end
106
+
107
+ def on_address_assignment(node)
108
+ process(node.children[0])
109
+ end
110
+
111
+ def on_address_stride(node)
112
+ process(node.children[0])
113
+ end
114
+
115
+ def on_address_alignment(node)
116
+ process(node.children[0])
117
+ end
118
+
119
+ def on_component_inst(node)
120
+ inst_id = process(node.children[0])
121
+ inst_values =
122
+ [
123
+ :array, :range, :reset_value, :address_assignment, :address_stride, :address_alignment
124
+ ].zip(node.children[1..]).to_h { |k, n| [k, process(n)] }
125
+ ComponentInst.new(inst_id, inst_values, node.token_range)
126
+ end
127
+
128
+ def on_component_insts(node)
129
+ insts = process_all(node.children)
130
+ ComponentInsts.new(insts, node.token_range)
131
+ end
132
+
133
+ def on_explicit_component_inst(node)
134
+ id = process(node.children[0])
135
+ insts = process(node.children[1])
136
+ ExplicitComponentInst.new(id, insts, node.token_range)
137
+ end
138
+
139
+ def on_component_named_def(node)
140
+ id, *elements = process_all(node.children[1..])
141
+ component_definition(node).new(id, elements, nil, node.token_range)
142
+ end
143
+
144
+ def on_component_anon_def(node)
145
+ *elements, insts = process_all(node.children[1..])
146
+ component_definition(node).new(nil, elements, insts, node.token_range)
147
+ end
148
+
149
+ def on_root(node)
150
+ elements = process_all(node.children)
151
+ Root.new(elements, node.token_range)
152
+ end
153
+
154
+ private
155
+
156
+ def component_definition(node)
157
+ case node.children[0].to_sym
158
+ when :addrmap then AddrMapDefinition
159
+ when :regfile then RegFileDefinition
160
+ when :reg then RegDefinition
161
+ when :field then FieldDefinition
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SystemRDL
4
+ module Evaluator
5
+ class Property
6
+ def initialize(instance, definition, value)
7
+ @instance = instance
8
+ @definition = definition
9
+ @value = value
10
+ end
11
+
12
+ attr_reader :value
13
+
14
+ def name
15
+ @definition.name
16
+ end
17
+
18
+ def types
19
+ @definition.types
20
+ end
21
+
22
+ def to_value(token_range)
23
+ Value.new(self, :property_reference, nil, token_range)
24
+ end
25
+
26
+ def full_name
27
+ [@instance.full_name, name].join('.')
28
+ end
29
+
30
+ def ref_target?
31
+ if @definition.ref_target.is_a?(Proc)
32
+ instance_exec(&@definition.ref_target)
33
+ else
34
+ @definition.ref_target
35
+ end
36
+ end
37
+
38
+ def dynamic_assign?
39
+ @definition.dynamic_assign
40
+ end
41
+
42
+ def per_element_assign?
43
+ @definition.per_element_assign
44
+ end
45
+
46
+ def assign(value)
47
+ @value = value
48
+ @assigned = true
49
+ end
50
+
51
+ def assigned?
52
+ @assigned || false
53
+ end
54
+
55
+ private
56
+
57
+ def set?
58
+ return false if value.nil?
59
+
60
+ value.value != false
61
+ end
62
+ end
63
+
64
+ class PropertyDefinition
65
+ def initialize(name)
66
+ @name = name
67
+ yield(self)
68
+ end
69
+
70
+ attr_reader :name
71
+ attr_accessor :targets
72
+ attr_accessor :types
73
+ attr_accessor :ref_target
74
+ attr_accessor :dynamic_assign
75
+ attr_accessor :per_element_assign
76
+ attr_accessor :default_value
77
+
78
+ def target?(instance)
79
+ return false if instance.root?
80
+
81
+ targets.nil? || targets.include?(instance.layer)
82
+ end
83
+
84
+ def create(instance)
85
+ value = eval_value(instance)
86
+ Property.new(instance, self, value)
87
+ end
88
+
89
+ private
90
+
91
+ def eval_value(instance)
92
+ value = instance.definition.find_default_property(name)
93
+ return value if value
94
+
95
+ value =
96
+ if default_value.is_a?(Proc)
97
+ default_value.call(instance)
98
+ else
99
+ default_value
100
+ end
101
+
102
+ return if value.nil?
103
+
104
+ create_value(value)
105
+ end
106
+
107
+ def create_value(value)
108
+ case types[0]
109
+ when :longint then Value.new(value, :bit, 64, nil)
110
+ when :boolean then Value.new(value, :boolean, 1, nil)
111
+ else Value.new(value, types[0], nil, nil)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end