gem5(5)——扩展gem5功能初探并实现简单的MemoryObject
iamywang

引言

参考learning gem5的part II部分进行gem5的学习。

主要工作:

  • 自定义实现了一个简单的SimpleObject,并将其成功在gem5中执行;
  • 将SimpleObject扩展为MemoryObject,并将其分别与CPU的i-cache/d-cache端口和内存总线相连;
  • 输出MemoryObject对应的配置图,并成功模拟执行。

SimpleObject

创建python类SimpleObject

首先创建一个python类,包含三个参数:

  • type:类名
  • cxx_header:对应的C++头文件
  • cxx_class:对应的C++类名
1
2
3
4
class SimpleObject(SimObject):
type = 'SimpleObject'
cxx_header = "learning_gem5/part2/simple_object.hh"
cxx_class = 'gem5::SimpleObject'

创建C++类SimpleObject

然后创建与python类对应的C++类,并创建简单的hello函数:

1
2
3
4
5
6
7
8
9
10
11
class SimpleObject : public SimObject
{
public:
SimpleObject(const SimpleObjectParams &p);
};

SimpleObject::SimpleObject(const SimpleObjectParams &params) :
SimObject(params)
{
std::cout << "Hello World! From a SimObject!" << std::endl;
}

注册SimpleObject

修改SConscript文件,将先前创建的python类和C++类添加进去:

1
2
SimObject('SimpleObject.py', sim_objects=['SimpleObject'])
Source('simple_object.cc')

重新编译gem5

执行scons重新编译gem5:

1
$ scons build/X86/gem5.opt -j5

配置并运行

修改自定义的配置文件,设置root.hello为SimpleObject(),并执行:

image

根据执行结果的输出,可以看到成功的添加SimpleObject并运行。

MemoryObject

创建基类

创建python类和C++类,假设MemoryObject一端连接CPU一端连接内存总线,那么需要创建三个接口:

  • CPU的i-cache;
  • CPU的d-cache;
  • 内存总线。
1
2
3
4
5
6
7
8
class SimpleMemobj(SimObject):
type = 'SimpleMemobj'
cxx_header = "learning_gem5/part2/simple_memobj.hh"
cxx_class = 'gem5::SimpleMemobj'

inst_port = ResponsePort("CPU side port, receives requests")
data_port = ResponsePort("CPU side port, receives requests")
mem_side = RequestPort("Memory side port, sends requests")
1
2
3
4
5
6
7
8
SimpleMemobj::SimpleMemobj(const SimpleMemobjParams &params) :
SimObject(params),
instPort(params.name + ".inst_port", this),
dataPort(params.name + ".data_port", this),
memPort(params.name + ".mem_side", this),
blocked(false)
{
}

函数说明

根据learning gem5网站的描述以及提供的开源代码,大致分为以下15个函数:

序号 作用域 函数
1 SimpleMemobj SimpleMemobj(const SimpleMemobjParams &params)
2 SimpleMemobj Port& getPort(const std::string &if_name, PortID idx)
3 SimpleMemobj::CPUSidePort void sendPacket(PacketPtr pkt)
4 SimpleMemobj::CPUSidePort AddrRangeList getAddrRanges() const
5 SimpleMemobj::CPUSidePort void trySendRetry()
6 SimpleMemobj::CPUSidePort void recvFunctional(PacketPtr pkt)
7 SimpleMemobj::CPUSidePort bool recvTimingReq(PacketPtr pkt)
8 SimpleMemobj::CPUSidePort void recvRespRetry()
8 SimpleMemobj::MemSidePort void sendPacket(PacketPtr pkt)
9 SimpleMemobj::MemSidePort bool recvTimingResp(PacketPtr pkt)
9 SimpleMemobj::MemSidePort void recvReqRetry()
10 SimpleMemobj::MemSidePort void recvRangeChange()
11 SimpleMemobj bool handleRequest(PacketPtr pkt)
12 SimpleMemobj bool handleResponse(PacketPtr pkt)
13 SimpleMemobj void handleFunctional(PacketPtr pkt)
14 SimpleMemobj AddrRangeList getAddrRanges() const
15 SimpleMemobj void sendRangeChange()

在learning gem5的网站中,给出了这样一个函数之间的关系图:

image

修改配置文件

主要分为以下步骤:

  • 将system.cpu的i-cache和d-cache的端口分别连接到MemoryObj的指令端口和数据端口;
  • 将MemoryObj的内存端口连接到系统总线端。
1
2
3
4
5
6
system.memobj = SimpleMemobj()
...
system.cpu.icache_port = system.memobj.inst_port
system.cpu.dcache_port = system.memobj.data_port
...
system.memobj.mem_side = system.membus.cpu_side_ports

部件连接图

在m5out中的config.dot.pdf的结果如下:

image

运行结果

执行结果如下,可以看出程序仍然能够正常执行:

image

参考文献

  1. http://learning.gem5.org/book/presentation_notes/part2.html
  2. http://learning.gem5.org/book/part2/helloobject.html
  3. http://learning.gem5.org/book/part2/memoryobject.html
 评论