Skip to content

Commit cd00065

Browse files
committed
Remove WEXPERIMENTAL for "if with unsupported statements"
1 parent 20f0ca5 commit cd00065

File tree

11 files changed

+148
-21
lines changed

11 files changed

+148
-21
lines changed

RELEASENOTES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,11 @@
204204
(fixes SIMICS-22848).
205205
- `release 6 6349`
206206
- `release 7 7054`
207+
- `note 6` DMLC no longer emits warnings saying
208+
`top-level 'if' body with unsupported statements`. These warnings were
209+
often triggered in common code, causing excessive polution in build logs.
210+
The same rules as before apply to `#if` statements: Statements such as
211+
`param` and `template` are forbidden inside `#if`, but a special exception
212+
allows forbidden statements to appear specifically inside an `#if (dml_1_2)`
213+
block. The warning message was meant to highlight this irregularity, but
214+
caused more harm than good; error messages surrounding the special case have been improved instead.

doc/1.4/language.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,8 +2318,8 @@ The *object declarations* are any number of declarations of objects, session
23182318
variables, saved variables, methods, or other `#if` statements, but not
23192319
parameters, `is` statements, or `in each` statements . When the conditional is
23202320
`true` (or if it's the else branch of a false conditional), the object
2321-
declarations are treated as if they had appeared without any surrounding *#if*.
2322-
So the two following declarations are equivalent:
2321+
declarations are treated as if they had appeared without any surrounding `#if`.
2322+
Thus, the two following snippets are equivalent:
23232323

23242324
```
23252325
#if (true) {
@@ -2329,12 +2329,34 @@ So the two following declarations are equivalent:
23292329
}
23302330
```
23312331

2332-
is equivalent to
2333-
23342332
```
23352333
register R size 4;
23362334
```
23372335

2336+
As a special exception, an `#if` statement that appears on top level is allowed
2337+
to contain any type of statement, as long as the condition doesn't reference
2338+
any identifiers other than `dml_1_2`, `true` and `false`. This is often useful
2339+
while migrating the devices of a system from DML 1.2 to DML 1.4,
2340+
as it allows conditional definitions of templates in common code used from both DML 1.2 and DML 1.4. For example, let's say an existing template `reset_to_seven`
2341+
is used in DML 1.2 code to set the reset value of a field to 7 in DML 1.2.
2342+
The parameters that control reset values have changed from DML 1.2 to DML 1.4,
2343+
and one way to handle this is to provide separate template definitions
2344+
depending on whether the device uses DML 1.2 or DML 1.4:
2345+
```
2346+
#if (dml_1_2) {
2347+
template seven is field {
2348+
param hard_reset_value = 7;
2349+
param soft_reset_value = 7;
2350+
}
2351+
} #else {
2352+
template seven is field {
2353+
param init_val = 7;
2354+
}
2355+
}
2356+
```
2357+
Later, when all related devices have been ported to DML 1.4,
2358+
the `dml_1_2` clause can be removed.
2359+
23382360
## In Each Declarations
23392361

23402362
In Each declarations are a convenient mechanism to apply a

py/dml/dmlparse.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,12 @@ def toplevel_param(t):
270270
def toplevel_if(t):
271271
'''toplevel_if : hashif LPAREN expression RPAREN \
272272
LBRACE device_statements RBRACE toplevel_else'''
273-
if all(stmt.kind in allowed_in_hashif for stmt in t[6] + t[8]):
274-
t[0] = ast.hashif(site(t), t[3], t[6], t[8])
273+
bad_stmts = [stmt for stmt in t[6] + t[8]
274+
if stmt.kind not in allowed_in_hashif]
275+
if bad_stmts:
276+
t[0] = ast.toplevel_if(site(t), t[3], t[6], t[8], bad_stmts)
275277
else:
276-
report(WEXPERIMENTAL(site(t), ("top-level 'if' body with unsupported "
277-
+ "statements")))
278-
t[0] = ast.toplevel_if(site(t), t[3], t[6], t[8])
278+
t[0] = ast.hashif(site(t), t[3], t[6], t[8])
279279

280280
@prod_dml14
281281
def toplevel_else_no(t):

py/dml/messages.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,18 @@ class ECONDINEACH(DMLError):
829829
version = "1.4"
830830
fmt = "conditional 'in each' is not allowed"
831831

832+
class EBADCONDSTMT(DMLError):
833+
"""
834+
`#if` statements in object scope are only allowed to contain
835+
certain kinds of declarations: objects, `method`, `session`,
836+
`saved`, `#if`, or `error`.
837+
838+
A special exception is that a `#if` on top scope may contain any
839+
kind of statement as long as the `#if` condition doesn't reference
840+
any identifiers other than `dml_1_2`, `true`, and `false`.
841+
"""
842+
fmt = "object of type %s not allowed inside `#if`"
843+
832844
# TODO: Consider re-wording the semantics of this error, allocate_type is only
833845
# relevant in 1.4 when imported from 1.2, and as per SIMICS-9393 this
834846
# error might not even be necessary

py/dml/toplevel.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,25 +148,29 @@ def scan_statements(filename, site, stmts):
148148
[text] = s.args
149149
footers.append(ctree.mkCText(s.site, text))
150150
elif s.kind == 'toplevel_if':
151-
[cond, tbranch, fbranch] = s.args
151+
[cond, tbranch, fbranch, bad_stmts] = s.args
152152
scope = symtab.Symtab()
153153
bsite = SimpleSite('<builtin>',
154154
dml_version=dml.globals.dml_version)
155155
# HACK Add constants to scope typically defined by dml-builtins,
156156
# which is not accessible here
157-
def add_constant(name, expr):
157+
constants = {
158+
'dml_1_2': ctree.BoolConstant(
159+
bsite, dml.globals.dml_version == (1, 2)),
160+
'true': ctree.BoolConstant(bsite, True),
161+
'false': ctree.BoolConstant(bsite, False),
162+
}
163+
for (name, expr) in constants.items():
158164
scope.add(ctree.ExpressionSymbol(name, expr, bsite))
159165

160-
add_constant(
161-
'dml_1_2',
162-
ctree.BoolConstant(bsite, dml.globals.dml_version == (1, 2)))
163-
add_constant('true', ctree.BoolConstant(bsite, True))
164-
add_constant('false', ctree.BoolConstant(bsite, False))
165166
try:
166167
expr = ctree.as_bool(codegen.codegen_expression(
167168
cond, None, scope))
168169
if not expr.constant:
169170
raise ENCONST(expr.site, expr)
171+
except EIDENT:
172+
for stmt in bad_stmts:
173+
report(EBADCONDSTMT(stmt.site, stmt.kind))
170174
except DMLError as e:
171175
report(e)
172176
else:

test/1.2/misc/T_import_dml14.dml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ constant x = 0;
1212

1313
parameter is_dml_12 = true;
1414

15-
/// WARNING WEXPERIMENTAL dml14.dml
1615
/// SCAN-FOR-TAGS dml14.dml
1716
import "dml14.dml";
1817

test/1.2/misc/dml14.dml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ bank testbank is (miss_pattern_bank, function_mapped_bank) {
401401

402402
bank overridden_bank is (unified_hard_reset, unified_soft_reset);
403403

404-
/// WARNING WEXPERIMENTAL
405404
#if (dml_1_2) {
406405
import "io-memory.dml";
407406
} #else {
@@ -475,10 +474,8 @@ attribute woa is (write_only_attr) {
475474

476475
param global_sym = 14;
477476

478-
/// WARNING WEXPERIMENTAL
479477
#if (!dml_1_2) {
480478
param cond = false;
481-
/// WARNING WEXPERIMENTAL
482479
} #else #if (!dml_1_2) {
483480
error;
484481
} #else {

