RISC-V on Rust 从零开始(8) - 实作instruction decoder

这次要来实作指令decoder,负责pipeline中的decode stage。计组教科书上常见的pipeline架构依序为:fetch、decode、execute、memory、write back,当然在一个instruction-accurate(IA)的模拟器中,没有必要去切得这麽细,目前只要大致分成fetch、decode以及execute三个步骤就好,memory与write back就合并在execute stage。这三个步骤做的处理罗列如下:

  • Fetch: 从memory中读取指令。
  • Decode: 解析指令的raw byte,并且呼叫指令相对应的函式。
  • Execute: 执行指令,依据指令的不同可能会读写记忆体(对应memory stage),或修改暂存器或PC的内容(对应write back stage)。

Fetch Stage

暂时先以常数取代,等memory model实作完成後再来时做此stage。

Decode Stage

稍微研究了现有的模拟器是如何实作decoder,发现主要有两种方法:

  • 将指令的特徵放在一个array,每次decode都去查表看符合哪个entry,很明显这个方法复杂度为O(n),n为指令列表的长度。通常这个方法会配合另一个buffer来记录最近match到的指令,每次decode就先查buffer,没有的话才查原本完整的表,由於locality的关系,只要这个buffer的大小合适,就能大大的降低decode所需的时间。
fn decode(inst_bytes) -> InstID {
    for entry in instruction_table_buffer {
        if (inst_bytes & entry.mask) == entry.opcode
            return entry.inst_id
            
    for entry in instruction_table {
        if (inst_bytes & entry.mask) == entry.opcode {
            instruction_table_buffer.add(entry)
            return entry.inst_id
        }
    }
}
  • 利用条件判断的方式,判断是哪个指令,复杂度为O(1),虽然复杂度较低,可以预见code会比较杂乱,会有大量的switch-case。
fn decode(inst_bytes) -> InstID {
    switch (inst_bytes & mask_a) {
        case 0: {
            switch (inst_bytes & mask_b) {
                case 0:
                    return InstID::SUB
                ...
            }
        }
        case 1:
            return InstID::ADD
        ...
    }
}

这边采用第二种方案,并且保留弹性,之後也可以实作第一种方案,并且比较两种的效能。

Execute Stage

很简单,直接呼叫对应的指令function就好。

Summary

将以上的三个stage结合起来就可以完整的执行一条指令:

impl RVCore {
    fn step(&mut self, inst_bytes: u32) {
        // Decode
        let inst = self.id_instance.decode(inst_bytes);
        
        // Execute
        (inst.operate)(self, &inst);
        self.pc += inst.len;
    }
}

let mut core = RVCore{};
// Fetch, 假设fetch的结果为0x00002197(AUIPC)
core.step(0x00002197);

完整的程序码可以参考此连结


<<:  使用证书对代码进行签章,以防止其被篡改并向用户验证您的身份-使用您的私钥对代码进行散列并加密结果

>>:  各家笔电还原的快速键

Feedly 和 Inoreader,用RSS阅读器蒐集实用数位行销blog推荐资讯

这个实用网路行销工具系列文,将会整理我平常研究的各项网路行销工具,帮助工程师如果有现成的服务可以快速...

Day 13 Section Summary

Implement audio wave generator using the Mbed API ...

Day 19 - WooCommerce: 初始化付款外挂

虽然在 WordPress 中扩充功能有很多方式,例如在布景主题上使用子布景主题 (child th...

远距 Scrum

前言 前两天分享了远距工作的好处与挑战,今天针对应用面来谈谈 Scrum 活动如何在远距工作的情况下...

sed - 6 Hold Space简介

前篇回顾 sed - 简介 读取编辑文字档的好工具 sed - 2 Pattern sed - 3 ...