从门电路到完整的SoC计算机系统

“一生一芯”主要回答三个问题

  1. 程序如何在计算机上运行?
  2. 如何设计一颗可支撑程序运行的处理器芯片?
  3. 如何将设计的处理器芯片转变成可流片的版图?

 

背后其实反映出两项重要的能力

  • 计算机系统软硬件协同能力
  • 处理器前后端全链条设计能力

计算机系统是个状态机

状态机模型帮助大家将程序, 指令集, 处理器关联起来

  • 建立计算机系统软硬件协同的基本认识

 

程序 抽象计算机 CPU
状态 \(\{<V, PC>\}\) \(\{<R, M>\}\) \(\{时序逻辑电路\}\)
状态转移规则 C语言语句的语义 指令的语义 组合逻辑电路
FM C语言标准手册 指令集手册 架构设计文档

 

  • 程序编译 = 将语句翻译成语义等价的指令序列(GCC)
  • 程序运行 = 指令序列驱动抽象计算机进行状态转移(NEMU)
  • 微结构设计 = 按照指令语义设计行为等价的电路(NPC)

程序编译 = 将语句翻译成语义等价的指令序列

  • 预处理 -> 编译 -> 汇编 -> 链接 -> 执行
  • 编译 = 词法分析 -> 语法分析 -> 语义分析 -> 中间代码生成 -> 优化 -> 目标代码生成

 

printf(6 - 2147483648 > 6 ? "T" : "F");
printf(6 - 0x80000000 > 6 ? "T" : "F");
printf("\n");
32位 64位
c90 TT FT
c99 FT FT
  • C语言标准中除了确切的行为, 还包含
    • Unspecified Behavior
    • Implementation-defined Behavior
    • Undefined Behavior
  • ABI手册记录了Implementation-defined Behavior的选择
    • 还反映出C语言标准, 编译器, 操作系统, 库函数, 处理器之间的协助
    • 程序的运行结果与源代码和上述因素都有关系

程序运行 = 指令序列驱动抽象计算机进行状态转移

YEMU = 指令集模拟器 = 用C语言实现指令集手册定义的状态机

  • 自定义freestanding运行时环境
    • 程序从地址0开始执行
    • 只支持两条指令(取指, 译码, 执行, 更新PC) - addiebreak
      • 对于ebreak指令:
        • 寄存器a0=0时, 输出寄存器a1低8位的字符 - 抽象成putch()
        • 寄存器a0=1时, 结束运行 - 抽象成halt()
void _start() {
  putch('H'); putch('e'); putch('l'); putch('l'); putch('o'); putch(','); putch(' ');
  putch('R'); putch('I'); putch('S'); putch('C'); putch('-'); putch('V'); putch('!');
  putch('\n');
  halt(0);
}
  • CEMU = C语言解释器 = 用其他语言实现C标准手册定义的状态机
    • hosted运行时环境
    • 支持若干简单C语句: 读语句, 解析, 执行, 更新PC

YEMU(Ysyx EMUlator) v1.0

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
uint32_t R[32], PC;
uint8_t M[64] = {
  0x13, 0x05, 0x00, 0x00, 0x93, 0x05, 0x10, 0x04, 0x73, 0x00, 0x10, 0x00,
  0x13, 0x05, 0x10, 0x00, 0x93, 0x05, 0x00, 0x00, 0x73, 0x00, 0x10, 0x00,
  0x6f, 0x00, 0x00, 0x00,
};
bool halt = false;

void inst_cycle() {
  uint32_t inst = *(uint32_t *)&M[PC];
  if (((inst & 0x7f) == 0x13) && ((inst >> 12) & 0x7) == 0) { // addi
    if (((inst >> 7) & 0x1f) != 0) {
      R[(inst >> 7) & 0x1f] = R[(inst >> 15) & 0x1f] +
        (((inst >> 20) & 0x7ff) - ((inst & 0x80000000) ? 4096 : 0));
    }
  } else if (inst == 0x00100073) { // ebreak
    if (R[10] == 0) { putchar(R[11] & 0xff); }
    else if (R[10] == 1) { halt = true; }
    else { printf("Unsupported ebreak command\n"); }
  } else { printf("Unsupported instuction\n"); }
  PC += 4;
}

