目录

一、解释一下gem5中的event-driven?

二、Creating a simple event callback

(1)定义一个新的 C++ 类,并继承自 SimObject 抽象基类

(2)实现必要的构造函数和初始化函数

(3)实现processEvent函数

三、Scheduling events

四、总结


肯定有很多朋友和我一样C++半吊子,入门水平看不太懂官网的C++案例,看完菜鸟教程之后不懂的还是不懂,真的是教出菜鸟的教程,以下记录一下我的学习理解。这篇是接着之前文章“创建一个简单的SimObject对象”,为了流畅性建议先戳下面这个链接观看,配合食用更加:

(14条消息) Gem5模拟器,详解官网教程Creating a very simple SimObject(二)_好啊啊啊啊的博客-CSDN博客

一、解释一下gem5中的event-driven?

gem5是一个用于模拟和测试计算机系统的软件框架。在这个框架中,事件驱动是一种模拟技术,用于模拟计算机系统中的事件。这种方法的核心思想是,模拟器会按照事件的发生顺序来处理事件。也就是说,模拟器会根据事件的时间戳来决定处理哪个事件,并且会按照事件的顺序来处理它们。

二、Creating a simple event callback

(1)定义一个新的 C++ 类,并继承自 SimObject 抽象基类

class HelloObject : public SimObject
{private:void processEvent();EventFunctionWrapper event;public:HelloObject(HelloObjectParams *p);void startup();
};

 Gem5中的EventFunctionWrapper 是干嘛的?

在 gem5 中,EventFunctionWrapper 是一个用于封装事件处理函数的类模板。事件处理函数是 gem5 中用于响应特定事件的函数,例如计时器超时、中断请求或网络数据到达。EventFunctionWrapper 类模板提供了一种方便的方法来封装这些处理函数,使它们能够被 gem5 框架调用。EventFunctionWrapper 类模板接受事件处理函数的参数类型和返回值类型作为模板参数,并提供了一个 operator() 符号重载函数,用于调用封装的事件处理函数。例如,下面是一个使用 EventFunctionWrapper 类模板封装事件处理函数的示例代码:

void handleEvent(int event_id)
{// Code to handle the event with the given event_id.
}EventFunctionWrapper<void, int> event_handler(&handleEvent);

在上面的代码中,event_handler 是一个 EventFunctionWrapper 类模板的实例,它封装了名为 handleEvent 的事件处理函数。event_handler 的类型为 EventFunctionWrapper<void, int>,表示它封装的事件处理函数接受一个 int 类型的参数,并返回 void 类型的值。在 gem5 框架中,可以通过调用 event_handler 的 operator() 符号重载函数来触发事件,并调用封装的 handleEvent 函数来处理该事件。

(2)实现必要的构造函数和初始化函数

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

这代码定义了 gem5::HelloObject 类的一个构造函数。它接受一个指针类型的参数,类型为 HelloObjectParams,表示该构造函数需要一个 HelloObjectParams 类型的参数来构造新的 HelloObject 对象。构造函数首先调用父类的构造函数,然后使用 C++11 的 lambda 表达式定义了一个事件处理函数,该函数将在特定事件发生时被调用。该事件处理函数将调用 gem5::HelloObject 类中的名为 processEvent 的成员函数。最后,构造函数使用 gem5 框架的 DPRINTF 宏打印了一条消息。

说一下C++11 的 lambda 表达式?

C++11 中的 lambda 表达式是一种新增的语法,它允许在程序中定义匿名函数。匿名函数是指没有名称的函数,它可以直接被调用,而无需通过函数名来引用。lambda 表达式由一对圆括号、一个函数参数列表、一个 C++ 返回类型和一个函数体组成。例如,下面是一个使用 lambda 表达式定义的简单函数:

auto add = [](int x, int y) -> int {return x + y;
};

在上面的代码中,add 是一个指向匿名函数的指针。该匿名函数接受两个 int 类型的参数 x 和 y,并返回一个 int 类型的值。匿名函数的函数体是一个大括号括起来的语句序列,它用于定义该函数的具体实现。在上面的代码中,匿名函数的函数体仅包含一条返回 x+y 的语句。

C++11 中的 lambda 表达式还支持一些高级特性,例如捕获外部变量、指定函数参数类型和返回类型以及使用默认参数值。例如,下面是一个使用 lambda 表达式捕获外部变量的示例代码:

