gem5学习(2):全流程运行Chiplet-Gem5-SharedMemory【巨详细版本】

目录

参考资料

一、简介

二、chiplet_shared_Memory操作手册

【注:一些可能涉及到的主要思想】

1、安装软件依赖

2、下载源码

3、编译gem5

4、在gem5/include写sourceCode.cpp(测试程序,可跳过)

5、将待执行文件编译成可执行文件(必须,不可跳过)

6、将可执行文件test.out放入镜像中

① 挂载镜像文件

② 将test.out和a.out都复制到镜像中

③ 删除挂载点

7、执行img镜像中的可执行文件

① 在gem5的根目录中执行:

② 启动M5端,使用m5term远程监听(稳定性更好)【首次使用到③,非首次到④】

③ 如果为首次使用m5term,执行以下操作

④ 如果非首次使用m5term,执行以下操作

⑤进入镜像文件

⑥ 返回到img文件的根目录中,执行test.out文件

⑦ 执行结果(每个chiplet的模拟都是两个窗口,后续可以考虑直接在原窗口进入到程序中,不知道是否可行)

8、得到两个chiplet的communication文件

9、将communication文件转为trace文件

三、popnet操作手册

1、下载源码

2、编译popnet

3、将bench文件移动到popnet/two_trace目录下

4、执行popnet仿真

5、实验结果


参考资料

  1. 华南理工大学王小航老师课题组开源项目Chiplet-Gem5-SharedMemory,该仿真器可模拟多芯粒集成的众核芯片。
  2. 基于 popnet 的、可对任意拓扑的片上网络(芯粒集成网络)进行仿真的软件,用户只需要准备轨迹文件和DOT格式的拓扑文件。gitee的popnet_modified源码(包含《任意拓扑网络仿真器说明书 v7.pdf》)。
  3. 好啊啊啊啊同学的《Gem5模拟器,popnet模拟器源码记录(十五)》
  4. 好啊啊啊啊同学的《Gem5模拟器,全流程运行Chiplet-Gem5-SharedMemory-main(十)》
  5. 好啊啊啊啊同学的《傻白探索Chiplet,A Methodology for Simulating Multi-chiplet Systems UsingOpen-source Simulators(十)》

本文主要基于上述材料进行复现,记录下来主要是为了便于复盘。帖子中仍存在了解不详细的部分,也希望大家可以为我指出错误,让我能学习进步。

本实验流程基础:《基于多芯粒集成的 X86 指令集共享式储存仿真器说明书》

一、简介

基于gem5和popnet构建的基于多芯粒集成的CPU共显示储存仿真器,能够支持精确互连模型的大规模并行模拟。

具体细节可以了解文档。

需要提前准备的文件:

  1. 制作好的ubuntu镜像文件。

    1. 可直接使用的img文件地址:我用夸克网盘分享了「gapbs.img」,点击链接即可保存。链接:夸克网盘分享

  2. linux内核文件

    1. 可直接使用的vmlinux内核文件地址:我用夸克网盘分享了「vmlinux-4.19.83」,点击链接即可保存。链接:夸克网盘分享

二、chiplet_shared_Memory操作手册

以下所有操作都是在该项目的gem5目录中完成。

【注:一些可能涉及到的主要思想】

Chiplet的主要思想是:

  •     如果你想在镜像中执行某个程序,需要将程序的可执行文件首先放到img镜像里。

  •    然后找个文件夹挂载镜像文件。

  •    然后再删除镜像文件的挂载点。

