zoukankan      html  css  js  c++  java
  • OR1200中指令Cache的结构

    下面内容摘自《步步惊芯——软核处理器内部设计分析》一书

    12.3 ICache结构

          OR1200中实现ICache的文件有or1200_ic_top.v、or1200_ic_fsm.v、or1200_ic_tag.v、or1200_ic_ram.v、or1200_spram.v,分别实现了ICache模块、IC_FSM模块、IC_TAG模块、IC_RAM模块、单口RAM。在ICache中例化了IC_FSM、IC_TAG、IC_RAM模块。在IC_TAG、IC_RAM模块中例化了单口RAM。如图12.4所看到的。当中IC_TAG、IC_RAM能够称为数据部分,IC_FSM能够称为控制部分,在数据部分进行查找操作,将查找结果(ICache命中或失靶)送到控制部分,由控制部分根据查找结果进行下一步的操作,比方:当发生失靶时。控制部分会读入16个字节填充到ICache。

    本节将介绍ICache中的数据部分、控制部分。


    12.3.1ICache模块与其余模块的连接关系

          在介绍ICache数据部分、控制部分之前。先给出ICache模块与其余模块之间的连接关系。有助于后面的分析。

    在第3章介绍QMEM时已经给出了ICache与QMEM、WB_BIU之间的连接关系。从中可知ICache与两者都是Wishbone总线接口。

    ICache的完整接口如图12.5所看到的。


          说明下面几点:

          (1)从图中可知ICache除了具有Wishbone总线接口外,还具有特殊寄存器訪问接口:spr_cs、spr_write、spr_dat_i。这说明ICache中有特殊寄存器。可是该特殊寄存器不能够读(没有spr_dat_o接口),仅仅能写(有spr_dat_i接口)。

          (2)QMEM的输出中有接口icqmem_ci_o,该信号实际直接来自IMMU,回顾一下ITLB中每一个表项都有一个标志位CI。表示相应的页能否够被缓存,该值终于通过QMEM的icqmem_ci_o输出到ICache中。假设要读一个内存块的内容,可是icqmem_ci_o的值为1。那么该内存块是不可能在ICache中的,无需查找ICache。直接从内存中读取,反之,假设icqmem_ci_o的值为0,还要首先在ICache中进行查找。

          (3)ICache与WB_BIU之间的接口名称都是icbiu_xxx_x的形式,ICache与QMEM之间的接口名称都是icqmem_xxx_x的形式,因此,能够通过名称知道这个接口的位置。

    12.3.2 ICache中数据部分

          ICache的数据部分包含IC_TAG、IC_RAM,其主体都是单口RAM。

    两者共同组成了图12.2中的文件夹表。查找方法如图12.6所看到的。


          此处採用的还是OR1200默认的ICache设置。

    IC_TAG共同拥有512个表项,每一个表项包括标识、V,当中标识就是物理地址的高19位。IC_RAM中包括的是数据,对ICache而言。此处的数据就是指令。IC_RAM中4个表项(每一个表项是一个Word,含4个字节)与IC_TAG中一个表项组成ICache文件夹表中的一个line。比方:IC_TAG的第1个表项与IC_RAM中位于地址4-7的Word组成ICache文件夹表的line1。当要取指时时需查找IC_TAG,利用要读取指令地址4-12位的值作为索引查找IC_TAG,得到IC_TAG相应的表项,将该表项返回给ICache模块,后者据此推断Cache是否命中。在查找IC_TAG表的同一时候,利用物理地址2-12位的值作为索引读出IC_RAM中相应的字,假设ICache命中,那么从IC_RAM中读出的字就是须要的指令。

          IC_TAG是通过单口RAM实现的,其主要代码例如以下:

    or1200_ic_tag.v
    module or1200_ic_tag(                             //IC_TAG
    	clk, rst, addr, en, we, datain, tag_v, tag
    );
    
    //数据宽度dw为20,包含地址高19位、有效标志位V
    parameter dw = `OR1200_ICTAG_W;            
    
    //地址宽度为9                
    parameter aw = `OR1200_ICTAG;                              
    ……
       or1200_spram #                 //例化单口RAM
         (   .aw(`OR1200_ICTAG),  .dw(`OR1200_ICTAG_W)      )
       ic_tag0             //从单口RAM中读出的数据doq包含标识、有效位
         (   .clk(clk),    .ce(en),   .we(we),   .addr(addr),  
             .di(datain),  .doq({tag, tag_v}) );   
    
    endmodule
    

          IC_RAM也是通过单口RAM实现的,其主要代码例如以下:

    or1200_ic_ram.v
    module or1200_ic_ram(                                 //IC_RAM
    	clk, rst, addr, en, we, datain, dataout
    );
    
    parameter dw = `OR1200_OPERAND_WIDTH;                 //数据宽度为32bit
    parameter aw = `OR1200_ICINDX;                        //地址宽度为11
    
    ……
       or1200_spram #                                     //例化单口RAM
         (  .aw(`OR1200_ICINDX), .dw(32)
          )
       ic_ram0
         (  .clk(clk),     .ce(en),   .we(we[0]),    .addr(addr),    
            .di(datain),   .doq(dataout) );   
    
    endmodule
    

    12.3.3 ICache中控制部分

          ICache的控制部分会根据IC_TAG、IC_RAM的查找结果控制ICache下一步的操作,ICache的控制部分主要在IC_FSM模块中实现。IC_FSM模块的主体是一个状态机,有三个状态:IDLE、CFETCH、LREFILL3。定义例如以下:

    or1200_defines.v
    `define OR1200_ICFSM_IDLE	2'd0
    `define OR1200_ICFSM_CFETCH	2'd1
    `define OR1200_ICFSM_LREFILL3	2'd2
    
    //本状态尽管定义了,可是并没有使用,所以IC_FSM中状态机仅仅有3个状态
    `define OR1200_ICFSM_IFETCH	2'd3       
    

          状态转换如图12.7所看到的。


          处理器复位的时候处于IDLE状态,当要取指时会进入CFETCH状态。此时分三种情况:

    •   假设ICache命中。那么将从IC_RAM中查找的指令返回给处理器。同一时候保持CFETCH状态
    •   假设ICache失靶。那么会从内存中读取所需指令,然后进入LREFILL3状态。在该状态下会读出所需指令所在内存块中剩余的3个字,也就是将所需指令所在内存块的4个字都读入ICache,然后回到IDLE状态
    •   假设所需指令所在内存块禁止缓存(即CI为1)。那么会从内存中读取所需指令。然后回到IDLE状态

          上述三种情况也是ICache的三种使用情景,本章在后面会结合代码深入分析这三种情景下ICache的工作过程。包含IC_FSM中状态机的状态转换,届时读者朋友会有更加深刻的认识。

    12.3.4 ICache数据部分与控制部分的对外接口

          IC_FSM、IC_TAG、IC_RAM都在ICache中例化。例化语句例如以下:

    or1200_ic_top.v
    ……
    or1200_ic_fsm or1200_ic_fsm(                      //例化IC_FSM
    	.clk(clk),	   .rst(rst),	.ic_en(ic_en),	
    	.icqmem_cycstb_i(icqmem_cycstb_i),
    	.icqmem_ci_i(icqmem_ci_i),	
    	.tagcomp_miss(tagcomp_miss),	
    	.biudata_valid(icbiu_ack_i),
    	.biudata_error(icbiu_err_i),	
    	.start_addr(icqmem_adr_i),	
    	.saved_addr(saved_addr),
    	.icram_we(icram_we),	
    	.biu_read(icfsm_biu_read),	
    	.first_hit_ack(icfsm_first_hit_ack),
    	.first_miss_ack(icfsm_first_miss_ack),	
    	.first_miss_err(icfsm_first_miss_err),
    	.burst(icfsm_burst),	
    	.tag_we(icfsm_tag_we)
    );
    
    or1200_ic_ram or1200_ic_ram(                      //例化IC_RAM
    	.clk(clk),	.rst(rst),	
    	.addr(ic_addr[`OR1200_ICINDXH:2]),	
    	.en(ic_en),
    	.we(icram_we),	
    	.datain(to_icram),	
    	.dataout(from_icram)
    );
    
    or1200_ic_tag or1200_ic_tag(                      //例化IC_TAG
    	.clk(clk),	.rst(rst),	
    	.addr(ictag_addr),	
    	.en(ictag_en),	
    	.we(ictag_we),
    	.datain({ic_addr[31:`OR1200_ICTAGL], ictag_v}),	
    	.tag_v(tag_v),	
    	.tag(tag)
    );
    ……
    

          參考上述例化语句得到图12.8。当中给出了IC_FSM、IC_TAG、IC_RAM模块的接口。以及各个接口连接到ICache的相应变量,每一个模块的左边是输入接口,右边是输出接口,每一个模块内部是接口名,外部引脚上的名称代表ICache中的相应变量。

          图12.8中,IC_TAG的输出tag_v、tag是查找结果,ICache根据此查找结果设置信号tagcomp_miss的值,该信号表示ICache是否命中,而且该信号输入到IC_FSM的同名接口,IC_FSM根据该值进行状态转换、输出控制信号。以进行下一步的操作。

          本章后面分析ICache时须要常常參考该图。读者此刻也不必明确各个接口的含义,笔者留在使用到该接口的时候再做介绍。






  • 相关阅读:
    不同数据类型的取值范围
    反正切函数求圆周率 atan
    HDOJ 1106
    HDOJ 1596
    HDOJ 1026 dfs路径保存
    qsort用法总结
    HDOJ 2088
    HDOJ 1878 欧拉回路 nyoj 42一笔画问题
    HDOJ 1863 prim算法 HDOJ 1879
    HDOj 1010 DFS优化
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6925168.html
Copyright © 2011-2022 走看看