-
Notifications
You must be signed in to change notification settings - Fork 47
D.3. Backward incompatible changes, not automatically converted
A number of changes are not taken care of by the conversion script.
Many incompatibilities can be captured as errors already in DML 1.2,
by passing the --strict-dml12
argument. This can be used to
split the conversion process into smaller steps: by running with
this flag before running port-dml.py
, one can
apply manual fixes one by one and validate each fix in isolation;
this means that the result of port-dml.py
will contain
fewer errors.
The following incompatible changes are caught as errors or warnings
by the --strict-dml12
flag:
-
In classic DML 1.2, an unused template is allowed to instantiate a non-existing template. This is not permitted in DML 1.4.
-
In DML 1.4,
$
is no longer used for object references, and top-level object scope is therefore merged with the global scope. This means that you cannot both declare a bank X (referenced as $X in 1.2, as X in 1.4) and a global constant X (referenced as X in both 1.2 and 1.4). -
When inlining a method with a constant value as an argument, the argument will no longer be considered constant in the method body if the argument was declared with a type. In classic DML 1.2, a constant is always inlined as a constant, whose type might not match with the declared type.
-
Anonymous banks (syntax:
bank { ... }
) are no longer allowed. -
DML 1.2 permitted certain C keywords, e.g.
signed
andregister
, to be used as names of local variables. This is no longer permitted. -
Integer arithmetic works differently in DML 1.4. In short, all operands to arithmetic operands are promoted to 64 bits before performing the operation, much like 16- and 8-bit operands are promoted to 32 bits in C.
Also, many semantic irregularities and bugs in 1.2 semantics have been corrected in 1.4.
-
It is no longer permitted to use a register or field object as operand to the
!
operator. In classic DML 1.2, there was a loophole that permitted this. -
In DML 1.2, you can reference a method in an
interface
object by casting it to a function pointer type. That is no longer permitted in DML 1.4. -
The
goto
statement has been removed from DML 1.3. We plan to re-introduce a restricted variant of the goto statement which is only allowed to jump forward, and to an enclosing scope. -
It is no longer allowed to iterate over the undocumented
vect
type in aselect
statement. In classic DML 1.2, this was permitted but had unexpected behaviour. -
If a method argument has type
const char *
, it is no longer permitted to pass a string literal. -
The
!
operator is stricter in 1.3; in particular, it no longer accepts a constant integer as operand. Other condition expressions, like theif
condition or&&
operands, no longer accept the 0 or 1 literal; usefalse
ortrue
instead. -
In DML 1.4, the
sizeof
andtypeof
operators require that the operand is an lvalue. -
A reference to an
implement
object can no longer be used as a value. -
In classic DML 1.2, one could write
extern X;
to declare that some symbol X is externally defined as a C symbol, without providing a hint on the type of X. This is not permitted in DML 1.4. -
The undocumented
c_name
parameter no longer has an effect oninterface
objects. This may affect old C + DML integrations. -
A method's input parameters now belong to the method's top scope, instead of a separate scope. Thus, it is illegal to declare a variable in method's top scope which shadows a method parameter.
-
In classic DML 1.2, the
loggroup X;
statement would expose the log group as an identifierX
in generated C code. This is no longer done, which may affect old C + DML integrations.
The following incompatible changes are not caught
by --strict-dml12
, and must be adjusted manually:
-
The API for initialization and reset has been rewritten. The most important differences:
-
When the device is initialized, all registers are reset to the new
init_val
parameter, defaulting to zero. In 1.2, similar results were achieved by performing a hard reset. -
The
hard_reset
andsoft_reset
methods in banks and devices, typically called to trigger a reset, are no longer available by default. The methods can be created by instantiating templates from theutility.dml
library (the templates are namedhreset
andsreset
, respectively). -
The
hard_reset
andsoft_reset
methods in registers and fields also do not exist by default. They are also created when instantiatinghreset
andsreset
templates. -
The
hard_reset_value
andsoft_reset_value
parameters in registers and fields are no longer recognized. Instead, the default implementations of thehard_reset
andsoft_reset
methods invoke theinit
method, effectively replacing thehard_reset_value
andsoft_reset_value
parameters withinit_val
. You must now override thesoft_reset
method explicitly in order to provide different reset values for hard and soft reset.
-
-
The API for declaring event objects has changed. Just like in DML 1.2, the event callback is defined by a method
event
, and the event is posted by a methodpost
. A number of things have changed since 1.2:-
Instead of defining a parameter
timebase
in each event object, you must now instantiate one of six predefined templates in each event object:-
simple_time_event
,simple_cycle_event
-
Event without data. The
event
method takes no arguments, and thepost
method only takes a single argument, the delay. -
uint64_time_event
,uint64_cycle_event
-
Event with integer data. The
post
method takes an argument of typeuint64
in addition to the delay argument. This argument is later passed on to theevent
method, which takes a singleuint64
argument. -
custom_time_event
,custom_cycle_event
-
Event with custom data. The
post
method takes an argument of typevoid *
in addition to the delay argument. This value is later passed on to theevent
method, which takes a singlevoid *
argument.
The difference between the
*_time_event
and*_cycle_event
templates is similar to the difference betweentimebase = "seconds"
andtimebase = "cycles"
in DML 1.2. I.e., when a method argument or return value represents time, then the variant of the method in a*_time_event
template represents time as a floating-point number, representing (simulated) seconds, whereas the variant in a*_cycle_event
template represents time as an integer, representing CPU cycles. -
-
The method
event
is abstract in all templates. In DML 1.2, there was a not-so-useful default implementation. -
The methods
next
,posted
andremove
are not available in thecustom_*_event
templates. They are available in thesimple_*_event
templates withoutdata
arguments, and inuint64_*_event
templates withdata
arguments of typeuint64
. -
The methods
set_event_info
,get_event_info
anddestroy
are only recognized by thecustom_*_event
templates, where the methods are abstract. In the other templates, serialization and deserialization are done automatically -
The
describe_event
method can no longer be overridden. -
The
post_on_queue
method is no longer available.
Example:
event simple is (simple_time_event) { method event() { log info: "hello"; } } event parameterized is (uint64_cycle_event) { method event(uint64 data) { log info: "hello %d", data; } } ... // no data args needed simple.post(1.0); assert simple.posted(); // in uint64_cycle_event, the methods posted, next // and remove check that the data argument matches parameterized.post(18, 4711); assert parameterized.next(4711) == 18; assert parameterized.next(42) < 0;
-
-
The parameters
partial
andoverlapping
in banks are nowtrue
by default. -
Some rarely used identifiers from C, in particular many C macros on the form
XYZ_INTERFACE
, are no longer automatically available in DML. This will cause compile errors on migration, which can be resolved by manually adding corresponding symbol definitions to the DML file. -
Methods that can throw an exception must be annotated with the new
throws
keyword:method m(bool condition) -> (int) throws { if (condition) throw; }
The
throws
annotation is required if the method contains either a throw statement or an invocation of a method with thethrows
annotation, unless all such statements are enclosed intry
blocks. -
Assignment operators (
=
as well as+=
,*=
, etc) are now separate statements, and disallowed inside expressions. These statements are allowed in some additional places, to replace common uses of assignment expressions:-
A
=
statement may contain multiple target expressions (a = b = c;
). The targets are assigned from right to left, like in C. -
The pre and post sections of a
for
statement may contain any assignment statement. So the following is still valid:for (i = j = 0; i < 10; i += 3, j++) { ... }
-
-
In DML 1.4, methods are no longer declared
extern
, rather they areexported
using theexport
statement. Anexported
method must be declared in the top scope, may not throw exceptions, and may have at most one return value. The generated C function now has extern linkage, and takes aconf_object_t *
as its first argument. -
The syntax of
switch
statement is now stricter, and now requires a conventional switch structure: The switch body must be a compound statement starting with acase
label, allcase
anddefault
statements must reside directly in this statement, and nocase
may appear after thedefault
statement. -
When declaring a template, a
desc
string may no longer be supplied. Thus, the following is now invalid:template t "short description" { ... }
This syntax used to create a parameter
desc
in the objects where the template is instantiated. -
The
#
operator is no longer supported. It was seldom useful in DML 1.2, and its behaviour was in many ways complex and undocumented. -
It is no longer allowed to refer to objects using the names
signed
,unsigned
andthis
. -
The expression
undefined
may no longer be passed as argument to an inline method -
If the condition of a
while
loop is statically evaluated to false, then faulty code in the loop body can cause compile errors in DML 1.4. In DML 1.2, the loop body was silently discarded. -
goto
statements, as well as goto labels, are not allowed in DML 1.4. -
The parameter
persistent
in fields is no longer supported. It was buggy in 1.2. As a replacement, checkpoint fields as separate attributes if persistence differs within a register. -
Objects of
register
orattribute
type withconfiguration="pseudo"
, that are either read-only or write-only, have to declare this specifically by setting the new parameterreadable
(orwritable
) tofalse
. In 1.2, DMLC used some heuristics to automatically guess the user's intent. -
The parameter
allocate_type
inattribute
objects has been removed. Three templates are available as a replacement:-
uint64_attr
replacesallocate_type="uint64"
-
int64_attr
replacesallocate_type="int64"
-
bool_attr
replacesallocate_type="bool"
-
double_attr
replacesallocate_type="double"
For the
allocate_type
values"uint8"
,"uint16"
,"uint32"
,"int8"
,"int16"
, and"int32"
, the corresponding 64-bit template is recommended. There is no replacement forallocate_type="string"
. -
-
In objects of type
attribute
,register
andfield
, storage is now allocated in a separate memberval
instead of the object itself. For example: when assigning a value to a register, you might changebank.reg = 4;
intobank.reg.val = 4;
. Note that theval
member is not automatically created by DMLC; it is merely a naming convention used by many standard templates (type
_attr for attributes, andalloc
,read_write
,read_only
for registers and fields). -
The following standard parameters have been removed:
-
Object parameters
-
logobj
,indexvar
-
bank
parameters -
mapped_registers
,unmapped_registers
,numbered_registers
-
register
parameters -
fields
,signed
-
connect
parameters -
interfaces
-
-
The bank parameters
miss_bank
,miss_bank_offset
,miss_pattern
,function
andlog_group
have been tentatively removed; we intend to replace them with standard templates. -
In
connect
objects, thevalidate
andvalidate_port
methods have been merged into one method, namedvalidate
. This method has the same signature and semantics asvalidate_port
in DML 1.2. -
In objects of type
attribute
,register
andconnect
, the methodsbefore_set
andafter_set
are no longer recognized. As a replacement, overrideset
with a method that performs intended logic before and after an invocation ofdefault
. -
The templates
signed
andnoalloc
have been removed, together with thesigned
andallocate
parameters in registers and fields. -
The parameter
offset
in registers can no longer be set toundefined
. Instead, use theunmapped
template to denote an unmapped register. -
The templates
unimplemented
,silent_unimplemented
,read_unimplemented
andwrite_unimplemented
have been renamed, tounimpl
,silent_unimpl
,read_unimpl
andwrite_unimpl
, respectively. Also, log levels of logged messages have changed: The first message is logged on level 2 bysilent_unimpl
, and level 1 by all the other templates, while subsequent messages are logged on level 3 in all templates.