gem5 garnet l1 l2 cache的创建与相连

2023-12-21 08:30
文章标签 创建 cache l2 l1 gem5 相连 garnet

本文主要是介绍gem5 garnet l1 l2 cache的创建与相连,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

gem5 garnet l1 l2 cache的创建与相连

主要就是这个图:
在这里插入图片描述

细节

我们用的是gem5/configs/deprecated/example/fs.py

#fs.py 引入了上两层路径,也就是当前可以看到 gem5/configs/路径。
addToPath("../../")

在这里插入图片描述

#fs.py引入了gem5/configs/ruby/Ruby.py
from ruby import Ruby
#fs.py 使用了gem5/configs/ruby/Ruby.py 中的 create_system
Ruby.create_system(args, True, test_sys, test_sys.iobus, test_sys._dma_ports, bootmem)
#fs.py 还使用了gem5/configs/ruby/Ruby.py 中的 Ruby.define_options(parser)

我们去看gem5/configs/ruby/Ruby.py 中的 create_system 和 define_options。
第1段代码关注于根据用户选择的协议创建和配置仿真系统。
第2段代码关注于定义用户可以通过命令行设置的仿真选项。
虽然两者都动态导入并利用了特定的协议模块,但它们各自处理的是仿真配置的不同方面。

#1 gem5/configs/ruby/Ruby.py 中的 create_system 使用了 buildEnv 
# buildEnv来自于 from m5.defines import buildEnv 
...
protocol = buildEnv["PROTOCOL"]
exec(f"from . import {protocol}")
try:(cpu_sequencers, dir_cntrls, topology) = eval("%s.create_system(options, full_system, system, dma_ports,\bootmem, ruby, cpus)"% protocol)
except:print(f"Error: could not create sytem for ruby protocol {protocol}")raise#2 gem5/configs/ruby/Ruby.py 中的 def define_options(parser): 使用了 buildEnv 
...
protocol = buildEnv["PROTOCOL"]exec(f"from . import {protocol}")eval(f"{protocol}.define_options(parser)")Network.define_options(parser)

这时候我们看gem5/build/X86/python/m5/defines.py 中的buildEnv

# gem5/build/X86/python/m5/defines.py 中只有下面一行代码。 全是关于 buildEnv的。
buildEnv = {'USE_SYSTEMC': True, 'HAVE_FENV': True, 'HAVE_PNG': True, 'HAVE_POSIX_CLOCK': True, 'HAVE_VALGRIND': False, 'HAVE_DEPRECATED_NAMESPACE': 1, 'HAVE_HDF5': True, 'HAVE_TUNTAP': True, 'HAVE_PROTOBUF': True, 'KVM_ISA': 'x86', 'HAVE_KVM': True, 'HAVE_PERF_ATTR_EXCLUDE_HOST': 1, 'EXTRAS': '', 'BATCH': False, 'BATCH_CMD': 'qdo', 'M5_BUILD_CACHE': False, 'USE_EFENCE': False, 'BUILD_GPU': False, 'USE_POSIX_CLOCK': True, 'NUMBER_BITS_PER_SET': '128', 'SLICC_HTML': False, 'USE_NULL_ISA': False, 'USE_X86_ISA': True, 'USE_RISCV_ISA': False, 'USE_POWER_ISA': False, 'USE_SPARC_ISA': False, 'USE_ARM_ISA': False, 'USE_ARM_FASTMODEL': False, 'PVLIB_HOME': '', 'PVLIB_FLAVOR': 'Linux64_GCC-7.3', 'MAXCORE_HOME': '', 'ARMLMD_LICENSE_FILE': '', 'ARMLMD_LICENSE_COUNT': 1, 'SIMGEN': '${MAXCORE_HOME}/bin/simgen', 'USE_MIPS_ISA': False, 'PROTOCOL': 'MESI_Two_Level', 'USE_KVM': True, 'TARGET_GPU_ISA': 'gcn3'}

fs.py 中create_system创立的l1 l2 们 但是先不相连

fs.py中创建了system,其中包括了l1 l2 , 主要是create system创建了硬件。 具体的是fs.py使用Ruby.create_system,然后 调用了MESI_Two_Level.create_system。

eval是Python的一个内置函数,功能十分强大,这个函数的作用是,返回传入字符串的表达式的结果。就是说:将字符串当成有效的表达式 来求值 并 返回计算结果。
fs.py中怎么创建硬件系统的?