int x = 5;
int y = 10;auto add = [x, y]() -> int {return x + y;
};

仔细说说event部分?

在上面的代码中,event 是一个 gem5::HelloObject 类中的成员变量。它是 gem5 框架中的 Event 类型,用于表示一个事件。Event 类提供了一个构造函数,可以接受一个事件处理函数和一个事件名称作为参数。在上面的代码中,event 的构造函数调用了两个参数:一个 lambda 表达式和一个调用 gem5::HelloObject 类的 name 函数的结果。lambda 表达式定义了一个匿名函数,该函数在被调用时将执行 gem5::HelloObject 类中的 processEvent 成员函数。name 函数返回 gem5::HelloObject 对象的名称,它将作为该事件的名称来使用。因此,event 是一个指向一个名称为 gem5::HelloObject 对象的名称的匿名函数的指针。该匿名函数的实现由 lambda 表达式指定,在被调用时将执行 gem5::HelloObject 类中的 processEvent 成员函数。

详解event中的this啥意思?

在 C++ 中,this 指针指向一个对象的实例本身。它是一个隐式参数,由编译器在需要时自动插入到函数或方法中。在上面的代码中,[this]{processEvent();} 表示定义一个捕获 this 指针的匿名函数。捕获 this 指针的匿名函数允许在函数体内访问该对象的成员变量和成员函数。在上面的代码中,processEvent 是 gem5::HelloObject 类的成员函数,匿名函数的函数体中调用了该成员函数。

因此,event 是一个指向一个捕获 this 指针的匿名函数的指针。该匿名函数的实现是执行 gem5::HelloObject 类的 processEvent 成员函数。在匿名函数中使用 this 指针可以方便地访问 gem5::HelloObject 对象的成员变量和成员函数。

event 是指向一个捕获 this 指针的匿名函数的指针是啥意思?

在 C++ 中,this 指针指向一个对象的实例本身。它是一个隐式参数,由编译器在需要时自动插入到函数或方法中。在上面的代码中,event 是一个指向一个捕获 this 指针的匿名函数的指针,意思是 event 是一个指针,它指向一个匿名函数,该匿名函数捕获了指向 gem5::HelloObject 类实例的 this 指针。这里的“捕获 this 指针”指的是,在匿名函数的函数体中可以使用 this 指针来访问 gem5::HelloObject 类实例的成员变量和成员函数。在上面的代码中,lambda 表达式中的 processEvent 方法就是通过 this 指针访问的。因此,event 是指向一个捕获 this 指针的匿名函数的指针,意思是 event 指向一个能够访问 gem5::HelloObject 类实例的成员变量和成员函数的匿名函数。

综上,event([this]{processEvent();}, name()) 在干啥?

它在创建 HelloObject 的时候被执行。这条语句创建了一个名为 event 的对象,它被初始化为一个调用 processEvent()方法的匿名函数。

在 C++11 中,可以使用 lambda 表达式创建匿名函数。该语句使用了 lambda 表达式,并将 this 作为参数传递给了匿名函数。这样,匿名函数中就可以访问 HelloObject 类的成员变量和成员函数。

另外,在 event 的构造函数中,还会传入name() 方法的返回值。这个方法会返回当前 HelloObject 对象的名称。这样,当 event 对象被调用时,它就可以使用这个名称来执行一些特定的操作。

总的来说,这条语句创建了一个名为 event 的对象,该对象持有一个调用 processEvent() 方法的匿名函数,并且可以使用当前 HelloObject 对象的名称来执行一些特定的操作。

(3)实现processEvent函数

gem5中的processEvent是一个函数,用于处理事件队列中的事件。该函数会按照事件的时间戳来决定处理哪个事件,并且会按照事件的顺序来处理它们。例如,如果一个事件的时间戳比另一个事件的时间戳更早,那么这个事件将会优先被处理。通常,gem5中的processEvent函数会在每次模拟器执行一个时间片之后被调用,以便处理所有已经到达的事件

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

三、Scheduling events

在Gem5中,调度事件是指用于管理处理器时间的事件。在Gem5模拟中,每个处理器都有一个调度器,负责在处理器上执行指令。当处理器上有多个线程需要执行时,调度器会根据特定的调度算法选择一个线程执行,并且在适当的时间调度其他线程。这些调度操作都是通过调度事件来完成的。在Gem5中,调度事件通常由两个部分组成:一个事件处理器,用于接收和处理调度事件;和一个事件队列,用于存储待处理的调度事件。

