实在是忍不住了!
懂HDL的竟然不知道microarchitechture!还在哪里叫着:“decode模块相同,所以两个芯片相同。”
我来科普一下(不一定准确,懂IC的来纠正,不懂的别瞎搀和)。
1、CPU干了什么工作?
CPU最核心的工作其实只有2个:
1)访问内存
2)根据指令要求计算,读写寄存器文件
2、CPU是怎么干这两个工作的?
我们编写程序,最终交给CPU的形式就是可执行文件。可执行文件最重要的就是代码段。
代码最终呈现给CPU的格式由CPU的指令集(ISA)规定,同样的代码可以在AMD的CPU上正确执行,也可以在Intel的CPU上正确执行,说明该代码使用的ISA再两个CPU上都实现了。反过来,使用3DNow!扩展指令集的代码就不能在Intel的CPU上正确执行。
CPU逻辑上一次从指定位置(PC寄存器的值)读取一个指令,并把PC的值改成下一个指令的位置。这个过程叫做Instruction Fetch。
取得的这一个指令可能有不同的格式,比如有些的加法指令,有些的访问内存指令。要分辨这些格式,并对不同的格式做出不同处理。这个分辨的过程就是Instruction Decode,decode的code是什么呢?就是Opcode(Operation Code),也就算我们所说的指令。由于x86早期内部不是现在这样流水线化的,所以现在在x86上,还需要一步把x86指令转换成内部流水化内核的指令(microcode)。
然后CPU对已经分辨出是什么类型的指令进行具体的操作了,是访存指令的去计算访问内存的具体位置,是加法指令的去做加法。这个过程叫着Execute。
然后CPU就访存(访存指令),这个过程比较长,叫做Memory Access。
最后把结果(ALU的或读内存的)写到寄存器。这个过程叫做Write-back
这个就是经典的MIPS 5级流水线,现在的CPU完成的基本工作都在这里了。
这里插两幅图:



但现代CPU不是单纯的RISC或者CISC,它有更多其他的技术,比如龙芯2采用的乱序超标量技术。
同样,先要IF,但龙芯2是4发射,一次可以读取4条指令。
然后ID,一次decode4条指令,但由于要乱序执行,就得对4条指令的依赖关系进行判断,做出相关的处理。
然后ALU,选择准备好的指令发射到最多4个执行单元(Load/store Unit,2 ALU,2FPU之中选)、MEM,作后WB的时候又得按指令的顺序进行,保证数据不会因为乱序执行而错乱。乱序超标量需要做大量的辅助工作,所以龙芯2的流水线从传统的7级超标量流水线(如R10000系列),分割到了9级。这一层次就叫做mircoarchitecture了,里面有大量的技术来保证指令快速,正确的运行。由于采用这种设计,龙芯2基本上可以接近或达到每个时钟周期运行2条指令(IPC=2)这样的水平。
这里插一幅图:


指令集相同,opcode必然相同,而opcode相同,decode模块就相同吗?
以下是我从网上找来的一个decoder的verilog(一种硬件描述语言)代码,
描述的这个模块把4-bit的binary_in,decode成16-bit的decoder_out。
//-----------------------------------------------------
// Design Name : decoder_using_case
// File Name : decoder_using_case.v
// Function : decoder using case
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module decoder_using_case (
binary_in , // 4 bit binary input
decoder_out , // 16-bit out
enable // Enable for the decoder
);
input [3:0] binary_in ;
input enable ;
output [15:0] decoder_out ;
reg [15:0] decoder_out ;
always @ (enable or binary_in)
begin
decoder_out = 0;
if (enable) begin
case (binary_in)
4'h0 : decoder_out = 16'h0001;
4'h1 : decoder_out = 16'h0002;
4'h2 : decoder_out = 16'h0004;
4'h3 : decoder_out = 16'h0008;
4'h4 : decoder_out = 16'h0010;
4'h5 : decoder_out = 16'h0020;
4'h6 : decoder_out = 16'h0040;
4'h7 : decoder_out = 16'h0080;
4'h8 : decoder_out = 16'h0100;
4'h9 : decoder_out = 16'h0200;
4'hA : decoder_out = 16'h0400;
4'hB : decoder_out = 16'h0800;
4'hC : decoder_out = 16'h1000;
4'hD : decoder_out = 16'h2000;
4'hE : decoder_out = 16'h4000;
4'hF : decoder_out = 16'h8000;
endcase
end
end
endmodule
上面是case版本的,也用不用case的版本:
//-----------------------------------------------------
// Design Name : decoder_using_assign
// File Name : decoder_using_assign.v
// Function : decoder using assign
// Coder : Deepak Kumar Tala
//-----------------------------------------------------
module decoder_using_assign (
binary_in , // 4 bit binary input
decoder_out , // 16-bit out
enable // Enable for the decoder
);
input [3:0] binary_in ;
input enable ;
output [15:0] decoder_out ;
wire [15:0] decoder_out ;
assign decoder_out = (enable) ? (1 << binary_in) : 16'b0 ;
endmodule
如果用C语言来描述一下,就相当于
static inline void decoder_using_case (bool enable,uint4 *binary_in, uint_16 *decoder_out)
{
if(enable)
*decoder_out=1<<*binary_in;
else
*decode_out=0;
}
指令相同,具体如何decode由具体的CPU决定,我可以把32位加法指令操作部分decode成1,也可以decode成2,随我喜欢,decode模块怎么可能就一定相同?
大家可以看看这本书:《Computer Architecture A Quantitative Approach》已经出到第4版了。
[
本帖最后由 jamesr 于 2008-7-3 15:17 编辑 ]