linux动态二进制翻译,仿真:解释和二进制翻译

2b3445c1f8e42fb34f9e0210246bc60d.png

仿真就是在一个具有某种接口和功能的系统或子系统上实现另一种与之具有不同接口和功能的系统或子系统的过程。

指令集仿真可以使用多种方法来实现,这需要不同数量的计算资源,并且提供不同的性能和可移植性。其中的一个极端就是直接的解释技术,另一个极端就是二进制翻译。解释包括取一条源指令,对其进行分析,执行需要的操作,再取下一条源指令这样一个循环过程,所有工作都是由软件完成的。另一方面,二进制解释试图分摊取值和分析的代价,它将源指令块翻译为目标指令块,并且将翻译后的代码保存起来以便反复使用。

其中使用了表驱动法的技术,并对其进行了某些扩展和优化

基本的解释

狭义上,一个解释器程序在一台实现源ISA的及其的完整结构状态上仿真运行,这些状态包括所有的结构寄存器和主存。客户机内存的印象,包括程序代码和程序数据,被保存在有解释器维护的内存区中。解释器的内存中还保存着一张称之为上下文块的表,它包含了源结构状态的不同部件。

一个简单的解释器是通过逐条指令地执行源程序来运行的,它根据指令读取并修改源状态。这样的解释器常被称为译码分派(decode-and-dispatch)解释器,因为它是围绕一个主循环来组织的,即译码一条指令,然后将其分派给基于指令的解释历程。

线索解释

译码-分派解释器的主分派循环包含许多直接和间接的分支指令。这些分支依靠硬件实现,它们往往会降低性能,特别是在它们难以被预测的时候。除了在循环顶部测试暂停或中断之外,还有针对switch语句的寄存器间接分支,到解释器历程的分支,从解释器历程返回的二级寄存器间接分支,一直最后的结束循环分支。其区别如下:

89e4fce204d5e4b2aa3154d04f40406a.png

预译码和直接线索解释

尽管间接线索解释器消除了集中分派循环,但是集中分派表还是会带来开销。在这个表中查找一个解释器历程仍然需要内存访问和寄存器间接分支指令。为了获得更高的效率,消除对集中表的访问时值得的。

进一步的观察发现,每次遇到一条指令,都会调用一个解释器历程。这样当同一源指令被解释多次时,对于这条指令的每个动态实例,检查指令和提取各个域的过程必须被重复进行。如果这些重复的操作仅仅被执行一次,将提取出的信息以中间形式保存,然后在每次这条指令被仿真时复用,这样看来就更高效了。这个过程称为预译码。

基本的预译码

预译码涉及解析一条指令并且将它表示成能简化解释的形式。

直接线索解释

尽管间接线索解释具有易于移植的优点,但是由分派表引起的间接性同样有性能代价:要访问这个表就需要一次内存查找。为了去除分派表查找引起的间接层,包含在中间代码中的指令代码可以用解释器历程的实际地址来代替。这样尽管速度快了,但是这使得中间形式变得依赖于解释器历程的精确位置,从而限制了可移植性。如果解释器代码被移植到一个不同的目标机器上,就必须为执行它的目标机器重新生成。然而一些编程技术和编译器特性可以在某种程度上减轻这一问题。

解释一个复杂的指令集

034578cc4e3607cb7a3495e809ed31bd.png

二进制翻译

把每个单独的源二进制指令映射到它自己的定制目标代码上,性能将会显著增强。这种将源二进制程序转化为目标二进制程序的过程称为二进制翻译。对预译码(带有线索解释)和二进制翻译,在两种情况下,起初的源代码都被转化为另一种形式。但是在预译码的情况下,仍然需要解释器例程,而在二进制翻译中转化后的代码被直接执行。

代码发现和动态翻译

代码发现的问题

在使用传统ISA的实际代码中,尤其是CISC ISA,代码发现会因为指令长度可变、寄存器间接跳转、在指令中穿插数据和为对齐指令所做的填充等成为一个问题。

代码定位的问题

源代码中的地址被翻译到目标代码中

增量式预译码和翻译

在前面提到的两种情况下,通常的解决方案是在程序正运行在实际输入数据时,即动态地翻译二进制代码,并且在程序到达新代码段时增量地预编译和翻译这些新代码段。

