C-FSM状态的一种热编码

C-FSM状态的一种热编码,c,state,state-machine,C,State,State Machine,基本上,我只是想知道手动对C FSM的状态进行热编码是否是个好主意。 我实现了这一点,以编写一个简单的状态转换验证器: typedef enum { FSM_State1 = (1 << 0), FSM_State2 = (1 << 1), FSM_State3 = (1 << 2), FSM_StateError = (1 << 3) } states_t; 我知道我只能使用整数的最大大小。但我没有那么多州。因此

基本上,我只是想知道手动对C FSM的状态进行热编码是否是个好主意。 我实现了这一点,以编写一个简单的状态转换验证器:

typedef enum
{
    FSM_State1 = (1 << 0),
    FSM_State2 = (1 << 1),
    FSM_State3 = (1 << 2),
    FSM_StateError = (1 << 3)
} states_t;
我知道我只能使用整数的最大大小。但我没有那么多州。因此,这不是一个问题


还有比这种编码更好的吗? 是否有一些缺点我还没有看到

谢谢你的帮助

编辑:根据用户3386109注释更改验证测试


最后的想法 最后我做的是:

1/状态枚举是“经典”枚举:

有效转换的2/位字段:

struct s_fsm_stateValidation
{
    bool State1IsValid: 1;
    bool State2Valid: 1;
    bool State3IsValid: 1;
    bool StateErrorIsValid: 1;

    /// Reserved space for 32bit reserved in the union
    uint32_t reserved: 28;
};
3/为验证创建一个联合体

typedef union FSM_stateValidation_u
{
    /// The bit field of critical system errors
    struct s_fsm_stateValidation state;
    /// Access the bit field as a whole
    uint32_t all;
} u_FSM_stateValidation;
4/我更改了验证:

states_t nextState, requestedState;
uint32_t validDestStates = 0;

// Compute requested state
requestedState = FSM_State1;

// Define valid transitions
validDestStates |= FSM_State2;
validDestStates |= FSM_State3;

// Check transition
if (validDestStates & requestedState)
{
    // Valid transition
    nextState = requestedState;
}
else
{
    // Illegal transition
    nextState = FSM_StateError;
}
u_FSM_stateValidation validDestStates;

// Set valid states
validDestStates.state.State1 = true;

// Compute requestedState
requestedState = FSM_State2;

if ((validDestStates.all & ((uint32_t) (1 << requestedState)) ))
{
    // Next state is legal
    return requestedState;
}
else
{
    return FSM_StateError;
}
u_FSM_状态验证有效状态;
//设置有效状态
ValidTestState.state.State1=真;
//计算请求状态
requestedState=FSM_State2;
如果((validdestates.all&((uint32_t)(1)来自快速谷歌,“一个热编码”意味着每个有效代码都有一个精确的位集,这似乎就是您正在做的。搜索结果表明这是一种硬件设计模式

我能想到的缺点是

  • 正如您所建议的,您极大地限制了有效代码的数量-对于32位,您最多有32个代码/状态,而不是超过40亿个

  • 它对于查找表并不理想,因为查找表是
    switch
    语句的常见实现。通常有一个内在函数可用于确定哪一个是最低位集,但我不希望编译器自动使用它

  • 不过,如果州的数量不多,这些问题就不是什么大问题

    因此,国际海事组织的问题是,是否有优势来证明这一成本。这不一定是一个巨大的优势,但必须有某种意义


    我能想到的最好办法是,您可以使用位技巧来指定状态集,这样您就可以有效地测试当前状态是否在给定的集中-如果您需要在状态中执行某些操作
    (1)只要您知道这些限制,我看不出这样的系统有任何问题。事实上,我认为它应该非常适合非常小的嵌入式环境中的小型状态机,因为空间非常宝贵。我认为这是一个@means matters的问题,您需要
    &
    而不是
    ,例如
    如果(ValidTestState&requestedState)nextState=requestedState;
    “还有比这种编码更好的吗?”更好地定义。更快、更安全、更少的内存消耗?首先使用位的原因是什么?如果是因为需要快速评估有效状态转换,则此方法比使用状态的向上计数整数稍快。如果需要快速调用实际状态,则此方法稍慢,因为不能使用基于函数指针的查找表,编译器也不能将swich语句转换为函数指针的查找表。(有关查找表,请参阅)是的,我有硬件设计师的背景。这是我在状态机中学习一个热编码的地方。我不知道你提到的第二个缺点。这就是我想要的评论。你的最后一点也很有趣。我不确定我是否需要这个技巧。但我会记住它。谢谢你的回答!
    u_FSM_stateValidation validDestStates;
    
    // Set valid states
    validDestStates.state.State1 = true;
    
    // Compute requestedState
    requestedState = FSM_State2;
    
    if ((validDestStates.all & ((uint32_t) (1 << requestedState)) ))
    {
        // Next state is legal
        return requestedState;
    }
    else
    {
        return FSM_StateError;
    }