Reputation: 77
I would like to optimize the dml-code I have for speed in a production environment. As far as I understand log
statements such as:
log info, <n>: <string>;
Get translated in at least one if statement in the executable, because there is a need to check whether the log-level
is larger than n.
I would like to avoid that by throwing the if statement out of the executable similar to #define
and #ifdef
statements in C and the only way I found in dml is by defining a constant and checking it and hoping the compiler will optimize out the code, recognizing it will never be executed.
constant LOG = 1; // there is not even the possibility to define a bool constant
if (LOG) log info, <n>: <string>;
My questions are:
Thanks in advance.
Upvotes: 1
Views: 68
Reputation: 898
My first reaction is that you should reconsider your ambition to do optimizations on this level. Do you have benchmarks that prove this code to be a bottleneck? The devices of a system seldom account for more than 5-10% of the total simulation time, and account for a vast majority of the development effort, so your device development effort is better spent on maintainability. There are definitely cases where devices account for more than that; in this case you need to understand why. It's often caused by a busy-wait loop, and there are techniques like hypersimulation that can be used to fast-forward simulation over busy-wait loops.
Also, the if
generated by a log
statement is an easy-to-predict branch instruction, so you will have a hard time even measuring the speed of it.
However, you may have other valid reasons for making sure a debug log is left out from the binary, e.g. concerns about code size or confidentiality. If you want to ensure that a statement stays outside the compiled result, then use #if
instead of if
. This ensures the body is expanded in compile-time; the discarded branch is even allowed to reference nonexistent identifiers.
To summarize, my answers to your three questions are:
#if
may be a better choice#if
gives you a hard guarantee that the code will be optimized out by DMLC; if you use if
then it will certainly be eliminated by the C compiler if you compile with optimization flags, but there is no formal guarantee.<host>/obj/modules/MODULE-NAME/DEVNAME-dml.c
.And a final note: The recommended construct for constants in DML 1.4 is param
; you can write param LOG = true;
. constant
is a remnant of DML 1.2, which remains only to bridge a current compiler limitation (param
s cannot be used when specifying array sizes in typedef
s).
Upvotes: 1
Reputation: 188
Note that trying to optimize away log statements (beyond the use of log levels/groups) is very likely premature, and only adds unneeded complexity to the model if so -- modeled devices only very rarely present a bottleneck within a simulation. Verify that the log statements actually do have a significant impact before resorting to trying to optimize them away.
That said, to answer each question in turn:
1. Use the compile-time if (else) statement (which is also available as an object statement):
param do_log = true;
method m() {
....
#if (do_log) log info, <n>: <string>;
}
Also note the use of param
instead of constant
here. param
is superior to constant
in every way, with the only exception being that they can't be used within typedef
s. As a plus, parameter definitions can even be made through the DMLC flag -D
, which is useful for this kind of conditional compilation.
2.
The DML compiler typically doesn't eliminate any operations which aren't explicitly compile-time (like #if
is). This is true for the run-time if
statement: it won't get eliminated by DMLC no matter how simple the condition is.
However, as DMLC generates references to constant
/param
by simply replacing them by their definitions, the C compiler will receive a if (1)
or if (0)
and so will almost certainly optimize the branch away.
3.
As DMLC generates C, and generates that C with line directives to the original source file (unless --noline
is provided to DMLC), you can look up the generated C corresponding to a given DML statement by searching for #line [line of statement in DML source file] [path to DML source file]
. Although the generated C is certainly hard to read, for some simple statements like if
the generated code can almost get verbatim to the original DML.
Upvotes: 3
Reputation: 5888
To expand on the other answer: you can use #if
and a param
. Like this:
// Not a complete device model
dml 1.4;
param log_reg_bb_r50 = false;
// some bank
bank bb {
register r50 size 8 @ 0x50 is write {
method write(uint64 v) {
default(v);
log info, 1 : "Write to R50, standard log";
#if(log_reg_bb_r50) {
log info, 1 : "Write to R50, conditional log";
}
}
}
}
Upvotes: 0