The preprocessor does not support conditional expressions (like ?:
). Instead, use a separate function macro to join the components:
#define JOIN4(a, b, c, d) a##b##c##d
#define RTL_REG(name, inst) JOIN4(DUT_, inst, _, name)
With that, RTL_REG(CLK_EN, 0)
expands to DUT_0_CLK_EN
, and RTL_REG(CLK_EN, 1)
expands to DUT_1_CLK_EN
.
The function-like macro call means that the macro arguments are evaluated by the preprocessor before the concatenation. This means that if you add a definition like
#define CLK_EN CLOCK_ENABLE
then RTL_REG(CLK_EN, 2)
expands to DUT_2_CLOCK_ENABLE
. If you further add
#define DUT_ WEIRDPREFIX_
then RTL_REG(CLK_EN, 3)
expands to WEIRDPREFIX_3_CLOCK_ENABLE
.
Let's say you cannot use the same prefix (DUT_0
, DUT_1
). No worries; you just need to add one layer of function-like macro calls, and redefine the prefixes:
#define JOIN3_(a, b, c) a ## b ## c
#define JOIN3(a, b, c) JOIN3_(a, b, c)
#define RTL_REG(name, inst) JOIN3(DUT_ ## inst, _, name)
Then, if you do say these additional definitions,
#define DUT_0 FIRST
#define DUT_1 SECOND
#define CLK_EN CLOCK_ENABLE
then RTL_REG(CLK_EN, 0)
expands to FIRST_CLOCK_ENABLE
, and RTL_REG(CLK_EN, 1)
to SECOND_CLOCK_ENABLE
. And, of course, if you do additional definitions like
#define FIRST_CLOCK_ENABLE foo(1)
#define SECOND_CLOCK_EANBLE bar(2)
then RTL_REG(CLK_EN, 0)
indeed expands to foo(1)
, and RTL_REG(CLK_EN, 1)
to bar(2)
.
You just need to be careful if the intermediate terms are already defined as macros, to not get too surprised. If you are using GCC, you can run gcc -dD -E source-or-header-file
to obtain the preprocessed source that includes all macro definition statements.