Skip to content

Commit f095d46

Browse files
committed
Rewrite section about parameters
1 parent f6e0f6d commit f095d46

File tree

2 files changed

+127
-68
lines changed

2 files changed

+127
-68
lines changed

doc/1.4/language.md

Lines changed: 125 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ referenced.
345345

346346
Parameters cannot be dynamically updated at run-time; however, a parameter
347347
can be declared to allow it being overridden by later definitions -
348-
see [Parameter Declarations](#parameter-declarations).
348+
see [Parameters detailed](#parameters-detailed).
349349

350350
Within DML's built-in modules and standard library, parameters are used to
351351
describe static properties of objects, such as names, sizes, and offsets. Many
@@ -1221,14 +1221,122 @@ template get_qname {
12211221
}
12221222
```
12231223

1224-
### Typed Parameters
1225-
A *typed parameter declaration* is a parameter declaration form that may only
1226-
appear within templates:
1224+
## Parameters detailed
12271225

1228-
<pre>
1229-
param <em>name</em> : <em>type</em>;
1230-
</pre>
1226+
Parameters may be typed or untyped.
1227+
Typed parameter declarations may only appear in template definitions.
1228+
1229+
Parameters are declared using one of the forms
1230+
1231+
```
1232+
param name;
1233+
param name: type
1234+
```
1235+
1236+
and assigned using the `=` operator. Parameters may also be given default values using the form `param name default expr`.
1237+
For example:
1238+
1239+
```
1240+
param offset = 8;
1241+
param byte_order default "little-endian";
1242+
```
1243+
1244+
A default value is overridden by an assignment (`=`).
1245+
There can be at most one assignment for each parameter.
1246+
Typically, a default value for a parameter is specified in a template, and the programmer may then choose to override it where the template is used.
1247+
See [Resolution of overrides](#resolution-of-overrides) for the resolution order when there are multiple definitions of the same parameter.
1248+
1249+
A parameter that is declared without an assignment or a default value must eventually be assigned elsewhere, or the model will not compile.
1250+
This pattern is sometimes useful in templates, as in:
1251+
1252+
```
1253+
template constant is register {
1254+
param value;
1255+
method get() -> (uint64) {
1256+
return value;
1257+
}
1258+
}
1259+
```
1260+
1261+
so that wherever the template `constant` is used, the programmer
1262+
is also forced to define the parameter `value`. E.g.:
1263+
1264+
```
1265+
register r0 size 2 @ 0x0000 is (constant) {
1266+
param value = 0xffff;
1267+
}
1268+
```
1269+
1270+
> [!IMPORTANT]
1271+
> When writing templates, always declare parameters that are referenced.
1272+
> Enabling the provisional feature `explicit_param_decls` enforces this.
1273+
>
1274+
> Leaving out the parameter declaration from the template
1275+
> definition can have unwanted effects if the programmer forgets to
1276+
> specify its value where the template is used. At best, it will only
1277+
> cause a more obscure error message, such as "unknown identifier"; at
1278+
> worst, the scoping rules will select an unrelated definition of the same
1279+
> parameter name.
1280+
1281+
### `explicit_param_decls` provisional feature
1282+
1283+
There is a shorthand syntax for combined declaration and definition of a parameter, currently enabled by the [`explicit_param_decls` provisional feature](provisional-auto.html#explicit_param_decls):
1284+
1285+
```
1286+
param NAME: TYPE = value;
1287+
param NAME: TYPE default value;
1288+
param NAME := value;
1289+
param :default value;
1290+
```
1291+
1292+
`explicit_param_decls` enforces that parameters are declared before they are assigned, or that the combined syntax is used.
1293+
This distinguishes between the intent to declare a new parameter, and the intent to override an existing parameter.
1294+
This distinction allows DML to capture misspelled parameter overrides as compile errors.
1295+
1296+
DMLC signals an error if the combined declaration and definition syntax is used to override an existing parameter.
1297+
This guards against unintentional reuse of a parameter name. An example:
1298+
1299+
```
1300+
// Included file not using explicit_param_decls
1301+
template foo_capability {
1302+
param foo_offset; // parameter which must be assigned by the device instantiating the template
1303+
param has_foo_feature default false; // overridable parameter with a default value
1304+
param id default 1; // overridable parameter with a generic name
1305+
}
1306+
```
1307+
1308+
```
1309+
// Device model file including the above
1310+
provisional explicit_param_decls;
1311+
1312+
template extended_foo_capability is foo_capability {
1313+
param has_bar_feature: bool default false;
1314+
1315+
// unintentional reuse of parameter name:
1316+
param id := 5; // error: the parameter 'id' has already been declared
1317+
}
1318+
1319+
bank foo_config {
1320+
is extended_foo_capability;
1321+
1322+
// correct assignment to template parameter:
1323+
param foo_offset = 0x10;
1324+
1325+
// misspelled parameter override:
1326+
param has_foo_featur = true; // error: parameter 'has_foo_featur' not declared previously.
1327+
}
1328+
```
1329+
1330+
It is recommended to enable `explicit_param_decls` in new DML source files and to use the new combined syntax when applicable to reduce the risk of bugs caused by misspelled parameters.
12311331

1332+
In some rare cases, you may need to declare a parameter without
1333+
knowing if it's an override or a new parameter. In this case, one
1334+
can accompany a `param NAME = value;` or `param NAME default
1335+
value;` declaration with a `param NAME;` declaration in the same
1336+
scope/rank. This marks that the parameter assignment may be either
1337+
an override or a new parameter, and no error will be printed.
1338+
1339+
### Typed Parameters detailed
12321340
A typed parameter declaration adds a member to the template type with the same
12331341
name as the specified parameter, and with the specified type. That member is
12341342
associated with the specified parameter, in the sense that the definition of the
@@ -1237,7 +1345,7 @@ parameter is used as the value of the template type member.
12371345
A typed parameter declaration places a number of requirements on the
12381346
named parameter:
12391347
* The named parameter must be defined (through a regular [parameter
1240-
declaration](#parameter-declarations)). This can be done either within the
1348+
declaration](#parameters-detailed)). This can be done either within the
12411349
template itself, within sub-templates, or within individual objects
12421350
instantiating the template.
12431351
* The parameter definition must be a valid expression of the specified type.
@@ -1281,72 +1389,22 @@ bank regs {
12811389
}
12821390
```
12831391

1284-
## Parameter Declarations
1392+
### Special parameters in the DML standard library
12851393

1286-
A parameter declaration has the general form "<code>param <em>name</em>
1287-
<em>specification</em>;</code>", where *`specification`* is
1288-
either "<code>= <em>expr</em></code>" or "<code>default <em>expr</em></code>".
1289-
For example:
1394+
You may see the following special form in some standard library files:
12901395

1291-
```
1292-
param offset = 8;
1293-
param byte_order default "little-endian";
1294-
```
1295-
1296-
A default value is overridden by an assignment (`=`). There can
1297-
be at most one assignment for each parameter.
1298-
Typically, a default value for a parameter is specified in a
1299-
template, and the programmer may then choose to override it where the
1300-
template is used.
1301-
1302-
The *`specification`* part is in fact optional; if omitted, it means that the
1303-
parameter is declared to exist (and *must* be given a value, or the model will
1304-
not compile). This is sometimes useful in templates, as in:
1305-
1306-
```
1307-
template constant is register {
1308-
param value;
1309-
method get() -> (uint64) {
1310-
return value;
1311-
}
1312-
}
1313-
```
1396+
<pre>
1397+
param <em>name</em> auto;
1398+
</pre>
13141399

1315-
so that wherever the template `constant` is used, the programmer
1316-
is also forced to define the parameter `value`. E.g.:
1400+
for example,
13171401

13181402
```
1319-
register r0 size 2 @ 0x0000 is (constant) {
1320-
param value = 0xffff;
1321-
}
1403+
param parent auto;
13221404
```
13231405

1324-
Note that simply leaving out the parameter declaration from the template
1325-
definition can have unwanted effects if the programmer forgets to
1326-
specify its value where the template is used. At best, it will only
1327-
cause a more obscure error message, such as "unknown identifier"; at
1328-
worst, the scoping rules will select an unrelated definition of the same
1329-
parameter name.
1330-
1331-
Also note that a parameter declaration without definition is redundant if a
1332-
[typed parameter declaration](#typed-parameters) for that parameter already
1333-
exists, as that already enforces that the parameter must be defined.
1334-
1335-
> [!NOTE]
1336-
> You may see the following special form in some standard library files:
1337-
>
1338-
> <pre>
1339-
> param <em>name</em> auto;
1340-
> </pre>
1341-
>
1342-
> for example,
1343-
>
1344-
> ```
1345-
> param parent auto;
1346-
> ```
1347-
>
1348-
> This is used to explicitly declare the built-in automatic parameters,
1349-
> and should never be used outside the libraries.
1406+
This is used to explicitly declare the built-in automatic parameters,
1407+
and should never be used outside the libraries.
13501408

13511409
## Data types
13521410

py/dml/provisional.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ def feature(cls: type[ProvisionalFeature]):
3434

3535
@feature
3636
class explicit_param_decls(ProvisionalFeature):
37-
'''This feature extends the DML syntax for parameter definitions to
37+
'''<a id="explicit_param_decls"/>
38+
This feature extends the DML syntax for parameter definitions to
3839
distinguish between an intent to declare a new parameter, and an intent to
3940
override an existing parameter (including when providing a definition
4041
for an abstract parameter). This distinction allows DML to capture

0 commit comments

Comments
 (0)