转自 simobject
一、SimObject
# /src/sim/sim_object.hh
class SimObject : public EventManager, public Serializable, public Drainable,
public statistics::Group, public Named
{
}
SimObject 类是一个非常复杂但又十分重要的类,它在 Gem5 中占有极为重要的地位。Gem5 的模块化设计是围绕 SimObject 类型构建的。 模拟系统中的大多数组件都是 SimObjects 的子类,如CPU、缓存、内存控制器、总线等。Gem5 将所有这些对象从 C++ 实现导出到 python,使用 python 配置脚本创建任何 SimObject 类对象,并设置其参数,并指定 SimObject 之间的交互。
SimObject一共有 5 个父类:EventManger、Serializable、Drainable、statistics::Group、Named
- EventManager 类:负责调度、管理、执行事件。EventManager 类是对 EventQueue 类的包装,SimObject 对象中所有的事件实际都由 EventQueue 队列管理。该队列以二维的单链表的形式管理着所有事件,事件以触发时间点从近到远排列。
- Serializable 类:负责对象的序列化。SimObjects 可通过
SimObject::serializeAll()
函数自动完成序列化,写入到自己的 sections 中。Serializable 类根据 SimObject 类对象的名字以及对象间的包含关系,帮助用户构建起了层次化的序列化模型,并使用该模型完成 SimObject 的序列化,以 ini 文件格式输出。 - Drainable 类:负责 drain 对象。DrainManager 类以单例的方式管理整个模拟器的 drain 过程。只有系统中所有的对象都被 drained,才能开始序列化、更改模型等操作。完成后需要使用
DrainManager::resume()
函数将系统回归到正常运行状态。 - statistics::Group 类:负责运行过程中统计、管理数据。Group 对象之间可组成树状层次,从而反应出 SimObject 对象间的树状层次
- Name 类:负责给 SimObject 起名。
二、ClockObject
用curTick()获取全局时钟的值 src/sim/cur_tick.hh
extern __thread Tick *_curTickPtr;
inline Tick curTick() { return *Gem5Internal::_curTickPtr; }
三、Clock类
Clocked 类为 SimObject 类提供时钟周期模拟。Gem5 在模拟 SimObject 对象的工作流程时,会模拟硬件中时钟打拍行为,进而得到准确的模拟性能。src/sim/clocked_object.hh
Clocked 类中有三个变量:
- ick 变量类型为
uint64_t
,指示下一个时钟边缘沿到来的 tick 值。tick 值是模拟器中时间的最小单位 - cycle 类型为 Cycles,该类表示当前经过的时钟周期总数,其内部包装了
uint64_t
。这是硬件中常说的时钟周期。之所以不直接使用uint64_t
,是为避免混淆 Tick 和 Cycles 这两个类型 - clockDomain 表示位于的时钟域。时钟域是若干个共享同一个时钟的 SimObject 对象集合。其中,
clockPeriod()
记录了时钟的周期(单位:Tick)
四、ClockedObject
src/sim/clocked_object.hh
五、自定义SimObject
每个 SimObject 都有一个与之关联的 Python 类,这个 Python 类描述了可以从 Python 配置文件控制的 SimObject 的参数。我们从没有参数的情况下开始配置我们的简单 SimObject。因此,我们只需要为我们的 SimObject 声明一个新类,并设置它的名称和 C++ 头文件,为 SimObject 定义 C++ 类。
上面是我创建的类,第一个是源码编译后产生的文件,之后的四个都是自己配置的代码;;
需要配置.cc .hh .py个文件,创建自定义XXXObject;
头文件:zwb_object.hh:
#ifndef __LEARNING_GEM5_ZWB_OBJECT_HH__ //gem5将所有头文件内容写在以文件名
#define __LEARNING_GEM5_ZWB_OBJECT_HH__ //及其所在目录命名的宏定义之间,防止循环
#include "params/ZwbObject.hh" //这个include
#include "sim/sim_object.hh" //多数情况下继承自SimObject的实现类,而不是SimObject本身
//所有SimObjects的构造函数都假定它将接受一个参数对象,
//这个参数对象是由构建系统自动创建的。
//此参数类型的名称是根据对象名称自动生成的,
//“ZwbObject”参数类型的名称是“ZwbObjectParams”
namespace gem5
{
class ZwbObject : public SimObject
{
private:
void processEvent();
EventFunctionWrapper event;
const Tick latency;
int timesLeft;
public:
ZwbObject(const ZwbObjectParams &p);
void startup() override;
};
} // namespace gem5
#endif // __LEARNING_GEM5_SIMPLE_OBJECT_HH__
构造函数:zwb_object.cc:
#include"zwb_object.hh"
#include"ZwbObject.hh"
#include <iostream>
namespace gem5
{
ZwbObject::ZwbObject(const ZwbObjectParams ¶ms) :
SimObject(params),event([this]{processEvent();},name()),latency(100),timesLeft(10)
{
std::cout << "function[1] : Hello World! From a ZwbObject!\n" << std::endl;
DPRINTF(ZwbObject,"function[2] : Created the test object!\n");
DPRINTF(ZwbObject, "function[2] test object!\n");
}
void ZwbObject::processEvent()
{
timesLeft--;
DPRINTF(ZwbObject, "Hello world! step[%d] Processing the event! %d left\n", timesLeft,timesLeft);
if (timesLeft <= 0)
{
DPRINTF(ZwbObject, "Finish Done firing\n");
}
else
{
schedule(event, curTick()+latency);
}
}
void ZwbObject::startup()
{
schedule(event, latency);
}
} // namespace gem5
ZwbObject.py
from m5.params import *
from m5.SimObject import SimObject
class ZwbObject(SimObject):
type = "ZwbObject"
cxx_header = "learning_gem5/part2/zwb_object.hh"
cxx_class = "gem5::ZwbObject"
sconsript:
Import('*')
SimObject('ZwbObject.py')
Source('zwb_object.cc')
rebuild:
scons build/X86/gem5.opt -j 16