一个简单的、增量式翻译过程工作如下:在源二进制代码被加载到内存中后,EM使用简单的译码-分派或间接线索方法开始解释二进制代码。随着它的进行,解释器动态地产生中间代码或翻译后的目标二进制代码。翻译代码被放到代码cache中,相应的SPC到TPC映射被放到映射表中。当遇到分支或跳转指令时,解释器就完成了一个动态基本快的翻译。接着,EM就沿着源程序的控制路径(使用映射表),或者在下一块已经被翻译(在表中有一个命中)时直接执行下一块,或者在下一块还没有翻译时开始翻译下一个动态基本块。逐渐地,程序的更多部分被发现和翻译,直到最终只执行翻译代码。

f1ff006efd01f1ba475c88482f143c9c.png

追踪源程序代码

控制转移优化

翻译链接

在这种方式中,每次翻译一个块,但是它们在构造时就被链接在一起形成链。后继翻译块的地址时通过SPC的值访问映射表,找出对应的TPC(如果相应的基本块已经被翻译)来确定的。如果后继块还没有被翻译,那么将插入标准的存根代码。在稍后的某一时刻,当后继块被翻译并且前驱块推出进到EM之后,EM将访问映射表,找出在表中的条目,取回后继块的TPC。

软件间接跳转预测

内联高速缓存,并非所有的映射都是通过hash查找来实现,最频繁使用的映射被单独提取出来。这种技术应该与profiling相结合,profiling提供关于间接跳转目标的精确信息。

影子栈

指令集问题

寄存器结构

条件码

惰性计算,它保存设置条件码的操作数和操作而不是条件码设置本身。这使得仅在需要的时候才生成所需的条件码。例如,可以维护一张惰性条件码表,它对每个条件码位建立一个表项。这个表项包含最近修改这个条件码位的指令的操作码、它的操作数和它的结果。不过,并不产生条件码本身。于是,如果随后的指令,如一个条件分支,需要使用一个或多个的条件码位,就会访问条件码表并产生所需的条件码。

数据格式和运算

内存地址解析

内存数据对齐

字节序

寻址地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是格雷码转二进制的 Verilog 程序及其 Testbench 文件的示例: ```verilog module gray_to_binary( input [3:0] gray, output reg [3:0] binary ); always @* begin binary[3] = gray[3]; binary[2] = binary[3] ^ gray[2]; binary[1] = binary[2] ^ gray[1]; binary[0] = binary[1] ^ gray[0]; end endmodule ``` 在上面的代码,我们定义了一个名为 `gray_to_binary` 的模块,它有一个 4 位灰码输入端口和一个 4 位二进制输出端口。在模块的 `always` 块,我们使用异或运算符(`^`)将每个灰码位与前一位二进制值进行异或运算,从而得到相应的二进制位。 接下来是 Testbench 文件的示例: ```verilog module gray_to_binary_tb; reg [3:0] gray; wire [3:0] binary; gray_to_binary dut( .gray(gray), .binary(binary) ); initial begin $dumpfile("gray_to_binary_tb.vcd"); $dumpvars(0, gray_to_binary_tb); #10 gray = 4'b0000; #10 gray = 4'b0001; #10 gray = 4'b0011; #10 gray = 4'b0111; #10 gray = 4'b1111; #10 $finish; end endmodule ``` 在 Testbench 文件,我们首先定义了一个名为 `gray_to_binary_tb` 的模块。该模块包含一个 4 位灰码寄存器和一个 4 位二进制线路。我们使用 `gray_to_binary` 模块实例化了一个 DUT(Design Under Test)。在 `initial` 块,我们通过改变输入灰码的值来测试 DUT 的功能。在每个输入值之后,我们使用 `#10` 延迟了 10 个时间单位,以等待 DUT 计算输出。最后,我们使用 `$finish` 命令停止仿真。 要运行这个 Verilog 程序及其 Testbench 文件,您需要使用 Verilog 模拟器。例如,在使用 Icarus Verilog 编译器的 Linux 系统上,您可以执行以下命令: ```bash iverilog -o gray_to_binary gray_to_binary.v gray_to_binary_tb.v vvp gray_to_binary gtkwave gray_to_binary_tb.vcd ``` 第一行命令将编译器使用 `gray_to_binary.v` 和 `gray_to_binary_tb.v` 文件生成一个可执行文件 `gray_to_binary`。第二行命令将运行可执行文件并执行仿真。最后一行命令将打开 GTKWave 波形查看器以查看仿真结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值