Gem5模拟器,关于Creating SimObjects in the memory system的一些问题记录(七)

目录

一、关于SE模式和FS模式

(1)SE模式的系统调用会涉及到操作系统吗?

(2)关于单线程系统(STS)模式和多线程系统(MTS)模式

二、内存

(1)关于MasterPort 和 SlavePort

三、以CPUSidePort为例定义一个SlavePort以实现内存系统通信

四、一些不容易想到的坑点

(1)关于sendRetryReq

(2)关于InvalidPortID

(3)关于pkt->req->isInstFetch()

(4)关于blockedPacket 

(5)关于输出

五、题外话记录:

(1)关于m5和gem5

(2)关于memory system mode


一、关于SE模式和FS模式

gem5支持两种系统模拟方式,一种是System Call Emulation(SE),也叫系统调用模拟模式;另一种是Full System Simuluation(FS),也叫全系统模拟模式。

模拟模式特点
SE

基于系统调用模拟的,它只模拟处理器和内存,而不模拟 I/O 系统和外部设备。这种模式可以在较短的时间内模拟出系统的性能,适用于快速的性能评估。

无法模拟和 OS 相关的操作,比如文件系统访问、网络通信等。它只能模拟处理器执行指令和内存访问,并不能模拟完整的操作系统行为。

FS基于全系统模拟的,它模拟了整个计算机系统,包括处理器、内存、I/O 系统和外部设备。这种模式可以更准确地模拟出系统的性能,适用于详细的性能分析和研究。

(1)SE模式的系统调用会涉及到操作系统吗?

SE 模式下,用户程序是运行在模拟器内部的,而不是真实的操作系统中。因此,系统调用并不会直接涉及操作系统,它们是由模拟器提供的接口,用来模拟系统调用的行为。模拟器内部会模拟出系统调用的效果,但不会真正调用操作系统。所以,SE 模式下,系统调用并不会涉及操作系统。

总的来说,SE 模式是模拟系统调用的行为,而 FS 模式是使用真实的操作系统来完成系统调用。因此,FS 模式更加精确,可以更准确地模拟出系统的性能,但模拟时间也更长。

(2)关于单线程系统(STS)模式和多线程系统(MTS)模式

  • STS 模式(Single Thread System Mode)是指 Gem5 模拟器运行在单线程模式下,只能使用一个 CPU 核心运行模拟的模式。在 STS 模式下,Gem5 模拟器只模拟硬件,不提供完整的操作系统环境。

  • MTS 模式(Multi-Thread System Mode)是指 Gem5 模拟器运行在多线程模式下,但是所有的线程都是由 gem5 端控制的,m5 端不能被调用的模式。在 MTS 模式下,Gem5 模拟器提供了一个完整的操作系统环境,用户可以在这个环境中运行应用程序,但是不能与模拟硬件进行交互。

二、内存

Gem5 模拟器可以模拟各种不同类型的内存,包括 DRAM、SRAM、Flash 和其他类型的存储器。gem5中的DRAM模型是事件驱动的,支持多种市面上常见的DRAM,如DDR3、DDR4、DDR5、GDDR、HMC、HBM等。在gem5中,DRAM模型不是时钟精确的,但是可以和时钟精确的DRAM模拟器DRAMSim3结合使用,gem5中提供了和DRAMSim连接的接口

(1)关于MasterPort 和 SlavePort

内存本身并不具备端口,它是一种计算机存储器,用来存储程序和数据。通常,内存由一个或多个内存模块组成,并且每个内存模块都有多个存储单元,用于存储数据。但是,内存本身不包含端口。

SlavePort 和 MasterPort 是模拟器程序中使用的概念,用于描述计算机系统中不同组件之间的数据传输关系。在模拟器中,SlavePort 和 MasterPort 是用于连接计算机系统中的各种组件的接口。例如,MasterPort 可以作为内存的接口,用于与处理器连接,并允许处理器读取和写入内存。同样,SlavePort 可以作为处理器的接口,用于与内存连接,并允许内存读取和写入处理器。

此外,内存模型两侧的 MasterPort 和 SlavePort 是可以随意选定的。在模拟器程序中,MasterPort 和 SlavePort 只是用于描述计算机系统中不同组件之间的数据传输关系的概念,并不存在“正确”或“错误”的使用方式。所以,在内存模型两侧的 MasterPort 和 SlavePort 可以随意选定。例如,如果希望将内存模型的 MasterPort 与 CPU 相连,那么与内存相连的另外一端就是 SlavePort,反过来也成立。不过,需要注意的是,MasterPort 和 SlavePort 的选定必须保证模拟器程序的正确性,因为它们决定了不同组件之间的数据传输方向

