Rocket - util - MaskGen

https://mp.weixin.qq.com/s/_aJqf1cFJDK5RVRBhxTWOw

介绍MaskGen的实现。

??

1. 基本介绍

给定总线宽度beatBytes,根据访问的地址(address)和访问的字节数(bytes = 2^lgSize),生成访问字节的掩码。

2. 实现

思路不复杂,写法很难懂。重构一下,提高可读性。

1) 首先忽略groupBy,清爽很多:

??

2) 把addr_lo重命名为address,把lgSize重命名为size,这样可以很明显的看出来address/size是一对参数。把内部的局部变量size重命名为siz。

??

3) 把beatBytes重命名为width,同时把lgBytes重命名为lgWidth

??

4) log2Up与log2Ceil意义相同,且被废弃,使用log2Ceil替代。替代之后发现,无需重新计算,直接使用lgWidth即可:

??

5) nbit的命名挺别扭,既不符合RTL习惯(bit_n),也不符合软件习惯(有下滑波浪线提示)。因为只有一处使用,所以可以直接去掉,无需使用临时变量。

??

上面这些重构比较简单,基本上都是从形式上进行。

6) 把helper重命名为getMask

从apply的返回值看,helper的返回值即是最终生成的掩码,只是位序相反。所以把helper从中性无意义的名字,修改为getMask这一个表示用途的名称:

??

7) i的意义

helper是递归方法,i每次减一。

helper(0)返回1位掩码:1 = 2^0;

helper(1)返回2位掩码:2 = 2^1;

helper(2)返回4位掩码:4 = 2^2;

把helper(i)中的i从对数值,换成原值,参数i的意义就是要返回的掩码位数:helper(n),n为要返回的掩码的位数。

helper(1)返回1位掩码;

helper(2)返回2位掩码;

helper(4)返回4位掩码;

调整内部对n的使用:

a. 对数值减法换为原值的除法;

b. 判断对数值为0,等价于判断原值为1;

??

8) 提取重复代码:log2Ceil(width / n)

width为mask的总宽度,n为要求取的掩码数。

width/n是把原有总共width个比特分成n个组(group),其值为每个组包含的比特数。

?

这样n的意义,除了表示求取的掩码数,也表示把原width个比特,划分成的小组的数目。

9) j重命名为group

生成掩码时使用的序号为j:

??

因为每个小组一个掩码,这个j同时也是小组的编号,将其从中性无意义的j,重命名为group,以表示小组的编号:

??

10) 重命名getMask为getMaskForNGroups

把getMask重命名为更清楚表达用途的名称getMaskForNGroups:

??

11) acc的意义

MaskGen是要生成访问内存的掩码。可以推测acc是访问(access)的意思。

更进一步,acc是一个标志位,标志着否访问所对应的group。这里有两个不同的可能意义:

a. 访问组内的比特对应的全部字节;

b. 访问组内的比特对应的部分字节;

12) n == 1

当n=1时,把所有width个比特看出一个整体,生成一位掩码。其实现为:

??

其中:acc = size >= UInt(lgWidth),eq = Bool(true)。

当acc=true时,size >= lgWidth,即要访问的长度,大于总线宽度。也就是说width个字节都要访问,即组内各比特对应的字节全部都要访问。这里把上面acc两种可能意义中的b排除掉了。

13) sub_acc

所谓sub,实际上是上一个层次,即当自己为1/4时,所在的1/2。

??

从acc的实现可以看出,如果sub_acc为真,则acc为真。意义为:如果width个比特中,如果某1/2的acc为真,则标志着这1/2个比特对应的字节全部都要访问,那么包含在这1/2中的2个1/4自然也都是要访问的。

14) bit = address(lgBitsInEachGroup)

用于计算地址中的偏移量,如同样访问一个字节,从0x0000开始访问与从0x0001开始访问的掩码是不同的,分别为0b0001和0b0010。

根据bitsInEachGroup的不同,其所对应的地址偏移量也不同。

如果小组内有1个比特,则每个组占用的偏移量为1个字节;

如果小组内有2个比特,则每个组占用的偏移量为2个字节;

如果小组内有4个比特,则每个组占用的偏移量为4个字节;

bit代表address中,与group占字节数相对应的地址位。比如:

当bitsInEachGroup=1时, lgBitsInEachGroup=0,取address的第0位,该位代表的偏移量为1;

当bitsInEachGroup=2时, lgBitsInEachGroup=1,取address的第1位,该位代表的偏移量为2;

当bitsInEachGroup=4时, lgBitsInEachGroup=2,取address的第2位,该位代表的偏移量为4;

15) siz = sizeOH(lgBitsInEachGroup)

