前言
《深入理解计算机系统》官网:http://csapp.cs.cmu.edu/3e/labs.html
该篇文章是是实验四Architecture Lab中的Writeup(archlab.pdf)、Simguide.pdf和全部文件夹的README机翻
archlab.pdf的原文:http://csapp.cs.cmu.edu/3e/archlab.pdf
其他原文请自行下载Architecture Lab文件夹,里面有。
在官网点击下方即可下载实验四的文件
archlab.pdf
Harry Bovik (bovik@cs.cmu.edu) 是这项任务的负责人。
1.介绍
在这个实验室中,您将学习流水线Y86-64处理器的设计和实现,优化它和一个基准程序,以最大限度地提高性能。您可以对基准测试程序进行任何语义保留转换,或者对流水线处理器进行增强,或者两者同时进行。当你完成实验后,你会对代码和硬件之间影响程序性能的交互有敏锐的鉴赏力。
实验室分为三个部分,每个部分都有自己的操作。在第A部分中,您将编写一些简单的Y86-64程序,并熟悉Y86-64工具。在B部分中,您将使用一条新指令扩展SEQ模拟器。这两个部分将为您准备C部分,即实验室的核心部分,在那里您将优化Y86-64基准测试程序和处理器设计。
2.组织工作
你将独自在这个实验室工作。
任何对作业的解释和修改都将公布在课程网页上。
3.材料说明
特定地点:在这里插入一段,解释学生应该如何下载archlab-handout.tar文件。
- 首先将archlab-handout.tar文件复制到您计划在其中进行工作的一个(受保护的)目录中。
- 然后输入命令:tar xvf archlab-handout.tar。这将导致以下文件被解压缩到该目录:README、Makefile、sim.tar、archlab.pdf和simguide.pdf。
- 接下来,输入命令tar xvf sim.tar。这将创建目录sim,其中包含您的Y86-64工具的个人副本。您将在这个目录中完成所有的工作。
- 最后,切换到sim目录并构建Y86-64工具:
4.A部分
在本部分中,您将在sim/misc目录下工作。
您的任务是编写并模拟下面三个Y86-64程序。这些程序所需的行为由examples.c中的示例C函数定义。确保把你的名字和ID放在每个程序开始的注释中。你可以先用YAS程序组装你的程序,然后用指令集模拟器YIS运行它们。
在所有Y86-64函数中,都应该遵循x86-64约定来传递函数参数、使用寄存器和使用堆栈。这包括保存和恢复您使用的所有调用保存寄存器。
sum.ys:迭代求和链表元素
编写Y86-64程序求和。sum.ys迭代地对链表的元素求和。您的程序应该由一些代码组成,这些代码设置堆栈结构,调用函数,然后停止。在本例中,函数应该是函数(sum_list)的Y86-64代码,该函数在功能上与图1中的C sum_list函数等效。使用下面的三个元素列表来测试你的程序
rsum.ys:递归求和链表元素
编写一个Y86-64程序rsum .ys,递归地对链表的元素求和。这段代码应该类似于sum.ys中的代码,除了它应该使用一个函数rsum_list来递归地求和一个数字列表,如图1中的C函数rsum_list所示。使用用于测试的相同的三元素列表list.ys来测试您的程序。
copy.ys:将源块复制到目标块
编写一个程序(copy.ys),将一块单词从内存的一部分复制到内存的另一部分(非重叠区域),计算所有被复制单词的校验和(Xor)。你的程序应该由建立堆栈框架,调用函数复制块,然后停止的代码组成。该函数在功能上应该与图1中所示的C函数复制块相同。使用以下三个元素的源和目标块来测试你的程序
5.B部分
在这一部分中,您将在目录sim/seq中工作。
你在B部分的任务是扩展SEQ处理器以支持iaddq,在家庭作业问题4.51和4.52中描述了这一点。要添加此说明,您需要修改文件seq-full。它实现了CS:APP3e教科书中描述的SEQ版本。此外,它还包含解决方案所需的一些常量的声明。
你的HCL文件必须以包含以下信息的头注释开头:
- 你的name和id。
- 对iaddq指令所需计算的描述。使用CS:APP3e中图4.18中对irmovq和OPq的描述作为参考。
构建和测试您的解决方案
一旦您完成了(seq-full.hcl)文件的修改,那么您将需要基于这个HCL文件构建一个SEQ模拟器(ssim)的新实例,然后测试它
- 构建一个新的模拟器。你可以使用make来构建一个新的SEQ模拟器
这将构建一个使用您在seq-full.hcl中指定的控制逻辑的ssim版本。为了节省输入,可以在Makefile中指定VERSION=full - 在一个简单的Y86-64程序上测试您的解决方案。对于您的初始测试,我们建议运行简单的程序,如asumi.yo(testing iaddq)在TTY模式下,比较结果与ISA模拟
如果ISA测试失败,那么您应该通过在GUI模式下单步执行模拟器来调试实现:
这将在基准测试程序上运行ssim,并通过将得到的处理器状态与高级ISA模拟的状态进行比较来检查其正确性。注意,这些程序都没有测试添加的指令。您只是要确保您的解决方案没有为原始指令注入错误。看到文件. ./y86-code/README文件了解更多详情。 - 执行回归测试。一旦可以正确地执行基准测试程序,就应该在…/ptest中运行一组广泛的回归测试。测试除iaddq和leave之外的所有内容:
测试您的iaddq实现:
有关SEQ模拟器的更多信息,请参阅讲义CS:APP3e Guide to Y86-64 Processor simulator (simguide.pdf)
6.C部分
在这一部分中,您将在目录sim/pipe中工作。
图2中的ncopy函数将len元素整数数组src复制到一个不重叠的dst,重新计算src中包含的正整数数。图3显示了ncopy的基线Y86-64版本。文件pipe-full.hcl包含管道的hcl代码副本,以及常量IIADDQ的声明。
在C部分中,您的任务是修改ncopy.ys和pipe-full.hcl,以创建ncopy。让我们尽可能快地运行。
你们要交两个文件:pipe-full.hcl and ncopy.ys.。每个文件应该以以下信息的头注释开始:
- 你的name和id。
- 对代码的高级描述。在每种情况下,请描述如何以及为什么修改代码。
编码规则
在以下约束条件下,您可以自由地进行任何修改:
- 你的ncopy.ys函数必须适用于任意数组大小。您可能想通过简单地编码64个复制指令来硬连接64个元素数组的解决方案,但这不是一个好主意,因为我们将根据解决方案在任意数组上的性能对其进行评级。
- 你的ncopy.ys的功能必须在YIS下正确运行。通过正确,我们的意思是它必须正确地复制src块并返回(在%rax中)正确的正整数数目。
- 您的ncopy文件的组装版本长度不能超过1000字节。您可以使用提供的脚本check-len.pl检查任何程序的长度,该脚本内嵌了ncopy函数
- 你的pipe-full.HCL实现必须通回归测试。…/y86-code和. ./ptest(不带测试iaddq的-i标志)。
除此之外,如果您认为有帮助的话,您可以自由地实现iaddq指令。你可以对ncopy进行任何保留语义的转换。功能,如重新排序指令,用单个指令替换指令组,删除某些指令,添加其他指令。你可能会发现阅读CS:APP3e第5.8节中关于循环展开的内容很有用。
构建和运行您的解决方案
为了测试你的解决方案,你需要建立一个驱动程序来调用你的ncopy函数。我们已经为您提供了gen-driver.pl程序,该程序为任意大小的输入数组生成一个驱动程序。例如,输入
将构造以下两个有用的驱动程序:
- sdriver.yo:一种小型驱动程序,它在带有4个元素的小数组上测试ncopy函数。如果您的解决方案是正确的,那么这个程序将在复制src数组后在寄存器%rax中以2的值停止。
- ldriver.yo:一个大型驱动程序,它在带有63个元素的较大数组上测试一个ncopy函数。如果您的解决方案是正确的,那么在复制src数组之后,这个程序将在寄存器%rax中的值为31 (0x1f)时停止。
每次你修改你的ncopy.ys,您可以通过键入重建驱动程序
每次您修改您的(pipe-full.hcl)文件,您可以通过键入来重建模拟器
如果要重新生成模拟器和驱动程序,输入
要在GUI模式下在一个小的4元素数组上测试解决方案,输入以下命令
要在一个更大的63个元素的数组上测试解决方案,输入以下命令
一旦您的模拟器在这两个块长度上正确运行您的版本ncopy.ys,您将希望执行以下额外测试:
- 在ISA模拟器上测试驱动程序文件。确保你的ncopy.ys的功能与YIS配合工作
- 使用ISA模拟器在块长度范围内测试代码。Perl脚本correctness.pl生成的驱动程序文件块长度从0到某个限制(默认值为65),再加上一些更大的块长度。它模拟它们(默认情况下使用YIS),并检查结果。它生成一个报告,显示每个块长度的状态:
该脚本生成测试程序,其中的结果计数在每次运行中随机变化,因此它提供了比标准驱动程序更严格的测试。
如果你对某个长度K得到不正确的结果,你可以为该长度生成一个包含检查代码的驱动文件,并且结果随机变化:
程序将以寄存器%rax的值结束:
0xaaaa:所有测试通过
0xbbbb:不正确的数
0xcccc:函数ncopy的长度超过1000字节
0xdddd:一些源数据没有复制到目标
0xeeee:在目标区域之前或之后的某个单词被破坏了 - 在基准程序上测试管道模拟器。一旦你的模拟器能够正确地执行sdriver.ys和ldriver.ys,你应该在…/y86-code中测试Y86-64基准程序:
这将在基准测试程序上运行psim,并将结果与YIS进行比较。 - 使用大量回归测试测试管道模拟器。一旦可以正确地执行基准测试程序,就应该使用…/ptest中的回归测试来检查它。例如,如果您的解决方案实现了iaddq指令,那么
- 使用流水线模拟器在一定范围的块长度上测试代码。最后,您可以在管道模拟器上运行与前面使用ISA模拟器所做的相同的代码测试
7.评价
实验值190分,其中A部分30分,B部分60分,C部分100分。
A部分
A部分值30分,每个Y86-64解决方案10分。将评估每个解决方案程序的正确性,包括堆栈和寄存器的正确处理,以及与examples.c中的示例C函数的功能等效性。
项目sum.ys和rsum.ys如果评分者没有发现ys中的任何错误,那么ys将被认为是正确的,它们各自的sum_list和rsum_list函数返回寄存器%rax中的总和0xcba。
B部分
这部分的实验值35分:
- 你对iaddq指令所需计算的描述得10分。
- 通过y86-code中的基准回归测试得10分,以验证您的模拟器仍然正确地执行基准测试套件。
- 通过iaddq的回归测试得到15分。
C部分
这部分实验值100分:如果您的ncopy.ys代码或修改后的模拟器未通过前面描述的任何测试,您将无法获得任何学分。
- ncopy.ys和pipe-full.hcll标题中的描述以及这些实现的质量各20分。
- 表现得60分。如前所述,要在此获得积分,您的解决方案必须是正确的。也就是说,ncopy可以在YIS中正常运行,pipe-full.hcl通过y86-code和ptest中的所有测试。
我们将以每个元素(CPE)的循环单位来表示函数的性能。也就是说,如果模拟代码需要C循环来复制包含N个元素的块,则CPE为C/N。PIPE模拟器显示完成程序所需的总周期数。对于CPE为897/63 = 14.24的情况,在标准PIPE模拟器上运行的ncopy函数的基线版本需要897个周期来复制63个元素。
由于一些周期用于设置对ncopy的调用以及在ncopy内设置循环,您将发现对于不同的块长度,您将获得不同的CPE值(通常CPE会随着N的增加而下降)。因此,我们将通过计算从1到64个元素的块的平均cpe来评估函数的性能。您可以在管道目录中使用Perl脚本benchmark.pl来运行您的ncopy.ys编码在一个块长度范围内,并计算平均CPE。只需运行命令
看看会发生什么。例如,ncopy函数的基线版本的CPE值在29.00到14.27之间,平均为15.18。注意,这个Perl脚本不检查答案的正确性。为此,请使用脚本benchmark.pl。
你应该能够达到低于9.00的平均CPE。我们最好的版本平均7.48。如果你的平均CPE为c,那么你在这部分实验中的分数为S:
默认情况下,benchmark.pl和correctness.pl编译和测试ncopy.ys。使用-f参数指定一个不同的文件名。h标志提供命令行参数的完整列表。
8.Handin指令
特定地点:插入一段描述,解释学生应该如何上交实验的三个部分。下面是我们在CMU使用的描述。
- 你将提交三组文件:
- A部分:sum.ys,rsum.ys,和 copy.ys.
- B部分:seq-full.hcl.
- C部分:ncopy.ys 和 pipe-full.hcl. - 确保你已经把你的name和ID包含在你的每个手写文件顶部的注释中。
- 要提交第X部分的文件,请进入archlab-handout目录并输入:
其中X是a、b或c, teamname是您的ID。例如,递交A部分:
- 提交后,如果你发现一个错误,并想提交一份修改后的副本,键入
每次提交都要增加版本号。 - 你可以往里看,以证实你的提交
您在此目录中有列表和插入权限,但没有读或写权限。
9.提示
- 根据设计,sdriver.yo和ldriver.yo都足够小,可以在GUI模式下进行调试。我们发现在GUI模式下调试最简单,建议您使用它。
- 如果您在Unix服务器上以GUI模式运行,请确保已经初始化了DISPLAY环境变量
- 对于一些X服务器,当你在GUI模式下运行psim或ssim时,“程序代码”窗口开始作为一个关闭的图标。只需单击图标展开窗口。
- 对于一些基于Microsoft windows的X服务器,“内存内容”窗口不会自动调整自己的大小。你需要手动调整窗口的大小。
- 如果您要求psim和ssim模拟器执行一个不是有效的Y86-64目标文件的文件,它们将以分割错误终止。
simguide.pdf
1.安装
模拟器的代码以名为sim.tar的tar格式文件分发。您可以从CS:APP3e网站(csapp.cs.cmu.edu)获得该文件的副本。
使用要安装代码的目录中的tar文件,您应该能够执行以下操作
默认情况下,这会生成模拟器的GUI(图形用户界面)版本,这要求您在系统上安装DISPLAY。如果不是,那么您可以选择安装在stdout上以ASCII文本形式输出的仅限tty的版本。有关如何生成GUI和TTY版本的描述,请参阅README文件。
目录sim包含以下子目录
- misc YAS (Y86-64汇编程序)、YIS (Y86-64指令集模拟器)和HCL2C (HCL到C转换程序)等实用程序的源代码文件。它还包含所有处理器模拟器使用的isa.c源文件。
- seq SEQ和SEQ+模拟器的源代码。包含作业问题4.52的HCL文件。有关编译模拟器的不同版本的说明,请参阅README文件。
- pipe PIPE模拟器的源代码。包含作业问题4.54-4.58的HCL文件。有关编译模拟器的不同版本的说明,请参阅README文件。
- y86-code Y86-64汇编代码的许多示例程序在本章中显示。您可以在这些基准程序上自动测试修改后的模拟器。有关如何运行这些测试的说明,请参阅文件README。作为一个运行的例子,我们将使用程序asum.ys在这个子目录中。该程序如图CS:APP3e图4.7所示。该程序的编译版本如图1所示。
- ptest 生成不同指令、不同跳跃可能性和不同危险可能性的系统回归测试的脚本。这些脚本非常擅长在你的家庭作业解决方案中寻找漏洞。有关如何运行这些测试的说明,请参阅文件README。
2.实用程序
安装完成后,misc目录包含两个有用的程序
YAS Y86-64汇编程序。这将获取扩展名为.ys的Y86-64汇编代码文件,并生成扩展名为.yo的文件。生成的文件包含目标代码的ASCII版本,如图1所示(与CS:APP3e图4.8所示的程序格式略有不同)。调用汇编程序的最简单方法是在y86代码子目录中使用或创建汇编代码文件。例如,要在此目录中的文件asum.ys中汇编程序,我们使用以下命令
YIS Y86-64指令模拟器。该程序根据指令集定义执行Y86-64机器级程序中的指令。例如,假设您要运行程序asum.yo来自y86-code子目录。简单地运行:
YIS模拟程序的执行,然后将更改打印到终端上的任何寄存器或内存位置,如CS:APP3e 4.1节所述。
3.处理器模拟器
对于SEQ、SEQ+和PIPE这三种处理器,我们分别提供了仿真器SSIM、SSIM+和PSIM。每个模拟器都可以在TTY或GUI模式下运行:
YAS mode 使用一个极简的、面向终端的界面。在终端输出上打印所有内容。不是很方便调试,但可以安装在任何系统上,并可用于自动化测试。所有模拟器的默认模式。
GUI mode 有一个图形用户界面,稍后描述。非常有助于可视化处理器活动和调试修改后的设计版本。需要在您的系统上安装Tcl/Tk。使用-g命令行选项调用。在GUI模式下运行只能从可执行模拟器程序所在的目录(pipe或seq)中进行。
3.1 模拟器命令行选项
对于这三个模拟器,您可以从命令行指定几个选项
-h 打印所有命令行选项的摘要。
-g 在GUI模式下运行模拟器(默认为TTY模式)。
-t (仅TTY模式)运行处理器和ISA模拟器,比较内存、寄存器文件和条件代码的结果值。如果没有发现差异,它将打印消息“ISA检查成功”。否则,它打印关于寄存器文件或内存中不同的单词的信息。这个特性对于测试处理器设计非常有用。
-l m (仅TTY模式)设置指令限制,在停止之前最多执行m条指令(默认限制为10000条指令)。
-v n (仅TTY模式)设置冗长级别为n,它必须在0到2之间,默认值为2。
在GUI模式下运行的模拟器必须使用命令行上的目标文件的名称来调用。在TTY模式下,对象文件名是可选的,默认来自stdin。
下面是一些在seq子目录中对模拟器的典型调用:
第一种情况打印SSIM的命令行选项摘要。第二种情况以TTY模式运行SSIM+,读取目标文件asum.yo从stdin。结果寄存器和内存值比较那些从高水平ISA模拟器。第三种情况以GUI模式运行SSIM,在目标代码文件1.yo中执行指令来自y86-code子目录。对于PIPE模拟器PSIM,同样的调用可以从管道子目录中执行。
3.2 GUI版本的SEQ模拟器
GUI版本的SEQ处理器模拟器是通过命令行上的目标代码文件名从SEQ子目录中调用的:
在命令行末尾的“&”允许模拟器在后台模式下运行。模拟程序启动并创建三个窗口,如图2-4所示。
第一个窗口(图2)是主控制面板。如果HCL2C使用-n name选项编译HCL文件,那么主控制窗口的标题将显示为“Y86-64 Processor: name”,否则它将显示为简单的“Y86-64 Processor”。
主控制窗口包含控制模拟器的按钮以及关于处理器状态的状态信息。窗口的不同部分在图中标记
Control:沿着顶部的按钮控制模拟器。单击Quit按钮会导致模拟器退出。单击Go按钮将使模拟器开始运行。单击Stop按钮会导致模拟器暂时停止。单击Step按钮会使模拟器执行一条指令,然后停止。单击Reset按钮将使模拟器返回到初始状态。地址为0的程序计数器,寄存器设为零,除程序外的内存被擦除,条件码设为ZF = 1, CF = 0, OF = 0,程序状态设为AOK。按钮下方的滑块控制模拟器运行时的速度。将它移到右边可以使模拟器运行得更快
Stage values:这部分显示器显示当前rent指令评估期间不同处理器信号的值。这些信号几乎与CS:APP3e图4.23所示的信号相同。主要的区别是,模拟器在一个标记为Instr的字段中显示指令的名称,而不是icode和ifun的数值。类似地,所有寄存器标识符都使用它们的名称而不是它们的数字值显示,“----”表示不需要进行寄存器访问。
Register file:这个部分显示15个程序寄存器的值。最近更新的寄存器用浅蓝色突出显示。寄存器内容在第一次将其设置为非零值之后才会显示。
记住,当指令写入程序寄存器时,寄存器文件直到下一个时钟周期开始时才更新。这意味着您必须再次步进模拟器以查看更新的发生情况。
Stat:这显示了当前正在执行的指令的状态。可能的值是:
- AOK:没有遇到的问题。
- ADR:试图读取指令或试图读取或写入数据时发生了寻址错误。地址不能超过0x0FFF。
- INS:遇到一条犯法指令。
- HLT:遇到了一个暂停指令。
Condition codes:这些代码显示了三个条件代码的值:ZF、SF和of。
记住,当指令更改条件代码时,条件代码寄存器直到下一个时钟周期开始时才更新。这意味着您必须再次步进模拟器以查看更新的发生情况。
图2所示的处理器状态是asum.yo的第29行第一次执行时的状态。程序如图1所示。我们可以看到程序计数器位于0x085处,它已经处理了addq %r8,%rdi指令,寄存器%rax保存着0xd000d000d,这是第一个数组元素的和,%rsi保存着4,这是将要减少的计数。寄存器%rdi保存着0x020,第二个数组元素的地址。对寄存器%rsi有一个0x03的未决写操作(因为dstE被设置为%rsi, valE被设置为0x03)。这个写操作将在下一个时钟周期开始时进行。
图3中描述的窗口显示了模拟器正在执行的目标代码文件。编辑框标识正在执行的程序的文件名。您可以在此窗口中编辑文件名,并单击Load按钮来加载一个新程序。显示器的左侧显示正在执行的目标代码,而右侧显示来自程序集代码文件的文本。中心有一个星号(*)表示当前正在模拟哪个指令。这相当于求和的第29行asum.yo程序如图1所示。
图4所示的窗口显示了内存的内容。它只显示自程序开始执行以来在最小地址和最大地址之间发生变化的那些位置。每行显示两个记忆单词的内容。因此,每一行显示内存的16个字节,其中字节的地址仅在它们的最低有效十六进制数字上有所不同。内存值的左边是“root”地址,其中最低有效数字显示为“-”。然后每一列对应于具有最低有效地址数字0x0和0x8的单词。图4中所示的示例具有指示内存位置0x01f0和0x01f8的箭头。
图中所示的内存内容显示了求和的堆栈内容。在执行sum过程期间,如图1所示的asum.
yo程序。查看到目前为止发生的堆栈操作,我们看到%rsp被初始化为0x200(第3行)。第4行对main的调用推动返回指针0x013,该指针被写入地址0x01f8。过程主程序调用sum(第16行),导致返回指针0x055被写入地址0x01f0。这就解释了在这个内存显示中显示的所有单词,以及被设置为0x01f0的堆栈指针。
3.3 PIPE模拟器
PIPE模拟器还生成三个窗口。图5显示了控制面板。它具有相同的控件集,以及寄存器文件、状态和条件代码的相同显示。中间部分显示了管道寄存器的状态。不同的字段对应于CS:APP3e图4.52。在这个面板的底部是一个显示器,显示已经模拟的循环数量(不包括使管道流动所需的初始循环)、已完成的指令数量和结果CPI。
如图6的特写视图所示,每个管道寄存器显示为两部分。白盒中的上值显示管道寄存器中的当前值。带有灰色背景的较低值表示管道寄存器的输入。这些将在下一个时钟周期加载到寄存器中,除非寄存器起泡或停止。
通过PIPE模拟器的值流与SEQ模拟器的值流非常不同。使用SEQ,控制面板显示执行单个指令产生的值。模拟器的每一步都执行一个完整的指令执行。使用PIPE,控制面板显示通过管道的多个指令的值。模拟器的每一步只对每条指令执行一个阶段的计算。
图7显示了PIPE模拟器的代码显示。它的格式与SEQ类似,不同之处在于,display使用字符F、D、E、M和W,而不是单个标记来指示哪条指令正在执行,用于获取、解码、执行、内存和回写阶段。
PIPE模拟器还生成一个窗口来显示内存内容。这与SEQ显示的格式相同(图4)。
图5和图7中的示例显示了在执行图1中的第26-30行循环时管道的状态。我们可以看到,模拟器已经开始了循环的第一次迭代,通过跳转到测试部分(第30行)进入了循环。各阶段的状态如下:
Write back:初始测试的jne指令(第30行)即将结束。
Memory:mrmovq指令(第26行)刚刚从地址0x018读取了0x0D000D000D。我们可以看到管道寄存器M的valE中的地址,以及在valM输入到管道寄存器W时从内存中读取的值。
Execute:这个阶段包含一个气泡。由于mrmovq指令(第26行)和addq指令(第27行)之间的负载-使用依赖关系,该气泡被插入。可以看到,这个气泡的作用就像一个nop指令。这就解释了为什么图7中没有标记为“e”的指令。
Decode:addq指令(第27行)刚刚从寄存器%rax读取了0x0。也读0x00d % r10寄存器,但我们可以看到转发的逻辑而不是使用价值0 x0d000d000d刚刚被从内存中读取(流水线寄存器视为valM输入W)的新值valA(流水线寄存器视为valA输入E)。
Fetch:刚刚从地址0x083获取了一条addq指令(第28行)。预测PC的新值为0x085。
与每个阶段相关联的是它的状态字段Stat。该字段显示了流水线中该阶段指令的状态。状态AOK意味着没有遇到异常。状态值BUB表示这个阶段有气泡,而不是正常的指令。其他可能的状态值:ADR引用一个无效的内存位置时,INS遇到非法指令码时,PIP当问题出现在管道(这发生在失速和泡沫的信号对于一些流水线寄存器设置为1),和停止当遇到停止指令。当最后四种情况中的任何一种达到回写阶段时,模拟器将停止。
4.一些建议
- 熟悉模拟器操作。尝试运行y86-code目录中的一些示例程序。在一些小例子中,确保你理解了如何处理每条指令。注意一些有趣的情况,例如预测错误的分支、负载联锁和过程返回。
- 你需要四处搜寻信息。看到数据转发的效果尤其棘手。在管道寄存器E中,信号valA有七个可能的源,信号valB有六个可能的源。要查看选择了哪一个,您需要将这些管道注册字段的输入与可能的源的值进行比较。可能的来源是:
- R[d_srcA] 源寄存器是通过管道寄存器e中srcA的输入来标识的。寄存器的内容显示在底部。
- R[d_srcB] 源寄存器是通过管道寄存器e中srcB的输入来标识的。寄存器的内容显示在底部。
- D_valP 这个值是管道寄存器D状态的一部分。
- e_valE 这个值在管道寄存器M中field valE的输入处。
- M_valE 这个值是管道寄存器M状态的一部分。
- m_valM 这个值位于管道寄存器W中的字段valM的输入处。
- W_valE 这个值是管道寄存器W状态的一部分。
- W_valM 这个值是管道寄存器M状态的一部分。 - 不要覆盖您的代码。由于数据和代码共享相同的地址空间,很容易让程序覆盖某些代码,从而在试图执行覆盖的指令时造成完全混乱。为了避免这种情况,将堆栈设置得离代码足够远是很重要的。
- 避免大地址值。模拟器不允许任何大于0x0FFF的地址。此外,如果您修改跨越广泛地址范围的内存位置,内存显示将变得笨拙。
- 注意gui模式模拟器(SSIM、SSIM+和PSIM)的一些“特性”。
- 您必须从它们的主目录执行程序。换句话说,要运行SSIM或SSIM+,您必须在seq目录中,而要运行PSIM,您必须在管道子目录中。这种需求是由于Tcl解释器定位模拟器配置文件的方式而产生的。
- 如果你在Unix机器上以GUI模式运行,记得初始化DISPLAY环境变量:
- 在一些Unix X窗口管理器中,“程序代码”窗口开始时是一个关闭的图标。如果你在模拟器启动时没有看到这个窗口,你需要通过点击它来手动展开。
- 对于某些Microsoft Windows X服务器,当内存内容改变时,“内存内容”窗口不会自动调整其自身大小。在这些情况下,您需要手动调整窗口的大小以查看内存内容。
- 如果您要求模拟器执行一个不是有效的Y86-64目标文件的文件,模拟器将以分割错误终止。
sim/README
此目录包含Y86-64工具的学生分发版。它是主发行版的适当子集,减去主发行版中的解决方案文件。
yas:Y86-64 汇编程序
yis:Y86-64 指令(ISA)模拟器
hcl2c:HCL到C的转换
hcl2v:HCL到Verilog转换
ssim:SEQ 模拟器
ssim+:SEQ+ 模拟器
psim:PIPE simulator
1.构建Y86-64工具
Y86-64模拟器可以配置为支持TTY和GUI界面。在TTY模式下运行的模拟器在终端上打印关于其运行时行为的所有信息。它很难理解发生了什么,但是对于自动化测试很有用,而且不需要任何特殊的安装特性。在GUI模式下运行的模拟器使用一个奇特的图形用户界面。很适合于可视化和调试,但需要在系统上安装Tcl/Tk。
要构建Y86-64工具,请执行以下步骤:
注意:如果你的导师为你准备了这个发行版,那么你可以跳过步骤1,直接进入步骤2。Makefile已经为您的系统提供了合适的gumode、TKLIBS和TKINC值。
步骤1:决定要使用TTY形式还是GUI形式的模拟器,然后相应地修改此目录中的./Makefile。(您对这个Makefile中的变量所做的更改将覆盖seq和管道目录中的Makefile中已经分配的值。)
构建GUI模拟器:如果您的系统上安装了Tcl/Tk,那么您可以通过初始化GUIMODE、TKLIBS和TKINC变量来构建GUI表单,以适合您的系统。(默认值适用于Linux系统。)
分配GUIMODE=-DHAS_GUI会导致模拟器源中包含必要的GUI支持代码。TKLIBS变量告诉gcc在哪里查找libtcl.so和libtk.so库。TKINC变量告诉gcc在哪里可以找到tcl.h和tk.h头文件。
构建TTY模拟器:如果您的系统上没有安装Tcl/Tk,那么通过注释掉Makefile中的这三个变量(GUIMODE、TKLIBS和TKINC)来构建TTY表单。
步骤2:修改Makefile以构建GUI或TTY表单之后,就可以通过键入来构造整个Y86-64工具集
2.文件
Makefile: 构建Y86-64工具
README: 这个文件
misc/: Y86-64汇编程序yas的源文件,Y86-64指令模拟器yis的源文件,以及处理器模拟器的-t选项用来检查ISA仿真结果的ISA .c文件。还包含程序hcl2c和hcl2v的文件
seq/: SEQ和SEQ+模拟器的代码。包含HCL文件,用于涉及修改SEQ的实验室和家庭作业问题。
pipe/: PIPE模拟器的代码。包含HCL文件,用于涉及修改PIPE的实验和家庭作业问题。
y86-code/: 来自CS:APP的Example.ys文件和用于对新处理器设计进行自动基准测试的脚本。
ptest/: 用于测试处理器设计的自动化回归测试脚本。
verilog/: 从HCL代码生成Verilog设计的系统
sim/misc/README
此目录包含以下内容的所有源文件
YAS Y86-64 汇编程序
YIS Y86-64 指令级仿真器
HCL2C HCL到C转换器
HCL2V HCL到Verilog转换器
1.构建工具
unix> make clean
unix> make
2.文件
Makefile Builds yas, yis, hcl2c, hcl2v
README 这个文件
学生发行版中的Makefile版本
(仅教师分配)
Makefile-sim
CS:APP架构实验室的A部分示例程序
examples.c C版本的三个Y86-64函数
ans-copy.ys 解决方案copy函数(仅限教员分发版)
ans-sum.ys 解决方案sum函数(仅限教员分发版)
ans-rsum.ys 解决方案rsum函数(仅限教员分发版)
指令模拟器代码由yas, yis, ssim, ssim+和psim共享
isa.c
isa.h
用于构建yas汇编器的文件
yas YAS的二进制
yas.c 源文件和头文件
yas.h
yas-grammar.lex Y86-64 词法扫描器规范
yas-grammar.c 从yas-grammar.lex生成的词法扫描器
用于构建yis指令模拟器的文件
yis YIS的二进制
yis.c yis源文件
用于构建hcl2c转换器的文件
hcl2c HCL2C的二进制
node.c 辅助例程和头文件
node.h
hcl.lex HCL 词法扫描器规范
lex.yy.c HCL 从hcl.lex生成的词法扫描器
hcl.y HCL 语法
hcl.tab.c HCL 从hcl.y生成的解析器
hcl.tab.h 令牌的定义
在编写CS:APP书时使用的HCL程序示例
(仅教师分配)
frag.{hcl,c}
mux4.{hcl,c}
reg-file.{hcl,c}
sim/seq/README
这个目录包含为SEQ、SEQ+以及作业练习中描述的SEQ+的变体构造模拟器的代码。
1. 构建模拟器
在处理不同的作业问题时,可以构造不同版本的SEQ和SEQ+模拟器来使用不同的HCL文件。
二进制 | 版本 | HCL文件 | 描述 |
---|---|---|---|
ssim | std | seq-std.hcl | 标准SEQ模拟器在教科书中描述。 |
ssim | full | seq-full.hcl | 将iaddq添加到SEQ。 |
ssim+ | std | seq±std.hcl | 标准SEQ+模拟器在教科书中描述。 |
模拟器以TTY或GUI模式运行:
- TTY mode:在TTY模式下运行的模拟器在终端上打印关于其运行时行为的所有信息。很难理解发生了什么,但是对于自动化测试很有用,而且不需要任何特殊的安装特性。
- GUI mode:在GUI模式下运行的模拟器使用一个奇特的图形用户界面。很适合于可视化和调试,但需要在系统上安装Tcl/Tk。
Makefile有构建TTY或GUI模拟器的简单指令。TTY模拟器只在TTY模式下运行。根据命令行参数,GUI模拟器可以在TTY模式或GUI模式下运行。
一旦配置好Makefile,就可以使用表单的命令构建不同的模拟器
2.使用模拟器
模拟器采用相同的命令行参数
使用: ssim [-htg] [-l m] [-v n] file.yo
file.yo在GUI模式下是必需的,在TTY模式下是可选的(默认stdin)
-h 打印此消息
-g 以GUI模式而不是TTY模式运行(默认TTY模式)
-l m 将指令限制设置为m[仅TTY模式](默认10000)
-v n 设置冗长级别为0 <= n <= 2[仅TTY模式](默认2)
-t 对ISA模拟器的测试结果(yis)[仅TTY模型]
3.文件
Makefile 构建SEQ和SEQ+模拟器
Makefile-sim 生成学生分配文件
README 这个文件
seq+.tcl TCL脚本的GUI版本的SEQ+
seq.tcl TCL脚本的GUI版本的SEQ
ssim.c 基本顺序模拟器代码和头文件
sim.h
seq-std.hcl 标准SEQ控制逻辑
seq±std.hcl 标准SEQ+控制逻辑
seq-full.hcl iaddq问题的模板(4.34-35)
seq-full-ans.hcl iaddq问题的解(4.34-35)(仅限讲师分配)
sim/pipe/README
这个目录包含为PIPE构建模拟器的代码,以及作业练习中描述的PIPE的变体。
1.构建模拟器
在处理不同的作业问题时,可以构造不同版本的PIPE模拟器来使用不同的HCL文件。
二进制 | 版本 | HCL 文件 | 描述 |
---|---|---|---|
psim | std(标准) | pipe-std.hcl | 标准模拟器(默认) |
psim | broken(破碎) | pipe-broken.hcl | 不处理任何危险 |
psim | full(完整) | pipe-full.hcl | 添加iaddq |
psim | nobypass | pipe-nobypass.hcl | 实现PIPE- (称为pipe-stall.hcl的文本) |
psim | lf | pipe-lf.hcl | 实现负载转发 |
psim | nt | pipe-nt.hcl | 用于实现NT分支预测 |
psim | btfnt | pipe-btfnt.hcl | 用于实现BTFNT分支pred |
psim | 1w | pipe-1w.hcl | 用于实现单个写端口 |
psim | super | pipe-super.hcl | 实现iaddq和负载转发 |
可以配置Makefile来构建支持GUI和/或TTY接口的模拟器。在TTY模式下运行的模拟器在终端上打印关于其运行时行为的所有信息。很难理解发生了什么,但是对于自动化测试很有用,而且不需要任何特殊的安装特性。在GUI模式下运行的模拟器使用一个奇特的图形用户界面。很适合于可视化和调试,但需要在系统上安装Tcl/Tk。
Makefile有构建TTY和GUI表单的简单指令。在这两种情况下,一旦配置了Makefile,就可以使用不同的HCL文件和表单命令构建不同版本的模拟器
2.使用模拟器
模拟器识别以下命令行参数
Usage: psim [-htg] [-l m] [-v n] file.yo
file.yo在GUI模式下是必需的,在TTY模式下是可选的(默认stdin)
-h 打印此消息
-g 以GUI模式而不是TTY模式运行(默认TTY模式)
-l m 将指令限制设置为m[仅TTY模式](默认10000)
-v n 设置冗长级别为0 <= n <= 2[仅TTY模式](默认2)
-t 对ISA模拟器的测试结果(yis)[仅TTY模型]
3.文件
Makefile: 构建模拟器
Makefile-sim: 生成学生分配文件
README: 这个文件
CS:APP架构实验室相关文件
示例程序
ncopy.ys:学生优化的ncopy的默认版本
ncopy.c:定义其语义的ncopy的C版本
预先构建的驱动程序(by gen-driver.pl)
sdriver.ys:驱动程序调用ncopy.ys在一个短(4个字)数组上
ldriver.ys:驱动程序调用ncopy.ys在较长的(63个字)数组上
这两个驱动程序都是由Makefile通过键入“make drivers”自动生成的。
解决方案文件(仅限教师)
gen-ncopy.pl:生成具有各种优化的基准程序版本。参见文件中的注释进行解释。
测试脚本
gen-driver.pl:为任意ncopy实现(默认ncopy.ys)生成一个驱动程序。输入“make drivers”来构造sdriver.y和ldriver.ys。
benchmark.pl:在大小为1到64的数组上运行ncopy的实现(默认的ncopy.ys),并以CPE(每个元素的循环)为单位计算其性能。
correctness.pl:对大小为0到64的数组和几个较长的数组运行ncopy实现,并检查每个的正确性。
check-len.pl:确定ncopy函数的.yo表示的字节数。
不同版本的模拟器的HCL文件
pipe-std.hcl:文本中描述的标准PIPE处理器
pipe-broken.hcl:不检测或处理危险的模拟器(在讲课中解释危险时很有用)
各种CS:APP作业问题的HCL文件
pipe-nobypass.hcl 4.51:构建PIPE的版本而不需要绕过(称为pipe-stall.hcl文本)
pipe-full.hcl 4.52-53: 添加iaddq指令到PIPE
pipe-nt.hcl 4.54: 实施支部不采取的策略
pipe-btfnt.hcl 4.55: 实施收回前不收回的策略
pipe-lf.hcl 4.56: 实现负载转发逻辑
pipe-1w.hcl 4.57:实现单端口注册文件
CS:APP作业问题的HCL解决方案文件(仅限教师)
pipe-nobypass-ans.hcl 4.51 解决方案
pipe-full-ans.hcl 4.52-53 解决方案
pipe-nt-ans.hcl 4.54 解决方案
pipe-btfnt-ans.hcl 4.55 解决方案
pipe-lf-ans.hcl 4.56 解决方案
pipe-1w-ans.hcl 4.57 解决方案
pipe-super.hcl 为实验室提供最佳的性能
PIPE模拟器源文件
psim.c Base 模拟器代码
sim.h PIPE 头文件
pipeline.h
stages.h
pipe.tcl TCL PIPE的GUI版本脚本
sim/y86-code/README
这个目录包含在CS:APP3e的第4章中使用的Y86-64汇编代码程序(扩展名’ .ys’)的示例。
给定一个汇编代码文件“file.ys”,您可以使用命令“make file.yo”对其进行汇编。生成的文件采用本书中描述的“目标代码”格式。
您可以在这个目录中组装和模拟所有的测试程序。首先,您需要在pipe(psim)和seq (ssim和ssim+)目录中创建不同的模拟器。然后使用以下命令:
PIPE: make testpsim
SEQ: make testssim
SEQ+: make testssim+
这些命令中的每一个都将导致许多程序被组装和模拟。会有很多东西滚动,但是您应该会看到每个被测试程序的“ISA Check succeeded”消息。
sim/ptest/README
此目录包含Perl脚本,这些脚本提供不同Y86-64模拟器的全面回归测试。有四种基本的测试类型,作为四种不同的脚本实现
optest.pl: 测试每个单独的指令类型
jtest.pl: 在不同条件下测试所有跳转类型
ctest.pl: 测试不同的管道控制组合
htest.pl: 测试许多不同的危险可能性
这需要运行864个以上的测试,因此需要一些时间。
每个测试都有以下可选参数:
-s simfile 使用simfile作为模拟器(默认的…/pipe/psim)。
-i 测试iaddq指令
您可以使用make来运行所有四个测试程序。选项包括:
SIM=simfile
TFLAGS=<any flags you want to give to the testing scripts>
例如,你可以说:
make SIM=…/pipe/psim TFLAGS=-i
测试包含iaddq指令的流水线模拟器。(注意,对于pipe的默认实现,这个测试将失败,因为它没有实现iaddq指令。)
当测试程序检测到一个错误的模拟时,它会将.ys文件留在目录中(通常它会删除它生成的测试代码)。然后您可以在其中一个失败案例上运行一个模拟器(GUI版本在这里特别有用)。假设失败的测试在文件bad-test.ys中。然后你可以执行“make bad-test.yo”来创建目标代码,并使用其中一个模拟器对其进行模拟。
请注意,标准测试代码只检测功能性bug,其中处理器模拟产生的结果与ISA级别模拟所预测的结果不同。