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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +127 -0
- data/lib/systemrdl/error.rb +55 -0
- data/lib/systemrdl/evaluator/address_allocation.rb +126 -0
- data/lib/systemrdl/evaluator/address_operation.rb +103 -0
- data/lib/systemrdl/evaluator/addrmap.rb +67 -0
- data/lib/systemrdl/evaluator/array_component.rb +42 -0
- data/lib/systemrdl/evaluator/builtin_properties.rb +400 -0
- data/lib/systemrdl/evaluator/common.rb +22 -0
- data/lib/systemrdl/evaluator/component_definition.rb +185 -0
- data/lib/systemrdl/evaluator/component_insts.rb +106 -0
- data/lib/systemrdl/evaluator/container_component.rb +16 -0
- data/lib/systemrdl/evaluator/field.rb +245 -0
- data/lib/systemrdl/evaluator/instance.rb +120 -0
- data/lib/systemrdl/evaluator/list.rb +26 -0
- data/lib/systemrdl/evaluator/literal.rb +173 -0
- data/lib/systemrdl/evaluator/operation.rb +241 -0
- data/lib/systemrdl/evaluator/processor.rb +166 -0
- data/lib/systemrdl/evaluator/property.rb +116 -0
- data/lib/systemrdl/evaluator/property_assignment.rb +220 -0
- data/lib/systemrdl/evaluator/reference.rb +135 -0
- data/lib/systemrdl/evaluator/reg.rb +156 -0
- data/lib/systemrdl/evaluator/regfile.rb +33 -0
- data/lib/systemrdl/evaluator/root.rb +39 -0
- data/lib/systemrdl/evaluator/value.rb +13 -0
- data/lib/systemrdl/evaluator.rb +14 -0
- data/lib/systemrdl/model/instance.rb +194 -0
- data/lib/systemrdl/model/value.rb +54 -0
- data/lib/systemrdl/model.rb +11 -0
- data/lib/systemrdl/parser/generated_parser.rb +2808 -0
- data/lib/systemrdl/parser/node.rb +17 -0
- data/lib/systemrdl/parser/parser.rb +86 -0
- data/lib/systemrdl/parser/scanner.rb +251 -0
- data/lib/systemrdl/parser/systemrdl.y +448 -0
- data/lib/systemrdl/parser/token.rb +58 -0
- data/lib/systemrdl/parser.rb +11 -0
- data/lib/systemrdl/version.rb +5 -0
- data/lib/systemrdl.rb +90 -0
- metadata +96 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SystemRDL
|
|
4
|
+
module Evaluator
|
|
5
|
+
module BuiltinProperties
|
|
6
|
+
class << self
|
|
7
|
+
attr_reader :properties
|
|
8
|
+
|
|
9
|
+
def find(name)
|
|
10
|
+
properties.find { |prop| prop.name == name }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def def_property(name, &)
|
|
16
|
+
@properties ||= []
|
|
17
|
+
@properties << PropertyDefinition.new(name, &)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Table G1—Property cross-reference
|
|
23
|
+
#
|
|
24
|
+
def_property :accesswidth do |prop|
|
|
25
|
+
prop.targets = [:reg]
|
|
26
|
+
prop.types = [:longint]
|
|
27
|
+
prop.dynamic_assign = true
|
|
28
|
+
prop.ref_target = false
|
|
29
|
+
prop.per_element_assign = false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def_property :addressing do |prop|
|
|
33
|
+
prop.targets = [:addrmap]
|
|
34
|
+
prop.types = [:addressingtype]
|
|
35
|
+
prop.dynamic_assign = false
|
|
36
|
+
prop.ref_target = false
|
|
37
|
+
prop.per_element_assign = false
|
|
38
|
+
prop.default_value = :regalign
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def_property :alignment do |prop|
|
|
42
|
+
prop.targets = [:addrmap, :regfile]
|
|
43
|
+
prop.types = [:longint]
|
|
44
|
+
prop.dynamic_assign = false
|
|
45
|
+
prop.ref_target = false
|
|
46
|
+
prop.per_element_assign = false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def_property :anded do |prop|
|
|
50
|
+
prop.targets = [:field]
|
|
51
|
+
prop.types = [:boolean]
|
|
52
|
+
prop.dynamic_assign = true
|
|
53
|
+
prop.ref_target = true
|
|
54
|
+
prop.per_element_assign = false
|
|
55
|
+
prop.default_value = false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def_property :bigendian do |prop|
|
|
59
|
+
prop.targets = [:addrmap]
|
|
60
|
+
prop.types = [:boolean]
|
|
61
|
+
prop.dynamic_assign = true
|
|
62
|
+
prop.ref_target = false
|
|
63
|
+
prop.per_element_assign = false
|
|
64
|
+
prop.default_value = false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def_property :desc do |prop|
|
|
68
|
+
prop.types = [:string]
|
|
69
|
+
prop.dynamic_assign = true
|
|
70
|
+
prop.ref_target = false
|
|
71
|
+
prop.per_element_assign = true
|
|
72
|
+
prop.default_value = proc { '' }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def_property :errextbus do |prop|
|
|
76
|
+
prop.targets = [:addrmap, :regfile, :reg]
|
|
77
|
+
prop.types = [:boolean]
|
|
78
|
+
prop.dynamic_assign = false
|
|
79
|
+
prop.ref_target = false
|
|
80
|
+
prop.per_element_assign = false
|
|
81
|
+
prop.default_value = false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def_property :fieldwidth do |prop|
|
|
85
|
+
prop.targets = [:field]
|
|
86
|
+
prop.types = [:longint]
|
|
87
|
+
prop.dynamic_assign = false
|
|
88
|
+
prop.per_element_assign = false
|
|
89
|
+
prop.ref_target = false
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def_property :hw do |prop|
|
|
93
|
+
prop.targets = [:field]
|
|
94
|
+
prop.types = [:accesstype]
|
|
95
|
+
prop.dynamic_assign = false
|
|
96
|
+
prop.ref_target = false
|
|
97
|
+
prop.per_element_assign = false
|
|
98
|
+
prop.default_value = :rw
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def_property :hwclr do |prop|
|
|
102
|
+
prop.targets = [:field]
|
|
103
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
104
|
+
prop.dynamic_assign = true
|
|
105
|
+
prop.ref_target = proc { set? }
|
|
106
|
+
prop.per_element_assign = false
|
|
107
|
+
prop.default_value = false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def_property :hwenable do |prop|
|
|
111
|
+
prop.targets = [:field]
|
|
112
|
+
prop.types = [:field_reference, :property_reference]
|
|
113
|
+
prop.dynamic_assign = true
|
|
114
|
+
prop.ref_target = proc { set? }
|
|
115
|
+
prop.per_element_assign = false
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def_property :hwmask do |prop|
|
|
119
|
+
prop.targets = [:field]
|
|
120
|
+
prop.types = [:field_reference, :property_reference]
|
|
121
|
+
prop.dynamic_assign = true
|
|
122
|
+
prop.ref_target = proc { set? }
|
|
123
|
+
prop.per_element_assign = false
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def_property :hwset do |prop|
|
|
127
|
+
prop.targets = [:field]
|
|
128
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
129
|
+
prop.dynamic_assign = true
|
|
130
|
+
prop.ref_target = proc { set? }
|
|
131
|
+
prop.per_element_assign = false
|
|
132
|
+
prop.default_value = false
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def_property :littleendian do |prop|
|
|
136
|
+
prop.targets = [:addrmap]
|
|
137
|
+
prop.types = [:boolean]
|
|
138
|
+
prop.dynamic_assign = true
|
|
139
|
+
prop.ref_target = false
|
|
140
|
+
prop.per_element_assign = false
|
|
141
|
+
prop.default_value = false
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def_property :lsb0 do |prop|
|
|
145
|
+
prop.targets = [:addrmap]
|
|
146
|
+
prop.types = [:boolean]
|
|
147
|
+
prop.dynamic_assign = false
|
|
148
|
+
prop.ref_target = false
|
|
149
|
+
prop.per_element_assign = false
|
|
150
|
+
prop.default_value = false
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def_property :msb0 do |prop|
|
|
154
|
+
prop.targets = [:addrmap]
|
|
155
|
+
prop.types = [:boolean]
|
|
156
|
+
prop.dynamic_assign = false
|
|
157
|
+
prop.ref_target = false
|
|
158
|
+
prop.per_element_assign = false
|
|
159
|
+
prop.default_value = false
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def_property :name do |prop|
|
|
163
|
+
prop.types = [:string]
|
|
164
|
+
prop.dynamic_assign = true
|
|
165
|
+
prop.ref_target = false
|
|
166
|
+
prop.per_element_assign = true
|
|
167
|
+
prop.default_value = proc { |inst| inst.name.to_s }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def_property :next do |prop|
|
|
171
|
+
prop.targets = [:field]
|
|
172
|
+
prop.types = [:field_reference, :property_reference]
|
|
173
|
+
prop.dynamic_assign = true
|
|
174
|
+
prop.per_element_assign = false
|
|
175
|
+
prop.ref_target = proc { set? }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def_property :onread do |prop|
|
|
179
|
+
prop.targets = [:field]
|
|
180
|
+
prop.types = [:onreadtype]
|
|
181
|
+
prop.dynamic_assign = true
|
|
182
|
+
prop.ref_target = false
|
|
183
|
+
prop.per_element_assign = false
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def_property :onwrite do |prop|
|
|
187
|
+
prop.targets = [:field]
|
|
188
|
+
prop.types = [:onwritetype]
|
|
189
|
+
prop.dynamic_assign = true
|
|
190
|
+
prop.ref_target = false
|
|
191
|
+
prop.per_element_assign = false
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def_property :ored do |prop|
|
|
195
|
+
prop.targets = [:field]
|
|
196
|
+
prop.types = [:boolean]
|
|
197
|
+
prop.dynamic_assign = true
|
|
198
|
+
prop.ref_target = true
|
|
199
|
+
prop.per_element_assign = false
|
|
200
|
+
prop.default_value = false
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def_property :paritycheck do |prop|
|
|
204
|
+
prop.targets = [:field]
|
|
205
|
+
prop.types = [:boolean]
|
|
206
|
+
prop.dynamic_assign = false
|
|
207
|
+
prop.ref_target = false
|
|
208
|
+
prop.per_element_assign = false
|
|
209
|
+
prop.default_value = false
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def_property :precedence do |prop|
|
|
213
|
+
prop.targets = [:field]
|
|
214
|
+
prop.types = [:precedencetype]
|
|
215
|
+
prop.dynamic_assign = true
|
|
216
|
+
prop.ref_target = false
|
|
217
|
+
prop.per_element_assign = false
|
|
218
|
+
prop.default_value = :sw
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def_property :rclr do |prop|
|
|
222
|
+
prop.targets = [:field]
|
|
223
|
+
prop.types = [:boolean]
|
|
224
|
+
prop.dynamic_assign = true
|
|
225
|
+
prop.ref_target = false
|
|
226
|
+
prop.per_element_assign = false
|
|
227
|
+
prop.default_value = false
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def_property :regwidth do |prop|
|
|
231
|
+
prop.targets = [:reg]
|
|
232
|
+
prop.types = [:longint]
|
|
233
|
+
prop.dynamic_assign = false
|
|
234
|
+
prop.ref_target = false
|
|
235
|
+
prop.per_element_assign = false
|
|
236
|
+
prop.default_value = 32
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def_property :reset do |prop|
|
|
240
|
+
prop.targets = [:field]
|
|
241
|
+
prop.types = [:bit, :field_reference, :property_reference]
|
|
242
|
+
prop.dynamic_assign = true
|
|
243
|
+
prop.ref_target = proc { set? }
|
|
244
|
+
prop.per_element_assign = false
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def_property :resetsignal do |prop|
|
|
248
|
+
prop.targets = [:field]
|
|
249
|
+
prop.types = [:field_reference, :property_reference]
|
|
250
|
+
prop.dynamic_assign = true
|
|
251
|
+
prop.ref_target = proc { set? }
|
|
252
|
+
prop.per_element_assign = false
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def_property :rset do |prop|
|
|
256
|
+
prop.targets = [:field]
|
|
257
|
+
prop.types = [:boolean]
|
|
258
|
+
prop.dynamic_assign = true
|
|
259
|
+
prop.ref_target = false
|
|
260
|
+
prop.per_element_assign = false
|
|
261
|
+
prop.default_value = false
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def_property :rsvdset do |prop|
|
|
265
|
+
prop.targets = [:addrmap]
|
|
266
|
+
prop.types = [:boolean]
|
|
267
|
+
prop.dynamic_assign = false
|
|
268
|
+
prop.ref_target = false
|
|
269
|
+
prop.per_element_assign = false
|
|
270
|
+
prop.default_value = false
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def_property :rsvdsetX do |prop|
|
|
274
|
+
prop.targets = [:addrmap]
|
|
275
|
+
prop.types = [:boolean]
|
|
276
|
+
prop.dynamic_assign = false
|
|
277
|
+
prop.ref_target = false
|
|
278
|
+
prop.per_element_assign = false
|
|
279
|
+
prop.default_value = false
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def_property :shared do |prop|
|
|
283
|
+
prop.targets = [:reg]
|
|
284
|
+
prop.types = [:boolean]
|
|
285
|
+
prop.dynamic_assign = false
|
|
286
|
+
prop.ref_target = false
|
|
287
|
+
prop.per_element_assign = false
|
|
288
|
+
prop.default_value = false
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def_property :sharedextbus do |prop|
|
|
292
|
+
prop.targets = [:addrmap, :regfile]
|
|
293
|
+
prop.types = [:boolean]
|
|
294
|
+
prop.dynamic_assign = false
|
|
295
|
+
prop.ref_target = false
|
|
296
|
+
prop.per_element_assign = false
|
|
297
|
+
prop.default_value = false
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def_property :singlepulse do |prop|
|
|
301
|
+
prop.targets = [:field]
|
|
302
|
+
prop.types = [:boolean]
|
|
303
|
+
prop.dynamic_assign = true
|
|
304
|
+
prop.ref_target = false
|
|
305
|
+
prop.per_element_assign = false
|
|
306
|
+
prop.default_value = false
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def_property :sw do |prop|
|
|
310
|
+
prop.targets = [:field]
|
|
311
|
+
prop.types = [:accesstype]
|
|
312
|
+
prop.dynamic_assign = true
|
|
313
|
+
prop.ref_target = false
|
|
314
|
+
prop.per_element_assign = false
|
|
315
|
+
prop.default_value = :rw
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def_property :swacc do |prop|
|
|
319
|
+
prop.targets = [:field]
|
|
320
|
+
prop.types = [:boolean]
|
|
321
|
+
prop.dynamic_assign = true
|
|
322
|
+
prop.ref_target = true
|
|
323
|
+
prop.per_element_assign = false
|
|
324
|
+
prop.default_value = false
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def_property :swmod do |prop|
|
|
328
|
+
prop.targets = [:field]
|
|
329
|
+
prop.types = [:boolean]
|
|
330
|
+
prop.dynamic_assign = true
|
|
331
|
+
prop.ref_target = true
|
|
332
|
+
prop.per_element_assign = false
|
|
333
|
+
prop.default_value = false
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def_property :swwe do |prop|
|
|
337
|
+
prop.targets = [:field]
|
|
338
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
339
|
+
prop.dynamic_assign = true
|
|
340
|
+
prop.ref_target = proc { set? }
|
|
341
|
+
prop.per_element_assign = false
|
|
342
|
+
prop.default_value = false
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def_property :swwel do |prop|
|
|
346
|
+
prop.targets = [:field]
|
|
347
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
348
|
+
prop.dynamic_assign = true
|
|
349
|
+
prop.ref_target = proc { set? }
|
|
350
|
+
prop.per_element_assign = false
|
|
351
|
+
prop.default_value = false
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def_property :we do |prop|
|
|
355
|
+
prop.targets = [:field]
|
|
356
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
357
|
+
prop.dynamic_assign = true
|
|
358
|
+
prop.ref_target = proc { set? }
|
|
359
|
+
prop.per_element_assign = false
|
|
360
|
+
prop.default_value = false
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def_property :wel do |prop|
|
|
364
|
+
prop.targets = [:field]
|
|
365
|
+
prop.types = [:boolean, :field_reference, :property_reference]
|
|
366
|
+
prop.dynamic_assign = true
|
|
367
|
+
prop.ref_target = proc { set? }
|
|
368
|
+
prop.per_element_assign = false
|
|
369
|
+
prop.default_value = false
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def_property :woclr do |prop|
|
|
373
|
+
prop.targets = [:field]
|
|
374
|
+
prop.types = [:boolean]
|
|
375
|
+
prop.dynamic_assign = true
|
|
376
|
+
prop.ref_target = false
|
|
377
|
+
prop.per_element_assign = false
|
|
378
|
+
prop.default_value = false
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def_property :woset do |prop|
|
|
382
|
+
prop.targets = [:field]
|
|
383
|
+
prop.types = [:boolean]
|
|
384
|
+
prop.dynamic_assign = true
|
|
385
|
+
prop.ref_target = false
|
|
386
|
+
prop.per_element_assign = false
|
|
387
|
+
prop.default_value = false
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def_property :xored do |prop|
|
|
391
|
+
prop.targets = [:field]
|
|
392
|
+
prop.types = [:boolean]
|
|
393
|
+
prop.dynamic_assign = true
|
|
394
|
+
prop.ref_target = true
|
|
395
|
+
prop.per_element_assign = false
|
|
396
|
+
prop.default_value = false
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SystemRDL
|
|
4
|
+
module Evaluator
|
|
5
|
+
module Common
|
|
6
|
+
include RaiseEvaluationError
|
|
7
|
+
|
|
8
|
+
def initialize(token_range)
|
|
9
|
+
@token_range = token_range
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :token_range
|
|
13
|
+
attr_reader :parent
|
|
14
|
+
attr_reader :component
|
|
15
|
+
|
|
16
|
+
def connect(parent, component)
|
|
17
|
+
@parent = parent
|
|
18
|
+
@component = component
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SystemRDL
|
|
4
|
+
module Evaluator
|
|
5
|
+
class ComponentDefinition
|
|
6
|
+
include Common
|
|
7
|
+
|
|
8
|
+
def initialize(id, elements, insts, token_range)
|
|
9
|
+
super(token_range)
|
|
10
|
+
@id = id || insts.insts[0].inst_id
|
|
11
|
+
@definitions = {}
|
|
12
|
+
@elements = elements
|
|
13
|
+
@insts = insts
|
|
14
|
+
@default_properties = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :id
|
|
18
|
+
attr_reader :definitions
|
|
19
|
+
|
|
20
|
+
def connect(parent, component)
|
|
21
|
+
super
|
|
22
|
+
@component&.add_definition(self)
|
|
23
|
+
@elements.each { |element| element.connect(self, self) }
|
|
24
|
+
@insts&.connect(self, self)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def upper_layers(include_self: false)
|
|
28
|
+
return [] if layer == :root
|
|
29
|
+
|
|
30
|
+
layers = [*component.upper_layers, component]
|
|
31
|
+
layers << self if include_self
|
|
32
|
+
layers
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def evaluate(instance, **optargs)
|
|
36
|
+
check_definable(instance)
|
|
37
|
+
@insts&.evaluate(instance, @parent, @id, **optargs)
|
|
38
|
+
end
|
|
39
|
+
|
|
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
|
+
)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def validate(_instance)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def revalidate(_instance)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def finalize(_instance)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def assign_default_property(name, value, token_range)
|
|
59
|
+
if @default_properties.key?(name)
|
|
60
|
+
message = "#{name} already assigned in this scope"
|
|
61
|
+
raise_evaluation_error message, token_range
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@default_properties[name] = value
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def find_default_property(name)
|
|
68
|
+
upper_layers.reverse_each do |component|
|
|
69
|
+
if (prop = component.default_properties[name])
|
|
70
|
+
return prop
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def check_power_of_2(instance, name, min_value)
|
|
80
|
+
value = instance.property_value(name)
|
|
81
|
+
return unless value
|
|
82
|
+
|
|
83
|
+
return if power_of_2?(value.value, min_value)
|
|
84
|
+
|
|
85
|
+
message = "#{name} must be a power of 2: #{value}"
|
|
86
|
+
raise_evaluation_error message, value.token_range
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def power_of_2?(value, min_value)
|
|
90
|
+
value >= min_value && value.nobits?(value - 1)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def check_property_exclusivity(instance, names)
|
|
94
|
+
properties =
|
|
95
|
+
names
|
|
96
|
+
.map { |name| instance.property_value(name) }
|
|
97
|
+
.select { |v| v&.value }
|
|
98
|
+
return if properties.size <= 1
|
|
99
|
+
|
|
100
|
+
labels = [names[..-2].join(', '), names[-1]].join(' and ')
|
|
101
|
+
message = "#{labels} properties are mutually exclusive"
|
|
102
|
+
|
|
103
|
+
raise_evaluation_error message, *properties.map(&:token_range)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def check_definable(instance)
|
|
107
|
+
return if instance.definable?(self)
|
|
108
|
+
|
|
109
|
+
message = "#{layer} definition not allowed in #{instance.layer}"
|
|
110
|
+
raise_evaluation_error message, token_range
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def eval_array(_inst_values)
|
|
114
|
+
yield(nil, nil)
|
|
115
|
+
end
|
|
116
|
+
|
|
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}"
|
|
120
|
+
raise_evaluation_error message, token_range
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
instance = instance_class.new(self, parent_instance, inst_name, array_info, token_range)
|
|
124
|
+
|
|
125
|
+
init_properties(instance)
|
|
126
|
+
eval_body(instance, **optargs)
|
|
127
|
+
apply_inst_values(instance, inst_values)
|
|
128
|
+
post_build(instance)
|
|
129
|
+
instance.validate
|
|
130
|
+
|
|
131
|
+
parent_instance.instances << instance if parent_instance
|
|
132
|
+
instance
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def unique_instance?(parent_instance, inst_name, array_info)
|
|
136
|
+
return true unless parent_instance
|
|
137
|
+
|
|
138
|
+
parent_instance.instances.none? do |inst|
|
|
139
|
+
if inst.name != inst_name
|
|
140
|
+
false
|
|
141
|
+
elsif inst.array? && array_info
|
|
142
|
+
inst.array_info.id != array_info.id
|
|
143
|
+
else
|
|
144
|
+
true
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def init_properties(instance)
|
|
150
|
+
prop_defs = BuiltinProperties.properties
|
|
151
|
+
prop_defs.each do |prop_def|
|
|
152
|
+
next unless prop_def.target?(instance)
|
|
153
|
+
|
|
154
|
+
prop = prop_def.create(instance)
|
|
155
|
+
instance.properties << prop
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def eval_body(instance, **optargs)
|
|
160
|
+
@default_properties.clear
|
|
161
|
+
@elements.each { |element| element.evaluate(instance, **optargs) }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def apply_inst_values(_instance, _inst_values)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def post_build(_instance)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
protected
|
|
171
|
+
|
|
172
|
+
def add_definition(definition)
|
|
173
|
+
id = definition.id.value
|
|
174
|
+
if @definitions.key?(id)
|
|
175
|
+
message = "duplicated component: #{id}"
|
|
176
|
+
raise_evaluation_error message, definition.token_range
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
@definitions[id] = definition
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
attr_reader :default_properties
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SystemRDL
|
|
4
|
+
module Evaluator
|
|
5
|
+
class ComponentInsts
|
|
6
|
+
include Common
|
|
7
|
+
|
|
8
|
+
def initialize(insts, token_range)
|
|
9
|
+
super(token_range)
|
|
10
|
+
@insts = insts
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :insts
|
|
14
|
+
|
|
15
|
+
def connect(parent, component)
|
|
16
|
+
super
|
|
17
|
+
@insts.each { |inst| inst.connect(self, component) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def evaluate(instance, base, id, **optargs)
|
|
21
|
+
component_definition = find_component_definition(base, id, **optargs)
|
|
22
|
+
check_recursive_instance(instance, component_definition)
|
|
23
|
+
check_instantiable(instance, component_definition)
|
|
24
|
+
|
|
25
|
+
@insts.each do |inst|
|
|
26
|
+
inst.evaluate(instance, component_definition, **optargs)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def find_component_definition(base, id, **optargs)
|
|
33
|
+
base.upper_layers(include_self: true).reverse_each do |component|
|
|
34
|
+
definition = component.definitions[id.value]
|
|
35
|
+
next unless definition
|
|
36
|
+
|
|
37
|
+
unless optargs[:test] || (definition.layer in :reg | :field)
|
|
38
|
+
message = "#{definition.layer} instance not supported yet"
|
|
39
|
+
raise_evaluation_error message, token_range
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
return definition
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
raise_evaluation_error "undefined component: #{id.value}", token_range
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def check_recursive_instance(instance, component_definition)
|
|
49
|
+
components = instance.definition.upper_layers(include_self: true)
|
|
50
|
+
return if components.none? { |component| component.equal?(component_definition) }
|
|
51
|
+
|
|
52
|
+
message = 'recursive instance not allowed'
|
|
53
|
+
raise_evaluation_error message, token_range
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def check_instantiable(instance, component_definition)
|
|
57
|
+
return if instance.instantiable?(component_definition)
|
|
58
|
+
|
|
59
|
+
message = "#{component_definition.layer} instance not allowed in #{instance.layer}"
|
|
60
|
+
raise_evaluation_error message, token_range
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class ComponentInst
|
|
65
|
+
include Common
|
|
66
|
+
|
|
67
|
+
def initialize(inst_id, inst_values, token_range)
|
|
68
|
+
super(token_range)
|
|
69
|
+
@inst_id = inst_id
|
|
70
|
+
@inst_values = inst_values
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
attr_reader :inst_id
|
|
74
|
+
|
|
75
|
+
def evaluate(instance, component_definition, **optargs)
|
|
76
|
+
inst_values = eval_inst_values(instance, **optargs)
|
|
77
|
+
component_definition.create_instances(instance, @inst_id.value, inst_values, @token_range, **optargs)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def eval_inst_values(instance, **optargs)
|
|
83
|
+
@inst_values&.transform_values { |value| value&.evaluate(instance, **optargs) }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class ExplicitComponentInst
|
|
88
|
+
include Common
|
|
89
|
+
|
|
90
|
+
def initialize(id, insts, token_range)
|
|
91
|
+
super(token_range)
|
|
92
|
+
@id = id
|
|
93
|
+
@insts = insts
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def connect(parent, component)
|
|
97
|
+
super
|
|
98
|
+
@insts.connect(self, component)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def evaluate(instance, **optargs)
|
|
102
|
+
@insts.evaluate(instance, @component, @id, **optargs)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|