-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathcompat.py
403 lines (327 loc) · 15.5 KB
/
compat.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# © 2024 Intel Corporation
# SPDX-License-Identifier: MPL-2.0
import abc
from dataclasses import dataclass
@dataclass(order=True, frozen=True)
class API:
ordinal: int
str: str
api_4_8 = API(4, "4.8")
api_5 = API(5, "5")
api_6 = API(6, "6")
api_7 = API(7, "7")
# All API versions known to the DML implementation. Note that the set
# of APIs accessible to the end-user is limited to what the associated
# Simics version supports.
apis = {api.str: api
for api in [api_4_8, api_5, api_6, api_7]}
class CompatFeature(abc.ABC):
def tag(self) -> str:
return self.__class__.__name__
@abc.abstractproperty
def __doc__(self): pass
@abc.abstractproperty
def short(self) -> str: pass
@abc.abstractproperty
def last_api_version(self) -> API: pass
# tag -> feature
features: dict[str, CompatFeature] = {}
def feature(cls: type[CompatFeature]):
assert issubclass(cls, CompatFeature)
singleton = cls()
features[singleton.tag()] = singleton
return singleton
@feature
class broken_conditional_is(CompatFeature):
'''This compatibility feature prevents DML from
reporting errors when instantiating a template within an `#if` block:
```
#if (true) {
group g {
// should be an error, but silently ignored when this
// feature is enabled
is nonexisting_template;
}
}
```
Up to Simics 7, a bug prevented DMLC from reporting an error; this
feature exists to preserve that behaviour.
'''
short = ("Allow (and ignore) instantiating nonexistent templates within "
+ "'#if' blocks")
last_api_version = api_7
@feature
class port_proxy_ifaces(CompatFeature):
'''Version 5 and earlier of Simics relied on interface ports (as
registered by the `SIM_register_port_interface` API function) for
exposing the interfaces of ports and banks. In newer versions of
Simics, interfaces are instead exposed on separate configuration
objects. When this feature is enabled, old-style interface ports
are created as proxies to the interfaces on the respective port
objects. Such proxies are not created for all banks and ports;
e.g., banks inside groups were not allowed in Simics 5, so such
banks do not need proxies for backward compatibility.
'''
short = "Generate proxy port interfaces for banks and ports"
last_api_version = api_7
@feature
class port_proxy_attrs(CompatFeature):
r'''In Simics 5, configuration attributes for `connect`,
`attribute` and `register` objects inside banks and ports were
registered on the device object, named like
<code><em>bankname</em>\_<em>attrname</em></code>. Such proxy
attributes are only created When this feature is enabled.
Proxy attributes are not created for all banks and ports, in the
same manner as documented in the `port_proxy_ifaces` feature.
'''
short = ("Generate top-level proxy attributes for attributes in banks and "
+ "ports")
last_api_version = api_7
@feature
class function_in_extern_struct(CompatFeature):
'''
This compatibility feature enables a traditionally allowed syntax for
function pointer members of `extern typedef struct` declarations, where
the `*` is omitted in the pointer type. When disabling this feature,
any declarations on this form:
```
extern typedef struct {
void m(conf_object_t *);
} my_interface_t;
```
need to be changed to the standard C form:
```
extern typedef struct {
void (*m)(conf_object_t *);
} my_interface_t;
```
'''
short = 'Allow non-pointer function members in extern structs'
last_api_version = api_7
@feature
class optional_version_statement(CompatFeature):
'''When this compatibility feature is enabled, the version
specification statement (`dml 1.4;`) statement at the start of
each file is optional (but the compiler warns if it is
omitted). Also, `dml 1.3;` is permitted as a deprecated alias for
`dml 1.4;`, with a warning.'''
short = "Make the DML version statement optional"
last_api_version = api_7
@feature
class io_memory(CompatFeature):
'''The `transaction` interface was introduced in 6, and will
eventually replace the `io_memory` interface. When this feature is
enabled, the top-level parameter `use_io_memory` defaults to
`true`, causing `bank` objects to implement `io_memory` instead of
`transaction` by default.'''
short = 'Use the io_memory interface by default in banks'
last_api_version = api_6
@feature
class port_obj_param(CompatFeature):
'''This compatibility feature changes the value of the `obj`
parameter in `bank` and `port` objects: Before Simics 6 there were
no dedicated port objects, so this parameter did not exist and if
you wrote `obj` inside a bank, this would resolve to
`dev.obj`. This feature preserves this legacy behaviour by making
the `obj` parameter of banks and ports resolves to `dev.obj`
rather than the port object.
'''
short = "Make 'obj' of ports and banks resolve to 'dev.obj'"
last_api_version = api_5
@feature
class shared_logs_on_device(CompatFeature):
'''This compatibility feature changes the semantics of log statements
inside shared methods so that they always log on the device object, instead
of the nearest enclosing configuration object like with non-shared methods.
This behaviour was a bug present since the very introduction of shared
methods, which has lead to plenty of script code having become reliant
on it, especially in regards to how banks log. This feature preserves the
bugged behaviour.'''
short = "Make logs inside shared methods always log on the device object"
last_api_version = api_6
@feature
class suppress_WLOGMIXUP(CompatFeature):
'''This compatibility feature makes it so the warning `WLOGMIXUP` is
suppressed by default. `WLOGMIXUP` warns about usages of a common faulty
pattern which results in broken log statements — for more
information, see the documentation of `WLOGMIXUP` in the
[Messages](messages.html) section.
`WLOGMIXUP` is suppressed by default below Simics API version 7 in order
to avoid overwhelming users with warnings, as the faulty pattern that
`WLOGMIXUP` reports is very prevalent within existing code. Addressing
applications of the faulty pattern should be done before or as part of
migration to Simics API version 7.
Passing `--no-compat=suppress_WLOGMIXUP` to DMLC has almost the same effect
as passing `--warn=WLOGMIXUP`; either will cause DMLC to report the warning
even when the Simics API version in use is below 7. The only difference
between these two options is that if `--no-compat=suppress_WLOGMIXUP` is
used (and `--warn=WLOGMIXUP` is not), then `WLOGMIXUP` may still be
explicitly suppressed via `--no-warn=WLOGMIXUP`. In contrast,
`--warn=WLOGMIXUP` doesn't allow for `WLOGMIXUP` to be suppressed at
all.'''
short = "Suppress the warning 'WLOGMIXUP' by default"
last_api_version = api_6
@feature
class legacy_attributes(CompatFeature):
'''This compatibility feature makes DMLC register all attributes using the
legacy `SIM_register_typed_attribute` API function instead of the modern
`SIM_register_attribute` family of API functions.
Disabling this feature will make the dictionary attribute type ("D" in type
strings) to become unsupported, and any usage of it rejected by Simics.
Thus, when migrating away from this feature, any attribute of the model
that leverages dictionary values should be changed to leverage a different
representation. In general, any dictionary can instead be represented by a
list of two-element lists, e.g. <code>[[<em>X</em>,<em>Y</em>]*]</code>,
where _X_ describes the type of keys, and _Y_ describes the type of
values.'''
short = ("Use legacy attribute registration, which supports use of the "
+ "dictionary type ('D')")
last_api_version = api_7
@feature
class lenient_typechecking(CompatFeature):
'''This compatibility feature makes DMLC's type checking very inexact and
lenient in multiple respects when compared to GCC's type checking of the
generated C.
This discrepency mostly affects method overrides or uses of `extern`:d C
macros, because in those scenarios DMLC can become wholly responsible for
proper type checking.
While migrating away from this feature, the most common type errors that
its disablement introduces are due to discrepencies between pointer
types. In particular, implicitly discarding `const`-qualification of a
pointer's base type will never be tolerated, and `void` pointers are only
considered equivalent with any other pointer type in the same contexts as
C.
Novel type errors from uses of `extern`:d macros can often be resolved by
changing the signature of the `extern` declaration to more accurately
reflect the macro's effective type.
'''
short = "Make type checking inexact and lenient"
last_api_version = api_7
@feature
class no_method_index_asserts(CompatFeature):
'''This compatibility feature makes it so that methods defined under
object arrays don't implicitly assert that the indices used to reference
the object array when calling the method are in bounds.
Migrating away from this compatibility feature should be a priority. If
its disablement makes the simulation crash due to an assertion failing,
then that **definitely signifies a bug in your model; a bug that would
very likely result in memory corruption if the assertion were not to
be made.**'''
short = ("Disable assertions made by methods of object arrays that the "
+ "the object array indices are valid. Migrate away from this "
+ "ASAP!")
last_api_version = api_7
@feature
class dml12_inline(CompatFeature):
'''When using `inline` to inline a method in a DML 1.2 device,
constant arguments passed in typed parameters are inlined as
constants when this feature is enabled. This can improve
compilation time in some cases, but has some unintuitive semantic
implications.
'''
short = ("Make inline method calls in DML 1.2 inline every constant "
+ "argument, even when typed")
last_api_version = api_6
# separate class only because last_api_version differs
@feature
class dml12_not(CompatFeature):
'''DML 1.2-specific: the operand of the `!` operator is not
type-checked; in particular, negation expressions on the form
`!$reg`, where `reg` is a register, are permitted'''
short = "Allow ! operator on register references in DML 1.2"
last_api_version = api_5
@feature
class dml12_misc(CompatFeature):
'''This compatibility feature preserves a number of minor language quirks
that were originally in DML 1.2, but were cleaned up in
DML 1.4. When this feature is enabled, DML 1.2 will permit the following:
* `sizeof(typename)` (see `WSIZEOFTYPE`)
* the `typeof` operator on an expression that isn't an lvalue
* `select` statements over `vect` types
* Passing a string literal in a (non-`const`) `char *` method argument
* Using the character `-` in the `c_name` parameter of `interface` objects
* Using the `c_name` parameter to override interface type in
`implement` objects
* `loggroup` identifiers are accessible under the same name in
generated C code
* Applying the `&` operator on something that isn't an lvalue
(typically gives broken C code)
* `extern` statements that do not specify a type (`extern foo;`)
* Anonymous banks (`bank { ... }`)
* Unused templates may instantiate non-existing templates
* The same symbol may be used both for a top-level object (`$`
scope) and a top-level symbol (non-`$` scope, e.g. `extern`,
`constant` or `loggroup`)
'''
short = "Enable various legacy DML 1.2 quirks"
last_api_version = api_6
@feature
class dml12_goto(CompatFeature):
'''The `goto` statement is deprecated; this compatibility feature
preserves it. Most `goto` based control structures can be reworked by
changing the `goto` into a `throw`, and its label into a `catch`
block; since this is sometimes nontrivial, it can be useful to disable
the `goto` statement separately.
'''
short = "Enable the goto statement in DML 1.2"
last_api_version = api_6
@feature
class dml12_int(CompatFeature):
'''This compatibility feature affects many semantic details of
integer arithmetic. When this feature is enabled, DMLC translates
most integer operations directly into C, without compensating for
DML-specifics, like the support for odd-sized
<tt>uint<i>NN</i></tt> types; this can sometimes have unexpected
consequences. The most immediate effect of disabling this feature
is that DMLC will report errors on statements like `assert 0;` and
`while (1) { ... }`, which need to change into `assert false;` and
`while (true) { ... }`, respectively. Other effects include:
* Integers of non-standard sizes are represented as a native C
type, e.g. `uint5` is represented as `uint8`, allowing it to
store numbers too large to fit in 5 bits. With modern DML
semantics, arithmetic is done on 64-bit integers and bits are
truncated if casting or storing in a smaller type.
Old code sometimes relies on this feature by comparing variables
of type `int1` to the value `1`. In DML 1.4, the only values of
type `int1` are `0` and `-1`, so such code should be rewritten
to use the `uint1` type. It can be a good idea to grep for
`[^a-z_]int1[^0-9]` and review if `uint1` is a better choice.
* Some operations have undefined behaviour in C, which is
inherited by traditional DML 1.2. In modern DML this is
well-defined, e.g., an unconditional critical error on negative
shift or division by zero, and truncation on too large shift
operands or signed shift overflow.
* Comparison operators `<`, `<=`, `==`, `>=`, `>` inherit C
semantics in traditional DML, whereas in modern DML they are
compared as integers. This sometimes makes a difference when
comparing signed and unsigned numbers; in particular, `-1 !=
0xffffffffffffffff` consistently in modern DML, whereas with
compatibility semantics, they are consiered different only if
both are constant.
The `dml12_int` feature only applies to DML 1.2 files; if a DML
1.4 file is imported from a DML 1.2 file, then modern DML
semantics is still used for operations in that file.
'''
short = "Use legacy integer semantics in DML 1.2"
last_api_version = api_6
@feature
class experimental_vect(CompatFeature):
'''<a id="experimental_vect"/> This compat feature
controls how DMLC reacts to uses of the `vect` syntax in files
where the [`simics_util_vect` provisional feature](provisional-auto.html#simics_util_vect)
is not enabled.
When the `experimental_vect` compatibility feature is
enabled, such uses are permitted, and give a `WEXPERIMENTAL`
warning in DML 1.4 (but no warning in DML 1.2). When
`experimental_vect` is disabled, DMLC forbids the `vect`
syntax.
'''
short = "Permit vect syntax without 'provisional simics_util_vect'"
last_api_version = api_7
@feature
class warning_statement(CompatFeature):
'''This compatibility feature enables the `_warning` statement.
This turned out to not be very useful, so in Simics API 8 and
newer the feature is no longer allowed.'''
short = "Allow the `_warning` statement"
last_api_version = api_7