Posts

缓存结构

1.直接映射     直接映射是将内存中每个地址,按缓存能够承载的数量进行分配。比如内存总共有12个地址而只能缓存三个的时候,每三个内存地址对应一个缓存位置。     当,两个内存地址不同但缓存位置相同的地址被轮流访问的时候,会不断发生缓存未命中。 2.组相联     一个内存中的数据可以放在缓存中不同位置,如果有n个位置,则称为n位组相联。

浮点数

浮点数有区别于整数,直接用二进制来表示具体的数字有一定难度。一般采取IEEE-754标准作为浮点数的表示方法。 如果以32位作为例子:           1       xxxxxxxx          xxxxxxxxxxxxxxxxxxxxxxx.....(23个)     符号位     exponent                         significand            具体的例子:         1        10000000       10000000000000000000....                                     -1*2^(128-127)*1.5=-3.0       当exponent=0时,会认为significand的基础值时0而非1。

流水线处理器基础知识

 基础概念  1. 流水线的结构本质上是增加更多的寄存器来提高指令的吞吐率,并以此来提高处理器的性能。  2. 流水线带来的加速比约等于流水线级数,5级流水线带来的加速比接近5(指令足够多时)。  3. 经典流水线的五个阶段:IF(取指),ID(译码),EX(执行),MEM(访存(如有必要)),WB(写回(如有必要))。  4. 流水线时在顺序指令流中的指令间并行技术。   流水线冒险  1. 结构冒险:两个指令同时对一个资源进行使用时,容易出现结构冒险。     2. 数据冒险: 两个前后指令同时依赖一个数据,比如:                       add x19,x0,x1                      sub x2,x19,x3      此时,指令1的输出被指令2依赖,然后指令2进行译码阶段时,指令1还没有进行到WB阶段,寄存器的值还并没有刷新,指令2的计算结果就会出现问题。 3. 数据冒险解决办法: 增加旁路(bypassing)或前递(forwarding)。 这是指,在2的例子中,x19的新值是可以在EX阶段后将值直接传递给指令2的EX阶段之前(ID阶段之后),由于指令2比指令1慢一个阶段,bypassing可以刚刚好解决这个问题。 4. 流水线停顿(pipeline stall  俗称: bubble): 虽然bypassing是很好的解决方案,但是这并不能避免所有的冒险。比如 ld指令取指一个值,然后一个紧跟的算术指令依赖这个被ld取的值,那么前递就无法解决问题。因为ld指令需要访存(MEM)阶段才能成功取值,此时后面的算术指令已经过了EX阶段,我们无法使用bypassing传递此时的值给第二条指令的ID阶段后,因为这是时光回溯(不可能的)。所以我们必须停顿流水线一个节拍后,那么对应的,第二条指令就会慢一拍,那么指令就刚执行到ID阶段后,此时,再使用bypassing,就可以解决问题。 5. 控制冒险:控制冒险是当遇到分支指令会发生的情况,所以也被叫做分支冒险。因为指令在完成IF阶段后,就会对PC进行运算,此时PC中的下一条指令已经进入流水线,但是很可能因为分支指令,这条指令其实是不该被运算的,那么就会出现冒险的情况。处理分支冒险比较复杂,简单的思路是,我们需要在ID阶段计算分支目标地址以及更新PC,所以这需要额外的资源,并