int main() {
  PC = 0; R[0] = 0; // can be omitted since uninitialized global variables are initialized with 0
  while (!halt) { inst_cycle(); }
  return 0;
}

微结构设计 = 按照指令语义设计行为等价的电路

  • 用nMOS和pMOS的开关特性实现01
  • 通过晶体管搭建门电路进行01的简单计算
    • not, nand, and, nor, or, xor
  • 通过门电路搭建组合逻辑电路处理信息
    • 译码器, 编码器, 多路选择器, 比较器, 加法器
  • 通过门电路搭建时序逻辑电路存储信息
    • SR锁存器, D锁存器, D触发器, 寄存器, SRAM

 

  • YPC = 处理器 = 用上述电路实现指令集手册定义的状态机
    • 通过仿真环境实现自定义freestanding运行时环境
    • 支持两条指令的指令周期: 取指, 译码, 执行, 更新PC

 

  • 硬件设计的本质 = 实例化 + 连线

全面认识RISC-V指令集

  • 指令集的7个评价标准
    • 成本, 简洁, 性能, 架构与实现分离, 提升空间, 代码大小, 易于编程/编译/链接
  • RISC-V的最大特点 - 通过模块化应对不同的应用场景
    • 指令扩展可自由组合 - 嵌入式(RV32E, RV32IC), 教学(RV64IMA), 桌面(RV64GC), 高性能(RV64GCBV)
    • 通过自定义指令的模块化解决生态碎片化问题
    • 用起来像是定长的变长指令集
  • RISC-V指令集的若干设计案例
    • 指令格式, 非法指令, 立即数符号扩展, 立即数编码方式…

 

  • 从计算机系统软硬件协同的视角理解指令集
    • RISC-V的设计对软硬件设计有何影响

C程序与RISC-V - 程序的机器级表示

  • 全面理解程序和指令序列的关联
    • 常数, 变量, 运算, 条件分支, 循环: RISC-V指令
    • 调用约定: 规范函数调用的机器级实现, 使不同函数可正确互相调用
    • 复杂数据类型: 在指令集视角中不复存在, 全是基于寻址的数据访问
  • 理解C程序如何精确控制机器底层行为
    • 预测写出的C代码将如何在计算机上运行

示例 - 手写递归版本汉诺塔的汇编代码

#include <stdio.h>
void hanoi(int n, char from, char to, char via) {
  if (n == 1) { printf("%c -> %c\n", from , to); }
  else {
    hanoi(n - 1, from, via, to);
    hanoi(1,     from, to,  via);
    hanoi(n - 1, via,  to,  from);
  }
}
int main() {
  hanoi(3, 'A', 'B', 'C');
  return 0;
}

要运行更多程序, 还需要运行时环境的支持

AM = 按照计算机发展史将计算机功能抽象模块化裸机运行时环境

  • 按计算机发展史模块化 - 从需求的角度启发我们如何设计计算机
    • AM = TRM + IOE + CTE + VME + MPE
    • 图灵机 -> 冯诺依曼机 -> 批处理系统 -> 分时多任务 -> …
  • 裸机运行时环境 - 软硬协同地揭示程序与计算机的关系
    • (在CPU中)实现功能 -> (在AM中)提供运行时环境 -> (在应用层)运行程序
    • (在CPU中)实现更强大的功能 -> (在AM中)提供更丰富的运行时环境 -> (在应用层)运行更复杂的程序
  • 抽象 - 支持各种计算机和程序, 打通系统方向各课程实验的关键
    • cputest, coremark, microbench, FCEUX, 甚至是OS及其软件栈
    • x86-nemu, mips32-qemu, riscv64-npc, 甚至是Linux native

用电路实现完整的RISC-V单周期处理器

  • 状态 - 时序逻辑电路
    • \(PC\) - 单个寄存器, 初值为0
    • \(R\) - 通用寄存器组, 可寻址, 用带使能的D触发器搭建存储器
    • \(M\) - 内存, 可寻址, 容量更大的存储器
  • 状态转移 - 组合逻辑电路
    • 数据通路 - 数据移动和计算所经过的路径及相关部件
      • 例如\(R\), \(M\), 选择器, 加法器, 移位器, 乘法器等
    • 控制信号 - 控制数据在数据通路中如何移动
      • 例如执行加法指令时, 需要将数据送入加法器, 而不是乘法器

 

  • 编写可读可维护的RTL代码 - 低熵实现
    • 选一个表达能力强的语言
    • 借助工具弥补语言的缺陷

