Specman: Why DAC macro interprets the type <some_name'exp> as 'string'?

181 Views Asked by At

I'm trying to write a DAC macro that gets as input the name of list of bits and its size, and the name of integer variable. Every element in the list should be constrained to be equal to every bit in the variable (both of the same length), i.e. (for list name list_of_bits and variable name foo and their length is 4) the macro's output should be:

keep list_of_bits[0] == foo[0:0];
keep list_of_bits[1] == foo[1:1];
keep list_of_bits[2] == foo[2:2];
keep list_of_bits[3] == foo[3:3];

My macro's code is:

define <keep_all_bits'exp> "keep_all_bits <list_size'exp> <num'name> <list_name'name>" as computed {
    for i from 0 to (<list_size'exp> - 1) do {
        result = appendf("%s keep %s[%d] == %s[%d:%d];",result, <list_name'name>, index, <num'name>, index, index);
    };
};

The error I get:

 *** Error: The type of '<list_size'exp>' is 'string', while expecting a
numeric type
             ...
    for i from 0 to (<list_size'exp> - 1)  do {

Why it interprets the <list_size'exp> as string? Thank you for your help

2

There are 2 best solutions below

0
On BEST ANSWER

All macro arguments in DAC macros are considered strings (except repetitions, which are considered lists of strings). The point is that a macro treats its input purely syntactically, and it has no semantic information about the arguments. For example, in case of an expression (<exp>) the macro is unable to actually evaluate the expression and compute its value at compilation time, or even to figure out its type. This information is figured out at later compilation phases.

In your case, I would assume that the size is always a constant. So, first of all, you can use <num> instead of <exp> for that macro argument, and use as_a() to convert it to the actual number. The difference between <exp> and <num> is that <num> allows only constant numbers and not any expressions; but it's still treated as a string inside the macro.

Another important point: your macro itself should be a <struct_member> macro rather than an <exp> macro, because this construct itself is a struct member (namely, a constraint) and not an expression.

And one more thing: to ensure that the list size will be exactly as needed, add another constraint for the list size.

So, the improved macro can look like this:

define <keep_all_bits'struct_member> "keep_all_bits <list_size'num> <num'name> <list_name'name>" as computed {
    result = appendf("keep %s.size() == %s;", <list_name'name>, <list_size'num>);
    for i from 0 to (<list_size'num>.as_a(int) - 1) do {
        result = appendf("%s keep %s[%d] == %s[%d:%d];",result, <list_name'name>, i, <num'name>, i, i);
    };

};

3
On

Why not write is without macro?

keep for each in list_of_bits {
    it == foo[index:index];
};

This should do the same, but look more readable and easier to debug; also the generation engine might take some advantage of more concise constraint.