码迷,mamicode.com
首页 > 其他好文 > 详细

or1200中IMMU分析(再续)

时间:2014-06-08 15:22:14      阅读:278      评论:0      收藏:0      [点我收藏+]

标签:or1200 openrisc 软核处理   or1200 软核处理器   处理器   软核   

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

 

 

ITLB代码分析

      ITLBIMMU中的主要模块,其实现也相对独立、简单。本节对ITLB的代码进行分析。ITLB的输入输出接口如图10.10所示,图中左边是输入接口,右边是输出接口。

 bubuko.com,布布扣

 

      因为在ITLB中实现了第2组特殊寄存器,所以有spr_csspr_writespr_addrspr_dat_ispr_dat_o等接口,这些接口的含义在分析特殊寄存器类指令的时候已经学习过,应该是非常熟悉的。剩下的输入输出接口含义如下:

  •   tlb_en:输入的ITLB使能信号
  •   vaddr:输入的有效地址
  •   hit:表示ITLB是否命中
  •   ppn:如果命中,那么ppn输出物理地址的13-31
  •   uxe:如果命中,那么uxe就是TR_RAM表中uxe属性位的值
  •   sxe:如果命中,那么sxe就是TR_RAM表中sxe属性位的值
  •   ci:如果命中,那么ci就是TR_RAM表中ci属性位的值

      ITLB内部有MR_RAMTR_RAM两个表,这两个表都是通过单口RAM实现的,单口RAM的代码如下:

 

or1200_spram.v
module or1200_spram  (   clk, ce, we, addr, di, doq   );
   
   parameter aw = 10;                           //地址线、数据线的宽度都可配置
   parameter dw = 32;
   
   input 				  clk;	               //时钟输入
   input 				  ce;	               //片选信号
   input 				  we;	               //写使能信号
   input [aw-1:0] 		  addr;	               //输入地址
   input [dw-1:0] 		  di;	               //输入数据
   output [dw-1:0] 	  doq;	               //输出数据
   

   reg [dw-1:0] 			  mem [(1<<aw)-1:0] 
   reg [aw-1:0] 			  addr_reg;		 //地址寄存器
   
   // Data output drivers
  assign doq = mem[addr_reg];                   //输出数据
   
   //
  always @(posedge clk)
     if (ce)
       addr_reg <=  addr;                       //寄存地址变量到addr_reg
   
   //
  always @(posedge clk)
     if (we && ce)
       mem[addr] <=  di;                        //写入RAM
   
endmodule // or1200_spram


 

      代码很明了,就是使用数组实现了一个RAMFPGA综合工具会自动选择芯片的存储单元实现这个RAM。在ITLB中例化了两个单口RAM,分别作为MR_RAM表、TR_RAM表。MR_RAM表的表项对应ITLBW0MRx寄存器,TR_RAM表的表项对应ITLBW0TRx寄存器。在五种情况下会使用到ITLB

      (1)地址翻译

      (2)使用指令l.mfspr读取ITLBW0MRx

      (3)使用指令l.mfspr读取ITLBW0TRx

      (4)使用指令l.mtsprITLBW0MRx

      (5)使用指令l.mtsprITLBW0TRx

      读者需要结合这五种情况理解ITLB代码,代码如下(为了便于说明,笔者改变了代码的顺序):

 

or1200_immu_itlb.v
module or1200_immu_tlb(  clk,  rst,  tlb_en,  vaddr,  hit,  ppn,  uxe,  
                         sxe,  ci,   spr_cs,  spr_write,  spr_addr,  
                         spr_dat_i,  spr_dat_o
);

parameter dw = `OR1200_OPERAND_WIDTH;
parameter aw = `OR1200_OPERAND_WIDTH;

input				clk;
input				rst;
input				tlb_en;
input	[aw-1:0]		vaddr;
output				hit;
output	[31:`OR1200_IMMU_PS]	ppn;
output				uxe;
output				sxe;
output				ci;
input				spr_cs;
input				spr_write;
input	[31:0]			spr_addr;
input	[31:0]			spr_dat_i;
output	[31:0]			spr_dat_o;

//######################          MR_RAM         #######################
//例化MR_RAM表,因为有64项,所以地址的宽度是6;另外数据宽度是14,在之前已有说明
   or1200_spram #
     (.aw(6),    .dw(14))
   itlb_mr_ram
     ( .clk(clk),   .ce(tlb_mr_en),  .we(tlb_mr_we),   .addr(tlb_index),
      .di(tlb_mr_ram_in),  .doq(tlb_mr_ram_out)  );

//MR_RAM使能的情况有两种:(1)要进行地址翻译,此时tlb_en为1;(2)使用l.mfspr、
//l.mtspr访问ITLBW0MRx寄存器。对于第二种情况的判断条件就是spr_addr[7]是否为0,
//如果为0那么就是ITLBW0MRx寄存器,反之是ITLBW0TRx寄存器
assign tlb_mr_en = tlb_en | (spr_cs & !spr_addr[`OR1200_ITLB_TM_ADDR]);