此时可以使用前面编译好的gem5.opt和vmlinux内核文件进入到远程连接的地方。在gem5根目录下执行命令行:build/X86/gem5.opt configs/example/fs.py --kernel=include/vmlinux-4.19.83 --disk-image=include/gapbs.img -n 3,会出现系统正在监听3456端口。不对当前页面进行任何操作。

  •    在m5端进行连接。打开一个新的窗口(可以使用相同的用户名连接到相同的ip上),然后进入到gem5根目录下的util/term目录,命令行make gcc -o mterm term.c编译,再安装:

    1. make install

    2. sudo install -o root -m 555 m5term /usr/local/bin

  •    安装完成后直接使用m5term localhost 3456远程端口监听连接模拟系统。

  •    这之后就需要等待大概15分钟,只到默认的根目录命令行出现。

  •    如果不再需要使用的话,可以直接使用m5 exit退出(也可以直接在被监听的窗口退出该命令即可)

将需要执行的程序编译并挂载的步骤:

  •     我们可以在include目录下直接执行sudo mount -o loop,offset=1048576 ./gapbs.img /mnt,把挂载的目录放到了根目录下。【可以新建挂载目录】【但是感觉在当前目录中mkdir mnt新建一个mnt目录,然后再sudo mount -o loop,offset=1048576 ./gapbs.img /mnt就可以直接挂载到当前目录了。省略了来回跳转的麻烦】

  •    编译文件:g++ -L./ test.cpp -o test.out -lm5

  •    移动可执行文件:sudo cp ./test.out /mnt,【这个时候一定要注意移动的路径】

  •    完成所有修改以后,就要使用umount命令卸载img文件:sudo umount /mnt

  •    然后安装上面的教程启动gem5,再使用m5连接后进入远程host

  •    直接进入到可执行文件所在的目录中,直接执行:/a.out

如果需要修改镜像文件的话,需要进行如下步骤:

  •    在gem5根目录下执行build/X86/gem5.opt configs/example/fs.py --kernel=include/vmlinux-4.19.83 --disk-image=include/gapbs.img -n 3,会提示没有six模块。

  •    安装six模块:使用echo $PYTHONPATH检查 PYTHONPATH 环境变量,输出为空,添加six包的路径到PATH中,export PYTHONPATH=$PYTHONPATH:/home/zyl/.local/lib/python3.8/site-packages,这时候再重新执行①中的命令就可以了。【不知道为什么再次登录打开的时候就需要重新执行这个步骤。有没有一种方法可以直接将这个路径添加到系统文件中?可以写到.bashrc文件中,将这行export写到文件的最下方,然后命令行中执行. .bashrc将命令生效】

  •    重新执行后会提示****REAL SIMULATION****,此时不要进行任何操作,否则可能会退出。

  •    打开新的终端(在我的SSH中就是打开新的SSH连接),登录上后cd home/zyl/chiplet_popnet/Chiplet_Gem5_SharedMemory/util/term跳转到m5端登录。

  •    如果是首次执行,需要按照(1)make gcc -o mterm term.c;(2)sudo make install;(3)sudo install -o root -m 555 m5term /usr/local/bin;(4)m5term localhost 3456流程进行完整的四步操作。但如果不是首次,可以直接在当前目录中输入(4)m5term localhost 3456即可进入到远程加载初始化中。

  •    加载大概需要15分钟左右【再次执行后的启动时间变成了30分钟】,等待,不要进行任何操作。

  •    加载完成后会提示使用默认的用户名root根目录的命令行root@gem5-host:/home/gem5/gapbs#后就可以进行下一步操作了。

  •    导航到可执行文件的目录,直接放在根目录得了,然后直接/test.out执行这个可执行文件。

1、安装软件依赖

sudo apt install build-essential git m4 scons zlib1g zlib1g-dev  libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev python3-dev python3-six
python3 libboost-all-dev pkg-config

如果安装过程中出现问题,就按照提示修改后单个安装。【单个安装不会出现很多问题】

2、下载源码

git clone https://github.com/FCAS-SCUT/Chiplet-Gem5-SharedMemory.git

目录格式(其中有一部分是我完成流程后截图的)

3、编译gem5

在gem5的根目录中执行编译。

sudo scons build/X86/gem5.opt -j 4
-j表示开启多线程,4表示线程数

编译完成【大概需要1h左右】

测试:

