# twip
**Repository Path**: tinusgraglin/twip
## Basic Information
- **Project Name**: twip
- **Description**: Tiny-Weeny Instruction Processor
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2021-07-11
- **Last Updated**: 2022-07-04
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# TWIP32 $0.1\beta$
[toc]
## 0. TWIP 介绍
**TWIP32** (**T**iny-**W**eeny **I**nstruction **P**rocessor **32** bit) 是一个心思简单的32位未成年微处理器,你可以叫她**Twipee** (/Twipi/)酱或者**缇酱**. \\( ̄︶ ̄*\\))
(欸,是在叫我吗(脸红).jpg)
她是一个字长为32位的多周期微处理器(Multi-cycle Microprocessor),使用微命令有限状态自动机控制单元实现多周期控制,现阶段支持6种16条不同的命令。
## 1. TWIP 指令集定义
### 1.1 指令集格式
Twip的16条指令按照操作数的类型和数量分为3种格式:
1. SSD(SourceReg-SourceReg-DestinationReg) ,即需要两个源操作寄存器,一个目标寄存器的
2. SSI(SourceReg-SourceReg-Immediate) ,即需要两个源操作寄存器,一个立即数的
3. SDI(SourceReg-DestinationReg-Immediate) ,即需要一个源操作寄存器,一个目标寄存器和一个立即数的
它们的具体格式如下:
可以看到,用以区分不同指令的6位指令编码Inst[31:26]由3位指令类型编码opType和3位功能编码funct组成,opType的值与指令类型的对应如下:
| opType[2:0] | 指令类型 |
| :---------: | :--------: |
| 000 | RR型ALU类 |
| 001 | Store |
| 010 | 无条件转移 |
| 011 | 条件转移 |
| 100 | Load |
| 101 | RI型ALU类 |
| 110 | 未使用 |
| 111 | 未使用 |
funct指定指令功能,与ALU功能的设置有关。
用以确定寄存器的寄存器标识有5位,即Twip有32个通用寄存器**x0~x31**,编码分别为**00000~11111**,值得注意的是,为了简化指令集,**x0这个寄存器的值恒为0**,且不能被更改,稍后我们将介绍x0的作用。
### 1.2 全部指令
#### 1.2.1 RR型ALU类
1. 书写格式
```
Add/Sub/And/Or/Xor dstReg, srcReg1, srcReg2
```
2. 操作
```
dstReg <= srcReg1 OP srcReg2
```
3. 编码格式
SSD型指令,opType = 000,参见1.1
| 指令 | funct |
| :--: | :---: |
| Add | 001 |
| Sub | 010 |
| And | 011 |
| Or | 100 |
| Xor | 101 |
4. 说明
注意`add x2, x1, x0`就相当于`mov x2, x1`.
#### 1.2.2 RI型ALU类
1. 书写格式
```
Addi/Subi/Andi/Ori/Xori dstReg, srcReg1, immediate
```
2. 操作
```
dstReg <= srcReg1 OP SignExtended(immediate)
```
3. 编码格式
SDI型指令,opType = 101,参见1.1
| 指令 | funct |
| :--: | :---: |
| Add | 001 |
| Sub | 010 |
| And | 011 |
| Or | 100 |
| Xor | 101 |
4. 说明
注意编码中16位的立即数会先符号扩展为32位后再参与计算。
另注意`addi x2, x0, -5`就相当于`mov x2, -5`.
#### 1.2.3 Store
1. 书写格式
```
StoreWord immediate[srcReg1], srcReg2
```
2. 操作
```
Mem[srcReg1 + SignExtended(immediate)] <= srcReg2
```
3. 编码格式
SSI型指令,opType = 001,参见1.1
| 指令 | funct |
| :-------: | :---: |
| StoreWord | 000 |
4. 说明
16位的立即数会先符号扩展为32位后再与寄存器srcReg1中的值相加,从而计算出地址,最后将srcReg2中的值存入这个地址对应的内存单元,一个内存单元为32位。
#### 1.2.4 Load
1. 书写格式
```
LoadWord dstReg, immediate[srcReg1]
```
2. 操作
```
dstReg <= Mem[srcReg1 + SignExtended(immediate)]
```
3. 编码格式
SDI型指令,opType = 100,参见1.1
| 指令 | funct |
| :------: | :---: |
| LoadWord | 000 |
4. 说明
16位的立即数会先符号扩展为32位后再与寄存器srcReg1中的值相加,从而计算出地址,最后将这个地址对应的内存单元的值存入dstReg中,一个内存单元为32位。
#### 1.2.5 无条件转移
1. 书写格式
```
jump immediate
```
2. 操作
```
PC <= (PC + 1 + SignExtended(immediate))
```
3. 编码格式
SSI型指令,opType = 010,参见1.1
| 指令 | funct |
| :--: | :---: |
| Jump | 000 |
4. 说明
注意16位的立即数是跳转目标相对于下一条指令的偏移量,16位的立即数同样会先符号扩展为32位后再参与计算。
#### 1.2.6 条件转移
1. 书写格式
```
BranchEqual/BranchLessThanSigned/BranchLessThanUnsigned immediate, srcReg1, srcReg2
```
2. 操作
```
if (srcReg1 ==/$< srcReg2)*
PC <= (PC + 1 + SignExtended(immediate))
```
*\* 为了表述方便起见,我们用$<表示有符号小于,用<表示无符号小于*
3. 编码格式
SSI型指令,opType = 011,参见1.1
| 指令 | funct |
| :--------------------: | :---: |
| BranchEqual | 010 |
| BranchLessThanUnSigned | 110 |
| BranchLessThanSigned | 111 |
4. 说明
注意编码中16位的立即数会先符号扩展为32位后再参与计算。
## 2. TWIP 数据通路
### 2.1 完整数据通路
TWIP的完整数据通路如下,蓝色部分为控制信号相关:
### 2.2 各主要数据通路组件
#### 2.2.1 程序计数器(Program Counter)
TWIP的程序计数器实质上为一个32位带写使能端(Write Enable)和异步清除端(Async Clear)的寄存器,当时钟信号上升沿到来且写使能端为高电平时,输入端的数据被锁存,呈现在输出端。
#### 2.2.2 主储存器(Main Memory)
TWIP的主储存器是一个32位、字可寻址(Word Addressable)的RAM,即一个字单元为32位,按字单元编址:

