【问题标题】:Custom Instruction Sets自定义指令集
【发布时间】:2021-04-21 17:49:30
【问题描述】:

我最近看了一个视频,它解释了如何制作自定义指令集(只是概念......它是如何工作的)。该视频是一个系列的一部分,该系列共有 3 个视频:“如何制作自定义指令集”、“如何为该自定义指令集制作汇编器”,第三个将是“如何模拟自定义指令”放”。不幸的是,第三个视频从未发布,所以我去看看我是否可以自己做。 经过我的研究,我很不确定。 制作自定义指令集是否可行?我如何模仿他们?如果我真的想运行它,我需要特定的硬件吗?我如何获得这个硬件?

PS:我看过的视频:1st video2nd video。 (点击它们)

【问题讨论】:

  • MARIE 是只存在于仿真中的机器的自定义指令集。模拟自定义指令集与模拟实际指令集的任务相同(但可能更容易)。仿真的关键在于您不需要需要特殊的硬件来运行它们。

标签: assembly cpu emulation cpu-architecture instruction-set


【解决方案1】:

可以通过多种方式进行仿真:

  1. 解释器循环

该处理器的解释器循环如下所示:

uint16_t memory [ 65536 ];
uint16_t registerFile [ 7 ];
uint16_t pc = 0;
for(;;) {
    uint32_t ix = (memory [ pc ] << 16) + memory [ pc + 1 ]; // instruction fetch (32-bits)
    pc += 2;  // advance two words worth for next instruction as default
    switch ( ix >> 24 ) {
    case 0x00 : // Load R, Immediate
        uint16_t imm = ix & 0xFFFF;
        int regNumber = (ix >> 16) & 0x7;
        registerFile [ regNumber ] = imm;
        break;
    // other opcodes handled by cases
        
    }
}

您可以对自定义处理器进行调整,例如处理器是字节可寻址还是仅字可寻址;无论是大端还是小端等。

  1. 各种形式的翻译

我们可以将一种形式的机器码翻译成另一种形式的机器码,即从自定义指令集到现有指令集。实际的翻译需要将自定义指令集的有状态特征映射到现有指令集的有状态特征,以及机器代码操作在这些有状态资源上的映射。

由于机器代码程序可以进行间接分支,其操作难以静态预测,因此翻译解决方案可能包括映射表,以便在给定模拟程序计数器的情况下找到翻译中的去向。

机器代码程序也可以(间接)从代码内存中加载,因此原始机器代码程序也可以保存在翻译中。

有时翻译也或多或少是动态完成的,如果自定义处理器允许写入代码内存并稍后执行新代码,这可能是必要的。

【讨论】:

  • 值得注意的是,当在 x86 上模拟一些其他常见的现有 ISA 时,qemu 使用动态转换(到 x86 机器代码)。它是开源的,因此您可以查看详细信息。另请参阅bochs.sourceforge.io - 本文 (bochs.sourceforge.net/Virtualization_Without_Hardware_Final.pdf) 从高层次上介绍了 BOCHS 用于快速模拟的一些技巧和设计技术。 (包括缓存一些解码会导致更容易解释的格式。)它必须模拟包括虚拟内存在内的 x86,因此需要模拟 TLB;一个玩具 ISA 通常会忽略这一点并且很容易解码。
  • 您好,非常感谢您的帮助。你甚至不知道你帮助了我多少。但是我还有一个问题:如何在真实硬件上运行这个硬件程序?我已经意识到要“定制”,这意味着没有硬件支持我的指令集。但是有什么方法可以制作我自己的硬件吗? (如果可能的话很容易:)
  • 您可以使用 Verilog 等硬件语言实现处理器,并在 FPGA 上运行。 Verilog 可读性很强,但对软件工程师来说有点陌生,所以学习曲线。不过,我自己没有使用过 FPGA,所以不知道难易程度。我想你必须有一个相当完整的系统,包括一些 I/O 设备。相比之下,软件仿真相当容易,因为您可以用 C、Java 或 C# 编写它,并且可以通过 C/Java/C# 语言运行时处理 I/O。
  • 另一件要考虑的事情是使用RISC V系统,因为硬件是开源的(免费的Verilog源代码)并且指令集是为自定义扩展而设计的,所以你可以从开源代码开始,添加一两条指令。与设计自己的定制处理器不同,但值得深思。