AM是个多源文件的项目, 需要了解链接

  • 现代工具链以源文件为单位进行编译/汇编, 然后链接成可执行文件
    • 但编译/汇编都无法处理跨节的函数和数据引用

  • 链接 = 符号解析 + 重定位
    • 符号解析 = 将符号的引用与符号的定义建立关联
    • 重定位 = 合并相同的节, 确定符号的最终地址, 并将其填写到引用处
// main.c
#include <stdio.h>
int a = 0, b = 0;
extern void f(), g();
int main() { 
  f(); printf("a = %d(0x%08x), b = %d(0x%08x)\n", a, a, b, b);
  g(); printf("a = %d(0x%08x), b = %d(0x%08x)\n", a, a, b, b);
  return 0;
}
// f.c
void f() { extern float  a; a = -1.0; }
// g.c
void g() { extern double a; a = -1.0; }
运行输出结果:
a = -1082130432(0xbf800000), b = 0(0x00000000)
a = 0(0x00000000), b = -1074790400(0xbff00000)

+IOE, 支持输入输出的计算机系统

  • 物理世界
    • 用户操作设备
  • 设备的电气部分
    • 将用户的操作转换成电气信号
  • 设备的数字部分
    • 将模拟信号转换成数字信号, 通过设备寄存器提供设备功能的抽象
  • CPU I/O指令
    • 访问这些设备寄存器, 让数字信号变成指令的操作数
  • AM的IOE抽象
    • 进一步提供I/O指令和常用设备的抽象
  • 程序
    • 用IOE的API编程, 实现游戏

+CTE, 指令执行可能失败

异常 = 一种特殊的跳转

  • CPU
    • 按照手册约定, 发生异常时跳转到一个预先设定的位置
    • 通过CSR保存部分状态(RTFM)
#include <klib.h>
void handler() {
  uintptr_t mepc;
  asm volatile ("csrr %0, mepc" : "=r"(mepc));
  printf("exception at mepc = %p\n", mepc);
  while (1);
}

int main() {
  asm volatile ("csrw mtvec, %0" : :"r"(handler));
  asm volatile (".word 0"); // illegal instruction
  printf("I am alive!\n");
  while (1);
}
  • AM的CTE抽象
    • 把异常抽象成事件, 提供事件处理模型
  • 上层应用
    • 决定如何处理事件

 

  • 真实应用
    • 系统调用, SBI调用, 指令模拟, 处理不对齐访存, 上下文切换…

总线 = CPU和外设之间的通信协议

  • 通过握手信号屏蔽模块内部细节
    • 握手时master和slave对数据传输达成一致
  • 总线的RTL实现 = 接口信号 + 状态机
    • 不同的状态下控制不同的接口信号
  • 处理器内部总线
    • 状态机不同的控制方式, 可实现不同微结构的处理器
    • 单周期, 多周期, 流水线, 乱序执行…
    +-----+ inst  ---> +-----+  ...  ---> +-----+  ...  ---> +-----+
    | IFU | valid ---> | IDU | valid ---> | EXU | valid ---> | WBU |
    +-----+ <--- ready +-----+ <--- ready +-----+ <--- ready +-----+
  • 系统总线
    • 只读同步总线 -> 可读写同步总线 -> 可读写异步总线(AXI-Lite)
  • 使用总线的真实问题: 避免死锁和活锁, 通过仲裁器支持多个master, 通过Xbar的地址译码支持多个slave

通过总线接入SoC, 实现真实的完整计算机系统

SoC的设备栈/存储栈:

MROM UART SRAM flash
程序功能 代码/只读数据 printf() 可写数据/堆/栈 代码/只读数据
函数 - putch() - flash_read()(非XIP)
C代码 指针解引用 指针解引用 指针解引用 指针解引用
RISC-V指令 取指/load store 取指/load/store 取指/load[/store(SPI)]
CPU单元 IFU/LSU LSU IFU/LSU IFU/LSU
SoC总线桥 - AXI-APB-wb - AXI-APB-wb-SPI
总线接口 AXI-Lite wishbone(wb) AXI-Lite SPI(含XIP)
地址译码 选择存储单元 选择寄存器 选择存储单元 选择存储单元
1 bit的访问 - 移位寄存器 字线选通晶体管 字线控制栅极加压(读)
1 bit的表示 电源/地 线缆信号 6管存储单元 浮栅晶体管的充/放电

 

  • 学习SoC = RTFM + RTFSC + WTFSC

DRAM - 存储密度更大的随机存储器

  • DRAM是主流的存储技术, 存储密度大, 但需要定时刷新
    • 定时刷新逻辑放在DRAM颗粒内部 - PSRAM颗粒
      • 串行PSRAM只有8个引脚 - 基础SPI, Dual SPI, Quad SPI, QPI
    • 定时刷新逻辑放在DRAM控制器 - SDRAM颗粒
      • 内部是个高维结构: 存储单元 -> 存储字 -> 行 -> 存储体 -> 颗粒
      • 内存条 = 对颗粒进行位扩展(面, rank)和字扩展(通道, channel)

  • 优化程序运行效率 - 二级bootloader = FSBL + SSBL

NVBoard + ysyxSoC + NPC + RISC-V + AM + RT-Thread + FCEUX = 计算机系统!

性能优化的科学方法

  1. 评估当前的性能
    • 量化指标 - 程序的执行时间, 代表性程序 - benchmark
  2. 寻找性能瓶颈
    • 用性能公式刻画程序的执行时间
              time      inst     cycle     time
      perf = ------- = ------ * ------- * -------
              prog      prog      inst     cycle
    • 通过简单模型分析影响IPC的因素: 指令供给, 数据供给, 计算效率
    • 性能计数器: 统计性能事件发生的频次, 观察程序运行时间花在哪里
    • 通过Amdahl’s law寻找性能瓶颈, 估算优化技术的潜在收益
      • 抛开workload谈优化就是耍流氓
  3. 采用合适的优化方法
    • 经典体系结构的4类优化方法 - 缓存, 并行, 预测, 加速器
  4. 评估优化后的性能, 对比获得的性能提升是否符合预期

缓存

  • 缓存是局部性原理的重要应用
    1. 时间局部性 - 当前访问的数据, 短时间内很可能再次访问
    2. 空间局部性 - 当前访问的数据, 短时间内很可能访问其相邻数据
            access time       /\          capacity    price
                             /  \
               ~1ns         / reg\          ~1KB     $$$$$$
                           +------+
cache ----->   ~3ns       /  SRAM  \        ~30KB     $$$$$
                         +----------+
               ~10ns    /    DRAM    \      ~10GB     $$$$
                       +--------------+
               ~10ms  /      disk      \     ~1TB      $$
                     +------------------+
               ~10s /        tape        \  >10TB       $
                   +----------------------+
  • 缓存的实现 = 块存储 + 元数据存储 + 控制器
    • 控制器 = 总线状态机的扩展
  • 缓存的验证: 形式化验证方法, REF = 不带缓存的访存过程
  • 缓存的性能优化 - AMAT公式
    • 提升命中率(3C模型): 预取, 扩容, 增加关联度, 调整块大小…
    • 降低缺失代价: 利用总线的突发传输
  • 通过cachesim快速评估一个设计的性能表现
    • 用C代码模拟缓存的工作流程, 输入简化版itrace, 维护元数据统计缺失次数

指令级并行 - 流水线

  • 流水线 = 让处理器的不同阶段处理不同的指令
  • 理想情况下, 5级流水线处理器执行程序的效率是单周期处理器的5倍
  • 简单流水线的实现需要检测并处理冒险问题
    • 结构冒险 - 消极等待, 添加硬件部件避免竞争
      • 总线的通信方式自动实现了等待功能
    • 数据冒险 - 消极等待
    • 控制冒险 - 消极等待, 推测执行
  • 流水线的验证: 形式化验证方法, REF = 单周期
  • 流水线的性能优化
    • 提升指令供给能力 - icache流水化
    • 减少数据冒险的阻塞 - 转发技术
    • 减少控制冒险的阻塞 - 分支预测
      • 用branchsim快速评估一个分支预测算法的性能表现

