架构
说下 RISCV 指令怎么运行的?
- 取指 IF
- 解码 ID
- 执行 EX
- 访存 MEM
- 写回 WB
CPU内部结构
- ALU
- Control Unit
- Reg
- Cache
- 总线接口单元
一个 rv 的 add 在 EX 阶段是怎样的?
Draft
- 获取操作数
- ALU 执行加法运算
- 更新状态
流水线怎么处理前后相关性指令?
Ai
- Data Hazards: 后一条依赖前一条的结果
- Read after Write: 后一条指令需要读取前一条指令写入的值
- 数据转发(Forwarding):通过直接将结果从执行阶段或写回阶段转发回 ALU 输入,避免等待写回到寄存器。
- 插入气泡(Stalling):在流水线中插入空操作,延迟后续指令的执行,以等待前一指令完成。
- Write after Write: 两条指令对同一寄存器进行写操作
- 顺序执行:控制器确保写操作按照程序顺序执行,避免后续指令覆盖前一指令的结果。
- Write after Read: 后一条指令在前一条指令读取寄存器之前对其进行写操作
- 硬件设计确保不会发生
- Control Hazards
- 分支预测:预测分支的结果,提前加载可能的指令。
- 延迟槽:在分支指令后插入无关指令,以填补延迟。
- 气泡插入:在分支决定后插入气泡,直到确定分支目标。
流水线冒险是什么?
经典流水线的弊端是由于流水线是静态调度且不能投机(Speculative),指令执行非独立。当遇到某种情况需要停机(Stall)时被称为流水线冒险(Pipelining Hazards)
- 数据冒险 / Data Hazard
- 控制冒险 / Control Hazard
- 结构冒险 / Structure Hazard
- 内存访问延迟
CPU 如何计算 IEEE 754 加法
Ai
IEEE 754浮点数加法的计算过程可以分为以下几个步骤:
1. 表示法
IEEE 754浮点数通常由三个部分组成:
- 符号位 (S): 1 位,表示正负。
- 指数 (E): 8 位(单精度)或 11 位(双精度),表示指数的偏移值。
- 尾数 (M): 23 位(单精度)或 52 位(双精度),表示有效数字。
2. 对齐指数
在进行加法之前,需要将两个浮点数的指数对齐:
- 找到两个数中较大的指数,将较小指数的尾数右移,以补偿指数差。
- 右移后,尾数可能会丢失精度。
3. 加法
- 对齐后,两个尾数进行加法。如果符号位不同,则进行减法。
- 结果可能需要进行归一化处理(即调整尾数,使其在有效范围内)。
4. 归一化
- 计算完后,如果尾数超出范围(例如,变成 1.0 或更大),则需要右移尾数并增加指数。
- 如果尾数小于 1,则需要左移尾数并减少指数。
5. 舍入
根据IEEE 754标准,结果需要进行舍入处理,以保证精度。常见的舍入方式包括:
- 向最近的偶数舍入
- 向上舍入
- 向下舍入
6. 输出结果
最后,根据处理后的符号、指数和尾数生成新的IEEE 754浮点数,并输出。
示例
假设我们要加两个浮点数
A和B:
A = 1.5(符号位:0, 指数:01111111, 尾数:10000000000000000000000)
B = -0.5(符号位:1, 指数:01111110, 尾数:00000000000000000000000)
- 对齐指数:将
B的尾数右移。- 进行加法:根据符号位进行相应的运算。
- 归一化处理。
- 舍入并输出结果。
这个过程确保了浮点数加法的准确性和符合IEEE 754标准。
Cache
结构
- Cache 结构:

- Cache 内部:Cache Line 结构:

访问
Cache 如何判断是否命中?
- 地址分解:标签(Tag),索引(Index),偏移(Offset)
- 查找缓存:
- 根据索引部分找到对应的缓存行,然后检查该行的标签是否与内存地址中的标签匹配。
- 如果标签匹配,则称为“命中”(Hit);如果不匹配,则称为“未命中”(Miss)
缓存一致性问题
Write Through 和 Write Back 以及广播机制

- Write Through / 写直达 :把数据同时写入内存和 Cache 中
- 检查若在 CPU Cache 则同时写入
- 每次都写到内存
- Write Back / 写回 :减少数据写回内存的频率,只有当修改过的 Cache Block「被替换」时才写到内存中
- 若对应存在于 CPU Cache 则写到 Cache,并标记为 Dirty,即缓存与内存不一致
- 若对应的 Cache Block 里存放的是「别的内存地址的数据」,则需要替换
- 若其为 Dirty,则说明存在不一致,需要先将其写回内存;若其非 Dirty,则说明一致。
- 由于 缓存一致性以及修改写入的大小与 Cache Line 大小可能不相同 的问题,我们接下来需要从内存读取当前整个的数据到 Cache Block
- 接下来再执行写入 Cache Block,并标记为 Dirty
对于不同核心等之间保证同步,需要 广播
总线嗅探与 MESI
- Bus Snooping / 总线嗅探 :通过总线把这个事件广播通知给其他所有的核心
- MESI
- 标记 Cache Line 状态,先询问+修改标记再更新数据
- 状态
Modified:等价于Dirty,更新但未写入内存;更新于广播修改之后,实际修改时Exclusive:干净,只存储在一个 CPU 核心的 Cache 里,自由写入;更新于读取到内存中不存在的新数据时Shared:干净,多个 CPU 核心的 Cache 里都有,更新需要广播;更新于读取到别人独占的数据时Invalidated:失效,不可读取;更新于收到别人更新的广播时
- 状态图

Misc
嵌入式
波特率是什么,为什么双方波特率要相同,高低波特率有什么区别
波特率 是 每秒钟信号变化的次数,用于描述 串行通信 中传输速度的一个单位。
如果两者的波特率不同,接收方会错误地解释信号,导致数据丢失、数据错误或者完全无法接收数据。