狀態(tài)機的可監(jiān)控維度該如何考慮
》狀態(tài)機該怎么監(jiān)控
最近遇到一個關于狀態(tài)機的問題,具體的業(yè)務就不講了。關于FSM怎么寫這種初級問題在這里也不講了。這里我們只關注下在真實的應用場景里,從監(jiān)控的角度來看,該如何去看待FSM。 FPGA設計里,除了功能實現(xiàn)之外,最重要的一部分就是DFX的設計。畢竟燒錄完之后我們也只能通過DFX來去觀測內部的狀態(tài)(說JTAG的請繞過,那頂多是開發(fā)階段)。在考慮資源允許的情況下,我們要做的應當是有充分的DFX能夠幫助我們去觀測內部的狀態(tài)。一個工程做下來往往是在補DFX時覺得要添加的太多了,而到真實需要定位問題的時候則又會感嘆“當初怎么不多添加些DFX”~ 回到對FSM的處理,一開始想到的可能是:
把FSM的當前狀態(tài)添加到DFX中。
沒毛病,我們能夠清楚的觀察到當前狀態(tài)機處于什么狀態(tài)。但當狀態(tài)機如果處于卡死不動的狀態(tài),那我們所需要的就是導致當前狀態(tài)卡住的信號的狀態(tài):
把FSM各條件跳轉的判斷信號添加到DFX中。
上面兩條也基本是我們之前設計常常會做的內容。然而這里面只是對下面的場景做了監(jiān)控:
狀態(tài)機卡住的場景——通過狀態(tài)跳轉條件的DFX信號去判斷卡住的原因
對于DFX信號,像我們通過PCIe寄存器鏈路去讀取DFX信號時不可能獲取到每拍的結果,因而上面的DFX信號添加方式也就只能針對FSM卡死的情況進行定位判斷。然而很不幸,這一次我遇到了一個狀態(tài)機在跳轉,只是沒有跳轉到一個需要響應某個動作的狀態(tài)。由于代碼從別人那里接手過來的,看代碼也能對case場景進行一個判斷。但回到監(jiān)控的角度,只是沒有跳轉到一個需要響應某個動作的狀態(tài)這個判斷是我針對看到的DFX抓取信號來判斷得到的結論,然而我并不能自證(當然可以通過仿真構造類似Case來進行驗證,這不提了),畢竟DFX不是每拍的結果都能看得到的,針對線上的問題,所有的判斷應當都是有充足的證據(jù)的,而不是結合觀測加推斷。那么針對這種場景,有必要再增加一種監(jiān)控手段:
記錄各狀態(tài)之間是否有過跳轉發(fā)生,軟件可清零。
通過記錄各狀態(tài)之間是否發(fā)生過跳轉,那么我們可以結合DFX當前狀態(tài)來充分說明某個狀態(tài)沒有到達。而記錄各狀態(tài)之間是否有過跳轉發(fā)生,所消耗的資源也非常少。 》example
來看一個簡單的狀態(tài)機:
import spinal.lib.fsm._ classTopLevelextendsComponent{ val io = newBundle { val result = out Bool() } val fsm = newStateMachine { val counter = Reg(UInt(8bits)) init(0) io.result := False val stateA : State = newState with EntryPoint { whenIsActive(goto(stateB)) } val stateB : State = newState { onEntry(counter := 0) whenIsActive { counter := counter + 1 when(counter === 4) { goto(stateC) } } onExit(io.result := True) } val stateC : State = newState { whenIsActive(goto(stateA)) } } }
這里面會存在三個狀態(tài)StateA、StateB、StateC:
StateA——>StateB
StateB——>StateC
StateC——>StateA
那么我們需要記錄的就是:
StateA_to_fsm_stateB_change
StateB_to_fsm_stateC_change
StateC_to_fsm_stateA_change
在SpinalHDL里,這種活兒還是不要手動的好,當然是自動化的處理好。下面給一個Demo,可能有大神有更加優(yōu)雅的解決方式,歡迎交流。
定義StateExtend:
class StateExtend(implicit stateMachineAccessor: StateMachineAccessor) extends State {
val nextStateBuffer=Set[StateExtend]()
def goto(state:StateExtend)={
nextStateBuffer.add(state)
stateMachineAccessor.goto(state)
}
}
主要是在原有State的基礎上重定義了goto函數(shù),記錄了每個狀態(tài)會跳轉的下一狀態(tài)。
然后定義FsmMonitor:
caseclassFsmState(monReg:Bool,curState:State,nextState:State) caseclassFsmMonitor(implicitstateMachineAccessor: StateMachine) extendsArea{ val stateMonMap=Map[State,ArrayBuffer[FsmState]]() val state_mon_clear=RegInit(False) simPublic() defgenerateFsmMonitor()={ val current_state_dly=RegNext(stateMachineAccessor.stateReg) val next_state_dly=RegNext(stateMachineAccessor.stateNext) for(state<-stateMachineAccessor.states){ ??????if(state.isInstanceOf[StateExtend]){ ????????for?(nextState <- state.asInstanceOf[StateExtend].nextStateBuffer){ ??????????val state_change=RegInit(False) setName (s"${state.getName()}_to_${nextState.getName()}_change") ??????????when(state_mon_clear){ ????????????state_change.clear() ??????????}elsewhen((current_state_dly===stateMachineAccessor.enumOf(state))){ ????????????when(next_state_dly===stateMachineAccessor.enumOf(nextState)){ ??????????????state_change.set() ????????????} ??????????} ??????????stateMonMap.getOrElse(state,ArrayBuffer[FsmState]()).append(FsmState(state_change,state,nextState)) ????????} ??????} ????} ??} }
在generateFsmMonitor中,會針對每個狀態(tài)來分別創(chuàng)建跳轉相應的跳轉監(jiān)控信號,并記錄到stateMonMap中去。state_mon_clear可用于清零狀態(tài)所有監(jiān)控信號。通過regif可講state_mon_clear及stateMonMap中的所有元素添加到寄存器總線中去(也可以直接用regif聲明創(chuàng)建寄存器)。
最終,在使用時如下即可:
case classfsmTest() extendsComponent{
val counter = out(Reg(UInt(8bits)) init (0))
val fsm = newStateMachine {
val stateA = newStateExtend() with EntryPoint setName("StateA")
val stateB, stateC = newStateExtend()
stateA.whenIsActive {
stateA.goto(stateB)
}
stateB.whenIsActive {
stateB.goto(stateC)
}
stateC.onEntry(counter := 0)
stateC.whenIsActive {
counter := counter + 1
when(counter === 3) {
stateC.goto(stateA)
}
}
val fsm_mon=FsmMonitor()
addPrePopTask(()=>{
fsm_mon.generateFsmMonitor()
})
}
}
差別點在于goto換成對應的StateA.goto等顯示調用的形式。通過例化FsmMonitor調用generateFsmMonitor即可注冊所有的狀態(tài)跳轉信號:

審核編輯:黃飛
-
FPGA
+關注
關注
1660文章
22408瀏覽量
636248 -
寄存器
+關注
關注
31文章
5608瀏覽量
129968 -
狀態(tài)機
+關注
關注
2文章
499瀏覽量
29141
原文標題:反思一下FSM
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
Verilog狀態(tài)機+設計實例
玩轉Spring狀態(tài)機
如何寫好狀態(tài)機
狀態(tài)機舉例
什么是狀態(tài)機 狀態(tài)機的描述三種方法
什么是狀態(tài)機?狀態(tài)機5要素
狀態(tài)模式(狀態(tài)機)
狀態(tài)機該怎么監(jiān)控
評論