./build/X86/gem5.opt ./configs/example/se.py -c ./tests/test-progs/hello/bin/x86/linux/hello

4、在gem5/include写sourceCode.cpp(测试程序,可跳过)

sourceCode.cpp程序是一个简单的运行程序示例,在后续的矩阵乘法中并没有涉及。

因此如果大家在后续需要完成后续的矩阵乘法的benchmark时,可以选择跳过这个环节。

#include "m5ops.h"
int main(){
m5_gadia_call(0, 1, 2, 0);      //chiplet0 send data2 to target chiplet1
uint64_t result = m5_gadia_receive(0);
return 0;
}

其中m5ops.h需要写入正确的位置。【我是直接把文件复制过来的】

对sourceCode.cpp文件进行编译,输出为a.out

g++ -L/Chiplet-Gem5-SharedMemory/gem5/include ./sourceCode.cpp -o a.out -lm5

此时文件夹中多了一个可执行文件a.out。

然后将a.out移动到img文件中:

(1)挂载img文件

sudo mount -o loop,offset=1048576 ./gapbs.img /mnt

(2)移动到gapbs.img镜像的根目录中

sudo cp ./a.out /mnt/

(3)解除挂载

sudo umount /mnt

(4)按照下述“7、执行img镜像中的可执行文件”步骤。根据是否为首次使用m5term完成远程监听。

(5)在远程监听窗口中,进入到a.out所在的目录中,运行可执行文件。

/a.out

说明:这步骤是评论中同学分享时发现遗漏的部分,在前期我运行过程中忽略了考虑这个文件的作用,并没有对程序进行测试,所以没有运行后结果。

至此,sourceCode.cpp的测试过程结果。

5、将待执行文件编译成可执行文件(必须,不可跳过)

以矩阵乘法为例,执行代码test.cpp如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
 
using namespace std;
#include "m5ops.h"
/*
本示例示范 2 个 chiplet 做 10*10 的矩阵乘工作,假设结果为 C,则 C 的大小为
10*10,用一维矩阵储存,则 chiplet0 计算矩阵乘 C 索引从 0 到 500*249 的结果,而
chiplet1 计算剩下的结果。
*/
extern "C" 
{
	const int N = 10;
	int main() {
		// 程序初始化开始
		long long *martrix = (long long *)malloc(N * N * sizeof(long long));
		for (int i = 0; i < N * N; i++) {
			srand(i);
			martrix[i] = rand() % 10;
		}
		cout << "init martrix" << endl;
		
		long long *martrix2 = (long long *)malloc(N * N * sizeof(long long));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				srand(i + j);
				martrix2[i * N + j] = rand() % 10;
			}
		}
		cout << "init martrix2" << endl;
		
		long long *martrix3 = (long long *)malloc(N * N * sizeof(long long));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				for (int k = 0; k < N; k++)
					martrix3[i * N + j] = 0;
			}
		}
		cout << "init martrix3" << endl;
		
		// 初始化结束
		// 初始化 gem5 的相关信息
		int chipletNumber = -1;
		cout << "enter the ChipletNumber" << endl;
		std::cin >> chipletNumber;
		// 完成 gem5 的相关信息初始化
		m5_gadia_call(chipletNumber, chipletNumber, 0, 0); // 记录启始 cycle
	   // 示例的 totalChipletNumber 为 2,故不显式的写出来。
		if (chipletNumber == 0) {
			for (int i = N / 2; i < N; i++) {
				for (int j = 0; j < N; j++) {
					for (int k = 0; k < N; k++)
						martrix3[i * N + j] = martrix3[i * N + j] + martrix[i * N + k] * martrix2[k * N + j];
				}
			}
			m5_gadia_call(chipletNumber, 1, -2, 0);
			int position = 0;
			cout << " coming 0" << "coming while" << endl; 
			while (true) {
				int result = (int)m5_gadia_receive(chipletNumber);
				// 检测 chiplet1 是否完成了矩阵乘的工作
				if(result == -1)
					continue;
				else if (result == -2)  //代表等待的Chiplet已经完成读写 
					break;
				else {
					martrix3[position] = result;
					position++;
				}
			}
			m5_gadia_call(chipletNumber, chipletNumber, 0, 0); // 记录结束 cycle
			return 0;
		}// the following is responsible for collect
		else if (chipletNumber == 1) {
			for (int i = 0; i < N / 2; i++) {
				for (int j = 0; j < N; j++) {
					for (int k = 0; k < N; k++)
						martrix3[i * N + j] = martrix3[i * N + j] + martrix[i * N + k] * martrix2[k * N + j];
					// chiplet 1 把结果写入到共享储存中。
					m5_gadia_call(chipletNumber, 0, (int)martrix3[i * N + j], 0);
				}
			}
			cout << "coming 1" << endl;
			// 告诉 chiplet0, chiplet1 已经完成矩阵乘法
			m5_gadia_call(chipletNumber, 0, -2, 0); 
			return 0;
		}
	}
}

