admin 管理员组

文章数量: 1184232


2024年1月18日发(作者:编程的主要内容)

SystemC中的SC_METHOD、SC_THREAD和SC_CTHREAD

2008-12-23 14:38

现实系统中很多活动都是同时发生的。SystemC用过程(Process)来模拟并发性。了解SystemC仿真器如何处理并发性,能使设计者写出高效的仿真模型。SystemC提供两种主要的过程类型:SC_THREAD和SC_METHOD。另外还有第三种,SC_CTHREAD,是SC_THREAD的变型。SystemC官方的Language Reference Manual不推荐在一般情况下使用SC_CTHREAD。

一、事件sc_event:

事件(Event)是SystemC这种事件驱动的仿真器的关键之处。事件就是在某个特定时间点发生的事情。一个时间没有取值,也没有持续时间。事件本身没有并不做任何可以被观察到的事情,它只是激发对它敏感的过程,从而表现出作用。SystemC中的过程通过动态或者静态敏感表来等待一个事件的发生。声明一个事件的语法如下:

sc_event name;

二、过程SC_THREAD:

过程SC_THREAD被且只被仿真器启动一次。SC_THREAD一旦被启动就完全控制仿真过程,直到其自己将控制返回给仿真器。SC_THREAD有两种返回控制给仿真器的方法,一种是简单退出(如return),这意味着永远结束该过程。因此,常常在SC_THREAD中使用含有wait语句的无限循环。

另一种返回控制的方法是使用wait来挂起过程。有时候wait并不是被直接使用的,比如sc_fifo的阻塞读和写在FIFO分别为空或满的时候将隐式的激活wait。

三、SC_THREAD::wait()的动态敏感表(dynamic sensitivity):

SC_THREAD依靠wait来挂起自身。当wait被执行时,当前SC_THREAD过程的状态将被保存,同时仿真内核得到控制权,接着启动另一个准备好的过程。当被挂起的过程重新被启动时,它将从wait后的语句开始执行。wait的语法如下:

wait(time);

wait(event);

wait(event1 | event2); // any of these events

wait(event1 & event2); // all of these events

wait(timeout, event1 | event2); // any of these events with timeout

wait(timeout, event1 & event2); // all events with timeout

wait(); // static sensitivity

带有timeout的wait将timeout值设为最大的等待时间,超过这个时间即使事件没有发生,过程同样也会被重新启动。我们可以在timeout的wait后面用布尔函数time_out()来

检测到底是不是timeout使得过程返回,例如:

...

sc_event ack_event, bus_error_event;

...

wait(t_MAX_DELAY, ack_event | bus_error_event);

if(time_out()) break; // test for timeout

...

四、启动事件-.notify():

事件通过notify()来显式的发生。notify()有以下两种语法风格,由于C++是面向对象的语言,因此建议使用前一种语法风格:

// Object-oriented style (preferred)

event_(); //immediate notification

event_(SC_ZERO_TIME); //delayed notification

event_(time); //timed notification

// Functional-call style

notify(event_name); //immediate notification

notify(event_name, SC_ZERO_TIME); //delayed notification

notify(event_name, time); //timed notification

上面最难理解的是.notify()和.notify(SC_ZERO_TIME)两种的区别。.notify()会立即使等待该事件的过程转为等待被执行。而.notify(SC_ZERO_TIME)会在当前等待被执行的所有过程完成后,才将等待该事件的过程转为等待被执行(所谓的下一个delta-cycle)。

对于.notify(time)来说,如果有多个notification,那么只有时间最近的那个是有效的。我们可以用.cancel()来取消所有notification。

五、过程SC_METHOD:

SC_METHOD与SC_THREAD的主要不同,是SC_METHOD不能在其内部被挂起,即不能直接或间接的使用wait(),否则会报runtime error的错误。SC_METHOD一旦运行便会运行到底,然后返回。仿真引擎根据动态敏感表不断的调用SC_METHOD。某种程度上,SC_METHOD很像Verilog中的always块。注册SC_METHOD过程的语法如下:

SC_METHOD(process_name); //Located inside constructor

SC_METHOD中的变量在其每次被调用时都要被声明和初始化。这和SC_THREAD中变量是永远存在的不一样。如果希望保存SC_METHOD中的值,那么就需要使用

SC_MODULE中定义的局部变量。

六、SC_METHOD::next_trigger()的动态敏感表:

SC_METHOD过程通过next_trigger()来处理动态敏感表。next_trigger()和wait()有着同样的语法。next_trigger不会阻碍当前SC_METHOD的执行,它会改变下一次调用该SC_METHOD的敏感表。如果没有静态敏感表,那么SC_METHOD的所有执行分支都应当有next_trigger,否则可能导致该SC_METHOD不再被调用。

七、过程的静态敏感表(Static Sensitivity):

前面说的动态敏感表示在仿真阶段的建立的,并且可以在仿真中被改变。静态敏感表是在仿真开始前建立的,在仿真过程中不能被改变。静态敏感表的申明有两种语法:

sensitive<

sensitive(event [, event]...); // functional style

同样建议选择类似于C++流的第一种语法风格。静态敏感表的申明必须紧跟在其过程的注册语句后面。

八、dont_initialize:

SystemC的仿真引擎将在开始时初始化执行所有的过程,然后有时候某些过程不需要在一开始就执行。可以在静态敏感表后面加上dont_initialize()来阻止初始化执行。

九、sc_event_queue:

正如前面讲的,sc_event只能被安排一次,如果多个notification只有时间最近的那个会被执行。sc_event_queue使得一个事件能够被安排多次,甚至是在同一个时间点。sc_event_queue的语法和sc_event类似。


本文标签: 过程 事件 执行 静态 使用