【解决方案2】:

定制指令集是否可行?

是的,当然!你可以做任何你喜欢的东西! (说真的):) 我假设您对“自定义”和“指令集”有特定的定义。对我来说,“定制”意味着它是一个未在已知硬件上实现的指令集。自定义指令集可能真的意味着自定义 CPU 架构。 (这导致了你最后一个问题的答案,我会回答。)如果你对“自定义”有不同的定义,那么你应该分享它。通过“指令集”,我假设您的意思是在功能和范围上与现有 CPU 指令集相似的命令(而不是更极端不同或异国情调的东西)。但无论哪种情况,答案仍然是“是”。

我如何模仿它们?

Erik 内容丰富的回答为这个问题提供了非常丰富的观点。我将专注于一个特定的方面。假设您正在考虑在标准von Neumann architecture 的上下文中运行的自定义指令集,该指令集在带有程序计数器的线性内存阵列中运行,那么您的仿真将是一个伪装成 CPU 的软件。因此,您会:

  • 定义代表 CPU 状态的变量:PC(程序计数器)、寄存器(如果您的自定义指令集支持它们)、CPU 状态位(如果您的自定义指令集和体系结构使用它们 - 可能会使用它们)、堆栈指针(如果您的指令集和架构有堆栈)等。
  • 模拟指令和架构的操作。要做到这一点,你必须考虑你的指令集是如何开始的。例如,一些 CPU 在上电时会在特定的内存位置启动。也许你会做类似的事情。您将在您的仿真软件中定义一个数组来表示您的自定义 CPU 的内存。当您的仿真开始(您的自定义 CPU 开机)时,您会将程序计数器和其他状态变量初始化为其初始条件(由您定义)并开始访问内存(您的数组)中的指令,就像 CPU 一样(获取/执行周期)。

如果我真的想运行它,我需要特定的硬件吗?我如何获得这个硬件?

如果它是自定义指令集,那么我认为直接执行它的硬件不存在,至少根据我对“自定义”的定义(否则,它以什么方式自定义?)。我对“指令集”的定义是它由“接近硬件”的指令组成,即与硬件直接知道如何执行的低级操作一一对应。但如前所述,您可以使用模拟器执行指令。 :)


回应 cmets 中的其他问题。

但是有什么方法可以制作我自己的硬件吗? (如果可能的话很容易:)

是的,当然有一种方法可以设计和创建运行自定义指令集所需的硬件。 容易吗?这取决于你的技能水平。您可以在线找到有关如何从头开始设计基本计算机的资源。尽管对于基本 CPU 而言,各个概念并不难理解,但这并不是一件容易的事,因为要实现的部分很多。您基本上是从头开始设计自己的计算机。

如果您从硬件角度对此主题感兴趣,我强烈建议您在 YouTube 上查找 Ben Eater。他有许多优秀的教学视频,讨论如何创建 CPU 的各个部分。

【讨论】:

  • 您好,非常感谢您的帮助。你甚至不知道你帮助了我多少。但是我还有一个问题:如何在真实硬件上运行这个硬件程序?我已经意识到要“定制”,这意味着没有硬件支持我的指令集。但是有什么方法可以制作我自己的硬件吗? (如果可能的话很容易:)
  • @MiguelCarvalho 你所说的“硬件程序”是什么意思?这只是一个程序。 :) 我会更新我的答案以包含您的其他问题。
  • @MiguelCarvalho:您可能想阅读 RISC-V 指令集手册;一些关于为什么以这种方式设计的 cmets 提到了在硬件中易于解码(例如,对于立即操作数的某些位减少复用,Why are RISC-V S-B and U-J instruction types encoded in this way? 引用了我正在谈论的文本+图表)。当然 RISC-V 的目标是高性能,但对于一个玩具项目,您可以只为硬件保持简单,并接受诸如较小的跳跃位移之类的权衡,而不是“借用”位用于其他目的。
猜你喜欢
  • 1970-01-01
  • 2023-04-04
  • 2019-11-06
  • 2015-11-16
  • 2014-06-24
  • 2018-10-20
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
相关资源
最近更新 更多