ECC

 汉明码是通过奇偶校验的方式对编码是否有错进行判断并纠正。  对于任一数据,首先需要将其改造为汉明码,即,预留,第01,10,100,1000(二进制)位等的数据。    然后比如,第110位,因为其位可以同时含有010和100,那么对应的第01和100位就需要记录对应位的值,并对所有记录的值进行奇偶性计算。比如,如果所有含有最后一位为1的位的数里,含有1的数量为奇数,那么第01位需要补一个1,使所有含有最后一位为1的位的数里的1的个数保持为偶数。以此类推,计算所有特殊位的值。计算有多少个1的数量是偶数还是奇数的过程可以通过xor来实现。    经过传递编码之后,现在需要对数字进行校验。    首先校验所有含有最后一位为1的位的数里1的数量的奇偶性。由于我们人工已经确保了这个值一定是偶数,如果出现奇数,则代表一定出现了错误。 以此类推,不断计算所有特殊位,如第10,100,1000,即倒数第二位为1,倒数第三位为1...等等。    假如,最后计算的结果是,倒数第一位为1的位的所有1的数量为奇数,且倒数第三位为1的的所有1的数量为奇数,其他都是偶数,那么发生错误的坐标可以直接计算出来:     第101位,即,汉明码的第5位。     这是因为实际上,我们利用二进制的加法,对原始数据进行了特殊处理,从而保证了所有奇偶校验位可以表达所有的位。 比如第8,4,2,1位的奇偶校验位可以表示直到汉明码的第15位。比如,第1111位,它实际含有四个1,所以他被这四个奇偶校验位全部追踪,有且只有它发生错误时,才会导致所有四位出现问题。实际上可以理解为,比如第1010位发生错误,由于它含有倒数第二位和倒数第四位的1,所以它被第8和第4位所检验的奇偶性包含。那么反过来,当8 4 两个奇偶性出问题时,这代表着所出现问题的数字一定是包含了1000和0010,即1010。 由于汉明码采取了正好是对应二进制数字每位的编码方式,如果其他位不出现奇偶性不出现问题,那么也证明所出现问题的位数一定不包含那些位。     这样的方法使得汉明码拥有一位纠错能力。     而实际上,我们还会使用最后多加的一位奇偶校验位来多验证一位。最后一位作为奇偶校验位时,如果只发生一位数字出错,那么由于奇偶性,可以检测,但是如果两位同时翻转,就无能为力了。     所以,将最后的奇偶校验位和汉明码结合一起就是,设最后

缓存

 缓存:    关键理解: 对于直接映射:  1. 内存地址的格式是根据缓存的结构来的,通常需要:index+tag+offset+index of block。      index是指缓存块的索引,缓存块是指以分块的形式将缓存的每一部分和内存对应。可以有重叠。比如,如果一共有1024个块,那么第1025和第1内存地址都指向缓存块1。index of block是指缓存块内的索引,一个缓存块可以存储多个字,利用空间局部性原理,增加缓存命中率。offset是字内索引,索引字节,一个字等于4字节,所以一般是2位。tag是内存位数减去其他所有。  2. 缓存的格式一般是 index+valid+tag+data。 index与tag是和内存里的解释一样的,valid则是用来判断此缓存是否已经被使用。data则是存储内存存储的数据,如果一个数据块大小是4个字,那么data会有4*4*8比特。  3.缓存块容量更大,通过空间局部性原理,我们可以推断缓存命中率会变高,但是,与此同时,如果缓存没有命中,那么替换缓存内的数据的成本则是更高,因为大缓存块里字比较多,很难快速替换完成。失效损失会增大,缓存性能反而有可能增大。  4. 存储的指令失效时,只是从内存中取数据到缓存,而写入操作还需要更新内存的数据(因为缓存内数据不一样了),所以周期会更长。为了能够降低写操作带来的影响,使用写回策略(write-back),只有当被改写的数据块不再被需要的时候,才将缓存数据写回内存。  5. 为了避免性能损失,只加大缓存块并不可取,如3中所写,会增加失效损失。但是,如果提高了存储带宽,也就是如果能够更快速的传输cache的数据块,那么便可以减少失效损失的影响。所以一般为了提高内存性能,需要带宽与缓存块大小共同发力。  对于组相联映射: 1.组相联映射理论上可以表示其他所有映射模式:如假设cache中有8个数据块。对于直接映射来说,这意味着一共有8组数据,每组数据只包含一路数据块,所以直接映射也可以被表示为一路组相联映射。而对于全相联映射来说,则意味着,只有一组数据,这一组数据之中会存在8路数据块,所以对于n个数据块的情况,全相联映射等价于n路组相联映射。 2.依然以8组数据块的cache为例。当cache以两路组相联映射为基础结构时,那么总共就有8/2=4个数据组,每个数据组里有两路数据块。