# 直接调用 fs.py 中 build_test_system
test_sys = build_test_system(np)#build_test_system中 先定义一个初步的test_sys
test_sys = makeLinuxX86System(test_mem_mode, np, bm[0], args.ruby, cmdline=cmdline)
#因为有ruby,额外操作 test_sysRuby.create_system(args, True, test_sys, test_sys.iobus, test_sys._dma_ports, bootmem)
#Ruby.create_system 中 protocol = buildEnv["PROTOCOL"] = 'MESI_Two_Level' (因为'PROTOCOL': 'MESI_Two_Level', )
#eval函数执行这个字符串表达式,相当于调用了对应协议模块中的create_system函数。这个函数负责根据给定的参数创建并配置仿真系统的组件。
#"%s.create_system(options, full_system, system, dma_ports, bootmem, ruby, cpus)" % protocol这一行是一个格式化的字符串表达式,它将protocol变量的值插入到字符串中。假设protocol的值为"MESI_Two_Level",那么格式化后的字符串将是"MESI_Two_Level.create_system(options, full_system, system, dma_ports, bootmem, ruby, cpus)"。 
try:(cpu_sequencers, dir_cntrls, topology) = eval("%s.create_system(options, full_system, system, dma_ports,\bootmem, ruby, cpus)"% protocol)

小结就是,其实Ruby.create_system 调用了MESI_Two_Level.create_system,其中 “MESI_Two_Level”会根据选定的协议不同而变化。

MESI_Two_Level.create_system

gem5/configs/ruby/MESI_Two_Level.py

#遍历每一个cpu 
for i in range(options.num_cpus):#实例指令cache和数据cachel1i_cache = L1Cache(size=options.l1i_size,assoc=options.l1i_assoc,start_index_bit=block_size_bits,is_icache=True,)l1d_cache = L1Cache(size=options.l1d_size,assoc=options.l1d_assoc,start_index_bit=block_size_bits,is_icache=False,)#暂未定prefetcher = RubyPrefetcher()#每一个cpu都可以有不同的时钟域clk_domain = cpus[i].clk_domain#把每个cpu的l2相连起来 Connect the L1 controllers and the networkl1_cntrl.mandatoryQueue = MessageBuffer()l1_cntrl.requestFromL1Cache = MessageBuffer()l1_cntrl.requestFromL1Cache.out_port = ruby_system.network.in_portl1_cntrl.responseFromL1Cache = MessageBuffer()l1_cntrl.responseFromL1Cache.out_port = ruby_system.network.in_portl1_cntrl.unblockFromL1Cache = MessageBuffer()l1_cntrl.unblockFromL1Cache.out_port = ruby_system.network.in_portl1_cntrl.optionalQueue = MessageBuffer()l1_cntrl.requestToL1Cache = MessageBuffer()l1_cntrl.requestToL1Cache.in_port = ruby_system.network.out_portl1_cntrl.responseToL1Cache = MessageBuffer()l1_cntrl.responseToL1Cache.in_port = ruby_system.network.out_port#然后是l2,先遍历每一个l2.数目是自己在命令行指定的,但是需要和cpu数一致。         
for i in range(options.num_l2caches):## First create the Ruby objects associated with this cpu#l2_cache = L2Cache(size=options.l2_size,assoc=options.l2_assoc,start_index_bit=l2_index_start,)l2_cntrl = L2Cache_Controller(version=i,L2cache=l2_cache,transitions_per_cycle=options.ports,ruby_system=ruby_system,)exec("ruby_system.l2_cntrl%d = l2_cntrl" % i)l2_cntrl_nodes.append(l2_cntrl)# Connect the L2 controllers and the networkl2_cntrl.DirRequestFromL2Cache = MessageBuffer()l2_cntrl.DirRequestFromL2Cache.out_port = ruby_system.network.in_portl2_cntrl.L1RequestFromL2Cache = MessageBuffer()l2_cntrl.L1RequestFromL2Cache.out_port = ruby_system.network.in_portl2_cntrl.responseFromL2Cache = MessageBuffer()l2_cntrl.responseFromL2Cache.out_port = ruby_system.network.in_portl2_cntrl.unblockToL2Cache = MessageBuffer()l2_cntrl.unblockToL2Cache.in_port = ruby_system.network.out_portl2_cntrl.L1RequestToL2Cache = MessageBuffer()l2_cntrl.L1RequestToL2Cache.in_port = ruby_system.network.out_portl2_cntrl.responseToL2Cache = MessageBuffer()l2_cntrl.responseToL2Cache.in_port = ruby_system.network.out_port
#3个vn
ruby_system.network.number_of_virtual_networks = 3#后面创建topology会把all_cntrls 传递进去。
all_cntrls = (l1_cntrl_nodes + l2_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes)#topology是调用的 from .Ruby import create_topology, create_directories
#然后ruby.py也是调用的 gem5/configs/topologies/Mesh_XY.py里的Mesh_XY(controllers),这意味着它会创建一个Mesh_XY类型的网络拓扑实例,并将controllers作为参数传递给它。topology = create_topology(all_cntrls, options)
return (cpu_sequencers, mem_dir_cntrl_nodes, topology)

