您的位置:首页 > 其它

MIPS cache指令

2016-03-25 16:33 274 查看
MIPS cache指令:

指令编码:

31...26        25...21     20...16    15......0

CACHE(101111)  base        op          offset

格式:

cache op,offset(base)

执行op制定的cace操作,16位的offset经符号位扩展,添加到base寄存器以形成有效地址;

==========================================================

cache指令中的op字段低两位[17:16]表示操作的是哪个cache

2‘b00 I-L1(primary instruction)

2'b01 D-L1(primary data or unified primary)

2'b10    L3Cache(Tertiary)

2'b11 L2Cache(secondary)

cache指令中的op字段高三位[20:18]表示的是cache操作模式,比如:

HitInvalidate, HitWritebackInvalidate, IndexInvalid, IndexStoreTag等。主要表示命中类型(hit/miss)、是否是地址类型(正常的内存访问),是否是索引类型(操作index)。

需要注意的是,对于不同的cache,这高3位所代表的含义不同!

具体含义请查看:

《MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set》

==========================================================

对于loongson提供的pmon中的start_ls232_sm502.S文件中有关cache初始化代码,用到了以下3个宏定义:

#define Index_Store_Tag_D 0x09   // 0x09 = 0000 1001

#define Index_Invalidate_I 0X00 //  0x00 = 0000 0000

#define Index_Writeback_Inv_D 0x01 //  0x01 = 0000 0001

这3个宏是作为op来使用的,下面具体分析它们所代表的含义:

