我正在尝试将多个基于硬件的产品的大型平台抽象库(PAL)移植到资源有限的小型嵌入式系统(即千字节数)。
当前的PAL有一个简单的getRegister()
函数,它返回特定产品的寄存器地址。例如,假设名为coconut
和pineapple
的产品,代码将如下所示:
#include "headers/Include/coconut.h"
#include "headers/Include/pineapple.h"
enum prodType {
PROD_COCONUT = 0,
PROD_PINEAPPLE,
PROD_MAX,
PROD_INVALID = (-1)
};
uint64_t getRegister(enum prodType prod, int regName) {
uint64_t r = 0;
switch (prodType) {
case PROD_COCONUT:
switch (regName) {
case REG_BASE:
r = COCONUT_REG_BASE;
break;
case REG_CORE:
r= COCONUT_REG_CORE;
break;
}
break;
case PROD_PINEAPPLE:
switch (regName) {
case REG_BASE:
r = PINEAPPLE_REG_BASE;
break;
case REG_CORE:
r= PINEAPPLE_REG_CORE;
break;
}
break;
default:
// Error.
break;
}
return r;
}
我想将此函数更改为一个简单的编译时宏等效项,以便getRegister(PROD_COCONUT, REG_BASE)
只查看值表并返回相应的寄存器值。这样做的原因是,如果我知道平台只支持coconut
,我可以使用宏来不包含其他产品的标头(即pineapple
),并减少程序大小。
到目前为止,我正在考虑这样的事情:
enum regs {
REG_BASE = 0,
REG_CORE,
REG_MAX,
REG_INVALID = (-1)
};
struct keyValPair {
int idx;
enum reg;
uint64_t val;
};
struct keyValPair tableCoconut[] = {
{ 0, REG_BASE, COCONUT_REG_BASE },
{ 1, REG_CORE, COCONUT_REG_CORE },
};
所以,我希望能够对索引到表格的效果做些什么,以便tableCoconut[REG_BASE]
返回COCONUT_REG_BASE
,在O(1)
时间内返回一个值无需迭代/搜索表格。理想情况下,它是编译时宏扩展而不是真正的函数调用。
是否有(简单/干净)方式实现某些中间映射,以便:
idx
结构中删除keyValPair
变量(可选)。O(1)
(即非基于搜索的查找)(必需)?这假设寄存器值是非连续且唯一的? I'm considering using pieces from a slightly similar question of mine from years ago,但不能完全得到这种与宏相关的双向稀疏到连续映射。我试图通过宏和##
操作创建一个自动递增索引值,以通过REG_BASE
连接创建一个前缀附加到REG_CORE
/ ##
的中间索引使用预处理器进行操作。
并非所有产品都具有相同的寄存器。该行可能有一个banana
产品,不会为BANANA_REG_CORE
提供条目。
答案 0 :(得分:1)
假设你的枚举从0开始并从那里顺序上升,你可以使用枚举值直接索引到数组中并检索你想要的值。虽然这可能不会在编译时发生,但是数组查找是O(1)所以它应该很快。
所以你可以像这样构建一个数组:
uint64_t tableCoconut[] = {
COCONUT_REG_BASE,
COCONUT_REG_CORE
};
而tableCoconut[REG_BASE]
或tableCoconut[REG_CORE]
会在O(1)中为您提供所需的值。
您可以进一步扩展此功能以考虑多种产品:
uint64_t tableAll[2][2] = {
{ COCONUT_REG_BASE, COCONUT_REG_CORE },
{ PINEAPPLE_REG_BASE, PINEAPPLE_REG_CORE },
};
执行O {1)查找,例如tableAll[PROD_COCONUT][REG_BASE]
或tableAll[PROD_PINAPPLE][REG_BASE]