Gem5: Dispatch
当前 Gem5 (v25.1.0.0) 开始支持分布式发射队列: Dispatch 阶段(IEW::dispatch()),根据 Dispatch 阶段当前状态 dispatchStatus[tid] 决定下一步动作: Running / Idle: 分派指令到 insts 数组:dispatchInsts(tid) Unblocking: 分派指令到 skidBuffer dispatchInsts(tid) 并将来自 Rename 阶段的指令写入 SkidBuffer skidInsert(tid) 并 unblock(tid) 其余状态不做任何动作 分派指令实际执行时:(IEW::dispatchInsts): 循环遍历宽度以内可分派的所有指令 如果遇到指令被冲刷(inst->isSquashed()): 则 continue 处理下一条指令 如果当前指令对应的发射队列 InstQueue 满了(instQueue.isFull(inst)):阻塞整个 Dispatch 阶段: block(tid); 退出循环 如果当前指令是访存指令或原子指令,对应的...
Gem5 Prefetcher
Gem5 version: v25.1.0.0 TODO List: Berti: 可以探索,不同 workload 对 DeltaList 和 HistoryTable 的容量需求是否不同? BOP: L1DCache 使用虚拟地址进行预测?(统计跨页预取) 组合预取器的效果? Gem5 预取器协议所有预取器的基类为 prefetch::Base 预取请求由 PrefetchInfo 类定义,在 Base::probeNotify() 中根据 cache 请求构建预取请求并通过 notify() 将预取请求下发到 cache Base 会根据 useVirtualAddresses 参数决定构建的 PrefetchInfo 中预取使用的地址是虚拟地址(pkt->req->getVaddr())还是物理地址(pkt->req->getPaddr())(useVirtualAddresses 默认 False) 一般而言,只有 L1DCache 有可能使用虚拟地址进行预取,其他 level cache 只能使用物理地址进行预取 L1DCa...
OS Virtual Memory Management
历史最早期的计算机系统 硬件: 物理内存容量小 软件 单个应用程序 + (简单)操作系统 直接面对物理内存编程 各自使用物理内存的一部分 多道编程时代 多用户多程序: 计算机很昂贵,多人同时使用(远程连接) 分时复用 CPU 资源: 保存恢复寄存器速度很快 分时复用物理内存资源: 将全部内存写入磁盘开销太高 多个进程同时使用、各占一部分物理内存: 没有安全性(隔离性) IBM 360 内存隔离: Protection Key 机制 内存被划分为一个个大小为 2KB 的内存块(Block) 每个内存块有一个 4-bit 的 key,保存在寄存器中 1MB 内存需要 256 个保存 key 的寄存器,占 256-Byte 内存变大,则需要改 CPU 以增加 key 寄存器 每个进程对应一个 key CPU 用另一个专门的寄存器,保存当前运行进程的 key 不同进程的 key 不同 当一个进程访问一块内存时 CPU 检查进程的 key 与内存的 key 是否匹配 不匹配则拒绝内存访问 缺点: 不具有可扩展性,随着内存扩大,需要的 key 寄存器太多,无法实现 可...
Linux RISC-V Boot 流程
硬件初始化两种启动方式: 定制化的主板(常见的 RISC-V 开发板,通常不再扩展其他设备) 通用主板(常见如 PC,通常需要再插入其他设备) 嵌入式设备启动 需要初始化具体主板相关硬件如 GPIO 和内存等 从 devicetree 获知有哪些设备 操作系统中需要很多设备相关的驱动 通常与设备强相关 ROM 通常是闭源的 早期启动流程通常是厂商提供的代码 缺点:对可插拔外设的兼容性 如 RISC-V 嵌入式设备支持 PCIe 外设,需要操作系统内核包含具体硬件上的 PCIe 控制器驱动 RISC-V嵌入式平台常见组合: ROM code(在ROM):主板厂商私有 Bootloader(在SD卡或 SPI flash):如u-boot(非必须) Linux kernel(在SD卡) 以常用的基于 U-Boot 和 OpenSBI 的启动流程为例: 从 ROM 中开始执行代码 SoC 芯片内部包含一块 ROM 保存了一些简单的驱动 从 SD 卡或 flash 加载 U-Boot SPL 到一块小内存中(单独的 SRAM 或 L2 cache-as-RAM) ...
Linux Boot 过程
参考: 中国科学院大学 2025年秋《高级操作系统教程》课件 Linux 启动流程 BIOS : 硬件检测,查找加载磁盘上的 MBR MBR : 存储 bootloader 信息,加载 Grub Grub : 查找并加载 kernel kernel : 装载驱动,挂载 rootfs, 执行 /sbin/init init : OS 初始化,执行 runlevel 相关程序 runlevel: 启动指定级别的服务 GrubLinux 上最常用的 bootloader (GNU GRUB: 来自 GNU 项目的启动引导程序) GRUB 允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统 GRUB 可通过链式引导来引导 Windows 系统 支持所有的 Linux 文件系统,也支持 Windows 的 FAT 和 NTFS 文件系统 支持图形界面,可定制启动菜单和背景图片,支持鼠标 拥有丰富的终端命令,用户可以查看硬盘分区的细节,修改分区设置,临时重新映射磁盘顺序,从任何用户定义的配置文件启动 ...
操作系统初始化
参考: 中国科学院大学 2025年秋《高级操作系统教程》课件 计算机启动启动流程: 从上电到内核的第一行代码:BIOS -> bootload任务: 硬件初始化 (BIOS) 初始化 BIOS 检查 CPU 寄存器 检查 BIOS 代码的完整性 检查 DMA, timer, interrupt controller 检查系统内存 检查系统总线和外部设备 跳转到下一级 BIOS (如 VGA-BIOS ) 执行并返回 识别可以启动的设备(CD-ROM? USB? HDD?) 加载内核代码到内存 (bootloader) BIOS (Basic Input/Output System,基本输入输出系统)存放于 BIOS 芯片(ROM)中 三大任务: 初始化硬件 在计算机开机时对系统各组件进行检查 启动操作系统 加载引导程序(bootloader)或操作系统 提供硬件的软件抽象 向操作系统提供系统配置信息 向操作系统提供硬件访问接口,向操作系统隐藏硬件的变化 现代操作系统会忽略 BIOS 提供的抽象层并直接访问硬件 BIOS 中的主...
操作系统:Interupt, Exception, Syscall
参考: 中国科学院大学 2025年秋《高级操作系统教程》课件 中断 Interrupt中断控制器不同 ISA 采用的中断控制器不同: x86: ARM: RISC-V: PLIC(Platform-level Interrupt Controller) 中断控制器需要考虑的问题: 如何指定不同中断的优先级 低优先级中断处理中,出现了高优先级的中断 嵌套中断 中断交给谁处理 如何与软件协同 中断控制器的主要功能:将中断分发给不同的核(对称或非对称)进行处理 分发:管理所有中断、 决定优先级、路由 CPU接口:给每个CPU核有对应的接口 中断处理 中断处理没有进程上下文 中断(和异常相比)和具体的某条指令无关 和中断时正在跑的进程、用户程序无关 中断处理程序不能睡眠 不能调用schedule()调度 不能释放信号或调用可能睡眠的操作 不能和用户地址空间交换数据 Linux 中断处理 在中断处理中做尽量少的事 推迟非关键行为 结构:Top half & Bottom half Top half: 做最少的工作后返回 Bottom half:推迟处...
OOO CPU Issue Stage: Issue Queue
发射队列 (Issue Queue) / 保留站 (Reservation Station) J. Abella, R. Canal, and A. González. Power- and Complexity-Aware Issue Queue Designs. IEEE Micro, 23(5):50–58, September–October 2003. doi:10.1109/MM.2003.1240212 任务:保存已被重命名但未被送到功能单元执行的指令 集中式 (Centralized) or 分布式 (Distributed)实例: reservation stations IBM Power6H.Q. Le, W.J. Starke, J.S. Fields, F.P. O’Connell, D.Q. Nguyen, B.J. Ronchetti, W.M. Sauer, E.M. Schwarz, and M.T. Vaden. IBM POWER6 Microarchitecture. IBM Journal of Research...
OOO CPU Issue Stage: Wake Up
任务:将功能单元计算出的结果通知到发射队列当中所有等待该数据的指令 Tomasulo 算法唤醒当指令执行完之后才将相关指令进行唤醒。 back-to-back 背靠背执行唤醒对于单周期指令 被仲裁电路选中的指令将其目的寄存器编号发送的对应的总线上广播 (tag bus) 发射队列当中的所有指令将 tag bus 上的编号和自己的源寄存器编号对比,如匹配则标记为 ready 通过旁路网络获得寄存器值(这样才能背靠背执行) 发射队列当中的指令如果源操作数均 ready ,则可以向仲裁电路发出请求 一条指令可以轮流向多个仲裁电路发送请求,直到找到愿意响应的仲裁电路(平衡负载) 仲裁电路对所有发送请求的指令进行仲裁选择发射 未发射的指令需要在下个 cycle 继续发送请求 发射的指令会收到仲裁电路的响应信号,并将其目的寄存器编号广播(第 1 步)不会马上离开发射队列:对于访存指令而言可能出现访存违例 发射队列对单周期指令唤醒电路的影响: 如果使用多个小容量的发射队列(分布式) 由于总容量并不变,所以 tag bus 总体的复杂度不变(由于布局布线的问题,可能复杂度会上升)...
OOO CPU Issue Stage: Select/Arbiter
任务:从发射队列中选择出 n 个 ready 的指令送到功能单元中 最优目标: oldest-first 对于压缩式发射队列:仲裁电路实现简单,只需选择发射队列最下面的 n 个 entry 对于非压缩式发射队列:对于分布式发射队列:采用 1-of-M 仲裁每周期从发射队列的 M 个 entry 中选出 1 条指令送到功能单元 识别出发射队列中的哪些指令是 oldest 的? 需要指令的年龄信息:可以利用 ROB 的地址 ROB 本质是 FIFO ,存在读写指针翻转的问题 给 ROB 的每个 entry 增加一位位置位表明是否翻转 当位置位相同时, ROB 的地址值越小,对应的指令越旧 当位置位不同时, ROB 的地址值越大,对应的指令越旧 指令的年龄信息需要写入发射队列(即发射队列每个 entry 需要 Age field ) 屏蔽掉未 ready 的指令? 发射队列中每个 entry 增加一位 ready 位 仲裁电路根据 ready 位和年龄信息进行比较 如何比较年龄信息选出最 oldest 的指令? 多级比较电路:对于容量为 N 的发射队列,需要的比较电路级数...