(1).Index_Store_Tag_D表示操作的是D-L1(L1的data cache,2’b01),操作模式是(3'b010)索引存储Tag,将TagLo和TagHi寄存器的值写入指定索引cache块的tag区(即D-L1的tag区)(该操作不允许引发异常);

有效地址操作类型:索引型

(2).Index_Invalidate_I表示操作的是I-L1(L1的instruction cache,2’b00),操作模式是(3’b000)索引作废,将指定索引的cache块状态设置为无效,常用于作废整个指令cache;

有效地址操作类型是:索引型

(3).Index_Writeback_Inv_D表示操作的是D-L1(L1的data cache,2’b01),操作模式是(3’b000)索引写回作废,对于写回型cache(龙芯的是写回型),如果索引的cache块状态为有效且脏,将该块数据写回内存。操作完成后,将该cache块置为无效,如果该块有效但不脏,仅将状态置为无效;

有效地址操作类型:索引型

Index Store Tag:

用TagLo/TagHi寄存器的值设置高速缓存标签!

要从未知状态初始化数据高速缓存,把TagLo/TagHi寄存器设为零,然后逐行进行该操作;

Index Invalidate:

设置该高速缓存行为无效,如果是D-Cache的行有效并且被修改过,那么先将其内容写入内存,再设为无效,这是初始化CPU时作废指令缓存最简单的方法;

Hit Writeback Invalidate:

作废该行,如果数据被污染,要先写回再作废,这是在运行中的数据高速缓存作废的推荐方法;

==========================================================

每种操作都有三种形式,区别在于怎样选择要操作的高速缓存项(即高速缓存行)的方式:

命中型---给出一个地址,从高速缓存中查找,如果找到(命中)则执行操作,否则什么也不干;

寻址型---给出内存中某个数据的地址,处理就和经过高速缓存访问一样,就是说,如果寻址的行不在高速缓存,那么在执行高速缓存操作之前要从内存中取出数据;

索引型---根据要用虚拟地址的低位依次选择高速缓存行内的字节,然后是高速缓存某一路内的行地址,然后是该路;

索引型作废、索引型存储tag、命中型写回作废这三种操作模式是必须实现的(对于MIPS32/64兼容型CPU);

==========================================================

cache数据更新方式

(1)关于回写型cache(write-back cache):

CPU只向cache写入,并用标记加以注明,直到cache中被写过的块要被进入的信息块取代时,才一次性写入主存;

(2)关于写透型cache(write-through cache):

CPU在向cache中写入数据的同时,也把数据写入主存以保证cache和主存中相应单元数据的一致性;

==========================================================

cache组织方式:

(1).全关连方式(fully associative):主存的区块可以映射到cache的任何一个地方;

(2).直接映射方式(direct mapped):主存的区块可以映射到cache的一个地方(惟一);

a.主存与缓存分成相同大小的数据块

b.主存容量是缓存容量的整数倍,将主存空间按缓存的容量分成区,主存中每一区的块数与缓存的总块数相等

c.主存中某区的一块存入缓存时只能存入缓存中块号相同的位置

存储块的位置:

(主存块号)mod(cache中的块数)

地址格式:

tag+index

tag用以标记主存的区是否与cache中缓存的区相匹配(主存按cache大小划分成区)

index用以在cache内寻址,查找对应于cache中的哪一块

(3).组相连方式(set associative):主存的区块可以映射到cache的有限的一个地方,在该方式下cache分为许多组,在一个组中有两个或多个区块,主存的区块映射到某个对应的组中,可以出现在该组的任何一个位置;

a.主存和cache按同样大小划分成块

b.主存和cache按同样大小划分成组

c.主存容量是缓存容量的整数倍,将主存空间按缓冲区大小划分成区,主存中每一区的组数与缓存的组数相同

d.当主存的数据调入缓存时,主存与缓存的组号应相等,也就是各区中的某一块只能存入缓存的同组号的空间内,但组内各地址之间可以任意存放;

即主存的组到cache的组之间采用的是直接映射,在两个对应的组内部采用的是全相连映射;

包含存储块的组:

(块号)mod(cache中组的个数)

n路组关联:

每个块有n个位置可放置的组关联cache

可以把直接映射看成是一路组相连,把含有m块的全关连cache视为m路组关联;

提高关联度能增大命中,但是也增加了命中时间;

地址格式:

tag     index   selector

高地址部分用作tag,低地址部分用作index和selector

==========================================================

初始化程序:

1.开辟一些内存以便可以从它来填充高速缓存。存入什么数据没有关系。一个好的窍门是至少到高速缓存初始化之前预留系统内存的低32K(0x8000)用于此目的;

2.将TagLo寄存器设为零,这样能保证对应行有效的那一位不会置位并且Tag(标签)的奇偶码是一致的,

TagLo寄存器将被cache IndexStoreTag指令用来强制作废对应的高速缓存行并清除标签的奇偶校验位。

3.禁止中断

4.先初始化I-Cache,然后是D-Cache,下面是初始化I-Cache的C代码:

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

  /*clear tag to invalidate*/

  Index_Store_Tag_I(addr);

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

  /*fill once,so data field parity is correct*/

  Fill_I(addr);

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

  /*invalidate again, prudent but not strictly necessay*/

  Index_Store_Tag_I();

  

5.D-Cache的初始化

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

/*clear all tags*/

  Index_Store_Tag_D(addr);

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

/*load from each line(in cached space)*/

  junk = *addr;

for(addr = KSEG0; addr < KSEG0+size; addr += lnsize)

  Index_Store_Tag_D(addr);

  

==========================================================

cache的行匹配和字选择:

cache格式:

-----------------------------------

|有效位  tag  高速缓存块(存放数据)|------>cache的一行

-----------------------------------

地址格式:

高位          低位

----------------------------

tag......index......selector

1.全相连

全相连的地址格式与其它两个不一样,全相连可以看成是只有一个组,所以就不需要index了:

高位          低位

----------------------------

tag.................selector

对每一行进行tag匹配(只有一个组)

若tag匹配成功,则利用selector找出字;

2.直接映射

首先利用index找出组;

比较tag(直接映射每组只有一行);

若tag匹配成功,则利用selector找出字;

3.组相连映射

首先利用index找出组;

对组中的每一行,比较tag;

若tag匹配成功,则在该行中利用selector找出字;

 

 

http://rf.eefocus.com/article/10-07/1968501280485418.html?sort=1751_1812_0_0

cache指令的形式和MIPS的load/store指令的通用形式相同(采用通常的寄存器加上十六位有符号数的偏移量进行寻址)― 但是对应于数据寄存器编码的地方是个5位的操作域,用以编码待操作的高速缓存、确定怎样找到相应高速缓存行、以及找到相应行之后怎么处理。用cache OP , addr这样的汇编代码写入高速缓存行,其中OP只是一个代表操作域的数值。

最好的做法就是使用一个C语言的预处理程序定义一个文本的“名字”代表相应操作的数值。对此没有标准的命名;我就随便用了在MIPS开发工具包的头文件里找到的C预处理中定义的名字。

该5位域的高2位选择要操作的是哪个高速缓存:

O = L1 I-cache

l = L1 ID-cache

2 = L3如果有的话

3 = L2如果有的话

在我们列出这些操作之前,先说明一下,每个操作都有三种形式,区别在于怎样选择要操作的高速缓存项(即高速缓存行)的方式:

命中型操作:给出一个地址从高速缓存中查找。如果找到(即“命中”)则执行操作,否则什么也不干。

寻址型操作:给出内存中某个数据的地址,处理就和经过高速缓存访问一样。就是说,如果你寻址的行不在高速缓存,在执行高速缓存操作之前要从内存取出数据。

索引型操作:根据需要用虚拟地址的低位依次选择高速缓存行内的字节,然后是高速缓存某一路内的行地址,然后是该路。“你必须知道高速缓存的大小才能知道各个域的确切边界,但地址用法跟下面差不多,如图3.3:




一旦选定了相应的高速缓存以及某一行,你有几个操作可以选择。CPU必须支持这三种操作才算得上是MIPS32/64兼容的:索引型作废、索引型存储标签、命中型回写作废。其余操作都是可选的一一如果要用的话,请仔细对照CPU手册。

synci指令为保证你刚刚写入的指令能够正确执行(合并了一个D-cache回写和I-cache作废操作)提供了一个明确清晰的机制。只要你的CPU支持,就应当使用synci而不是传统的替代方案(用一对cache指令来做:D-cache回写后跟一个I-cache作废)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cache指令