锻炼工程思维, 学会独立解决问题

不畏惧新问题/新知识 - STFW, RTFM, RTFSC

遇到问题时知道去哪里找到正确的答案

 

  • 手册 - C语言标准, ABI手册, RISC-V手册, AXI手册, IP核手册, Flash颗粒手册, PSRAM颗粒手册, SDRAM颗粒手册, GCC/LLVM手册, Makefile手册, Verilator手册…
    • 蕴含着你对计算机系统工作原理的认识

 

  • 社区 - stackoverflow, wikipedia, github issue区, mailing list…
    • ChatGPT - 但不一定能得到正确的答案, 需要有能力核实

 

  • 项目 - README, 文档, 源代码, 构建脚本…
    • 尽最大努力理解一切细节

使用Linux工具提升生产力

使用工具 = 编程

  • 常用命令, strace, PATH环境变量, shell, 命令别名, 正则表达式, 任务管理, 输入输出重定向, 管道, 脚本

 

学习工具首先需要端正心态 - 我真的想提高效率

  • 相信总有对的工具能帮助我做得更好
  • 并愿意付出时间去找到它, 学它, 用它
    • STFW + RTFM + RTFSC, 让计算机为我所用

 

短时间的投入是负收益, 但这些技能会让你终身受益

  • 坚持四周, 就会慢慢适应
  • 坚持半年, 就会有所不同
  • 坚持一年, 就会大有不同

科学地读代码

读代码的最终目的是理解程序

  • 看源码(source): 可以得知每一处静态细节, 但较繁琐
  • 看踪迹(trace): 容易了解运行动态行为, 但不全面

先从容易理解的方式下手(trace), 再结合程序的动态行为理解静态代码

  • make -n -> Makefile
  • 运行NEMU -> GDB -> NEMU代码

 

使用正确的工具提升工作效率

  • 处理make -n的信息方便理解
  • GDB的TUI
  • 查看宏展开结果/代码对齐
  • kconfig/menuconfig/fixdep

科学地写代码

正确的代码 != 好代码

  • 好代码更大概率是正确的

 

好代码的两条重要准则

  • 不言自明 - 仅看代码就能明白是做什么的(specification)
  • 不言自证 - 仅看代码就能验证实现是对的(verification)

 

使用正确的编程模式写出好代码

  • 防御性编程 - 通过assert检查非预期行为
  • 减少代码中的隐含依赖 - 使得 “打破依赖”不会发生
    • 头文件 + 源文件
  • 编写可复用的代码 - 不要Copy-Paste
  • 使用合适的语言特性 - 把细节交给语言规范和编译器

用正确的工具和方法解决bug

需求 -> 设计 -> 代码 -> Fault -> Error -> Failure

  1. 调试公理: 机器永远是对的; 未测试代码永远是错的
  2. 需求 -> 设计: RTFM
  3. Error -> Failure: 添加断言
    • sanitizer = 编译器自动添加断言, DiffTest = 超强的断言
  4. Fault -> Error: 单元测试, 集成测试, 系统测试
    • 形式化验证 = 超强的测试验证方法
  5. Fault -> Failure: 使用lint工具, -Wall, -Werror
  6. 代码 -> Fault: 正确的编程模式, 不言自明, 不言自证

 

  • 自顶向下理解程序行为
    • 通过高层信息快速缩小观察范围, 通过底层信息仔细分析状态变化
    • ftrace, itrace, mtrace, dtrace, etrace / sdb & gdb / trace & 波形

性能bug

  • 使用profiler发现性能瓶颈
    • 了解程序的运行时间都花在哪里
99.99%     0.00%  callgraph  [unknown]
        |
        ---0x64e258d4c544155
           __libc_start_main
           main
           |
           |--58.81%--A
           |          |
           |          |--23.57%--C
           |          |
           |           --23.52%--B
           |                     |
           |                      --11.78%--C
           |
           |--23.51%--B
           |          |
           |           --11.78%--C
           |
            --11.79%--C