Mesh_XY(SimpleTopology) 的创立(先不相连)

路径如下是:

  1. fs.py 调用了 gem5/configs/ruby/Ruby.py 中的 Ruby.create_system( args, True, test_sys, test_sys.iobus, test_sys._dma_ports, bootmem )
  2. Ruby.create_system 调用了MESI_Two_Level.create_system
  3. MESI_Two_Level.create_system底部 内嵌了Ruby.create_topology
  4. Ruby.create_topology调用了 TopoPython.topoClass(controllers),其中TopoPython 是 import topologies.{options.topology} as TopoPython. {options.topology} 是我们命令行输入的,也就是import了 Mesh_XY.py 。 topoClass,是Mesh_XY.py 中的一个class ,定义是 class Mesh_XY(SimpleTopology):。
  5. 之后我们就详解,class Mesh_XY(SimpleTopology):如何处理传递进来的 all_cntrls。

1.本身的类型是SimpleTopology

如下,就是简单的说一下自己继承自哪个类型。这个类型来自于 from topologies.BaseTopology import SimpleTopology。 引用的文件的路径是gem5/configs/topologies/BaseTopology.py。

class Mesh_XY(SimpleTopology):description = "Mesh_XY"

2. 初始化需要controller

def __init__(self, controllers):self.nodes = controllers        

这时候把MESI_Two_Level.create_system 传递进来的 l1 l2 nodes等传递给mesh_xy.py中的代码,但是没有进一步操作。

3. 将controller们 相连

调用流程是 fs.py中 ruby.create_system,其中内嵌的ruby.create_topology 调用了topology.makeTopology( options, network, IntLinkClass, ExtLinkClass, RouterClass ), topology是mesh_xy,所以调用了gem5/configs/topologies/Mesh_XY.py中的 def makeTopology(self, options, network, IntLink, ExtLink, Router):这个函数 .

因为这里很重要,单独一个大节来写。

ruby. create_system里 将controller们 相连: 调用mesh_xy.makeTopology

fs.py调用了 ruby.create_system,

  1. 先调用 MESI_Two_Level.create_system
    1.1 MESI_Two_Level.create_system 底部 内嵌了Ruby.create_topology 创建了 这个topology但是没有相连。 这里的create 只是调用mesh_xy(ctrls)进行初始化。
  2. ruby.create_system 紧接着 topology.makeTopology( options, network, IntLinkClass, ExtLinkClass, RouterClass ),调用了 gem5/configs/topologies/Mesh_XY.py中的Mesh_XY. makeTopology. 进行相连
    2.1 其中,from network import Network 是创建了network,会要在互联时使用。gem5/configs/

下面是相连的代码

Mesh_XY类定义了一个基于XY路由算法的二维网格(mesh)拓扑结构。这个拓扑用于在gem5仿真中配置处理器核心、缓存和其他控制器之间的网络连接。代码中定义了如何将控制器(controllers)连接到网格中的路由器,并设置了路由器之间的内部链接(int_links)。这里的controllers是传入的参数,包含了L1控制器、L2控制器、目录控制器和DMA控制器的节点。

下面是对代码中关键部分的解释:

控制器与路由器的连接(External Links)

控制器(如缓存控制器和DMA控制器)通过外部链接(ExtLink)连接到网格中的路由器。
代码首先将大部分控制器平均分配给所有路由器,每个路由器连接相同数量的控制器。
如果有剩余的控制器(比如由于控制器数量不能被路由器数量整除),这些控制器将被连接到网格中的第一个路由器。

路由器间的内部连接(Internal Links)