//如果是使用指令l.mtspr写ITLBW0MRx寄存器,那么tlb_mr_we为1
assign tlb_mr_we = spr_cs & spr_write & !spr_addr[`OR1200_ITLB_TM_ADDR];

//如果是使用指令l.mtspr写ITLBW0MRx寄存器,那么tlb_mr_ram_in就是要写入的值
//可见只取了spr_dat_i的[31:19]、spr_dat_i[0],参考表10.2可知,spr_dat_i[31:19]
//就是有效地址的19-31位,spr_dat_i[0]正是标志位V
assign tlb_mr_ram_in = {spr_dat_i[`OR1200_ITLB_TAG], 
                        spr_dat_i[`OR1200_ITLBMR_V_BITS]};

//MR_RAM、TR_RAM的访问地址,分两种情况:(1)要进行地址翻译,此时需要读取的
//MR_RAM、TR_RAM的地址就是提供的有效地址的13-18位,即vaddr[18:13];(2)使用
//指令l.mfspr、l.mtspr访问ITLBW0MRx、ITLBW0TRx寄存器,此时需要读取的MR_RAM、
//TR_RAM的地址就是spr_addr[5:0]
assign tlb_index = spr_cs ? spr_addr[`OR1200_ITLB_INDXW-1:0] :
                            vaddr[`OR1200_ITLB_INDX];

//MR_RAM的输出,将高13bit赋值给vpn,最低bit赋值给v,参考图10.7可以理解
assign {vpn, v} = tlb_mr_ram_out;

//将查询得到的vpn与CPU提供的有效地址的19-31位作比较,如果相等,且v等于1,那么
//ITLB命中,hit为1,反之ITLB失靶,hit为0
assign hit = (vpn == vaddr[`OR1200_ITLB_TAG]) & v;

//#######################          TR_RAM           #########################

//例化TR_RAM表,因为有64项,所以地址的宽度是6;另外数据宽度是22,在之前已说明
or1200_spram #
     (.aw(6),  .dw(22))
  itlb_tr_ram
     (.clk(clk),   ce(tlb_tr_en),   .we(tlb_tr_we),   .addr(tlb_index), 
      .di(tlb_tr_ram_in), .doq(tlb_tr_ram_out)  );  

//MR_RAM使能的情况有两种:(1)要进行地址翻译,此时tlb_en为1;(2)使用l.mfspr、
//l.mtspr访问ITLBW0TRx寄存器
assign tlb_tr_en = tlb_en | (spr_cs & spr_addr[`OR1200_ITLB_TM_ADDR]);

//如果是使用指令l.mtspr写ITLBW0TRx寄存器,那么tlb_tr_we为1
assign tlb_tr_we = spr_cs & spr_write & spr_addr[`OR1200_ITLB_TM_ADDR];

//如果是使用指令l.mtspr写ITLBW0TRx寄存器,那么tlb_tr_ram_in就是要写入的值
//可见只取了spr_dat_i的[31:13]、spr_dat_i[7]、spr_dat_i[6]、spr_dat_i[1],
//参考10.3.3节
assign tlb_tr_ram_in = {spr_dat_i[31:`OR1200_IMMU_PS], 
                        spr_dat_i[`OR1200_ITLBTR_UXE_BITS],
			                  spr_dat_i[`OR1200_ITLBTR_SXE_BITS],	
			                  spr_dat_i[`OR1200_ITLBTR_CI_BITS]};

//TR_RAM的输出,将高19bit赋值给ppn,剩下的3bit分别赋值给uxe、sxe、ci,参考
//图10.7可以理解
assign {ppn, uxe, sxe, ci} = tlb_tr_ram_out;

//###################          读出的特殊寄存器的值        ###############
//如果使用指令l.mfspr读取ITLBW0MRx,实际就是从MR_RAM中对应的地址读出数据,将该
//数据按照ITLBW0MRx的格式变换,作为spr_dat_o的值输出;如果使用指令l.mfspr读取
//ITLBW0TRx,实际就是从TR_RAM中对应的地址读出数据,将该数据按照ITLBW0TRx的格式
//变换,作为spr_dat_o的值输出;
assign spr_dat_o = (!spr_write & !spr_addr[`OR1200_ITLB_TM_ADDR]) ?   //读ITLBW0MRx               
                    {vpn, tlb_index, {`OR1200_ITLB_TAGW-7{1'b0}}, 1'b0, 5'b00000, v} :
		               (!spr_write & spr_addr[`OR1200_ITLB_TM_ADDR]) ?    //读ITLBW0TRx
			              {ppn, {`OR1200_IMMU_PS-8{1'b0}}, uxe, sxe, {4{1'b0}}, ci, 1'b0} :32'h00000000;

endmodule


 

      从ITLB的代码可知,ITLB并不判断异常,在IMMU模块中会例化ITLB,同时使用ITLB的输出hitsxeuxe判断是否命中或者是否违反页保护策略,这一点会在后面进一步分析。

      在IMMU模块内部例化ITLB的代码如下:

 

or1200_immu_top.v
……
or1200_immu_tlb or1200_immu_tlb(
	.clk(clk),
	.rst(rst),

  .tlb_en(itlb_en),	      .vaddr(icpu_adr_i),	
  .hit(itlb_hit),	        .ppn(itlb_ppn),	
  .uxe(itlb_uxe),   	    .sxe(itlb_sxe),	
  .ci(itlb_ci),           .spr_cs(itlb_spr_access),	
  .spr_write(spr_write),	.spr_addr(spr_addr),	
  .spr_dat_i(spr_dat_i),	.spr_dat_o(itlb_dat_o)
);


 

 

or1200中IMMU分析(再续),布布扣,bubuko.com

or1200中IMMU分析(再续)

标签:or1200 openrisc 软核处理   or1200 软核处理器   处理器   软核   

原文地址:http://blog.csdn.net/leishangwen/article/details/28872843

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!