项目维护和管理

  • 学会使用正确的工具做正确的事情
    • 读/写代码 -> 编辑器及其高级功能
    • 代码编译和管理 -> make
    • 终端分屏 -> tmux
    • 加速编译 -> ccache, icecream
    • 自动编译运行 -> inotifywait
    • 调试代码 -> trace, DiffTest, gdb, …

 

  • 工具不够用的时候, 学会改进/制造新工具
    • 这是从课程大作业迈进复杂项目的必经之路
      • “每个人都能起Linux”并不是梦
    • 从小事做起 - 理解框架代码中的每一处细节

成为专业码农

  • 要熟悉项目了 -> STFW/RTFM/RTFSC, 尝试理解一切细节
  • 要写代码了
    • 仔细RTFM, 正确理解需求
    • 编写可读, 可维护, 易验证的代码(不言自明, 不言自证)
    • 用lint工具检查代码
    • 进行充分的测试
    • 添加充分的断言
  • 要调试了
    • 默念 “机器永远是对的/未测试代码永远是错的”
    • sanitizer, trace, printf, gdb, 波形, …
  • 平时 -> 用正确的工具/方法做事情
  • 感到不爽了 -> 找正确的工具/搭基础设施
  • 调试了很长时间 -> 反思应该如何改进

第六期课程总结

疫情结束后, 事情开始多起来 😂

  • 高校巡回演讲, 项目攻关, 项目验收, 写材料, 指导学生…
  • 社畜的一天: 开会, 处理微信/邮件, 处理微信/邮件中突然到来的事情, 处理昨天没做完的事情…
    • 今天想做的事情还没开始, 明天再说吧 😂

 

  • 幸好第五期积累了很多课件和素材
    • 比较成熟的课件, 就直接讲了

 

  • 尽管这样, 还是咕咕咕了很久
  • 一个理由: 想着优化一下内容再发布
    • 如果来不及优化, 还不如🕊一下, 让大家先看上一期的资源
    • 和第五期相比能看到一些区别

第五期课程总结时立的Flag

Flag 进度 说明
完善课件的已知问题 ✔️ 重新讲之前都会看看之前记录的问题
将课件内容同步到讲义 🔺 硬件部分基本上重写了, 必做题不多的内容还没想好怎么同步到讲义
添加更多的示例代码 ✔️ 已添加CEMU, 程序的机器级表示demo, 异常处理demo
添加开源EDA ✔️ 已添加yosys + iNO + iSTA
添加性能优化目标 🔺 B阶段已添加面积目标, A阶段暂未添加性能目标
出个基于开源EDA的后端学习讲义 ✖️ EDA小组正在编写, 将要发布初版
改进直播和录制效果 ✔️ 基本上没什么噪声了

第六期自评 - 硬件部分终于重写了, 符合心中预期

  • 约10w字, 字数和我的博士论文相当 😂
    • 异常处理 - 加了移植到AM的RT-Thread, 并集成了AM上的应用程序
    • 总线 - 源自第五期课件, 还加了死锁活锁, 仲裁器, Xbar, PMA等内容
    • SoC - 终于有了像样的SoC讲义了
      • 接入NVBoard, 从板卡到程序的全栈都齐了
      • 相比之下, 前几期接入SoC几乎什么都没学到
    • 性能评估 - 体系结构设计能力的扫盲课
      • 用microbench量化评估NPC性能, 理解每一项技术带来的性能提升
    • cache - 先实现简单版本, 然后介绍如何验证, 最后才是优化
      • 引入3C模型, 梳理优化的技术
      • 添加cachesim, 进行真正的设计空间探索
    • 流水线 - 先实现简单版本, 然后介绍如何验证, 最后才是优化
      • 添加branchsim, 探索不同的分支预测算法

建立了更完整的计算机软硬件系统栈

NVBoard + ysyxSoC + NPC + RISC-V + AM + RT-Thread + FCEUX

  • 你可以知道超级玛丽中的像素是如何显示在NVBoard的屏幕上的

建立了相对完整的处理器前端设计流程