当时钟信号上升沿到来且写使能端为高电平时,输入端的数据根据当前的输入地址被存入主存的对应字单元。值得注意的是,主储存器的读端口是组合逻辑读取(Combinational Read)端,即输入地址变化时,输入地址对应字单元的数据经过一段时间后就会呈现在数据输出端,读取操作不与时钟同步。
#### 2.2.3 寄存器组(Register File)
TWIP的寄存器组由32个32位的寄存器组成,地址分别为00000~11111,其中,0号寄存器的数据始终为0,且不能被更改。TWIP寄存器组有两个读取端,一个写入端,如图,Adr1与Adr2为两个欲读取寄存器的地址,Adr3为欲写入寄存器的地址,与主存一样,读取不与时钟同步,地址变化后,经过一定的组合逻辑延迟,数据输出端就会呈现新地址对应的数据。
#### 2.2.4 算术逻辑单元(ALU)
TWIP的32位ALU可以执行8种不同的运算,由功能选择端控制,功能选择端的值与不同运算的对应关系如下:
| ALU Sel |功能| 运算 |
| ------- |--| -------------------- |
| 000 |0| out = 0 |
| 001 |加| out = opA + opB |
| 010 |减| out = opA - opB |
| 011 |逻辑与| out = opA AND opB |
| 100 |逻辑或| out = opA OR opB |
| 101 |逻辑异或| out = opA XOR opB |
| 110 |无符号小于判断| out = (opA < opB)* |
| 111 |有符号小于判断| out = (opA $< opB)* |
*\* 为了表述方便起见,我们用$<表示有符号小于,用<表示无符号小于*
ZF(Zero Flag)输出端为高电平当且仅当主输出端out=0.
## 3. TWIP 控制逻辑
TWIP的控制逻辑电路实际上是一个时序逻辑电路(或者说,Moore型有限状态自动机),根据当前的状态(State)和输入计算出下一个状态,在时钟上升沿到来时,更新状态,而输出则是当前状态(State)的函数。TWIP的控制逻辑单元作为一个时序逻辑电路,它的输出是控制TWIP数据通路的12个控制信号,输入为当前正在执行的指令之编码,根据TWIP6种16条指令的不同操作,可以绘出它的状态转移图,由于其输出只与其状态相关,输出的控制信号写在了表示状态的圆圈(只写出了对于当前状态必须设置的控制信号,未写明的其他信号均为0),状态的编号写在状态圆圈的一边:
为了方便每个状态控制信号的输出和状态转移图中占多数的无条件转移,我们将每个状态要输出的控制信号和无条件转移时的后继状态(如果转移有条件则这一部分为0)列出来,整理出一张表:

这就相当于输出相对于状态的函数的函数表。将这张表存入ROM,我们就构建好了输出逻辑。
而对于计算新状态的部分,一方面当可以无条件转移至下一个状态时,我们可以利用这张表确定下一个状态,另一方面,当向下一个状态的转移有(输入)条件,即下一个状态随输入的不同而不同时,我们就需要考察输入的情况,例如对于图中的状态2,下个状态的确定可循以下的伪代码^:
```:L
if(CurrentState == 2)
case (Op[5:2])
000x: NextState = 3
101x: NextState = 5
100x: NextState = 6
010x: NextState = 10
0110: NextState = 11
0111: NextState = 12
```
计算出新状态后,等到时钟上升沿到来,状态即可被更新。
^ 代码中的x代表Don't Care,即无关位
---
