gem5学习(6):Event-driven programming

目录

一、官网教程

1、创建简单的事件回调

2、调度事件

3、More event scheduling

二、我的测试代码

1、ZylObject.py

2、zyl_object.hh

3、zyl_object.cc

4、SConscript

5、run_zyl.py

三、输出结果

1、可能存在的输出

2、实际输出


官网教程:gem5: Event-driven programming

官方教程是基于HelloObject开始,创建和调度事件。

一、官网教程

1、创建简单的事件回调

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

  • 通常都是从:cppEvent继承的类。
  •  gem5中提供了一个用于创建简单事件的包装函数。

(1)在HelloObject的.hh头文件中,需要声明一个新的函数processEvent(),每次事件触发时都会执行该函数。【该函数不带有参数,不返回任何内容】

(2)增加一个Event实例。使用EventFunctionWrapper,允许执行任何函数。

(3)添加了一个startup() 函数

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

    EventFunctionWrapper event;

  public:
    HelloObject(const HelloObjectParams &p);

    void startup() override;
};

(4)在HelloObject构造函数中构造这个事件。EventFunctionWrapper 接受两个参数:要执行的函数(function to execute)和一个名称(name)。

  • 第一个参数是一个没有参数和返回值的函数(std::function<void(void)>),通常情况是一个简单的lambda函数,调用一个成员函数。

    例如:下面这段代码主要是通过调用SimObject的构造函数实现了HelloObject 的构造函数。

    HelloObject::HelloObject(const HelloObjectParams &params) :
        SimObject(params), event([this]{processEvent();}, name())
    {
        DPRINTF(HelloExample, "Created the hello object\\n");
    }
    
    //HelloObject::HelloObject(const HelloObjectParams &params):这是HelloObject类的构造函数的定义,它接受一个类型为HelloObjectParams的参数引用。
    //SimObject(params):在构造函数的成员初始化列表中,调用了基类SimObject的构造函数,传递了params参数。这表明HelloObject类是SimObject类的派生类,且通过构造函数参数初始化了基类。
    //event([this]{processEvent();}, name()):这是另一个成员初始化,初始化了event成员变量。event是gem5中的一个事件对象,其构造函数接受两个参数:一个Lambda表达式和一个字符串。
    //DPRINTF(HelloExample, "Created the hello object\\n");:这是gem5中的调试输出宏,用于打印调试信息。
    
  • 第二个参数name通常是拥有该事件的 SimObject 的名称,当打印名称时,名称的末尾会自动添加 ".wrapped_function_event"。【主要是用来标记事件所属的SimObject】

    例如:有一个名为 "ExampleObject" 的 SimObject,并在其中创建了一个名为 "processEvent" 的事件,那么事件的完整名称将是 "ExampleObject.processEvent.wrapped_function_event"。

(5)定义 processEvent 函数的实现。

void
HelloObject::processEvent()
{
    DPRINTF(HelloExample, "Hello world! Processing the event!\\n");
}
//使用了条件编译指令 #ifdef DEBUG
//这表示代码块只有在定义了 DEBUG 宏的情况下才会被编译

这段代码会简单打印一段文字。同时说明processEvent 函数是 HelloObject 类的成员函数,用于处理事件的逻辑。

2、调度事件

使用:cppschedule 函数完成事件执行时间的调度。

事件驱动模型不允许事件在过去执行,所以:cppschedule 函数可以在未来的某个时间安排一个Event实例完成执行。

(1)在HelloObject 类中的添加startup() 函数中进行事件的初始调度。startup() 函数用于在 SimObject 内部安排事件。它在模拟开始之前不会执行(即从 Python 配置文件中调用 simulate() 函数时)。

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

#在 startup() 函数中使用 schedule 函数来安排事件的触发时间。
#参数包括要调度的事件(event)和触发时间(当前时钟周期 curTick() 加上 100 个周期)
#事件将在指定的时间点执行 processEvent() 函数中定义的逻辑。

(2)schedule()的第2个参数为未来时刻的偏移量。即事件的触发时间为“当前时钟周期 curTick() 加上 100 个周期”。

3、More event scheduling

为 HelloObject 添加一个延迟参数和一个控制触发事件次数的参数。

(1)在 HelloObject 类的声明中,添加一个成员变量用于存储延迟和触发事件次数。

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

    EventFunctionWrapper event;

    const Tick latency;

    int timesLeft;

  public:
    HelloObject(const HelloObjectParams &p);

    void startup() override;
};

(2)在构造函数中为延迟(latency)和剩余触发次数(timesLeft)添加默认值。

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

(3)更新startup() and 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个时钟周期后结束。

二、我的测试代码

这个阶段中我使用的是自建的新类ZylObject,如果大家想重新命名可以直接按照这个思路新建属于自己的简单类。

1、ZylObject.py

from m5.params import *
from m5.SimObject import SimObject

class ZylObject(SimObject):
    type = 'ZylObject'
    cxx_header = "dsic/zyl_object.hh"
    cxx_class = "gem5::ZylObject"

2、zyl_object.hh

#ifndef __DSIC_ZYL_OBJECT_HH__
#define __DSIC_ZYL_OBJECT_HH__

#include "params/ZylObject.hh"
#include "sim/sim_object.hh"

namespace gem5
{

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

    EventFunctionWrapper event;
    const Tick latency;
    int timesLeft;

  public:
    ZylObject(const ZylObjectParams &p);

    void startup() override;
};

} // namespace gem5

#endif // __DSIC_ZYL_OBJECT_HH__

3、zyl_object.cc

#include "dsic/zyl_object.hh"
#include "debug/ZylObject.hh"

#include <iostream>

namespace gem5
{

ZylObject::ZylObject(const ZylObjectParams &params) :
    SimObject(params), event([this]{processEvent();},name()),
    latency(100), timesLeft(10)
{
    std::cout << "function[1]: Hello World! From a ylZha's SimObject!" << std::endl;
    DPRINTF(ZylObject, "function[2]: Created the test object\\n");

{
    DPRINTF(ZylObject, "function[2]: text object\\n");
}
}

void
ZylObject::processEvent()
{
    timesLeft--;
    DPRINTF(ZylObject, "Hello world! step[%d] Processing the event! %d left\\n", timesLeft,timesLeft);

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

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

} // namespace gem5

4、SConscript

Import('*')

SimObject('FzzObject.py', sim_objects=['FzzObject'])
SimObject('RouterObject.py', sim_objects=['RouterObject'])
SimObject('FucoreObject.py', sim_objects=['FucoreObject'])
SimObject('ZylObject.py', sim_objects=['ZylObject'])

Source('fzz_object.cc')
Source('router_object.cc')
Source('fucore_object.cc')
Source('zyl_object.cc')

DebugFlag('FzzObject')
DebugFlag('RouterObject')
DebugFlag('FucoreObject')
DebugFlag('ZylObject')

5、run_zyl.py

import m5
from m5.objects import *

root = Root(full_system = False)
root.zyl = ZylObject()

m5.instantiate()

print("Beginning zylobject simulation!")
exit_event = m5.simulate()
print('Exiting @ tick {} because {}'
      .format(m5.curTick(), exit_event.getCause()))

三、输出结果

1、可能存在的输出

2、实际输出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值