cs61c-lec
Lec06 Floating Point
规格化
overflow - underflow
浮点数standard - sign exponent significand
IEEE 754 使用 “biased exponent” 表示 + 原因(P&H p136)
浮点数实际表示值(使用biased notation后)
(-1)^S x (1+Significand) x 2^(Exponent-127)
FP 表示0;infinity
;NaN
(Not a Number)
- (sild lec06 p19-p23)
FP 表示Denorms
(非规格化数) 重要理解
https://youtu.be/Gs0ARZzY-gM?list=PLnvUoC1Ghb7zz9gZ7A6DHo_YI7m_QtTwo&t=456
- 表示 1/3
- FP 加法不可交换
- FP Precision & Accuracy
舍入操作 (P & H 3.5.7)
由于浮点数的significand 每次加一后,对整个浮点数其实加1*2^(exponent+127),所以它会跳过某些数
因此,无法精确表示且将舍入的第一个整数是:
对于float
而言,16,777,217(224 + 1)。
对于double
而言,9,007,199,254,740,993(253 + 1 )。
Lec07 RISC-V Intro
Risc-V 抽象层
Risc-v -> ISA(Instrument Set Architecture)
寄存器(register)
基础操作符 - add sub addi
Lec08 RISC-V lw, sw, Decisions I
字节
1个字32个位,即4个字节;一个字节8个位。
小尾数法(Little Endian) 内存存储字节
从寄存器访问比从内存访问快
lw
Load from Memory to Register (一个字32位)
sw
Store from Register to Memory (一个字32位)
加载存储字节, 加载8位而不是32位,存储到寄存器中时需要sign-extend
保留addi 的原因
- beq; bne; blt; bge
- j(jump) label
if-else 语法
for-loop 语法
Lec09 RISC-V Decisions II
逻辑运算符
immediate 版
掩码(mask)
使用Xor with 11111111_2
替代 not
逻辑左移 sll & slli
逻辑右移sra & srai
Assembly 编译
程序存储在memory中,一个指令4个字节
PC(program counter)存储下一条指令的内存地址,从内存中抓取指令,然后control
使用Datapath
和memory
执行,更新PC
pseudoinstructions: mv , li & nop
function call - jal(j and l) jalr(jr)
jal & jalr
pseudoinstructions : j, jr & ret
Lec10 RISC-V Procedures
主要讲stack,嵌套函数调用,寄存器
32 个寄存器的用处,symbolic name
当需要多余的寄存器时,我们讲旧的冲突的寄存器值存储与stack中
sp -> stack pointer,sp自上而下增长 - sp always points to the last used space in the stack
leaf类型函数调用
assembly
保存了s0,s1 的stack
嵌套函数调用,
callee(被调用程序) 会破坏 caller(调用程序)的register值,例如所有的函数返回地址(ra)都存储在x1中,callee的ra会与caller的ra冲突;或者是两个函数各自的参数,这些我们都需要存储register值在stack中
为了避免存储所有的register,造成巨大的负担,caller需要知道那些register的值,一定会被callee恢复,那些register的值不会被callee确保恢复。
&n
&n
c中的automatic & static 变量存储
对不适合寄存器存储的自动变量(automatic or local variables)使用stack
过程帧 活动变量 - Procedure frame or activation record stack中存储寄存器和自动变量的部分
使用stack的例子
执行程序时,static,stack,heap在memory中
&n
&n
&n
Risc-v 32 的 以学指令
Risc-v 伪指令
- 依赖于x0
- 不依赖于x0
Lec11 RISC-V Instruction Formats I
从本节课开始学习机器语言程序
六种指令形式
将32位的指令分为几个fields
32个寄存器正好用五位二进编码
32位指令可以用8位16进制数表示
R-Format 指令
R-Format instructions
I-Format 指令
- 指令中的immediates,必然要在32位中表示出来,否则也无法直接使用
- 由于immediates 11位,为了跟32位进行运算,所以默认sign-extension在进行运算之前
I-Format instructions
shamt 是移位的位数
I-Format Load 指令
&n
Load-instructions
lh
load halfword 加载16个字节,sign-extention后,存储到32 的register中
S-Format 指令
- 存储时需要的偏移值(immediates)被分割,为了使
rs1/rs2
跟其他类型的指令在同一位置- Register names more critical than immediate bits in hardware design
S-Format instructions
Lec12 RISC-V Instruction Formats II
B-Format 指令
- 分支指令,主要用来跳转到label,接下来先介绍如何对label进行编码
- branch指令通常用于(if-else,while,for-loop),一般较短,相比下函数调用和无条件跳转label位置较远会使用jump 指令
- 由于pc(program counter)会保存当前位置的地址,所以我们采用
PC-Relative Addressing
(pc相对寻址)来确认branch的label的地址
- 能跳转到pc相对
2^11*32bits
前后的指令,由于branch一般不大,是能满足使用需求的
- 一般pc应该加
immediate * 4
不过risc-v为了满足它支持的16位指令,所以加的是immediate * 2
B-Format fields
- 由于跳转的相对地址(immediates)一定是偶数(如果是奇数,就会跳转到16位或是32位指令的中间,而不是头部),最后一位数一定是0,所以默认不保存
Branch example
- 计算偏差
- 完成编码
B-Format-instructions
注意,由于branch中的跳转offset是计算出来固定的,如果你修改代码中单个某行的位置,offset就会错误;如果移动整个代码文件,由于offset是相对的,相对位置没有变化,offset仍是正确的。就是你导入这个文件branch不会出错,修改branch相关代码位置就会出错。
I型编码后immediates值具体存储
如果branch 的offset 过大
U-Format for “Upper Immediate” Instructions
- 存储较大的immediate,能存储20位(用于存储32位中高的20位)
- 主要用于
lui
&auipc
两个指令
LUI 创建32位immediate -> 伪指令li
- 由于addi sign-extension 的缘故,后12位符号扩展后,两个数相加,中间的位值会小1
- 汇编器会自行处理这个问题 -> 给20位最后一位加一,我们直接使用pseudo instruction
li
即可得到正确的数值
AUIPC
J-Format(jal)
- 顾名思义,用于jump 指令,也只有一个jump指令
- 在
rd
中保存pc+4
- 设置
pc = pc + offset
- 前后
218 32-bit instructions
JAL用处
JALR Instruction (I-Format)
- 注意 I-Format
- 直接加值,不乘2
- 一般用于跳转到绝对地址
Summary
Lec14 Intro to Synchronous Digital Systems
之后制作risc-v processor
risc-v processor is a Synchronous Digital System
- 接下来学习基础block
Switch
Transistor
使用晶体管构造Nand block
是由于上下晶体管不同,组合出的效果,基于nand gate ,可以构造出And
,Or
, Not
Clock : the heart of the system
信号组合
adder propagation delay (加法传播延迟)
Two Basic Types of Circuits
adder circuit
register circuit
Lec15 State, State Machines
状态电路作用(state elements)
累加器(使用寄存器)
寄存器详细
D Type Flip-flop
触发器内部时间节点
在时钟的上升沿,对输入 d 进行采样并传输到输出。 在所有其他时间,输入d 被忽略。
在时钟上升边沿前,输入必须保持有效的最短时间为 建立时间
在时钟上升边沿后,必须保持有效的最短时间为 保持时间
Accumulator 例子详细分析时间点
- reset $S_{i-1}$
- add $S_{i-1}$ & $x_i$ 加法传播延时
- sample from $S_i$ to $S_{i-1}$
- add $S_{i-1}$ & $x_i$ again,但是此时会出现 $x_0 + x_0$ 的
wrong value
- 虽然出现
wrong value
但是,由于clk smaple 之前留有足够的时间 set up,所以最终会是准确值
所以超频系统容易出现错误,超频时,黄线收缩(周期减小),最终没有时间稳定set up,sample wrong value
最大CLK 频率
Pipeline 提高表现
为了效率,clk 的周期不能设置的无限长,当任务量过大时,一个周期可能完不成(受限于类似adder propagation delay 这样的原因)
所以我们使用多个寄存器分步(管道)完成任务,每个周期完成一部分。
Finite State Machine (有限状态机器)
- 状态转移图有一个输入端
- 外部箭头,或者某个状态双圆圈表示
- 每个状态都有两个可能输入状态,两个可能输出状态
由state elements 和 combinational logic block 构成 FSM
Lec16 Combinational Logic
Truth Table
Majority circuit
- 顾名思义,选择多数的。即0多选0,1多选1
Logic Gates(and,or,not,xor,nand,nor)
3 inputs xor
Truth Table -> Gates
Majority
FSM
Boolean Algebra(布尔算式)
- 由 AND、OR、NOT 门组成的电路与 BA 中的方程之间存在一一对应的关系
+
means OR,•
means AND, $\bar{x}$ means NOT
- BA 用于简化电路图
Laws of BA(布尔算式规则)
Canonical forms (范式)
MUX 2to1 canonical forms
TT LG BA (真值表,逻辑门,布尔算式互相转换)
Lec17 Combinational Logic Blocks [08/25]
多选器(Mux)
2-to-1 MUX
- TT
- circuit
4-to-1 Multiplexor
- 使用2-1的Mux构造4-1
Arithmetic Logic Unit(ALU) - 算术逻辑单元
一个简单的算数逻辑单元,仅包含ADD, SUB, bitwise AND (&), bitwise OR (|)
- circuit
Adder/Subtractor
1-bit adder
N 1-bit adder 组合成 1 N-bit adder
处理overflow - signed add
subtractor
Lec18 Single-Cycle CPU Datapath I [09/12]
CPU
回顾架构
cpu 包含 datapath 和 control
Datapath
Five Stages of the Datapath
excute an instruction
基础结构,包含pc,mux,reg[],DMEM,IMEM,ALU
在一个周期中执行完5个阶段 -> single-cycle cpu
Datapath Elements: register
register file 包含32 个 register 结构
register 两个进线,一个出线
Datapath Elements: Memory
State :Reg_file, pc, Mem(Imem, Dmem)
R-Type Datapath
完成R型指令的Datapath 构造
- 指令对机器的状态有两个改变
- Reg[rd] = Reg[rs1] + Reg[rs2]
- PC = PC + 4
add datapath
- Timing for add datapath
sub datapath
跟add 几乎相同,除了执行的是sub 而不是add
设置一个ALUsel 选择执行sub 或是add 即可
- inst[30] selects between add and subtract,两个的opcode 相同
其他的R-Type相似,只需要更改ALUsel 即可
I-Type Datapath
I type instructions
由于I型相比R型少了rs2,多了一个immediate
我们要修改下面的地方
修改后
Imm.Gen
其他的I-Type相似,只需要更改ALUsel 即可
Lec19 Single-Cycle CPU Datapath II [09/12]
R+I Arithmetic/Logic Datapath
Load Datapath
添加DMEM,load 需要操作memory
步骤:
- pc = pc + 4
- fetch instruction
- 提取register
- 根据inst 设置Control logic 的参数
- rs1 + offset
- memory access
- write back to register
其他L型命令
如果要满足16位,或者8位的需要加一些mux,gates即可
Store Datapath
添加了一条rs2 的出线,存储位置
步骤:类似Load, 设置memory为write,rs2
S & I immediate Generation
其他S型命令
Branch Datapath
- Different change to the state:
需要计算 pc + immediate
和 比较rs1 rs2 的值
修改
Branch Comparator
Branch Immediates
还没看懂具体哪里不同
可以之后理解下
步骤:
- 使用branch comparator,比较后得到的BrLT,BrEq传输给control logic
- control logic 基于BrLT,BrEq确定PCSel的值
JALR Datapath
对机器状态的改变
- Writes PC+4 to rd (return address)
- Sets PC = rs1 + immediate
改变:添加一个多选器选项,将pc+4写入DataD
步骤:
JAL Datapath
对机器状态的改变
- jal saves PC+4 in register rd (the return address)
- Set PC = PC + offset (PC-relative jump
immediate 编码类似Branch Datapath
步骤:
U-Type Datapath
LUI
AUIPC
Conclusion
Lec 20 Single-Cycle CPU Control [10/03]
20.1 Control and State Register(CSRs)
- 用于监控状态和性能,由最高4096个CSRs
- 不在基本的ISA中,但是有模块化扩展
- 对计数器和计时器很重要,还和外设交流(打印机,显示器之类的)
20.1.1 CSR Instructions
- 注:uimm需要Zero-extended to 32b
20.1.2 CSR Instructions example
- CSRRW(原子读/写 CSR)指令“原子地”交换 CSRs 和 integer registers中的值
20.1.3 System Instructions
20.2 Control Logic Design
20.2.1 Control Logic 真值表
20.2.2 Two Realization Options
- ROM
- “Read-Only Memory”
- Popular when designing control logic manually
- Combinatorial Logic
- Today, chip designers use logic synthesis tools to convert truth tables to networks of gates
20.2.3 RV32I, 九字节ISA
- 通过9个字节就可以确定指令类型
20.2.4 ROM-based Control
- 11-bit address(inputs) 15-bit control bit(outputs)
20.2.4.1实现
- AND-OR Structure
20.2.5 Combinational Logic Control
- 通过逻辑操作得到控制符的值
20.2.5.1 example:BrUn
20.2.5.2 example:add
Lec 21 Pipelining I
评估性能
CPI
Lec 22 Pipelining II
Pipeline RV32I
- 顺序执行
- 流水线执行
- 每个阶段用时统一
- 两者比较
- 性能提高约4倍
- 执行时,一个阶段五个部件会被同时使用
Pipeline Datapath
- 由于流水线设计,我们需要在两个阶段中间维持指令的数据,保证指令的正常运行
- Pipeline registers separate stages, hold data for each instruction in flight
Pipelined Control
Pipeline Hazards
- 结构冒险(Structural hazard)
- 一个需要的资源被占用
- 数据冒险(Data hazard)
- 指令之间的数据依赖
- 需要等待前面的指令完成数据读写
- 控制冒险(Control hazard)
- 指令执行流依赖之前的分支指令
Strucural Hazard
Strucural Hazard:Memory Access
- 解决方法 use two seperate memories
- 同时 RV32I 也被设计避免结构冒险
- 每条指令最多一次memory access
Data Hazard
Data Hazard:Register Access
- 在以下的指令中
sw
抓取的是old/new value
- 由于regfile 的高效率(100ps)
- WB updates value
- ID reads new value
- finish in one cycle(200ps)
- 不一定总是能够在一个周期完成读写,特别是在高频的设计中
Data Hazard:ALU Result
- 问题:指令取决于先前指令的结果
Solution 1: Stalling
stall -> 将control 中的控制符设置为不选取即可控制后面三个阶段暂停
stalls 显然影响性能,可以
- 编译重新排布代码,避免前后依赖
- 添加 nop(addi x0, x0, 0)
Solution 2: Forwarding
- 正规解法,前递(aka 旁路)
- 从pipeline stage抓取操作数,而不是regsiter file
如何判断是否需要前递
- 比较 $inst_X.rd == inst_D.rs1$
- 相等就说明有数据依赖
- 忽略x0
Lec 23 Pipelining III
Load Data Hazard
- 对于load 导致的Data Hazard 前递无法解决问题
- 当出现load data hazard 时我们需要stall 一个周期
- slot after a load is called a load delay slot
- 相当于添加一个nop,类似之前
- 同样为了处理stall 导致的performance loss
- Put unrelated instruction into load delay slot
Control Hazards
- branch 由于写入地址在第4阶段,导致接下来的两个原本不需要执行的指令执行
- 如果跳转,接下来的两个指令转换为nops
- 如此的话,每条branch inst 都会衔接两个dead cycles
- 使用”branch prediction” 猜测是否这条branch inst 是否跳转
- 如今的”branch prediction”能达到90%以上的准确率