在gem5框架中,系统调度器是一个负责调度运行在计算机系统中的各个任务的模块。它主要负责以下几项工作:

  • 将任务加入调度器的任务队列中,并对任务队列进行排序,依据调度策略选择下一个要运行的任务。
  • 将任务从任务队列中取出,提交给CPU运行。
  • 负责监控任务的执行情况,并在任务完成或者发生错误时进行响应。
void
HelloObject::startup()
{schedule(event, 100);
}

解释一下schedule函数是干嘛的?

gem5 框架中的 schedule 函数用于调度指定的事件。它接受两个参数:一个事件和一个时间值。事件参数指定要调度的事件,它必须是 gem5 框架中的 Event 类型。时间值参数指定事件的触发时间,它必须是 gem5 框架中的 Tick 类型。在上面的代码中,schedule 函数用于调度 event 事件。

在调用 schedule 函数后,gem5 框架会在指定的时间到达时触发事件。触发事件时,gem5 框架会执行事件处理函数,即 gem5::HelloObject 类的 processEvent 成员函数。在上面的代码中,event 事件的触发时间由调用的第二个参数指定。

gem5中的startup()函数是干啥的?

startup() 是 gem5 模拟器的一个函数。gem5 是一个用于模拟计算机系统的模拟器。startup()  函数负责初始化模拟器,并启动模拟。

在 gem5 中,每个模拟的计算机系统都有一个相应的模拟器对象,该对象继承自 SimObject类。startup() 是SimObject类的一个方法,每个模拟器对象都可以调用它来启动模拟。

在 startup()  函数中,会首先初始化模拟器对象,然后启动模拟过程。这通常包括初始化模拟器对象的内部状态,创建模拟的计算机系统的构件(如处理器、内存和 I/O 设备),并将它们连接在一起。

启动模拟后,模拟器会按照指定的时间间隔(即模拟步长)来模拟计算机系统的运行。

四、总结

在 Gem5 模拟器中自定义一个 SimObject 的具体过程包括以下几步:

  1. 定义一个新的 C++ 类,并继承自 SimObject 抽象基类。这个类需要实现 SimObject 类中的所有纯虚函数,以便完成模拟器中的某些功能。
  2. 实现必要的构造函数和初始化函数。构造函数用于在创建新的 SimObject 对象时完成对象的初始化,而初始化函数则用于指定该对象的一些参数,例如它的名称和父对象。
  3. 实现必要的方法。根据需要,需要为新的 SimObject 类实现一些方法,以完成它在模拟器中所需要实现的功能。例如,如果新的 SimObject 类代表一个内存系统,那么它可能需要实现一个方法来处理内存读写请求。
  4. 最后,在模拟器配置文件中指定新的 SimObject 类,并在模拟器运行时创建新的SimObject对象。

SimObject 类中的所有纯虚函数如下:

class MySimObject : public SimObject
{private:// 私有成员和函数public:MySimObject(MySimObjectParams *p);// 构造函数,接受一个MySimObjectParams类型的指针作为参数virtual void startup() override;// 虚函数startup()的实现,执行一些在模拟开始时需要完成的初始化工作virtual void init() override;// 虚函数init()的实现,执行一些在模拟开始之前需要完成的初始化工作virtual void regStats() override;// 虚函数regStats()的实现,注册模拟过程中需要收集的统计信息virtual void resetStats() override;// 虚函数resetStats()的实现,重置收集的统计信息// 其他虚函数的实现
};

