事件驱动编程

本文介绍了如何在GEM5的事件驱动模型中创建和调度事件,以HelloObject为例,包括创建事件回调、使用EventFunctionWrapper和cppschedule函数进行事件调度。
摘要由CSDN通过智能技术生成

GEM5 是事件驱动的仿真器。本节将研究如何创建和调度事件,我们从hello-simobject-chapter简单的HelloObject进行构建(building)

 创建简单的事件回调

在gem5的事件驱动模型中,每个事件都有一个回调函数用于处理事件。

这个函数一般是从:cppEvent继承而来的一个类,但是,gem5提供了一个封装函数,用于创建简单的事件。 

HelloObject头文件中,我们只需要声明需要在每次事件触发时(processEvent)执行的一个新函数,同时这个函数必须不带任何参数并做空返回。

然后,添加一个事件(Event)的实例。在本例中,我们使用一个事件函数封装(EventFunctionWrapper),因为它可以用于执行任意函数,我们还添加了一个Startup功能,这个功能我们将在后面解释。

class HelloObject : public SimObject
{
  private:
    void processEvent();

    EventFunctionWrapper event;

  public:
    HelloObject(const HelloObjectParams &p);

    void startup() override;
};

接下来,必须在HelloObject的构造函数中构造这个事件。EventFuntionWrapper需要两个参数:一个函数用于执行外加一个名字。这个名字通常是拥有这个事件的SimObject的名字,当这个名字打印时,字符串 “.wrapped_function_event”会自动附加到名称的尾部。 

第一个参数只是一个不带参数且没有返回值的函数(std::function<void(void)>),通常是调用成员函数的简单Lambda函数,它实现用户想要的任何功能。下面,这段代码主要是通过调用SimObject的构造函数实现了HelloObject 的构造函数,同时使用lambda ([this])捕获了this指针,使得用户可以调用类的实例的成员函数。

HelloObject::HelloObject(const HelloObjectParams &params) :
    SimObject(params), event([this]{processEvent();}, name())
{
    DPRINTF(HelloExample, "Created the hello object\n");
}

 此外,用户还需要定义进程(process)函数的实现。本例中,我们只需要在调试时简单地打印一些内容。 

void
HelloObject::processEvent()
{
    DPRINTF(HelloExample, "Hello world! Processing the event!\n");
}

 调度事件

最后,要处理的事件,必须先进行调度gem5使用cppschedule函数将某个实例调度到未来的某个时间执行(事件驱动的仿真禁止将事件调度到过去执行)。 

我们往HelloObject类中添加的startup()函数首先进行调度,startup()函数能够调度SimObject内部事件。它只在仿真首次启动时执行(即从Python配置文件调用simulate()函数)。  

void
HelloObject::startup()
{
    schedule(event, 100);
}

本例中,我们只简单地将事件调度到tick=100时执行。通常用户可以使用当前tick的相对偏移量进行调度,这里因为我们知道startup()函数在当前时间为0时被调用,我们可以使用显式tick值。

这里运行“HelloExample”时,输出调试标志是当前时刻。

gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 11:01:46
gem5 started Jan  4 2017 13:41:38
gem5 executing on chinook, pid 1834
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
      0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
    100: hello: Hello world! Processing the event!
Exiting @ tick 18446744073709551615 because simulate() limit reached

 更多事件调度

用户还可以在事件处理进程process)的行为中调度新的事件。例如,我们将向HelloObject添加一个延迟参数以及一个记录事件(event)触发次数的参数,下一节中,我们还将使用Python配置文件获取这些参数。

这里,在HelloObject类声明中为延迟latency和触发次数timesLeft分别增加成员变量。

class HelloObject : public SimObject
{
  private:
    void processEvent();

    EventFunctionWrapper event;

    const Tick latency;

    int timesLeft;

  public:
    HelloObject(const HelloObjectParams &p);

    void startup() override;
};

然后,在构造函数中添加latency和timesLeft的默认值。

HelloObject::HelloObject(const HelloObjectParams &params) :
    SimObject(params), event([this]{processEvent();}, name()),
    latency(100), timesLeft(10)
{
    DPRINTF(HelloExample, "Created the hello object\n");
}

最后,更新startup()函数和processEvent()函数

void
HelloObject::startup()
{
    schedule(event, latency);
}

void
HelloObject::processEvent()
{
    timesLeft--;
    DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);

    if (timesLeft <= 0) {
        DPRINTF(HelloExample, "Done firing!\n");
    } else {
        schedule(event, curTick() + latency);
    }
}

这时候运行gem5,事件应该被触发 10 次,同时仿真在1000个tick后结束,具体输出如下所示:

gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jan  4 2017 13:53:35
gem5 started Jan  4 2017 13:54:11
gem5 executing on chinook, pid 2326
command line: build/X86/gem5.opt --debug-flags=Hello configs/learning_gem5/part2/run_hello.py

Global frequency set at 1000000000000 ticks per second
      0: hello: Created the hello object
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
    100: hello: Hello world! Processing the event! 9 left
    200: hello: Hello world! Processing the event! 8 left
    300: hello: Hello world! Processing the event! 7 left
    400: hello: Hello world! Processing the event! 6 left
    500: hello: Hello world! Processing the event! 5 left
    600: hello: Hello world! Processing the event! 4 left
    700: hello: Hello world! Processing the event! 3 left
    800: hello: Hello world! Processing the event! 2 left
    900: hello: Hello world! Processing the event! 1 left
   1000: hello: Hello world! Processing the event! 0 left
   1000: hello: Done firing!
Exiting @ tick 18446744073709551615 because simulate() limit reached

你可以这里查看更新的头文件,在这里查看更新后的实现文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值