执行编译:

g++ -L./ test.cpp -o test.out -lm5
  //正常来说-lm5应该是放在前面的,但是在这里编译的时候放到前面会提示undefined reference to 'm5_gadia_call'错误,将-lm5放在后面就可以正常编译

此时在include目录中得到test.out文件。

【如果在当前的目录中执行可能会遇到Illegal instruction (core dumped)报错,这是正常的,文件可以在img镜像中正确执行】

6、将可执行文件test.out放入镜像中

【因为实验中使用了两个chiplet进行仿真,所以需要按照以下步骤制作两个镜像文件,img1用于仿真chiplet0,img2用来仿真chiplet1,为了简便,本说明文档中只示范了一个镜像文件的执行步骤,但结果中仍使用两个chiplet进行呈现】

① 挂载镜像文件

将前文中提到的img镜像文件和vmlinux文件下载到gem5/include目录中。

sudo mount -o loop,offset=1048576 ./gapbs.img /mnt

挂载在根目录的mnt/目录中。

② 将test.out和a.out都复制到镜像中

sudo cp ./a.out /mnt/
sudo cp ./test.out /mnt/

查看mnt目录

③ 删除挂载点

sudo umount /mnt

此时就不能再查看目录了。

7、执行img镜像中的可执行文件

① 在gem5的根目录中执行:

build/X86/gem5.opt configs/example/fs.py --kernel=vmlinux-4.19.83 --diskimage=gapbs.img -n 1
  //使用一个核

此时当前窗口的显示页面如下:

表明可以使用4567端口进行远程监听。

② 启动M5端,使用m5term远程监听(稳定性更好)【首次使用到③,非首次到④】

新打开一个窗口,进入到cd home/zyl/chiplet_popnet/Chiplet_Gem5_SharedMemory/util/term。

就是当前的gem5/util/term目录中。

③ 如果为首次使用m5term,执行以下操作

编译:

make gcc -o mterm term.c

安装:

sudo make install
sudo install -o root -m 555 m5term /usr/local/bin

远程监听:

m5term localhost 3456

大概需要等待30分钟左右。

④ 如果非首次使用m5term,执行以下操作

远程监听:

m5term localhost 3456

大概需要等待30分钟左右。

⑤进入镜像文件

此时已经进入到img镜像中。

⑥ 返回到img文件的根目录中,执行test.out文件

⑦ 执行结果(每个chiplet的模拟都是两个窗口,后续可以考虑直接在原窗口进入到程序中,不知道是否可行)

img1-chiplet1:

img2-chiplet0:

8、得到两个chiplet的communication文件

两个chiplet执行结束后,在为img1执行build/X86/gem5.opt configs/example/fs.py --kernel=vmlinux-4.19.83 --diskimage=gapbs.img -n 1所在目录中出现了两个新的communication文件。

9、将communication文件转为trace文件

使用count.cpp文件。[说明教程中给的名字是convertpop.cpp,但名字无所谓]