网格中的每个路由器通过内部链接(IntLink)相互连接,形成网格结构。
东西方向的链接(East-West)和南北方向的链接(North-South)被创建,以实现网格的二维结构。
每个链接的权重和延迟设置反映了网格的物理和性能特性。在XY路由中,通常东西方向和南北方向的链接权重会有所不同,以支持死锁避免算法。

网格拓扑的构建过程

计算路由器数量、行数和列数。
为每个路由器创建Router对象,并将它们存储在一个列表中。
根据提供的控制器节点创建外部链接(ExtLink),将控制器连接到相应的路由器。
创建内部链接(IntLink),根据网格拓扑将路由器彼此连接。
将所有创建的外部链接和内部链接分别存储在network.ext_links和network.int_links中。
通过这种方式,Mesh_XY类构建了一个基于XY路由的网格网络拓扑,它连接了仿真中的各个控制器和路由器,从而实现了复杂的网络通信模式。

在仿真中,这个网格拓扑模型被用来研究不同网络配置和通信模式对整体系统性能的影响,特别是在处理多核处理器和复杂内存系统的场景中。

代码逐行解读: def makeTopology(self, options, network, IntLink, ExtLink, Router):

我们诸行解读,从不跳过。为了方便阅读,直接写在注释里了。

def makeTopology(self, options, network, IntLink, ExtLink, Router):nodes = self.nodes # 来自于自己的init时读的all_cntrls <- def __init__(self, controllers): self.nodes = controllersnum_routers = options.num_cpus#命令行给的输入,例如64 或1 ,我们先用64做个例子num_rows = options.mesh_rows# #命令行给的输入,例如8 或1 我们用64作为例子,这里再用8x8作为例子(2x32,4x16 也可以,但是8x8常见)# default values for link latency and router latency.# Can be over-ridden on a per link/router basislink_latency = options.link_latency  # used by simple and garnet #我们命令行没有输入,使用默认值router_latency = options.router_latency  # only used by garnet  #我们命令行没有输入,使用默认值# There must be an evenly divisible number of cntrls to routers# Also, obviously the number or rows must be <= the number of routers#len(nodes) = 是这么计算的: 64 +64+ 64 + 0#all_cntrls = ( l1_cntrl_nodes + l2_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes ) #分为l1 ctrl num = cpu num,是64, l2 ctrl num是 单独命令行输入的 64# dir和dma是  gem5/configs/ruby/MESI_Two_Level.py 中 from .Ruby import create_topology, create_directories,然后  gem5/configs/ruby/Ruby.py  中 def create_directories(options, bootmem, ruby_system, system):     return (dir_cntrl_nodes, None) 。  其中for i in range(options.num_dirs):  dir_cntrl_nodes.append(dir_cntrl) 。#  dir num是 单独命令行输入的 l2 dir num 64    dma_cntrl_nodes是返回的none也就是 0.cntrls_per_router, remainder = divmod(len(nodes), num_routers)#然后每个router分到了3个cntrls 没有remainder#64个节点整除8行,得到8列。 如果router数目不够而row太大,就报错。 如果除不尽(通过检查相乘是否相等)就报错。assert num_rows > 0 and num_rows <= num_routersnum_columns = int(num_routers / num_rows)assert num_columns * num_rows == num_routers#遍历64个路由器,实例话64个router。# Create the routers in the meshrouters = [Router(router_id=i, latency=router_latency)for i in range(num_routers)]#传递给network ,这里的network是一个类,名字叫garnetnetwork,继承自class RubyNetwork(ClockedObject):,s RubyNetwork中的 routers = VectorParam.BasicRouter("Network routers")network.routers = routers# link counter to set unique link idslink_count = 0# Add all but the remainder nodes to the list of nodes to be uniformly# distributed across the network.network_nodes = []remainder_nodes = []for node_index in range(len(nodes)):if node_index < (len(nodes) - remainder):network_nodes.append(nodes[node_index])else:remainder_nodes.append(nodes[node_index])# Connect each node to the appropriate routerext_links = []#这行代码使用enumerate函数遍历network_nodes列表,i是索引,n是当前迭代的节点(控制器)。#l1_cntrl_nodes + l2_cntrl_nodes + dir_cntrl_nodes + dma_cntrl_nodes#  cntrl_level 分别是0,1,2。 3因为dma不存在所以没有。for (i, n) in enumerate(network_nodes):cntrl_level, router_id = divmod(i, num_routers)assert cntrl_level < cntrls_per_routerext_links.append(ExtLink(link_id=link_count,ext_node=n,int_node=routers[router_id],latency=link_latency,))#这里完成后,每个cpu和对应的router之间有3个线。分别是 l1_cntrl+ l2_cntrl  + dir_cntrl。link_count += 1#我们# Connect the remainding nodes to router 0.  These should only be# DMA nodes.for (i, node) in enumerate(remainder_nodes):assert node.type == "DMA_Controller"assert i < remainderext_links.append(ExtLink(link_id=link_count,ext_node=node,int_node=routers[0],latency=link_latency,))link_count += 1#这些ext links指的是l1 l2 和router相连network.ext_links = ext_links#int links指的是noc之内,router之间的相连# Create the mesh links.int_links = []#左边router的east outport 连接右边一列的router的west inport# East output to West input links (weight = 1)for row in range(num_rows):for col in range(num_columns):if col + 1 < num_columns:east_out = col + (row * num_columns)west_in = (col + 1) + (row * num_columns)int_links.append(IntLink(link_id=link_count,src_node=routers[east_out],dst_node=routers[west_in],src_outport="East",dst_inport="West",latency=link_latency,weight=1,))link_count += 1#左边router的east inport 连接右边一列的router的east outport# West output to East input links (weight = 1)for row in range(num_rows):for col in range(num_columns):if col + 1 < num_columns:east_in = col + (row * num_columns)west_out = (col + 1) + (row * num_columns)int_links.append(IntLink(link_id=link_count,src_node=routers[west_out],dst_node=routers[east_in],src_outport="West",dst_inport="East",latency=link_latency,weight=1,))link_count += 1#上边router的 North outport 连接下边一行的router的westinport# North output to South input links (weight = 2)for col in range(num_columns):for row in range(num_rows):if row + 1 < num_rows:north_out = col + (row * num_columns)south_in = col + ((row + 1) * num_columns)int_links.append(IntLink(link_id=link_count,src_node=routers[north_out],dst_node=routers[south_in],src_outport="North",dst_inport="South",latency=link_latency,weight=2,))link_count += 1#上边router的 North intport 连接下边一行的router的west outport# South output to North input links (weight = 2)for col in range(num_columns):for row in range(num_rows):if row + 1 < num_rows:north_in = col + (row * num_columns)south_out = col + ((row + 1) * num_columns)int_links.append(IntLink(link_id=link_count,src_node=routers[south_out],dst_node=routers[north_in],src_outport="South",dst_inport="North",latency=link_latency,weight=2,))link_count += 1network.int_links = int_links# Register nodes with filesystemdef registerTopology(self, options):for i in range(options.num_cpus):FileSystemConfig.register_node([i], MemorySize(options.mem_size) // options.num_cpus, i)