Dadda和Wallace乘法器的区别

 Dadda是从bottom到top反向推算如何进行数据压缩,高层是低一层的1.5倍取整。最低一层是2,所以从下到上是2,3,4,6,9,13...   Wallace乘法器则是遇见三列可压缩的数据就可以压缩,所以可以这样计算:                  新stage层数 n,  旧stage层数k,则                            n=2*(k/3取整)+kmod3,如k=8时,则n=2*2+2=6    具体实施时,wallace一定要维持3:2的压缩,dadda则是按着规定的层数递减即可,最终dadda会比wallace省用很多加法器。    压缩的时候需要进行递补的原则,比如 竖着的三位如若使用FA进行压缩,就会只剩一位,那么此时需要后面的列使用HA来传递一位补位。具体可以根据以下网站的图片来理解。 https://stackoverflow.com/questions/54374925/differences-between-wallace-tree-and-dadda-multipliers                         具体而言当使用wallace来压缩时,因为对于三列的阵列来说,当遇到第一个三列进行压缩时,FA虽然能压缩3bit的数据到2bit,但是cout是传递到后一列的,所以实际上,每一列的压缩其实等价于是4->2。而第一个使用3列的部分,需要从前一列得到补位来维持两列,所以前一位需要使用HA来传递一位进位。   而使用dadda压缩时则不那么激进,比如我们现有最大8列数据,我们只需要进行最简单化的8->6压缩即可。所以,对于8列数据的隔壁7列数据来说,使用一个HA即可,实现7->6。而7列数据的进位被传递到了拥有8列数据的阵列,那么实际上8列会变成9列,所以需要进行9-3,即使用一个FA和一个HA。那么同理,8列数据左边的数据也会得到2个进位,从而变成7+2=9列数据,所以也需要一个FA和一个HA。以此类推。最终实现6列数据即可。正因如此,dadda会比wallace省用很多加法器。             

托福 TPO词汇题汇总

  TPO1: Incredible : unbelievable Out of sight: hidden Overlie: cover Plug: fill up Champion: support Attribute: ascribe 导致,把。。归咎于 Autonomous : independent 自治 独立 Penchant : inclination 倾向 Dramatic (剧烈的) striking (显著的 突出的) Attain :   achieve Prone( 有。。倾向 ) : likely Prevalent : widespread TPO2: Threatened : endangered Delicate : fragile Progressively : increasingly devoid of (缺乏): lacking in precious : valuable exposed : visible propulsion(推进) : moving forward readily (轻而易举): easily assistance : help expanded : was enlarged TPO3: feasible(可行的):achievable enhance:improve devise(设计、 发明): creat integral(完整的,必须的):essential (基本的,必要的) arduous(艰巨的):difficult ensuing(跟随、接下来):subsequent unprecedented(史无前例):unlike anything in past vitually(几乎):almost inevitable:unavoidable particular(特别的,特定的):specific guarantee:ensure pales (苍白无力):loses significance adjacent : neighbouring TPO4: inhibit(阻拦,阻止): restrict in the same breath: immediately re

基于verilog的单周期CPU

 最近研究了一下CPU的运行原理,以MIPS指令集为例,用verilog写了个单周期的CPU,算是对CPU的理解加深了一些。   完整代码和注释在: https://github.com/ChenlinShi/Verilog_Basic_Circuits

基于verilog的微复杂电路

 Ripple cary adder: module eight_bit_adder (   a ,   b ,   cin ,   cout ,   sum ,   clk ,   rst ); input [ 7 : 0 ] a , b ; input cin , clk , rst ; output   reg cout ; output   reg [ 7 : 0 ] sum ; reg [ 6 : 0 ] bit_carry ; always @( posedge clk or negedge rst ) begin     if (~ rst ) begin     cout <= 0 ;     sum <= 0 ;     end     else begin     { bit_carry [ 0 ], sum [ 0 ]}<= a [ 0 ]+ b [ 0 ]+ cin ;     { bit_carry [ 1 ], sum [ 1 ]}<= a [ 1 ]+ b [ 1 ]+ bit_carry [ 0 ];     { bit_carry [ 2 ], sum [ 2 ]}<= a [ 2 ]+ b [ 2 ]+ bit_carry [ 1 ];     { bit_carry [ 3 ], sum [ 3 ]}<= a [ 3 ]+ b [ 3 ]+ bit_carry [ 2 ];     { bit_carry [ 4 ], sum [ 4 ]}<= a [ 4 ]+ b [ 4 ]+ bit_carry [ 3 ];     { bit_carry [ 5 ], sum [ 5 ]}<= a [ 5 ]+ b [ 5 ]+ bit_carry [ 4 ];     { bit_carry [ 6 ], sum [ 6 ]}<= a [ 6 ]+ b [ 6 ]+ bit_carry [ 5 ];     { cout , sum [ 7 ]}<= a [ 7 ]+ b [ 7 ]+ bit_carry [ 6 ];     end end endmodule //8_bit_adder testbench: module tb_rca_bi