在communication文件所在的目录中新增一个count.cpp文件:

// 此程序用于统计共享储存的通信文件并输出 popnet 的输入文件
// 该程序的工作原理是 1 将所有共享存储的通信记录一次性读入程序中。 2
// 读入完成后根据通信记 录的目标 chiplet 编号对通信记录分类。 3 分类之后按 cycle
// 排序。 4 选择 chiplet0 的 cycle,将其 他 chiplet 的 cycle 向 chiplet0
// 对齐,即同步大家的 cycle。 4 将所有 chiplet 的 cycle 排序,将通信 记录输出成
// trace 文件”bench”。 5 将各自 chiplet 在 3 中分类的而形成的类别,分文件输出。
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
class CommunicationRecord;
class Chiplet {
public:
  void setTime(unsigned long long time) { this->chipletStartCycle = time; }
  Chiplet() : chipletStartCycle(0), chipletNumber(-1) {
    // do nothing
  }
  int chipletNumber;
  unsigned long long chipletStartCycle;
  std::vector<CommunicationRecord *>
      relatedRecord; // if the srcCore number is the ChipletNumber, the record will be put here //
};
class CommunicationRecord {
public:
  CommunicationRecord() : cycle(0), srcCore(0), targetCore(0) {}
  CommunicationRecord(unsigned long long _cycle, int _srcCore,
                      int _targetCore) {
    this->cycle = _cycle;
    this->srcCore = _srcCore;
    this->targetCore = _targetCore;
  }
  unsigned long long cycle;
  int srcCore;
  int targetCore;
};
/*
 * this Program is aimed to generate the popnet trace file from the
 * communication record
 */