小结

我们这里发现,所以router都连接上了3个ext links 连上的 ctrl分别是 l1 l2 和dir,同时intlinks互相链接router。我们在之后的博客看到底数据是怎么传输的,怎么从 core 流向caches再流向 router.

这篇关于gem5 garnet l1 l2 cache的创建与相连的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/519264

相关文章

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

PHP7扩展开发之类的创建

本篇文章主要将如何在扩展中创建一个对象。创建的对象的过程,其实和一个小孩出生,成长的过程有些类似。 第一步,办准生证 生孩子第一步,先办准生证。声明我要生孩子了。对象创建的时候,如何办准生证呢?只要定义一个zend_class_entry变量即可。代码如下: zend_class_entry ce; zend_class_entry 是啥?可以认为它使一个原型,定义了一些对象应该有哪些东西

创建表时添加约束

查询表中的约束信息: SHOW KEYS FROM 表名; 示例: 创建depts表包含department_id该列为主键自动增长,department_name列不允许重复,location_id列不允许有空值。 create table depts(department_id int primary key auto_increment,department_name varcha

UML- 统一建模语言(Unified Modeling Language)创建项目的序列图及类图

陈科肇 ============= 1.主要模型 在UML系统开发中有三个主要的模型: 功能模型:从用户的角度展示系统的功能,包括用例图。 对象模型:采用对象、属性、操作、关联等概念展示系统的结构和基础,包括类图、对象图、包图。 动态模型:展现系统的内部行为。 包括序列图、活动图、状态图。 因为要创建个人空间项目并不是一个很大的项目,我这里只须关注两种图的创建就可以了,而在开始创建UML图