軟件設計中,F(xiàn)SM(Finite-State Machine)分為3部分:狀態(tài)(State),事件(Event),動作(Action)。
狀態(tài)模式(State Pattern)是行為型(Behavioral)設計模式,將軟件主機端的行為歸類為各個狀態(tài),狀態(tài)之間可以互相轉(zhuǎn)化,每種狀態(tài)的行為不相同;統(tǒng)一交給一個Context類型的模塊負責調(diào)度各個狀態(tài)的跳轉(zhuǎn);
硬件設計中的FSM,不僅是一種電路的描述工具,而且也是一種思想方法;數(shù)字邏輯本質(zhì)上都可以歸一化為FSM;RTL描述FSM可以歸類為常用的幾種方法,通常采用三段式的描述;
在我們的驗證環(huán)境中,有時也需要一個組件專門負責FSM的建模;例如驗證USB Device DUT時,驗證環(huán)境需要模擬USB Host的行為;對于USB協(xié)議復雜的狀態(tài)機,使用專門的FSM組件模擬,可以減少組件間的耦合;也可以將FSM組件的狀態(tài)賦值到virtual interface上,通過波形協(xié)助debug;
并不是所有DUT模塊中包含F(xiàn)SM,驗證環(huán)境中就需要對應的FSM建模;RTL的硬件電路是cycle級的時序電路,采用FSM可以很好的描述算法運算;而驗證環(huán)境都是事務級的基于事件的高級抽象模型,是否需要采用FSM根據(jù)驗證環(huán)境而定;對于簡單的設計,不需要模擬FSM;對于復雜的標準協(xié)議,VIP中都會采用FSM建模來完成,具有高內(nèi)聚低耦合的好處。
Simple example
本篇對一個示例,分別使用兩種方式來描述:
一個簡單的FSM如下,分為4種狀態(tài);對于狀態(tài)的跳轉(zhuǎn)條件,本篇通過uvm_event類型的事件觸發(fā),驗證環(huán)境中的實際情況可以是事件,某一個signal狀態(tài),或者if的判斷等;不同狀態(tài)下的Action,僅使用一句display代表,驗證環(huán)境中的實際情況可以調(diào)用某一個task,對signal的驅(qū)動,或者調(diào)用其他組件的API等;僅做結構上的演示;
通過randsequence產(chǎn)生激勵sequence,遍歷狀態(tài)機跳轉(zhuǎn)條件;
classclient; state_machineFSM; uvm_event_poolevents_pool; uvm_eventto_idle,to_state_a,to_state_b,to_state_c; functionnew(); events_pool=uvm_event_pool::get_global_pool(); to_idle=events_pool.get("to_idle"); to_state_a=events_pool.get("to_state_a"); to_state_b=events_pool.get("to_state_b"); to_state_c=events_pool.get("to_state_c"); endfunction taskrand_simulate(); for(inti=0;i<2;i++)?begin ??????bit?FLAG?=?0; ??????randsequence?(stream) ?????????stream?:?first?second?third?last; ?????????first??:?state_a; ?????????second?:?state_b?{FLAG?=?1;}?|?state_c; ?????????third??:?if?(FLAG?==1)?state_c?else?state_b; ?????????last???:?state_idle; ?????????state_idle:?{`INTERVALTIME;to_idle.trigger();}; ?????????state_a???:?{`INTERVALTIME;to_state_a.trigger();}; ?????????state_b???:?{`INTERVALTIME;to_state_b.trigger();}; ?????????state_c???:?{`INTERVALTIME;to_state_c.trigger();}; ??????endsequence ??????end ???endtask ?...... ?......
use task
類state_machine包含四個狀態(tài)的task;通過request_state_change函數(shù)實現(xiàn)狀態(tài)跳轉(zhuǎn);每進入一個狀態(tài),對應一個線程,當跳出狀態(tài)時,注意線程需要disable掉;
classstate_machine; typedefenum{ IDLE,STATE_A,STATE_B,STATE_C }state_t; uvm_event_poolevents_pool; uvm_eventto_idle,to_state_a,to_state_b,to_state_c; localstate_tcur_state; externfunctionnew(); externfunctionvoidstart(); externfunctionvoidrequest_state_change(state_tcur_state); externtaskdo_idle(); externtaskdo_state_a(); externtaskdo_state_b(); externtaskdo_state_c(); endclass functionstate_machine::new(); events_pool=uvm_event_pool::get_global_pool(); to_idle=events_pool.get("to_idle"); to_state_a=events_pool.get("to_state_a"); to_state_b=events_pool.get("to_state_b"); to_state_c=events_pool.get("to_state_c"); endfunction functionvoidstate_machine::start(); cur_state=IDLE; request_state_change(cur_state); endfunction functionvoidstate_machine::request_state_change(state_tcur_state); case(cur_state) IDLE:begin fork begin $display("Enter%sstate!",cur_state.name()); do_idle(); end join_none return; end STATE_A:begin fork begin $display("Enter%sstate!",cur_state.name()); do_state_a(); end join_none return; end STATE_B:begin fork begin $display("Enter%sstate!",cur_state.name()); do_state_b(); end join_none return; end STATE_C:begin fork begin $display("Enter%sstate!",cur_state.name()); do_state_c(); end join_none return; end default:begin $display("Enterunknowstate!"); $finish; end endcase endfunction taskstate_machine::do_idle(); state_tcur_state; $display("IDLE:nothingtodo! "); fork:disable_fork begin to_state_a.wait_trigger(); //$display("dosomething! "); cur_state=STATE_A; end join_any request_state_change(cur_state); endtask taskstate_machine::do_state_a(); state_tcur_state; $display("STATE_A:dosomething! "); fork:disable_fork begin to_state_b.wait_trigger(); //$display("dosomething! "); cur_state=STATE_B; end begin to_state_c.wait_trigger(); //$display("dosomething! "); cur_state=STATE_C; end join_any disablefork; request_state_change(cur_state); endtask taskstate_machine::do_state_b(); state_tcur_state; $display("STATE_B:dosomething! "); fork:disable_fork begin to_state_c.wait_trigger(); //$display("dosomething! "); cur_state=STATE_C; end begin to_idle.wait_trigger(); //$display("dosomething! "); cur_state=IDLE; end join_any disablefork; request_state_change(cur_state); endtask taskstate_machine::do_state_c(); state_tcur_state; $display("STATE_C:dosomething! "); fork:disable_fork begin to_state_b.wait_trigger(); //$display("dosomething! "); cur_state=STATE_B; end begin to_idle.wait_trigger(); //$display("dosomething! "); cur_state=IDLE; end join_any disablefork; request_state_change(cur_state); endtask
use Sate Pattern
采用狀態(tài)模式的設計,每個狀態(tài)繼承于virtual class state,實現(xiàn)各自的do_something和request_state_change;state_machine通過宏REGISTER_STATE創(chuàng)建各個state實例;state_machine中forvever執(zhí)行;狀態(tài)模式和策略模式的實現(xiàn)類似,都是使用OOP的組合 + 多態(tài)實現(xiàn);
virtualclassstate; state_machineFSM; uvm_event_poolevents_pool; uvm_eventto_idle,to_state_a,to_state_b,to_state_c; functionnew(); events_pool=uvm_event_pool::get_global_pool(); to_idle=events_pool.get("to_idle"); to_state_a=events_pool.get("to_state_a"); to_state_b=events_pool.get("to_state_b"); to_state_c=events_pool.get("to_state_c"); endfunction purevirtualtaskdo_something(); purevirtualtaskrequest_state_change(); endclass classstate_idleextendsstate; taskdo_something(); $display("STATE_IDLE:nothingtodo! "); endtask taskrequest_state_change(); state_tcur_state; fork:disable_fork begin to_state_a.wait_trigger(); //$display("dosomething! "); cur_state=STATE_A; end join_any FSM.set_state(cur_state); endtask endclass classstate_aextendsstate; taskdo_something(); $display("STATE_A:dosomething! "); endtask taskrequest_state_change(); state_tcur_state; fork:disable_fork begin to_state_b.wait_trigger(); //$display("dosomething! "); cur_state=STATE_B; end begin to_state_c.wait_trigger(); //$display("dosomething! "); cur_state=STATE_C; end join_any disablefork; FSM.set_state(cur_state); endtask endclass classstate_bextendsstate; taskdo_something(); $display("STATE_B:dosomething! "); endtask taskrequest_state_change(); state_tcur_state; fork:disable_fork begin to_state_c.wait_trigger(); //$display("dosomething! "); cur_state=STATE_C; end begin to_idle.wait_trigger(); //$display("dosomething! "); cur_state=STATE_IDLE; end join_any disablefork; FSM.set_state(cur_state); endtask endclass classstate_cextendsstate; taskdo_something(); $display("STATE_C:dosomething! "); endtask taskrequest_state_change(); state_tcur_state; fork:disable_fork begin to_state_b.wait_trigger(); //$display("dosomething! "); cur_state=STATE_B; end begin to_idle.wait_trigger(); //$display("dosomething! "); cur_state=STATE_IDLE; end join_any disablefork; FSM.set_state(cur_state); endtask endclass classstate_machine; localstatestate_m; statestate_pool[state_t]; functionvoidset_state(state_tstate); $display("Enter%sstate!",state.name()); state_m=state_pool[state]; endfunction functionvoidfsm_init(); `REGISTER_STATE(IDLE,idle) `REGISTER_STATE(A,a) `REGISTER_STATE(B,b) `REGISTER_STATE(C,c) this.set_state(STATE_IDLE); endfunction taskrun(); fsm_init(); foreverbegin state_m.do_something(); state_m.request_state_change(); end endtask endclass
note
state_machine中還可以加入reset stop函數(shù)控制FSM的更多行為;封裝更多API供其他模塊調(diào)用;加入assertion做基于cycle的條件判斷;加入covergroup收集功能覆蓋率;
審核編輯:劉清
-
RTL
+關注
關注
1文章
385瀏覽量
59837 -
UVM
+關注
關注
0文章
182瀏覽量
19185 -
狀態(tài)機
+關注
關注
2文章
492瀏覽量
27557 -
fsm
+關注
關注
0文章
35瀏覽量
12826 -
DUT
+關注
關注
0文章
189瀏覽量
12409
原文標題:UVM設計模式 (九) 狀態(tài)模式、Modelling Finite-State Machines in Testbench
文章出處:【微信號:數(shù)字芯片設計工程師,微信公眾號:數(shù)字芯片設計工程師】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論