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

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时须要常常參考该图。读者此刻也不必明确各个接口的含义,笔者留在使用到该接口的时候再做介绍。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

OR1200中指令Cache的结构的更多相关文章

  1. CPU中的cache结构以及cache一致性

    一. 引子 在多线程环境中,经常会有一些计数操作,用来统计线上服务的一些qps.平均延时.error等.为了完成这些统计,可以实现一个多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值.在实 ...

  2. or1200中载入存储类指令说明

    下面内容摘自<步步惊芯--软核处理器内部设计分析>一书 OR1200中实现的载入存储类指令有8条,每条指令的作用与说明如表9.1所看到的. watermark/2/text/aHR0cDo ...

  3. Linux中表示“时间”的结构体和相关函数

    转载于:http://blog.chinaunix.net/uid-25909722-id-2827364.html      Linux中表示“时间”的结构体和相关函数 2011-09-13 17: ...

  4. 浅谈数据库系统中的cache

    Cache和Buffer是两个不同的概念,简单的说,Cache是加速“读”,而buffer是缓冲“写”,前者解决读的问题,保存从磁盘上读出的数据,后者是解决写的问题,保存即将要写入到磁盘上的数据.在很 ...

  5. Windows中进程的内存结构

    基础知识: 栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表.允许插入或删除操作的一端称为栈顶,另一端称为栈底,对栈的插入和删除操作被称为入栈和出栈. 有一组CPU指令可以实现对进程 ...

  6. or1200中IMMU分析(续)

    下面内容摘自<步步惊芯--软核处理器内部设计分析>一书 2 IMMU中的特殊寄存器 OR1200处理器中的IMMU包括第2组特殊寄存器,如表10.1所看到的. ITLBW0MRx是指令TL ...

  7. loongson 2f 和u-boot中的cache命令对照

    00000 Index Invalidate INDEX_INVALIDATE_I (I) 00001 Index WriteBack Invalidate INDEX_WRITEBACK_INV_D ...

  8. Linux内核中内存cache的实现【转】

    Linux内核中内存cache的实现 转自:http://blog.chinaunix.net/uid-127037-id-2919545.html   本文档的Copyleft归yfydz所有,使用 ...

  9. 浅谈数据库系统中的cache(转)

    http://www.cnblogs.com/benshan/archive/2013/05/26/3099719.html 浅谈数据库系统中的cache(转)   Cache和Buffer是两个不同 ...

随机推荐

  1. NodeJS 常用模块积累

    cluster&forever cluster & forever 虽然 nodejs 原生已经提供了 cluster 模块,大部分情况下可以满足我们的基本需求,但这两个模块 clus ...

  2. Python之上下文管理

    http://www.cnblogs.com/coser/archive/2013/01/28/2880328.html 上下文管理协议为代码块提供包含初始化和清理操作的上下文环境.即便代码块发生异常 ...

  3. netty 入门二 (传输bytebuf 或者pojo)

    基于流的数据传输:在基于流的传输(如TCP / IP)中,接收的数据被存储到套接字接收缓冲器中. 不幸的是,基于流的传输的缓冲区不是数据包的队列,而是字节队列. 这意味着,即使您将两个消息作为两个独立 ...

  4. IDEA安装步骤详解

    IDEA开发工具是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.各类版本工具(git.svn.github ...

  5. 小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果

    0x00 前言 发现最近没有了写长篇大论的激情,可能是到了冬天了吧.所以这篇小文只是简单介绍下如何在Unity中利用shader很简单的实现雪地效果以及毛皮效果,当然虽然标题写在了一起,但其实这是俩事 ...

  6. 状态压缩 - LeetCode #464 Can I Win

    动态规划是一种top-down求解模式,关键在于分解和求解子问题,然后根据子问题的解不断向上递推,得出最终解 因此dp涉及到保存每个计算过的子问题的解,这样当遇到同样的子问题时就不用继续向下求解而直接 ...

  7. python打包exe pyinstaller 简单使用

    源由 最近公司让做了一个小工具,使用python写的,写完之后要求能放在其它电脑上运行,于是就开始寻找方案; 按网上的说法 py2exe已经很久没更新了,资料也不多: 于是就采用pyinstaller ...

  8. 关于Python在Linux、Mac和Windows上的安装方法总结

    一.Linux下安装python   1.python源码安装包下载地址:   https://www.python.org/downloads/source/   2.下载完tar.xz压缩包以后, ...

  9. Java数据结构和算法(一)——简介

    本系列博客我们将学习数据结构和算法,为什么要学习数据结构和算法,这里我举个简单的例子. 编程好比是一辆汽车,而数据结构和算法是汽车内部的变速箱.一个开车的人不懂变速箱的原理也是能开车的,同理一个不懂数 ...

  10. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...