sc_core::sc_fifo可以设置深度,默认深度为16。
explicit sc_fifo( int size_ = 16 )
: sc_prim_channel( sc_gen_unique_name( "fifo" ) ),
m_data_read_event( sc_event::kernel_event, "read_event" ),
m_data_written_event( sc_event::kernel_event, "write_event" )
{ init( size_ ); }
explicit sc_fifo( const char* name_, int size_ = 16 )
: sc_prim_channel( name_ ),
m_data_read_event( sc_event::kernel_event, "read_event" ),
m_data_written_event( sc_event::kernel_event, "write_event" )
{ init( size_ ); }
Sc_fifo的read 、write 函数都提供了non-block 和block两种形式,其中non-block 函数有一个bool类型的返回值,比如nb_read(),当fifo为empty的时候,返回false,read到一个entry的时候返回true;nb_write()如果返回值为false,则说明full了。
Read和write则是阻塞型的,没有返回值,也就是说函数中会自动进行wait。
sc_fifo的最大问题在于没有时序,write的当拍就可以read到。而这个feature跟实际的硬件设计肯定是不一致的,因为RTL 的fifo往往从push到pop至少花费1拍时间。
peq (payload event queue) 带时序,但没有full / empty的概念。故一般情况下,需要设置一个depth的成员变量进行配合,来模拟RTL中FIFO的时序功能。 peq 的使用方法可参考之前的博客: systemC/TLM:peq的简单用法_123axj的博客-CSDN博客
在SystemC编码过程中,可能会遇到这样的场景:Thread A push fifo1,Thread B push fifo2, Thread C 根据fifo 1 和fifo2的状态进行仲裁。由于SystemC调度影响,假设同一拍的调用顺序是Thread A --> Thread B --> Thread C,则C在仲裁时可以看到fifo1和fifo2都有request;但假设调用顺序是Thread C --> Thread A --> Thread B,则C在仲裁时看到的就是 fifo1和fifo2没有request。这样就会导致相同的测试条件下,前后两次的测试结果可能不一致,给debug工作带来了麻烦。
为消除SystemC调度对仿真结果的影响,可以让Thread A /B push fifo的内容always只能下一拍才能看到,这样0T Thread A/B push fifo,1T Thread C 看到两个request,ThreadC 的状态就是固定的了。