与小组占字节数相对应的大小位:

当bitsInEachGroup=1时, lgBitsInEachGroup=0,取sizeOH的第0位,代表访存大小是否为1;

当bitsInEachGroup=2时, lgBitsInEachGroup=1,取sizeOH的第1位,代表访存大小是否为2;

当bitsInEachGroup=4时, lgBitsInEachGroup=2,取sizeOH的第2位,代表访存大小是否为4;

siz用于计算acc:

??

在sub_acc为假的情况下,即当前1/4所在的1/2没有被完全访问的情况下,计算当前1/4是否被全部访问。

siz为其中一个条件,意义为:访存大小等于当前1/4所含的比特数。

a. 如果访存大小小于当前1/4所含的比特数,则无法全部涵盖当前1/4,则acc=false;

b. 如果访存大小大于当前1/4所含的比特数,则size大于等于1/2包含的比特数;同时因为sub_acc为假,所以当前1/4所在的1/2都没有被访问。那么当前1/4也没有被访问,即acc=false;

16) eq

??

eq的意义为:当前小组是否被访问(全部或者部分)。

当n=1,即所有width个比特都在一个组内的情况下,eq为真,即总被访问(全部或者部分)。

sub_eq的意义为:当前1/4小组所在的1/2小组是否被访问。若要所在的1/2没有被访问,则当前1/4也不可能被访问:

??

如果所在的1/2全部被访问,则sub_acc=true,两个1/4的acc也都为true;

如果所在的1/2部分被访问,则sub_acc=false,两个1/4中只有一个被访问。至于哪一个被访问,则与bit的值有关。

第一个1/4(group%2=0)是否被访问与!bit相同;

第二个1/4(group%2=1)是否被访问与 bit相同;

即:

如果bit=0,则第一个1/4被访问;

如果bit=1,则第二个1/4被访问;

结合bit的意义:

如果bit=0,则从基地址0开始访问;

如果bit=1,则需要加上一个偏移量;

17) eq的命名

eq是equal的缩写,相等的意思。

相等涉及两个参量,a=b,这里的eq表示谁和谁相等呢?

被访问的小组和当前小组?

这个名称提示意义不足。

18) acc总结:

??

若要acc为真,有两种可能:

a. sub_acc为真,即1/4所在的1/2全部要访问;

b. siz && eq: 访问的大小与当前小组的大小一致,并且当前小组被访问。也就是当前小组被全部访问。

19) acc与eq重命名

acc => allBitsInGroupAccessed;

eq => anyBitsInGroupAccessed;

这样是不是更容易理解一些?

??

3. groupBy

按注释:

??

groupBy的功能是把width个比特,分成每groupBy个比特一组,每一组中原来的掩码使用OR reduction求一个值作为新的掩码值。

然而groupBy的实现是错的。没有发现是因为现有工程中,没有使用groupBy的功能,都是默认值1。

实现中:

??

else里面求取的是_._1,即allBitsInGroupAccessed。也就是说分组中全部的比特都要被访问,而不是只要一个比特被访问即可,是AND reduction,而非OR reduction。

_._2即anyBitsInGroupAccessed是OR reduction,但是生成的mask是错误的。所以groupBy的实现实际上是错误不可用的。

把groupBy加回来:

??

1) 没有必要判断groupBy == width

当width == groupBy时,else中返回的也是UInt(1),所以没有必要单独判断:

??

2) width / groupBy

groupBy即是每个小组中包含的比特数,width / groupBy是分成的小组的个数。

3) UInt(groupBy * 2 - 1)

生成一个掩码,其中位[groupBy-1, 0]为1。

4) 对sizeOH的影响

若读取的字节数大于groupBy包含的比特数(每个比特对应一个字节),则没有影响;

若读取的字节数小于groupBy包含的比特数,则相当于把读取的字节数拓宽到groupBy中包含的比特数个字节。

例如:

size=0(读取的字节数为1),groupBy=2(最小分组包含2个比特):

原sizeOH=0b01,新sizeOH=0b11。

sizeOH(1)=1,起到读取了2个字节的效果。

4. 实例

??

参考链接:https://docs.qq.com/sheet/DUWZaWXdFcW1TYW56?opendocxfrom=admin&preview_token=&coord=J2%24J2%240%240%240%240&tab=5xebeq

很遗憾的是,与注释中的例子不一样:

??

欢迎指出我的错误之处,谢谢!

5. 附录

原文地址:https://www.cnblogs.com/wjcdx/p/10952169.html

时间: 2024-10-18 02:26:22

Rocket - util - MaskGen的相关文章

Rocket - util - AsyncQueue