Gem5模拟器,详解官网教程Event-driven programming(五)相关推荐

  1. Gem5模拟器,详解官网教程Debugging gem5(四)

    目录 一.Gem5中的多种debug模式 二.gem5中的调试标志 三.介绍一下DPRINTF是啥? 四.如何添加一个新的debug flag 五.关于Debuug output gem5是一种用于模 ...

  2. Gem5模拟器,详解官网教程的statistics and output(三)

    gem5是一个计算机模拟器,它可以用来模拟不同类型的计算机系统,以帮助计算机科学家和工程师更好地理解和优化计算机系统的性能.gem5提供了许多统计信息和输出功能,可以帮助用户更好地了解模拟的计算机系统 ...

  3. GitHub使用教程详解——官网操作指南(翻译)

    GitHub使用教程详解--官网操作指南(翻译) GitHub使用指南 原文地址:GitHub官网 示例项目:Hello World 十分钟轻松教学 在学习计算机语言编程的过程中创建Hello Wor ...

  4. 海岛奇兵服务器修改,海岛奇兵NPC刷新详解 官网阐述未来更改变动

    海岛奇兵NPC刷新机制到底是怎么样的呢?如何加快NPC的刷新速度呢?赶紧一起来看看海岛奇兵官方的讲解吧! 一.当前版本规则说明 1.敌方入侵数量上限,包括PVP玩家基地以及NPC基地. 2.敌方入侵数 ...

  5. yolov5——detect.py代码【注释、详解、使用教程】

    yolov5--detect.py代码[注释.详解.使用教程] yolov5--detect.py代码[注释.详解.使用教程] 1. 函数parse_opt() 2. 函数main() 3. 函数ru ...

  6. lammps输出MSD(均方根位移)详解及示例教程

    [lammps第十五讲]lammps输出MSD(均方根位移)详解及示例教程 原创 一直陪着你的 LAMMPS交流站 2021-10-23 11:45 收录于话题 #lammps21个内容 #lammp ...

  7. Spring Boot 2.0 的配置详解(图文教程)

    本文来自作者 泥瓦匠 @ bysocket.com 在 GitChat 上分享 「Spring Boot 2.0 的配置详解(图文教程)」 编辑 | 哈比 Spring Boot 配置,包括自动配置和 ...

  8. Away3D 4.0官网教程(翻译)

    使用Away3D 4.Stage3D 创建3D游戏和应用程序 (此帖每天都会更新,一定让大家完全的搞明白) 补充区:        'vase.awd' 可以使用 Prefab3D打开(在帖子后面回复 ...

  9. MNE溯源fieldtrip官网教程

    MNE溯源fieldtrip官网教程 Introduction 在本教程中,您可以找到有关如何使用最小范数估计进行源重构的信息,以重构单个主题的事件相关字段(MEG).我们将使用预处理教程中描述的数据 ...

最新文章

  1. DB2load遇到SQL3508N错误
  2. 【c语言】C语言配置文件解析库——iniparser
  3. Oracle 之 配置HugePages内存
  4. Calendar日历小程序
  5. java中string.trim()函数
  6. 15行代码AC——习题3-1 得分 (UVa1585,Score)
  7. Enterprise Library 2.0 Hands On Lab 翻译(3):数据访问程序块(三)
  8. 样式缓存没更新_差点没认出来:Office 2019/365桌面新图标来啦
  9. 追根溯源:EntityFramework 实体的状态变化
  10. 1087 有多少不同的值 (20 分)—PAT (Basic Level) Practice (中文)
  11. 羊坊店不眠夜(续集)
  12. linux进程管理数据结构,谢烟客---------Linux之进程管理基础概念
  13. 不要想当然,相信自己(自己在C中踩过的坑)
  14. 2018版本及2017版本的IntelliJ IDEA破解步骤,非lanyu,到2099年
  15. 基于OpenCv的视频流处理方法
  16. Oracle中 to_date()函数用法详解
  17. tf.logging
  18. Java之Builder模式使用
  19. 如何用java创建一个文件
  20. 网络教育专科计算机考试试题电子科大,电子科技大学网络教育专科英语(理)入学考试模拟题及答案...

热门文章

  1. 小米6弹HTML查看器,小米6浏览器远程代码执行(CVE-2019-13322)
  2. Linux环境下程序的多核CPU占用率高的问题分析和解决
  3. 小白搭建个人网站最详细的全过程
  4. java 字符串驻留_JAVA 字符串驻留池
  5. 小学期软件工程团队项目进度5
  6. A星融合DWA的路径规划算法,可实现静态避障碍及动态避障,代码注释详细,matlab源码
  7. Javaweb(四)RequestResponse
  8. 嵌入式linux 不识别sata,sata硬盘识别不了的常见问题和解决方法
  9. 计算机新技术在体育中的应用,应用计算机技术在现代体育领域中的运用
  10. 贵大计算机学院张达敏,贵大计算机研究生怎么样?