文章目录
Nirgam : 互联和应用建模的NoC仿真器
此为使用nirgam时对nirgam手册的翻译。其中包含了个人的理解,并非严格翻译。
1. 引言
Nirgam能做什么?
基于systemC设计,覆盖NoC设计的各个环节:拓扑机制,切换机制,虚拟通道,buffer参数,路由机制和应用。可扩展新的应用和路由算法。
拓扑
2D mesh和2D torus可选。拓扑大小由行、列决定。
切换机制
支持虫孔切换(wormhole)机制,在wormhole中,packets被分为flits。1个packets包含3种类型的flits。head/data/tail (hdt)。packet切换机制可通过创造包含1个flit的的packet来建模。一种特殊的hdt flit被用于建模单个flit的packet。
虚拟通道
用户可为每个物理通道配置虚拟通道
Buffer
用户可指定输入通道fifo中的buffer数量,每个buffer和flit的尺寸相同。
时钟频率
时钟频率可被指定,默认的时钟频率为1GHz。
路由算法
可选以下3种路由算法。
- 源头路由source routing–针对torus或者mesh结构
- 确定性路由–针对mesh结构
- 适应性奇偶路由–针对mesh结构
应用
下列应用可被加入到网络中的每个tile中
- source (sender)
- sink (receiver)
- synthetic traffic generator
- CBR : constant bit rate (连续bit率)
可配置的CBR流量参数如下:- packet size (byte为单位)
- load percentage (被使用的通道带宽比例)
- destination 用户可指定固定的目的地或者随机选择的目的地
- inter-flit intervals(时钟周期为单位)
- Bursty:
Bursty流量通过改变on/off周期来表示。在on期间,packets在固定的间隔被产生。在off期间,没有packets被产生。流量被下面的指数分布的变量表示。- packet尺寸(byte表示)
- load percentage (被使用的通道带宽比例)
- destination 用户可指定固定的目的地或者随机选择的目的地
- inter-flit intervals(时钟周期为单位)
- 平均burst长度(packets数量为计量)
- 平均off时间(时钟周期为计量)
- 基于input trace
- 这个应用和此前仿真一样产生了同样的traffic(流量)。此举支持比较traffic相同而参数不同时的NoC性能比较。
- CBR : constant bit rate (连续bit率)
性能分析
支持基于每个通道的运行时间性能分析。对于每个仿真记录下列性能指标
- 平均每个通道中每个packet的延迟(单时钟周期)
- 平均每个通道中每个flit的延迟(单时钟周期)
- 每个通道的平均吞吐量(Gbps单位)
2. 仿真基础
本节描述仿真器和建模的基本架构,使得读者更好地使用内建能力。需要扩展功能的高级用户可参考第4章获得更多仿真器内部的细节。
NoC模型
Nirgam的NoC模型是一个2维tile互联结构。每个tile包含1个ipcore,通过1个双向的核通道连接到router/switch中。本文router和switch是可以互换的。一个tile通过双向channel连接到另一个tile。每个tile有一个标识符id:tileID。同样地,每个tile可以被一个x或者y坐标来定位。图2.1和图2.2分别举例了一个3x4的mesh或者torus拓扑,在网络中的每个tile都用一个圈来表示。
XY或者OE(Adaptive Odd Even)算法可被用于2维mesh拓扑结构。这些算法的输入是目的地的tileID。Source routing可被同时用于mesh或者torus。Source routing的输入是从source到destination的路由编码。每个router有5个可能的方向:NSEWC (north, south, west, east, core。每个方向用如下的代码表示:
N: 0------000
S: 1------001
E: 2------010
W: 3------011
C: 4------100
在任何router中,最右侧的3bit决定了输出方向。source routing通过读取route code中最右侧的3个bits然后右移3bits实现。通过一个例子的帮助来解决特定路径下产生router code生成的问题。考虑产生图2.2(torus结构)中将packet从tile9送入到tile1的route code:9->8->0->1。这个路径将会通过方向序列:WSEC决定。route code即这些方向的逆序,即W(011) → S(001) → E(010) → C(100) = 100 010 001 011 = 2187。也可以通过反复乘以 8 并将方向码按相反顺序相加来获得十进制的路由码。(??)
代码结构
- application: 应用和应用库的源码
- config:包含simulator的所有配置文件,包含traffic。用户可改变这些文件中的参数从而实现不同的设计,并开展实验
- core:包含实现noc拓扑和架构的文件
- gnuplot:包含产生图形的文件
- log:
- gnu/matlab:输入数据的图形脚本文件
- nirgam:完整仿真log文件
- traffic:包含每个tile中的traffic文件
- vcdtrace:使用systemC产生的vcdtrace波形文件
- matlab:
- 包含产生图形的matlab脚本
- router:
- 包含路由算法的源代码和库,可连接到tile上
n0name@xm:~/Documents/a11_23git/nirgam-v2$ tree -L 2
├── application
│ ├── lib
│ └── src
├── config
│ ├── application.config
│ ├── application.config_MIX
│ ├── application.config_normal
│ ├── constants.h
│ ├── default.h
│ ├── examples
│ ├── extern.h
│ ├── nirgam.config
│ └── traffic
├── core
│ ├── ..h, ..o, ...cpp......
├── gnuplot
│ └── results.gnu
├── log
│ ├── gnuplot
│ ├── matlab
│ ├── nirgam
│ ├── traffic
│ └── traffic_pattern
├── Makefile
├── Makefile.defs
├── matlab
│ ├── images_scripts
│ ├── plot_core_graphs.m
│ └── plot_graphs.m
├── results
│ └── test
├── router
│ ├── lib
│ └── src
3. 运行仿真
本章介绍配置和运行仿真
安装
配置systemC和nirgam,此处参考
其中存在很多问题
- Makedefs.h文件需要修改(1)安装路径;(2)-fPIC参数问题;(3)application/lib和router/lib文件不产生的问题;(4)W1改为Wl
- Makefile文件中(1)TARGET_ARCH从linux改为linux64;(2)CFLAGS = $(DEBUG) $(OTHER) $(LDFLAG) -std=c++17 -fPIC
编译结束之后,仍旧存在如下的一个问题,需要在环境变量中加上export SC_SIGNAL_WRITE_CHECK=DISABLE
Error: (E115) sc_signal cannot have more than one driver:
signalnoc.nwtile[3][3].signal_35' (sc_signal) first driver
noc.nwtile[3][3].CBR.port_6’ (sc_inout)
second driver `noc.nwtile[3][3].IC2.port_18’ (sc_out)
In file: …/…/…/src/sysc/communication/sc_signal.cpp:67
配置
配置文件在config目录下实现。
- Noc配置参数:nirgam.config。
- 应用映射(指定哪个application在哪个tile中):application.config。接受tile ID pair作为输入。
- traffic配置参数:对于traffic产生器,可以在config/traffic说明
仿真
每个配置都会产生:results,logs,graphs。在gnuplot,log,matlab,result目录下即可查看仿真结果。
性能分析
nirgam在每个通道的基础上测量性能。图3.1展示了matlab产生的性能指标的代表。R0-R15展示了tile/router的布局。
R0 和 R1 之间的红色条 代表从 R0 到 R1 的东向通道(east channel)的度量值(metric)
R0 和 R1 之间的蓝色条 代表从 R1 到 R0 的西向通道(west channel)的度量值。
R0 和 R4 之间的绿色条 代表从 R0 到 R4 的南向通道(south channel)的度量值。
R0 和 R4 之间的橙色条 代表从 R4 到 R0 的北向通道(north channel)的度量值。
清除
清除编译和仿真的命令为:
- make clean 删除所有object files和libraries.
- make cleanlogs 删除所有logfiles
- make cleanresults 删除所有结果
- make ultraclean 删除以上所有
例子
在以下3个例子的帮助下描述仿真器的配置
- 字符串拼接 (string concatenation)
- 随机目的 的CBR
- 固定目的 的CBR
字符串拼接 string concatenation
应用描述:
• Tile 0 将包含3个flits的packet送入tile 5. 每个flit在payload中包含1个string
• Tile 5将从tile0收到的flits concatenates string到自己的payload中然后送入tile6
• Tile 6 收到这个concatenated string.
列表3.1表示了nirgam.config。仿真了2维3x4 mesh拓扑结构,使用了XY routing算法,并存储到str_concat中。
@nirgam.config
TOPOLOGY MESH
NUM ROWS 3
NUM COLS 4
RT ALGO XY
DIRNAME s t r c o n c a t
LOG 1
WARMUP 5
SIM NUM 100
@application.config
0 App send . s o
5 App concat . s o
6 App recv . s o
简单的配置文件可以在$NIRGAM/config/examples/string concatenation/中发现。
随机目的地的CBR
CBR:constant bit rate
每个tile表现为一个source和sink,即既可以产生数据又可以接收数据。每个tile产生CBR traffic到随机目的地中。
下表显示了nirgam.config的配置,仿真了2维3x4的mesh结构。使用了XY routing algorithm, 结果存储在随机CBR中。流量产生在5个时钟周期之后,并持续300个时钟周期。1000个时钟周期后仿真停止。
@nirgam.config
TOPOLOGY MESH
NUM ROWS 3
NUM COLS 4
RT ALGO XY
DIRNAME cbr random
LOG 1
WARMUP 5
SIM NUM 1000
TG NUM 300
@application.config
0 CBR. s o
1 CBR. s o
2 CBR. s o
3 CBR. s o
4 CBR. s o
5 CBR. s o
6 CBR. s o
7 CBR. s o
8 CBR. s o
9 CBR. s o
10 CBR. s o
11 CBR. s o
针对每个PE的Traffic配置文件需要在$NIRGAM/config/traffic/中指定。下表展示了tile-n的traffic配置例子,n表示tileID。tile n产生了8-byte的packets到随机的目的地。flits之间的interval是2个时钟周期。Traffic load是50%。packets之间的interval是load percentage的函数。
@traffic-tile-n
PKT SIZE 8
LOAD 50
DESTINATION RANDOM
FLIT INTERVAL 2
简单的配置文件存储在$NIRGAM/config/examples/CBR random/中。
固定目的地的CBR
应用描述:
- Tile 0 sends CBR traffic to tile 6.
- Tile 5 sends CBR traffic to tile 2.
- Tile 10 sends CBR traffic to tile 0.
- Tile 11 sends CBR traffic to tile 13.
- Tile 14 sends CBR traffic to tile 5.
下表展示了nirgam.config的情况。仿真了2维4x4的mesh拓扑结构。使用了 XY路由算法,结果存储在CBR中。Traffic 在5个时钟周期后产生,并持续300个时钟周期。仿真在1000个时钟周期后结束。
@nirgam.config
TOPOLOGY MESH
NUM ROWS 4
NUM COLS 4
RT ALGO XY
DIRNAME c b r f i x e d
LOG 1
WARMUP 5
SIM NUM 1000
TG NUM 300
@application.config
0 CBR. s o
5 CBR. s o
10 CBR. s o
11 CBR. s o
14 CBR. s o
2 Sink . s o
6 Sink . s o
13 Sink . s o
针对tile-0/5/10/11/14的配置文件需要在$NIRGAM/config/traffic/提供。下表展示了traffic配置文件:
CBR fixed: traffic/tile-0
PKT SIZE 8
LOAD 100
DESTINATION FIXED 6
FLIT INTERVAL 2
CBR fixed: traffic/tile-5
PKT SIZE 8
LOAD 100
DESTINATION FIXED 2
FLIT INTERVAL 2
CBR fixed: traffic/tile-10
PKT SIZE 8
LOAD 100
DESTINATION FIXED 0
FLIT INTERVAL 2
CBR fixed: traffic/tile-11
PKT SIZE 8
LOAD 100
DESTINATION FIXED 13
FLIT INTERVAL 2
CBR fixed: traffic/tile-14
PKT SIZE 8
LOAD 100
DESTINATION FIXED 5
FLIT INTERVAL 2
简单的配置逻辑在$NIRGAM/config/examples/cbr fixed/中。
4. 仿真器内部结构
拓扑和仿真结构可从配置文件中读出,应用和router库被粘附到tile上。每次仿真后会生成log file。
flit结构
在ports和modules之间流动数据的称为flit。结构定义在$NIRGAM\core\flit.h中。下图4.2展示了flit数据结构。
flit myflit ;
myflit中的整数数据字段表示NOC packet中的一个HEAD flit。可以通过如下的数据结构访问:
myflit.pkthdr.nochdr.flithdr.header.datahdr.dataint=10
NOC架构
NIRGAM的core engine实现了NOC。本节描述NOC架构在NIRGAM中的实现。NOC被建模为2维tile网络,并用“NOC”模块表示。每个tile被模块“NWTile”表示,每个tile中主要的组件和实现他们的模块如下所示:
- 输入通道:Input Channel Controller (IC): 被模块“InputChannel”表示。每个tile针对每个相邻的tile包含1个IC,同时也为一个ipcore增加了1个IC。例如,一个tile有4个相邻tile:NSEW,因此共有5个IC, NSES+core IC。每个IC包含1个或者更多的虚拟通道VC。每个VC包含1个fifo buffer。
- 控制器Controller: 被模块“Controller”表示。每个tile包含一个Controller,服务所有IC的路由请求。
- 虚拟通道分配器Virtual Channel Allocator(VCA): 通过模块“VCAllocator”表示,每个tile包含1个VCA,服务来自所有IC的虚拟通道分配。
- 输出通道控制器Output Channel Controller (OC):通过模块“OutputChannel”表示。每个tile针对每个相邻tile包含1个OC,对 ipcore也包含1个OC。针对每个input port每个OC包含一个寄存器阵列r_in。针对相邻tile的IC中的VC,OC包含一个寄存器阵列,r_vc。
- ipcore:通过模块“ipcore”表示,每个tile包含1个ipcore (IP element),此处一个application或者traffic generator可被attach。
虫孔路由
当一个头数据包到达虚拟通道(VC)时,该特定 VC 将被保留给该数据包,直至数据包的尾数据包离开 VC。每个 VC 都关联有一个寄存器“vc route”。当为head/hdt flit做出路由决策时,此寄存器将被设置以存储下一跳方向(N, S, E, W, C)。头数据包之后的data/tail flits将根据此寄存器中存储的信息转发到下一个芯片。尾数据包离开 VC 时,该寄存器将重置为“未定义”(ND,not defined)。
Buffer
取决于buffer的实现,3种状态的NOC架构是可行的。
- IB(input buffer)+ OB(output buffer)
- 只有IB
- 只有OB
我们已经实现了包含枝叶IB的的架构。每个IC包含一个或者更多的VCs。每个VC包含1个buffer(fifo queue)。OC只包含1个针对每个input port的寄存器r_in,和针对每个相邻tile中VC的寄存器r_vc。考虑到连接到2维mesh中4个相邻tile,让我们假设每个物理通道只有1个VC。 tile包含5个防线N S E W C。每个IC包含1个VC。每个VC包含1个buffer。tile包含5个OC:N S E W C。每个OC有5个r_in寄存器。一个用于存储来自于IC的flit。1个r_vc寄存器来存储被传输到相邻tile中的flit。一个tile的IC的输出端口连接到相同tile中的OC的input port。OC的输出端口连接到相邻的tile中的IC的输入端口。
flit的流动
接下来,我们将描述一个flit从一个tile到另一个tile的传输过程。请注意,下面所描述的事件是并发的,而非串行的。这些事件的发生由 SystemC 进程及其敏感性来控制。
当flit到达tile的input port时,对应IC (N、S、E、W或磁芯©)的IC接收信号。IC读取传入的flit并将其存储在VC通道的的fifo缓冲区。存储flit的虚拟通道VC由flit head中的vcid字段决定。
IC中的“route flit”进程读取fifo head的flit。如果是head/hdtflit且路由没有设置(vc route是not defined),它发送请求路由到控制器。除了请求之外,它还发送控制器所需的信息,例如源地址和目的地址。
在每个时钟周期中,控制器接受发出请求的IC路由请求。针对每个请求的路由取决于(下一跳)附加到控制器的路由算法。完成后,控制器将下一跳方向和就绪信号发送回相应的输入通道IC中。
如果这个VC的下一跳已经确定(VC route被设置为其中一个输出方向),则IC中的“transmit flit”过程读取fifo头部的flit。然后,该IC向VCA发送请求,请求在由输出方向确定的相邻块IC中分配虚拟通道。
tile中的VCA接收来自tile中的ic的请求,以便在相邻tile中分配虚拟通道。VCA还从相邻tile接收credit信息(每个VC的缓冲状态)。根据相邻tile中的buffer和VC的状态,它分配一个VC(如果空闲)给一个IC。它将分配的VC的cid和一个就绪信号发送回相应的IC。
当IC等待传输1个flit到输出方向时,从VCA接收到准备好,在flit header中设置vcid字段。如果输出方向对应的OC准备好接收一个flit,则IC将该flit发送到相应的输出端口。OC的状态是由从OC发送到IC的ready siganl 决定的。由于OC只有一个寄存器来存储一个flit,所以它设置就绪信号为true。寄存器是空闲的,否则它将就绪信号设置为false。
IC发送的信号在OC的输入端口接收。OC读取传入的数据并将其存储在与输入端口相对应的寄存器中。当r vc空闲时,该文件被转移到寄存器r vc。
在每个时钟周期中,OC从寄存器r vc向输出端口发送一个flit,并且该flit在相邻的tile上接收。
增加新的应用
application表示1个tile上的PE。实现动态的class loading 使得用户可以粘贴任何用户到NoC中。如果没有application粘贴到tile上,那么tile表现为1个router。
在compile阶段,application库被生成,并存储到 $NIRGAM/application/lib。appplication被定义为从ipcore中获得的module,因此application继承了ports, processes和ipcore的功能。接着,我们描述ipcore和功能,从而可以在application中被应用。
ipcore: ports:
输入端口:
- clock: sc_in_clk
- flit_inport: sc_in<flit>, flit到达的端口。可以在一个应用中创造一个对event敏感的process,并读出这个incoming flit。
下列代码表示创建了1个对这个端口敏感的process
wait(); // waiting until flit inport event
if( flit_input.event() ){
flit flit_recd = flit_inport.read();// read incoming flit
}
- credit in[NUM VCS]: sc in<creditLine>,虚拟通道VC的credit信息(buffer状态)输入端口。每个tile中的ipcore会直接连接到此tile中的input channel。
输出端口:
- flit_outport: sc out<flit>将flit送入core input channel 的端口。可以床在一个flit并写入这个端口。创造flits的wrapper函数的描述将会在下文展开。
ipcore: SystemC Processes
- void entry():对module进行仿真计数。在任何时间时钟周期的计数都存储在变量sim count中。
- virtual void_send():虚拟进程。它必须在任何派生 class/module中被overridden。产生flit。
- virtual void recv(): 虚拟进程。它必须在任何派生 class/module中被overridden。在application中此模块读取和处理输入的flit。
ipcore: functions
此处列出可在application中使用的module。
- 创建new flit
- 写入flit data
- 读取flit data
- 产生随机目的地
创建应用
需要在$NIRGAM/application/src中加入header文件和cpp文件,作为从ipcore module派生的systemC模块。
模板文件参考“App sample” 。
- Sending flits:
- Recieving flits:
- Logging:
增加新的router
router的复杂性取决于它的智能和路由逻辑。或许用户可能希望破解Controller和InputChannel模块来实现任何路由算法。然而,作为源地址和目的地址函数的路由算法可以很容易地作为class router派生的类来实现。接下来,我们将解释添加这样一个router的步骤。作为一个例子,让我们考虑我们需要添加一个名为“R”的路由算法和名为“myrouter.so”的库。