I have a long list defines defining with numerous properties for these registers. I'd like to have a function that takes the string of the register name and concatenates the bigdefine name and evaluates the `define int value upon process.
A simple function called liked the following:
PrintRegInfor(REGA);
Here's the class code that doesnt work:
`define CHIP_REGA_ADDR 16'h0000
`define CHIP_REGA_RESET_VAL 0
`define CHIP_REGB_ADDR 16'h0100
`define CHIP_REGB_RESET_VAL 1
.
.
`define CHIP_REGZ_ADDR 16'h1000
`define CHIP_REGZ_RESET_VAL 0
clase module;
function PrintRegInfo(string reg_name)
string reg_reset_string;
string reg_addr_string;
int reg_reset_int;
int reg_addr_int;
reg_reset_string = {"`CHIP_",reg_name,"_RESET_VAL"};
reg_addr_string = {"`CHIP_",reg_name,"_ADDR"};
reg_reset_int = reg_reset_string;
reg_add_int = reg_add_string;
$display("Reg %s at address 0x%x has a reset value of 0x%x\n",reg_name, reg_add_int,reg_reset_int);
endfunction
endclass
It looks like the conversion of string to int is converting the actual string from the ascii value into int. I'd like it to evaluate the `define of the string created. Is this possible?
I would like to get:
Reg Rega at address 0x0000 has a reset value of 0x0
I get something like:
Reg Rega at address 0x3478 has a reset value of 0x8373
Thanks!
You cannot use string variables to form identifiers in procedural code. You could create a macro to do this
`define PrintRegInfo(reg_name) \
$display("Reg %s at address 0x%x has a reset value of 0x%x\n", `"reg_name`", \
`CHIP_``reg_name``_ADDR, \
`CHIP_``reg_name``RESET_VAL);
However, the argument you pass to the macro cannot be a string variable.
You might rethink the way you organize your data by not using define statements and instead create a database with associative arrays.
Related
I have the following enum in my code:
enum myenum {
ready,
waiting,
stopping,
};
then I have a struct like so:
typedef struct {
int a;
int b;
uint8 step; // this is set using myenum.
} mystruct;
During GDB debugging session I am trying to declare an array of strings and then use its index to convert to string but running into couple of issues:
It requires me to keep the array elements to be of the same size:
(gdb) set $step_str={"ready", "waiting", "stopping"}
array elements must all be the same size
If I fix #1 by adding spaces and make all strings of same size then printf doesn't work with it:
(gdb) set $step_str={"ready ", "waiting ", "stopping"}
(gdb) printf "step=%s", $step_str[0]
Attempt to take address of value not located in memory.
The only way I could make it work is by using output command but the problem with output also is that if I end up adding a lot of spaces to a particular string then it is printed like this:
(gdb) set $step_str={"ready ", "this_is_a_long_enum_symbol"}
(gdb) output $step_str[0]
"ready", ' ' <repeats 21 times>
Having "' ' <repeats 21 times>" doesn't look nice and a bit confusing to the new readers of my output. I am trying to do this with a lot of enums and trying to gather debug info using GDB scripts on a core dump.
Another solution I thought of was to declare a helper command and make it set a variable but that becomes really long if I have several enums. For example:
define enum2str
if $arg0 == 0
set $retval="ready"
end
if $arg0 == 1
set $retval="this_is_a_long_enum_symbol"
end
... and so on but this will grow crazy if I have 20 enum values ...
Is there a better way to convert enum value to string? So I don't have to add those spaces to make array of same size elements and don't get that in my output?
Thanks much in advance!
I believe the $_as_string convenience function is what you're after.
$_as_string(value)
Return the string representation of value.
This function is useful to obtain the textual label (enumerator) of an
enumeration value. For example, assuming the variable node is of an
enumerated type:
(gdb) printf "Visiting node of type %s\n", $_as_string(node)
Visiting node of type NODE_INTEGER
For example I have a macro:
#define PRINT(int) printf(#int "%d\n",int)
I kinda know what is the result.
But how come #int repersent the whole thing?
I kinda forget this detail. Can anybody kindely give me a hint?
Thanks!
In this context (applied to a parameter reference in a macro definition), the pound sign means to expand this parameter to the literal text of the argument that was passed to the macro.
In this case, if you call PRINT(5) the macro expansion will be printf("5" "%d\n", 5); which will print 5 5; not very useful; however if you call PRINT(5+5) the macro expansion will be printf("5+5" "%d\n", 5+5); which will print 5+5 10, a little less trivial.
This very example is explained in this tutorial on the C preprocessor (which, incidentally, is the first Google hit for c macro pound sign).
"#" can show the name of a variable, it's better to define the macro as this:
#define PRINT(i) printf(#i " = %d\n", i)
and use it like this:
int i = 5;
PRINT(i);
Result shown:
i = 5
That is a bad choice of name for the macro parameter, but harmless (thanks dreamlax).
Basically if i write like so
PRINT(5);
It will be replaced as
printf("5" "%d\n",5);
or
printf("5 %d\n",5);
It is a process called Stringification, #int is replaced with a string consisting of its content, 5 -> "5"
'#' is called a stringize operator.
Stringize operator puts quotes around the parameter passed and returns a string. It is only used in a marco statements that take the arguments.
#include<stdio.h>
#define stringLiteral(sl) #sl
int main()
{
char StringizeOpreator = 'a';
printf(stringLiteral(StringizeOpreator));
return 0;
}
Here the stringLiteral marco takes the formal argument sl and returns #sl. Actual argument passed is StringizeOpreator variable. The return statement #sl has # operator, that puts quotes around the argument like "StringizeOpreator" and returns a string.
So the output of the above program is the name of the actual parameter 'StringizeOpreator' rather than the value stored in the actual parameter passed.
output :
StringizeOperator
...
exitcode 0
To learn more visit this link:
Stringize Operator
I have a tricky, but interesting question. Hang in there!
Let's assume I write embedded code, and I am in a system where I have to store values in 16bit unsigned to be compatible with other systems. Some values have a decimal part, but luckily I know the position of the separator in advance (fixed point).
Now let's consider this structure:
typedef struct{
// pointer to a function that computes the "real" value
float (*getRealValue)(void);
// pointer to a function that computes a "stringified" value
bool (*getCustomString)(char *);
} var_info_t;
And let's declare one variable var1, which is a temperature:
uint16_t var1 = 1530; // means 15.3°C
float var1_toFloat(void){ return (float)var1/100; } // should return 15.3
var_info_t var1_info = { .getRealValue = var1_toFloat, .getCustomString = NULL };
and another variable var2, which happens to be more like a boolean:
uint16_t var2 = 1; // means Enabled
bool var2_toString(char* buffer){ // should write "Enabled"
if(buffer) sprintf(buffer, "%s", var2 ? "Enabled" : "Disabled");
return true;
}
var_info_t var2_info = { .getRealValue = NULL, .getCustomString = var2_toString };
Now I want to display these values together on a screen, with some fancy formatting that can change depending of where these value are written on the screen.
(I just have to call TEXT_SetText(int widget_id, char* text) to update my GUI widgets.)
What I want to accomplish is to create a "wrapper" to TEXT_SetText() like this...
static char text[128], buf[2][32];
#define GET_VAR_AUTO(var_info, i) \
((var_info.getCustomString != NULL && var_info.getCustomString(buf[i])) ? buf[i] : \
(var_info.getRealValue != NULL ? var_info.getRealValue() : 0))
void my_TEXT_SetText(int widget_id, char* format, var_info_t a, var_info_t b){
snprintf(text, sizeof(text), format, GET_VAR_AUTO(a, 0), GET_VAR_AUTO(b, 1));
TEXT_SetText(widget_id, text);
}
...so that calling my_TEXT_SetText(0, "Regulator is %s at %.1f\260C", var2_info, var1_info);
will display a nice Regulator is Enabled at 15.3°C inside my box.
The real advantage here is that you can update the text in real-time just by calling this same function periodically from "anywhere" (without "knowing anything" about the variables or their values). Also you can simply expand the number of variables inside the same text by increasing the number of snprintf arguments.
The problem: the GET_VAR_AUTO macro is not syntactically correct because it mixes char* from buf[i] and float from getRealValue() in the possible results of the ternary operator:
error: type mismatch in conditional expression
BUT, knowing that sprintf is a variadic function, that treats its arguments according to the types given in the format string (%f, %s, ... thanks to the va_arg() function), is there a way to find a common abstract type for the ternary operator which would be accepted by the sprintf ?
I tried a lot of things but I can't get the char* and float to work simultaneously.
(Unfortunately I'm using C, not C++)
No, there simply isn't any generic type, and it cannot be done in C except in very special cases.
For example floating point arguments are passed in floating point/SSE registers on x86-64 for example, whereas integer arguments in integer registers. There is no way of passing a variable argument that is passed as "both" in variable arguments, because in a function call like
printf("%f %d", f, d );
R1 F1 R2
The arguments would be passed in two general-purpose registers and one floating point register like so, whereas in
printf("%d %f", d, f );
R1 R2 F1
they would be passed in the same registers again!
Indeed,
#include <stdio.h>
int main(void) {
printf("%f %s\n", "hello world", 2.5);
}
compiled with GCC for x86-64/Linux, and run, will not print any random garbage but exactly 2.50000 hello world. So on x86-64 the most you could do is to pass the last argument in both a floating point and a general purpose register.
What you could do is to write your own printf-like function that would accept pointers to void for the arguments, then dereference them based on the actual type.
It will still be quite tricky.
If you're really desperate, consider trying libffi.
Define
#define FLOAT_STR_SIZE_MAX (32) /* or what ever you feel suits */
#define FTOA(b, s, x) \
(snprintf(b, s, "%f", x), b)
and replace
(var_info.getRealValue != NULL ? var_info.getRealValue() : 0)
by
FTOA((char[FLOAT_STR_SIZE_MAX]){'\0'},
FLOAT_STR_SIZE_MAX,
(var_info.getRealValue != NULL ? var_info.getRealValue() : 0.))
:-)
I am programming a uC. To interact with the uC I've written an menu. In this menu I want to print some information on a PC in a terminal window (in this case tera term VT).
Therefore I want to print something like this:
dec. duty cycle by x% and x should be replaced by a number defined in a marco. To do this, each menu item contains a description string. This string is passed to the menu item via the 1interlaceMenuFct(...)-function an will be printed to the terminal by the print_text(...)-function. So I wrote:
Header file:
#define X 5
#define _STR(s) #s
#define _XSTR(s) _STR(s)
extern void interlaceMenuFct(menuFct_t *fct, const char *description, const char *symbol, menuItem_t *parent, menuFct_t *prev, void *action, unsigned char cnt);
extern void print_text(const char *text);
in code file:
interlaceMenuFct(&decDC_mf,"dec. duty cycle by "_XSTR(X)"%","-",&io_mi,&incDC_mf,&decrementDutyCycle,0);
Here I use the _XSTR(s)-function to replace the X by the number.
Now my "problem": This works, but I do not understand why.
The function interlaceMenuFct(...) expect a pointer to the string. But in the function call I (think that I) create three strings: dec. ..., 5, %
Does it works because these strings are static and the linker place them in ascending order in the memory or does the compiler concatenate this three strings automatically, because there is nothing else written between the "-tags?
§5.1.1.2 of the C standard describes the various stages of compilation (referred to as "translation" in the document). Specifically, stage six is:
Adjacent string literal tokens are concatenated.
In other words, after macro expansion takes place (which is stage 4), any string literals right next to each other (aka adjacent) are combined into one large string. Thus, the 3 strings "dec. duty cycle by ", "5", and "%" are combined into one large string "dec. duty cycle by 5%".
Then, later on in stage 7, the code is actually compiled into machine code, so it sees the interlaceMenuFct call with only one string in that parameter.
For example I have a macro:
#define PRINT(int) printf(#int "%d\n",int)
I kinda know what is the result.
But how come #int repersent the whole thing?
I kinda forget this detail. Can anybody kindely give me a hint?
Thanks!
In this context (applied to a parameter reference in a macro definition), the pound sign means to expand this parameter to the literal text of the argument that was passed to the macro.
In this case, if you call PRINT(5) the macro expansion will be printf("5" "%d\n", 5); which will print 5 5; not very useful; however if you call PRINT(5+5) the macro expansion will be printf("5+5" "%d\n", 5+5); which will print 5+5 10, a little less trivial.
This very example is explained in this tutorial on the C preprocessor (which, incidentally, is the first Google hit for c macro pound sign).
"#" can show the name of a variable, it's better to define the macro as this:
#define PRINT(i) printf(#i " = %d\n", i)
and use it like this:
int i = 5;
PRINT(i);
Result shown:
i = 5
That is a bad choice of name for the macro parameter, but harmless (thanks dreamlax).
Basically if i write like so
PRINT(5);
It will be replaced as
printf("5" "%d\n",5);
or
printf("5 %d\n",5);
It is a process called Stringification, #int is replaced with a string consisting of its content, 5 -> "5"
'#' is called a stringize operator.
Stringize operator puts quotes around the parameter passed and returns a string. It is only used in a marco statements that take the arguments.
#include<stdio.h>
#define stringLiteral(sl) #sl
int main()
{
char StringizeOpreator = 'a';
printf(stringLiteral(StringizeOpreator));
return 0;
}
Here the stringLiteral marco takes the formal argument sl and returns #sl. Actual argument passed is StringizeOpreator variable. The return statement #sl has # operator, that puts quotes around the argument like "StringizeOpreator" and returns a string.
So the output of the above program is the name of the actual parameter 'StringizeOpreator' rather than the value stored in the actual parameter passed.
output :
StringizeOperator
...
exitcode 0
To learn more visit this link:
Stringize Operator