7.8 SC_METHOD: next_trigger()的动态敏感表
SC_METHOD processes 使用 next_trigger() 动态的指定它们的敏感性。 语法如下:
next_trigger不会阻碍当前SC_METHOD的执行,它会改变下一次调用该SC_METHOD的敏感表。如果没有静态敏感表,那么SC_METHOD的所有执行分支都应当有next_trigger,否则可能导致该SC_METHOD不再被调用。
7.9 进程的静态敏感表
动态敏感表示在仿真阶段的建立的,并且可以在仿真中被改变。
静态敏感表是在elaboration阶段(仿真前)建立的,静态敏感表一旦建立就不能再改变。静态敏感表只应用于最近的进程注册。
建议选择类似于C++流的第一种语法风格。
7.10 dont_initialize
SystemC的仿真引擎将在开始时初始化执行所有的进程,然后有时候某些进程不需要在一开始就执行。SystemC提供了dont_initialize()来阻止初始化
// IMPORTANT: Must follow process registration
dont_initialize();
使用 dont_initialize 需要一个静态敏感表,否则将没法启动进程。
7.11 sc_event_queue
sc_event只能被安排一次(如果多个notification只有时间最近的那个会被执行),sc_event_queue可以使一个事件被安排多次甚至是在同一时间。
(八)基本通道
并发过程之间的通讯可以使用事件和模块成员数据。由于没法保证下一个从就绪态执行的是哪个进程,在共享数据是必须十分小心使用这两种方法。
SystemC提供一种“握手(handshake)”变量来实现过程间的通讯,称作通道(channel)。通道有primitive和hierarchical两种。
8.1 Primitive Channels 基本通道
基本通道不包含任何进程,也不对外展现出任何可见结构,它们也不能够直接的或者间接的调用其它基本通道。
所有的primitive channel都是从sc_prim_channel基类继承而来。 下面介绍最简单的三种primitive channel:sc_mutex、sc_semaphore、sc_fifo。
8.2 sc_mutex
在elaboration阶段,mutex被创建(有唯一的名字),之后任何需要该资源的进程必须lock该mutex以阻止其他进程使用该共享资源,当进程不再使用互斥资源时需要unlock该mutex,如果另一个进程试图使用一个锁定的资源,该进程将被阻止直到资源解锁。
SystemC 通过sc_mutex 通道实现mutex。sc_mutex包含许多访问函数,包括阻塞和非阻塞两种风格。阻塞风格的函数只能在SC_THREAD过程中使用。 语法如下:
在电子设计中,可以用sc_mutex作为共享总线的仲裁。当仲裁器设计好后再替换该sc_mutex。
8.3 sc_semaphore
有些资源可以有多个copy或owner,SystemC提供sc_semaphore来管理这种资源。当建立信号量对象时,指定有多少可用是必须的。其实mutex是只有一个计数值的信号量。
信号量代表可用资源实体的数量,所以可以认为信号量就是一个资源计数器,它限制的是同时使用某共享资源(也称为临界资源)的进程的数量。信号量计数的值代表的就是当前仍然可用的共享资源的数量。 sc_semaphore的语法如下:
sc_semaphore实现的是sc_semaphore_if接口。
其中,wait()方法获得一个信号量,其作用效果是获得一份资源的使用权,使信号量计数减一,如下面的实现代码。 int sc_semaphore::wait(){
while( in_use() ) { sc_prim_channel::wait( m_free ); } -- m_value; return 0; }
8.4 sc_fifo
FIFO是用来管理数据流的最常用的数据结构。SystemC提供sc_fifo来实现FIFO。sc_fifo<>在默认情况下深度是16,另外还需要指定元素的数据类型。 sc_fifo的语法如下:
sc_fifo
write(&T)read()write(&T)代表写FIFO的方法。
read()是读FIFO的方法,它返回队头单元的数据。 num_free()用于查询FIFO还有多少空单元。 num_available()查询FIFO还有多少个数据可以读。
num_free()num_avaiable()Size.........Size代表FIFO的总单元数, 对于sc_fifo,Size的默认值为16。 对于复杂数据类型的元素,将指针传给sc_fifo将会更加高效。
(九)EVALUATE-UPDATE CHANNELS
通常,电子信号有单一的来源,但是多个接收器。使所有的sinks能在同一时间检测到信号更新是很重要的。
9.1 Completed Simulation Engine
信号通道使用这个更新状态作为数据同步点。为了达到同步,每个通道有两个存储区域:当前值和更新值。有两组数据可见:新的和当前的。当一个进程写入信号通道时,该进程存入更新域而不是当前域,同时进程调用request_update()以引起仿真内核在更新状态调用该通道的update()方法。 当evaluate phase 完成后(没有就绪进程),内核为每一个请求更新的通道实例调用update()。update()方法有时不只是简单的将更新值复制到当前当前值,也可能指出改变或唤醒一个等待态的进程。
9.2 sc_signal, sc_buffer
基本通道sc_signal<>和跟它比较相似的sc_buffer<>都是使用的evaluate-update paradigm。 关于声明、读及写的定义:
这两种通道的好处之一是他们有一个限制:在一个特定的delta-cycle只有一个进程可以写入给定的信号.