和业界现有的流程非常类似, 只不过使用开源组件

  • 不少工具作为作业, 更能让大家体会相应步骤的意义

建立了相对完整的处理器前端设计流程(2)

  • 终于能展示什么叫体系结构设计
    • 软件发挥重要作用: 功能模拟器 + 负载生成 + 性能评测
    • 再次说明体系结构设计 != RTL设计
  • 增强功能验证
    • 终于加入了强无敌的形式化验证
      • 单周期处理器的高光时刻
  • 性能验证
    • 性能版DiffTest: 和功能模拟器对比部分性能计数器的指标
  • 电路评估
    • yosys + iSTA评估面积和时序

 

自我启发: 在课件/视频中说100次, 还不如在讲义中加一道必做题

  • cache和流水线的讲义就是按照这个流程的顺序设计的

当然也有还不满意的地方 - 给下一轮迭代立个Flag

  • 重写讲义的硬件部分后, B阶段内容暴增
    • 需要更合理的阶段划分, 更加motivation-driven
  • 预学习阶段的坡度还是有点陡
    • 添加C语言和数电的练习, 逐渐过渡到NEMU和NPC
    • 用Logisim建立电路思维
    • Linux系统的搭建和使用往后移
    • 更简单的ISA和更多的示例代码: 用3条指令实现的数列求和程序
    • 用更多的工具展示状态机的理念

 

PS: 以后去掉 “期”的概念, 讲义会按时间版本重新梳理

  • 第五期 -> v22.05
  • 第六期 -> v23.06
  • 下一轮迭代是v24.07

给下一轮迭代立个Flag(2)

  • 给总线添加形式化验证
  • 尝试各种技术路线的testing技术: fuzzing, 求解器…
    • UVM框架太重, 人工写测试/追求覆盖率也不太符合我的技术价值观: 想学就出门右转
      • 有bug就找反例, 没bug就说正确
  • 更专业的benchmark & 性能打榜
  • 功耗评估和优化方法
  • 后端物理设计的学习讲义(EDA团队先出一个版本)
  • 结合开源工艺库学习数字电路
  • A阶段启动Linux
  • S阶段先继续咕咕咕
    • 你在B阶段构建的体系结构设计能力, 已经足够你独立探索S阶段了
    • 总是可以自己探索一个设计方案, 评估后迭代改进

即将启用新的学习阶段划分方案

预学习阶段还分F阶段和E阶段

残酷的事实

  • 以985高校计算机方向的知识点来评价
    • 完成预学习阶段 = 大一上学期水平
    • 完成D阶段 = 大一下学期水平
    • 完成C阶段 = 大二上学期水平
    • 完成B阶段 = 大二下学期水平
    • 完成A阶段 = 大三下学期水平
    • 完成S阶段 = 研究生水平

 

  • “一生一芯”的训练比相应时期的课程大作业还要深入一些
  • 但如果你觉得寸步难行, 你心里也大概知道怎么回事了
    • 懂得都懂
  • 我们看到有的同学, 完成了预学习阶段就把学习经历写到简历上
    • 只能说, 自己掂量吧…

在你们的前方: AI, 开源芯片, 敏捷开发…

技术迭代真的很快

  • 5年前RISC-V还是开会的人占多数, 现在已经有不少人在做了
  • 香山团队用先进技术设计CPU, 3年达到Intel i7-10850K(2020年)水平
    • 这里只谈单核仿真的性能估算数据, 距离产品化还有很长的路要走
  • ChatGPT在2023年年初席卷全球
    • 现在AI已经可以作为一种高级搜索引擎来使用
  • 今年的诺贝尔物理学奖和化学奖都和AI相关
    • AI在将来很可能会成为每个学科的基础设施

 

  • 这些其实对大家的学习提出更高的要求
    • 只会写RTL? 搞不好马上就被AI取代了
      • Logisim作为一个教学工具, 都可以从电路图生成VHDL代码
    • 如果连基础都学不扎实, 就更有可能被AI取代: 考试用AI辅助答题

在你们的后方: 初中生来了

北京一零一中学的初中生尝试学习 “一生一芯”

希望大家能用掌握的知识和能力,
追求更高的目标