-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
116 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
--- | ||
comments: true | ||
authors: | ||
- stormckey | ||
categories: | ||
- Lab | ||
- 计算机体系结构 | ||
date: 2023-12-17 | ||
nostatistics: true | ||
--- | ||
|
||
# 计算机体系结构 - lab5 Scoreboard | ||
|
||
!!! abstract | ||
介绍一下实验中 Scoreboard 设计的思想,包括一些运行的原则和对各种hazard的处理。在一些具体的细节上均按照实验给予的框架进行解释。包括功能单元的安排和表的设计等,详情请看 [实验指导:octicons-link-16:](https://zju-arch.pages.zjusct.io/arch-fa23/lab5/)。 | ||
|
||
<!-- more --> | ||
|
||
## 基本原则 | ||
|
||
在Scoreboard算法中,我们主要维护的是两张表,FUS (1) 和 RRS(2)。我们用 issue(3)一词来指代我们将取到的指令放入FUS 和 RRS的过程 | ||
{ .annotate } | ||
|
||
1. Functional Unit Status,记录了正在每个功能单元上运行或等待运行的指令的状态 | ||
2. Register Result Status,记录了每个寄存器正在被FUS中哪个单元作为目的寄存器,或者不被任何单元作为目的寄存器 | ||
3. 发射 | ||
|
||
以下是一些算法执行的基本原则: | ||
|
||
<div class="annotate" markdown> | ||
- 我们不会将错误取址(1)的指令发射 | ||
- 从指令被发射的那一个周期到执行结束的那一个周期,指令都会存在于上述两张表中 | ||
- 在本lab的设计实现中,当前IS指令被阻塞会导致后续指令也被阻塞,直至当前IS指令被成功发射或者被flush | ||
- 在IF阶段我们取得一条指令,该指令下一周期会进入IS阶段被决定发射或是阻塞 | ||
</div> | ||
|
||
1. 错误取址就是指跳转的过程中取得的其实不应被执行的指令 | ||
|
||
## 发射原则(IS) | ||
|
||
我们通过以下两条规则来在一般情况下决定一条指令是否可以被发射: | ||
|
||
- 如果当前IS指令的目的寄存器同时也是表中某条指令的目的寄存器,那么阻塞该指令的发射直到不再存在冲突 | ||
- 如果当前IS指令需要使用的运行单元已经被表中的指令占据,那么阻塞该指令直到不在存在该冲突 | ||
|
||
以上两个要求可以通过检测 | ||
|
||
- RRS中目的寄存器是否为空 | ||
- FUS中运行单元是否busy | ||
|
||
来决定。 | ||
|
||
可以看出上述两条原则是无论如何要被满足的,否则的话 | ||
|
||
- RRS对应状态会被新发射的指令覆盖 | ||
- FUS中的指令会被新发射的指令覆盖 | ||
|
||
以上就是关于发射的一般原则,但是为了满足只有正确取址的指令才会被发射的原则,我们需要一些额外的检测,这些检测主要跟跳转指令有关,一般来说: | ||
|
||
- 如果当前FUS中没有跳转指令 | ||
- 无阻塞 | ||
- 如果当前FUS中有跳转指令 | ||
- 如果该跳转指令还未done | ||
- 目前IS和IF阶段指令正确性未知,阻塞其发射 | ||
- 如果跳转指令done并且 | ||
- 不需要跳转 | ||
- 当前IS和IF中顺序取址的是对的指令,不再阻塞 | ||
- 需要跳转 | ||
- 当前IS和IF中顺序取址的是错的,刷新错误IF和IS,下一周期IF中会取上正确的指令 | ||
|
||
如果一条指令通过了跳转的发射检测和一般的发射检测,那么就可以发射了。并且我们应当注意到一般原则的第一条就阻止了WAW hazard的发生 | ||
|
||
## 执行原则(EX) | ||
|
||
所有刚进入FUS的指令都要等待源寄存器均就位(1),而后可以发送信号和数据给功能单元开始执行。 | ||
{ .annotate } | ||
|
||
1. 这里的就位就是FUS中的Ready位均置1 | ||
|
||
具体而言,FUS的Ready位的设置遵循以下原则: | ||
|
||
<div class="annotate" markdown> | ||
- 指令被发射进入FUS时,表内已有的指令都必然是先于该指令的(1),如果这些先前的指令需要写新指令的源寄存器,那么我们就应该等,初始Ready置0 | ||
- 一条指令完写后,要回来把表中所有在他的目的寄存器上等待的指令的对应Ready位置1,以通知这些指令新数据已就位(2) | ||
- 若无先前指令要写,初始Ready置1 | ||
</div> | ||
|
||
1. 发射上先于一定意味着指令顺序上先于,因为在本实验中只有一个发射口,前面的指令发射完了才能轮到后面的 | ||
2. 由于发射的第一条一般原则,对某一目标寄存器写的指令同时在表中只会有一条 | ||
|
||
一条指令把数据和使能信号给功能单元后,执行开始,就只需要等数据而不在要读寄存器了,此时我们需要把Ready全置0并且清零Q位来表明这一点。另外等待数据就位的过程也是在解决RAW hazard | ||
|
||
!!! tip | ||
由于一条指令写完后,回头进行通知可能同时令多条指令就位。我们要多个周期把这些指令的Ready位请0表示读操作数结束并且开始执行。为了做到这一点,我们需要加上else保证一周期只有一条指令开始执行,并且保证未被执行的指令保持当前状态到下一周期 | ||
|
||
## 写回原则(WB) | ||
|
||
像执行原则中提到的一样,我们可能有多个功能单元在同一周期同时结束,我们需要多个周期让他们逐一写回。除此以外,我们还需要解决WAR hazard,具体来说,如果我们发现某个FUS中的指令的Ready位仍然是1,那么就意味着: | ||
|
||
<div class="annotate" markdown> | ||
- 该寄存器当前值就是它需要拿去运算的源寄存器的值 | ||
- 该指令还未读取该源寄存器值并拿给功能单元执行(1) | ||
</div> | ||
|
||
1. 这就解释了为什么执行原则中把数据读走执行后要把Ready置0了,这是告诉那些等WAR的指令说,我已经读完了,现在你把新数据覆盖上去也没关系 | ||
|
||
所以显然这些寄存器我们现在是不能写的,否则FUS中的寄存器就没法拿正确的值去执行了 | ||
|
||
总的来说,我们需要以下的检测: | ||
|
||
- 对于所有FUS中的指令,如果其源寄存器跟我的目标寄存器不一样,那么不构成 WAR hazard | ||
- 对于所有FUS中的指令,如果其源寄存器跟我的目标寄存器一样,那么如果其Ready位为0,那么不构成 WAR hazard | ||
- 一旦存在某一FUS中的指令其源寄存器跟我的目标寄存器一样,且其Ready位为1,那么构成 WAR hazard,阻塞写回 | ||
|
||
|
||
|