std::string communicationBaseFileName = "communication";
int TotalChipletNumber = 0;
unsigned long long chipletNumberZeroStartCycle;
void sortTheChipletRecord(unsigned long long *cycle, int *sequency, int length);
// 输出bench0.0 bench0.1 等文件
void outputSenderFile(Chiplet *ChipletSet) {
  for (size_t j = 0; j < ::TotalChipletNumber; j++) {
    std::ofstream file;
    int chipletNumber = j;
    std::string baseName = "bench.0.";
    baseName += char(chipletNumber + '0');
    file.open(baseName.c_str(), std::ios::out);
    // look for the record whose srcCore is j
    std::vector<CommunicationRecord *> tmpRecordSet;
    for (size_t i = 0; i < ::TotalChipletNumber; i++) {
      for (size_t k = 0; k < ChipletSet[i].relatedRecord.size(); k++) {
        CommunicationRecord *tmp = ChipletSet[i].relatedRecord[k];
        if (tmp->srcCore == chipletNumber) {
          tmpRecordSet.push_back(tmp);
        }
      }
    }
    // sort the record
    CommunicationRecord *record2sort =
        new CommunicationRecord[tmpRecordSet.size()]();
    int *sequency = new int[tmpRecordSet.size()]();
    unsigned long long *cycle = new unsigned long long[tmpRecordSet.size()];
    for (size_t j = 0; j < tmpRecordSet.size(); j++) {
      record2sort[j] = *tmpRecordSet[j];
      sequency[j] = j;
      cycle[j] = tmpRecordSet[j]->cycle;
    }
    sortTheChipletRecord(cycle, sequency, tmpRecordSet.size());
    for (int i = 0; i < tmpRecordSet.size(); i++) {
      record2sort[i] = *tmpRecordSet[sequency[i]];
    }
    // write to the sender file
    for (int i = 0; i < tmpRecordSet.size(); i++) {
      unsigned long long cycle = (record2sort[i].cycle - chipletNumberZeroStartCycle) / 1000;
      int targetCore = record2sort[i].targetCore;
      file << cycle << " 0 " << j << " 0 " << targetCore << " 5" << std::endl;
    }
    file.close();
  }
}
// 输出bench文件
void outputTheFile(CommunicationRecord *Record, int length) {
  std::ofstream file;
  file.open("bench", std::ios::out);
  for (size_t i = 0; i < length; i++) {
    unsigned long long cycle =(Record[i].cycle - chipletNumberZeroStartCycle) / 1000;
    int srcCore = Record[i].srcCore;
    int targetCore = Record[i].targetCore;
    file << cycle << " 0 " << srcCore << " 0 " << targetCore << " 5"
         << std::endl;
  }
  file.close();
}
// 用于生成全部trace文件
void generatePopnetTraceFile(Chiplet *chipletSet) {
  int recordSize = 0;
  for (size_t i = 0; i < ::TotalChipletNumber; i++) {
    recordSize += chipletSet[i].relatedRecord.size();
  }
  // bool* recordComplete = new bool[::TotalChipletNumber]();
  int *ptr2ChipletRecord = new int[::TotalChipletNumber]();
  CommunicationRecord *TotalRecord = new CommunicationRecord[recordSize]();
  for (size_t i = 0; i < recordSize; i++) {
    bool init = false;
    CommunicationRecord tmpRecord = CommunicationRecord(0, 0, 0);
    int targetChipletNumber = -1;
    for (size_t j = 0; j < ::TotalChipletNumber; j++) {
      if (ptr2ChipletRecord[j] >= chipletSet[j].relatedRecord.size()) {
        continue;
      }
      if (!init) {
        tmpRecord = *chipletSet[j].relatedRecord[ptr2ChipletRecord[j]];
        init = true;
        targetChipletNumber = j;
      }
      // compare the time and decide the min
      if ((chipletSet[j].relatedRecord[ptr2ChipletRecord[j]])->cycle <
          tmpRecord.cycle) {
        tmpRecord = *chipletSet[j].relatedRecord[ptr2ChipletRecord[j]];
        targetChipletNumber = j;
      }
    }
    TotalRecord[i] = tmpRecord;
    ptr2ChipletRecord[targetChipletNumber]++;
  }
  outputTheFile(TotalRecord, recordSize);
  outputSenderFile(&chipletSet[0]);
}
void swap(int *first, int *second) {
  int *tmp = first;
  second = tmp;
  first = second;
}
void swap(unsigned long long *first, unsigned long long *second) {
  unsigned long long *tmp = first;
  second = tmp;
  first = second;
}
void sortTheChipletRecord(unsigned long long *cycle, int *sequency,
                          int length) {
  // buble sort because not requring high performance
  for (int i = 0; i < length - 1; i++) {
    for (int j = 0; j < length - 1; j++) {
      if (cycle[j] > cycle[j + 1]) {
        swap(&cycle[j], &cycle[j + 1]);
        swap(&sequency[j], &sequency[j + 1]);
      }
    }
  }
}
// 排序时间,防止出现cycle无法对齐的情况
void sortChipletTime(Chiplet *chipletSet) {
  for (size_t i = 0; i < ::TotalChipletNumber; i++) {
    // for each chiplet
    Chiplet *currentChiplet = &chipletSet[i];
    int size = currentChiplet->relatedRecord.size();
    CommunicationRecord *tmp = new CommunicationRecord[size];
    int *sequency = new int[size]();
    unsigned long long *cycle = new unsigned long long[size];
    for (size_t j = 0; j < size; j++) {
      tmp[j] = *currentChiplet->relatedRecord[j];
      sequency[j] = j;
      cycle[j] = currentChiplet->relatedRecord[j]->cycle;
    }
    sortTheChipletRecord(cycle, sequency, (chipletSet[i]).relatedRecord.size());
    currentChiplet->relatedRecord.clear();
    for (int i = 0; i < size; i++) {
      currentChiplet->relatedRecord.push_back(&tmp[sequency[i]]);
    }
  }
}
// 查找chiplet的开始时间,因为gem5启动操作系统一般需要几十万cycle的开销。
void initChipletStartPoint(Chiplet *chiplet, bool isMainChiplet = false,
                           unsigned long long mainChipletCycle = 0) {
  // here is some stuff that something must be fixed in the future
  chiplet->setTime(chiplet->relatedRecord[0]->cycle);
  if (!isMainChiplet) {
    unsigned long long base = chiplet->relatedRecord[0]->cycle;
    chiplet->relatedRecord[0]->cycle = chiplet->relatedRecord[0]->cycle - base +
                                       mainChipletCycle + (rand() % 20) * 1000;
    for (size_t i = 1; i < chiplet->relatedRecord.size(); i++) {
      chiplet->relatedRecord[i]->cycle =
          chiplet->relatedRecord[i]->cycle - base + mainChipletCycle;
    }
  } else {
  }
}
void processOneFile(Chiplet *chipletSet, int currentChipletNumber) {
  std::ifstream myFile;
  std::string realFile =
      communicationBaseFileName + (char)(currentChipletNumber + '0');
  myFile.open(realFile.c_str(), std::ios::in);
  std::stringstream ss;
  std::string line = "";
  while (std::getline(myFile, line)) {
    ss.clear();
    ss.str(line);
    unsigned long long cycle;
    int srcCoreNumber;
    int targetCoreNumber;
    int data; // we don't need it but for skipping
    ss >> cycle >> srcCoreNumber >> targetCoreNumber >> data;
    if (targetCoreNumber == -1) { // the message is for all
	    CommunicationRecord *tmp = new CommunicationRecord(cycle, srcCoreNumber, currentChipletNumber);
for (size_t i = 0; i < ::TotalChipletNumber; i++) {
  chipletSet[i].relatedRecord.push_back(tmp);
}
    } else {
      chipletSet[targetCoreNumber].relatedRecord.push_back(
          new CommunicationRecord(cycle, srcCoreNumber, currentChipletNumber));
    }
  }
  myFile.close();
}
int main() {
  std::cout << "Enter the TotalChipletNumber" << std::endl;
  std::cin >> ::TotalChipletNumber;
  // bool* chipletInit = new bool[TotalChipletNumber]();
  Chiplet *myChipletSet = new Chiplet[::TotalChipletNumber]();
  for (int i = 0; i < TotalChipletNumber; i++) {
    myChipletSet[i].chipletNumber = i;
  }
  for (int i = 0; i < ::TotalChipletNumber; i++) {
    processOneFile(myChipletSet, i);
  }
  sortChipletTime(myChipletSet);
  initChipletStartPoint(&myChipletSet[0], true);
  for (size_t i = 1; i < ::TotalChipletNumber; i++) {
    initChipletStartPoint(&myChipletSet[i], false,
                          myChipletSet[0].chipletStartCycle);
  }
  chipletNumberZeroStartCycle = myChipletSet[0].relatedRecord[0]->cycle;
  generatePopnetTraceFile(myChipletSet);
  return 0;
}

编译count.cpp:

g++ -L./ ./count.cpp -o count.out

执行count.out文件,得到bench文件【这个bench文件就是pop的输入】

cheiplet仿真结束。

三、popnet操作手册

1、下载源码

git clone https://gitee.com/hic_0757/popnet_modified.git

2、编译popnet

mkdir build
cd build
cmake ..
make

3、将bench文件移动到popnet/two_trace目录下

cp /home/zyl/chiplet_popnet/Chiplet-Gem5-SharedMemory/gem5/bench /hom                e/zyl/chiplet_popnet/popnet_modified/two_trace/

4、执行popnet仿真

build/popnet -A 16 -c 1 -V 3 -B 8 -O 8 -F 4 -L 1000 -T 2000 -r 1 -I two_trace/bench  -R 0

5、实验结果

以上为popnet的全仿真流程,在运行的过程中会出现各种各样的问题如缺少six模块,undefined reference,程序执行时间过长等,这些不具备通性,如果有老师同学在执行的过程中存在任何问题,可以随时交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值