test/1.4/errors/T_EBADCONDSTMT.dml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
© 2024 Intel Corporation
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
dml 1.4;
6+
7+
device test;
8+
9+
constant x = 1;
10+
11+
#if (x == 1) {
12+
/// ERROR EBADCONDSTMT
13+
param p = 3;
14+
/// ERROR EBADCONDSTMT
15+
typedef int i_t;
16+
} #else {
17+
/// ERROR EBADCONDSTMT
18+
template t {
19+
}
20+
21+
/// ERROR EBADCONDSTMT
22+
extern typedef int i_t;
23+
}
24+
25+
#if (true) {
26+
// no error
27+
param p = 3;
28+
}

test/1.4/errors/T_ECONDINEACH.dml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ port p {
2222
}
2323
}
2424

25-
/// WARNING WEXPERIMENTAL
2625
#if (false && true && dml_1_2) {
2726
// Experimental support for complex top-level conditionals allows in-each
2827
// to be used
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
© 2024 Intel Corporation
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
dml 1.4;
6+
7+
device test;
8+
9+
/// COMPILE-ONLY
10+
11+
#if (true) {
12+
extern typedef int a_t;
13+
typedef int b_t;
14+
param p = 1;
15+
} #else {
16+
extern void *x;
17+
import "nonexisting.dml";
18+
param p = 2;
19+
error;
20+
}
21+
22+
#if (p != 1) { error; }
23+
24+
#if (false) {
25+
typedef void *a_t;
26+
extern typedef void *b_t;
27+
error;
28+
template t { error; }
29+
} #else {
30+
extern int x;
31+
import "imported.dml";
32+
template t { param from_t = true; }
33+
}
34+
35+
#if (!imported) { error; }
36+
37+
is t;
38+
#if (!from_t) { error; }
39+
40+
#if (dml_1_2 || false) {
41+
error;
42+
} #else {
43+
#if (true) {
44+
#if (!false) {
45+
// nested top-level #ifs are permitted
46+
param foo = true;
47+
}
48+
}
49+
}
50+
51+
#if (!foo) { error; }

0 commit comments

Comments
 (0)