具体来说,MasterPort 表示数据的发送方,而 SlavePort 表示数据的接收方。因此,在模拟器程序中,MasterPort 和 SlavePort 的选定决定了不同组件之间的数据传输方向。例如,如果内存模型的 MasterPort 连接到处理器,那么数据就会从内存模型流向处理器。同样,如果内存模型的 SlavePort 连接到处理器,那么数据就会从处理器流向内存模型。

三、以CPUSidePort为例定义一个SlavePort以实现内存系统通信

class CPUSidePort : public SlavePort
{
  private:
    SimpleMemobj *owner;

  public:
    CPUSidePort(const std::string& name, SimpleMemobj *owner) :
        SlavePort(name, owner), owner(owner)
    { }

    AddrRangeList getAddrRanges() const override;

  protected:
    Tick recvAtomic(PacketPtr pkt) override { panic("recvAtomic unimpl."); }
    void recvFunctional(PacketPtr pkt) override;
    bool recvTimingReq(PacketPtr pkt) override;
    void recvRespRetry() override;
};

这段代码定义了一个名为 CPUSidePort 的类,它继承自 SlavePort 类。在 CPUSidePort 类的构造函数中,它接受两个参数:name 和 owner。这两个参数分别用于指定新创建的 CPUSidePort 对象的名称和所属的 SimpleObject 对象。它首先调用 SlavePort 类的构造函数,将 name 和 owner 传递给父类。接着,它将 owner 参数赋值给 CPUSidePort 类的同名成员变量 owner。该构造函数用于创建一个 CPUSidePort 对象,并初始化其名称和所属的SimpleObject 对象。

CPUSidePort 类中包含了五个成员函数:getAddrRanges()、recvAtomic()、recvFunctional()、recvTimingReq() 和 recvRespRetry()。

  • CPUSidePort 类中的第一个成员函数 getAddrRanges() 用于获取内存模型的地址范围,并返回一个 AddrRangeList 类型的值。
  • 第二个成员函数 recvAtomic() 用于处理原子操作的数据包(Atomic Packet)原子操作是指不能被中断的操作,通常用于同步或互斥操作。该函数接收一个 PacketPtr 类型的参数 pkt,但由于该函数未实现,因此如果调用该函数会导致程序崩溃,并引发 panic 错误。
  • 第三个成员函数 recvFunctional() 用于处理功能请求的数据包(Functional Packet)。功能请求是指不改变系统状态的请求,通常用于读取数据或检查系统状态。
  • 第四个成员函数recvTimingReq() 函数用于处理定时请求的数据包。定时请求是指需要等待一段时间后才能完成的请求,通常用于写入数据或执行耗时操作。
  • 第五个成员函数recvRespRetry() 函数用于处理响应重试的数据包。响应重试是指接收到响应时,系统需要重新发送请求才能完成操作。这种情况通常发生在系统存在某些冲突或限制时。

四、一些不容易想到的坑点

(1)关于sendRetryReq

void
SimpleMemobj::CPUSidePort::trySendRetry()
{
    if (needRetry && blockedPacket == nullptr) {
        needRetry = false;
        DPRINTF(SimpleMemobj, "Sending retry req for %d\n", id);
        sendRetryReq();
    }
}

当时我看这段代码,眼睛看花了都没有找到sendRetryReq()函数的实现在哪里,结果是自带的。gem5 模拟器中的计算机总线交互是基于 SystemC TLM (Transaction Level Modeling) 标准的,所以它提供了一系列的函数来支持计算机总线交互。其中就包括了 sendRetryReq 函数。

在 gem5 中,你可以在 SimpleMemObject 类的 CPUSidePort 类型中使用 sendRetryReq 函数,来向对端主端口发送重试请求。(比如,如果CPUSidePort 和CPU相连,那这个函数会向该端口再次发送请求重试,无需自己实现)

(2)关于InvalidPortID

class SimpleMemobj : public SimObject
{
  private:

    <CPUSidePort declaration>
    <MemSidePort declaration>

    CPUSidePort instPort;
    CPUSidePort dataPort;

    MemSidePort memPort;

  public:
    SimpleMemobj(SimpleMemobjParams *params);

    Port &getPort(const std::string &if_name,
                  PortID idx=InvalidPortID) override;
};

我觉得 <CPUSidePort declaration>,<MemSidePort declaration>这俩代码没啥用,因为CPUSidePort和MemSidePort类都已经定义好了,可以删掉,有问题咱们可以讨论别骂我。

此外,InvalidPortID 是一个常量,它的值通常是 -1。它可能是在某些库中定义的,表示无效的端口 ID。在 gem5 模拟器中,InvalidPortID 是在头文件 <base/port.hh> 中定义的。gem5 中的端口是通过 PortID 类型的变量来标识的,InvalidPortID 常量用来表示无效的端口 ID。

(3)关于pkt->req->isInstFetch()