https://mp.weixin.qq.com/s/6McbqOKM4fu4J5vdpZvxKw 简单介绍异步队列(AsyncQueue)的实现. ?? 0. 异步队列 异步队列的两端分属不同的时钟域,拥有各自的复位逻辑. 异步队列用于存值的一端为上游端(source),用于取值的一端为下游端(sink). 1. AsyncQueueParams ?? 异步队列的参数,包含如下几项: a. depth 队列深度,表示队列可以存储几个元素: b. sync 表示流水线的级数. c. safe 使

Rocket - util - ECC

https://mp.weixin.qq.com/s/yato1PrnHe517J8twgZFOg 介绍ECC(Error Correcting Code/Error Checking and Correcting)的实现框架.不涉及编码的具体实现细节. ?? 1. 码:Code ?? 所有编码(如奇偶校验码.海明码)的抽象父类. 包含如下几个方面: a. 能否检错:canDetect: b. 能否纠错:canCorrect: c. width():输入为数据的宽度,输出为编码后码文的宽度,一般

Rocket - util - MultiWidthFifo

https://mp.weixin.qq.com/s/CUnrpyQN5LRBR5bxC5u86A 简单介绍MultiWidthFifo的实现. ?? 1. 基本介绍 实现一个输入宽度为inW,输出宽度为outW,可存n个outW宽度元素的FIFO. a. 如果inW == outW,直接使用队列(Queue)实现: b. 如果inW > outW,则相当于每次输入多个元素,而输出只能有一个元素: c. 如果inW < outW,则相当于每次输出多个元素,而输入只能有一个元素: 需要注意的是,

Rocket - util - Repeater

https://mp.weixin.qq.com/s/xyEq3DgYuf2QuNjssv8pkA 简单介绍Repeater的实现. ?? 1. 基本功能 A Repeater passes it's input to it's output, unless repeat is asserted. When repeat is asserted, the Repeater copies the input and repeats it next cycle. 2. 实现 1) io ?? a.

Rocket - util - PrefixSum

https://mp.weixin.qq.com/s/G2vLP-ncoJzSOgxGGEJkfA 简单介绍PrefixSum的实现. ?? 1. 基本介绍 ?? 把一个序列从前向后逐个执行迭代(assocOp),每针对一个元素执行一遍迭代,针对一整行执行一次迭代(layerOp). 2. PrefixSum ?? a. layers:抽象方法,返回层数,等于layerOp执行的次数: b. idLayer: 默认的layerOp,即没有动作,把输入原样返回: 3. RipplePrefixSu

Rocket - util - Replacement

https://mp.weixin.qq.com/s/zCP7wPuxgQ-r94Tr6BV5iw 简单介绍Replacement的实现. ?? 1. 基本介绍 用于实现Cache替换相关的功能. ?? From: Cache Replacement Policies, Prof. Mikko H. Lipasti, University of Wisconsin-Madison, ECE/CS 752 Spring 2016 2. ReplacementPolicy 代表替换策略的抽象类. ?

Rocket - util - ReduceOthers

https://mp.weixin.qq.com/s/gbR5fuDbE_nUFVxw-p4rsA 简单介绍ReduceOthers的实现. ?? 1. 基本介绍 输入一组Bool元素,把其他位置元素逐个相与的结果,作为当前位置的值输出. 2. helper helper实现ReduceOthers的核心功能: ?? 1) 输入参数 x是输入的一组Bool类型的元素. 2) 返回值 返回一个元组:(Seq[Bool], Bool) a. Seq[Bool]:每个位置上返回其他位置上元素逐个相与的

Rocket - util - Timer

https://mp.weixin.qq.com/s/Z4JJhZ_jL1lqF1nf_orq9A 简单介绍Timer的实现. ?? 1. 基本功能 实现定时器的功能. 2. Timer 实现一个静态装入的定时器: ?? 1) initCount 定时器的初始值,静态配置,不可动态改变. 2) maxInfligh 定时器事件的种类. 3) io ?? a. start:某个定时器事件需要启动定时器,io.start.bits为这个定时器事件的ID: b. stop:某个定时器事件需要停止定时器

64位开源处理器Rocket的源代码简单介绍

最近大概阅读了一下UCB发布的Rocket处理器的源码,对源代码各个文件的功能有了一些大致的了解,Mark一下. Rocket是一款64bit的标量处理器,5级流水线,采用的是risc-v指令集,集成FPU,并有许多or1200没有的特性,比如:无阻塞缓存.分支预测.返回地址堆栈.硬件页表填充.cache支持ECC.支持多核等. Rocket的源代码是使用Chisel编写的,Chisel是UCB发布的基于Scala的领域特定语言.可以在https://github.com/ucb-bar/roc