bool
SimpleMemobj::handleResponse(PacketPtr pkt)
{
    assert(blocked);
    DPRINTF(SimpleMemobj, "Got response for addr %#x\n", pkt->getAddr());

    blocked = false;

    // Simply forward to the memory port
    if (pkt->req->isInstFetch()) {
        instPort.sendPacket(pkt);
    } else {
        dataPort.sendPacket(pkt);
    }

    instPort.trySendRetry();
    dataPort.trySendRetry();

    return true;
}

isInstFetch() 是 Packet 类的一个成员函数,它用于判断当前的 Packet 对象是否是用于指令访问的请求。如果是,则返回 true;否则返回 false。Packet 类是 gem5 模拟器中用于封装访问请求和响应的类,它在头文件 <mem/packet.hh> 中定义。isInstFetch() 函数是 Packet 类中自带的函数,不需要你自己实现。如果你的代码中使用了 isInstFetch() 函数,那么你需要包含 <mem/packet.hh> 头文件。

(4)关于blockedPacket 

void
SimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt)
{
    panic_if(blockedPacket != nullptr, "Should never try to send if blocked!");

    if (!sendTimingResp(pkt)) {
        blockedPacket = pkt;
    }
}

我觉得官方教程太简陋了,很多变量出现的有点没头脑也不介绍是从哪儿来的,对新手入门一点也不友好……比如,blockedPacket 在我自己写的CPUSidePort或者SimpleMemobj类中压根没有这个成员变量,它其实是继承来的,具体继承的是谁呢?不清楚……可能blockedPacket 是从 SimObject 类继承而来的,更多有关这些类的信息,可以尝试查看相关的文档或源代码

(5)关于输出

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

gem5 compiled Jan  5 2017 13:40:18
gem5 started Jan  9 2017 10:18:51
gem5 executing on chinook, pid 5157
command line: build/X86/gem5.opt --debug-flags=SimpleMemobj configs/learning_gem5/part2/simple_memobj.py

Global frequency set at 1000000000000 ticks per second
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
      0: system.memobj: Got request for addr 0x190
  77000: system.memobj: Got response for addr 0x190
  77000: system.memobj: Got request for addr 0x190
 132000: system.memobj: Got response for addr 0x190
 132000: system.memobj: Got request for addr 0x190
 187000: system.memobj: Got response for addr 0x190
 187000: system.memobj: Got request for addr 0x94e30
 250000: system.memobj: Got response for addr 0x94e30
 250000: system.memobj: Got request for addr 0x190

救命,我没看出来这个debug模式的输出为啥是这样的,迷了迷了,公开求解,有知道的小伙伴欢迎留言告知,非常感谢♥。

五、题外话记录:

(1)关于m5和gem5

Gem5模拟器通常由两个部分组成:m5端和gem5端

m5 是一个用 C++ 编写的模拟实验室,它提供了用于模拟的硬件模型和模拟控制器。它的主要功能是提供一个可以模拟各种硬件的环境,用于测试和评估软件。m5 端通常包括一个模拟内存子系统、一个模拟处理器架构、一个模拟 I/O 子系统和一个模拟存储子系统等。

gem5 是一个用 C++ 和 Python 编写的模拟引擎,它用来运行模拟和生成性能指标。gem5 端通常包括一个模拟操作系统、一个模拟应用程序、一个模拟库函数和一个模拟驱动程序等。

m5 和 gem5 端是互补的,即 m5 端主要负责模拟硬件,而 gem5 端则主要负责模拟软件。因此,m5端和gem5端可以说是两个互补的部分,共同完成了Gem5模拟器的功能。

因此,如果你想同时调用 m5 端和 gem5 端,那么你需要使用 FS 模式。FS 模式(Full System Mode)是指 Gem5 模拟器运行在多线程模式下,同时模拟硬件和软件的模式。在 FS 模式下,Gem5 模拟器提供了一个完整的操作系统环境,用户可以在这个环境中运行应用程序,并通过硬件模型与模拟系统进行交互。

(2)关于memory system modes

memory system modes指的是gem5模拟器中的内存系统模式。gem5模拟器支持三种不同的内存系统模式:timing mode、atomic mode和functional mode。

  1. atomic模式:在这种模式下,所有内存访问都是原子的,也就是说,在一个内存访问操作完成之前,不会有其他内存访问操作,用于将模拟快速转发到感兴趣的区域。

  2. timing模式:在这种模式下,内存访问的时间是真实的,也就是说,内存访问的时间是基于真实的内存访问时间模拟的。最重要的内存系统模式,它模拟了真实系统中的内存访问时间,可以精确模拟出内存访问的时序关系。

  3. functional模式:在这种模式下,内存访问的结果是正确的,但是内存访问的时间是不真实的。它只模拟内存访问操作的功能,不考虑时序和原子性。也称为调试模式,用于从主机读取数据到模拟器内存。它大量用于系统调用仿真模式

  4. detailed模式:在这种模式下,内存访问的时间和结果都是真实的,也就是说,它提供了最细粒度的模拟。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值