https://mp.weixin.qq.com/s/-z9n6SHyAiK2OE7mOSvC2Q

 
简单介绍SRAM的实现。
 
​​
 
1. 基本介绍
 
实现一个支持读写的静态存储器。存取的内容可以使用ECC进行编解码和验证。
 
2. TLRAM
 
TLRAM是DiplomaticSRAM的子类:
​​
 
1) 类参数
 
a. address:支持的地址集合;
b. cacheable:是否可被缓存;
c. executable:是否可执行;
d. beatBytes:数据总线宽度;
e. ecc:ECC编码参数;
f. devName:设备名称;
 
2) 限定条件
 
​​
a. eccBytes:ECC编码每次处理的数据字节数;
b. code:编码类型;
c. eccBytes需要大于1,并且是2的幂;
d. 数据总线宽度需要大于1,并且是2的幂;
e. ECC编码一次编解码的字节数要小于等于总线宽度,否则无法提供足够的数据给ECC编码使用;
 
3) diplomacy node
 
diplomacy node用于与其他节点连接,并协商参数。
 
​​
需要注意的是,这是一个manager节点,也就是他没有下游节点,只能作为节点路径上的最后一个节点。
 
使用类参数生成一个manager的参数:
a. address:使用类参数address生成一个地址集合序列;
b. regionType:根据是否可以缓存进行赋值,即上游节点是否可以缓存SRAM中的数据,SRAM节点本身是不支持缓存的;
c. supportsXXX:不支持burst请求;
d. fifoId:安装FIFO顺序处理请求;
 
使用类参数生成一个ManagerPort的参数:
a. beatBytes:使用类参数beatBytes赋值;
b. minLatency = 1:最低延迟一个时钟周期才能回复响应消息,即a.fire()和d.fire()之间间隔至少一个时钟周期;
 
4) lazy module
 
lazy module用于实现节点的内部逻辑。这里主要是实现SRAM的读写,以及编解码逻辑。
 
下面先介绍不考虑sublane(a_rmw_mask == 0)并且eccBytes == 1的情况。
 
A. 只有一条输入边,而没有输出边
 
​​
符合最下游节点的位置特点。
 
B. 计算需要多少个ECC编解码通道
 
​​
因为每个ECC编解码的数据字节数有限,为了满足beatBytes个字节的数据同时编解码的要求,需要使用多个通道,同时进行编解码。
 
C. 生成一块同步读/同步写的内存
 
​​
 
mem是一块SyncReadMem:
​​
 
D. 用于存储channel a请求信息的寄存器:
 
​​
其中:
a. d_ram_valid:注释的意思是:如果刚从SRAM中读出来的那个时钟周期,那么d_ram_valid为真;其他时钟周期其值为0;
 
 
E. 解码原始数据
 
根据之前对ECC的介绍,对部分变量进行了重命名:
​​
 
a. d_raw_data
 
按ECC编解码通道进行划分的原始数据,从内存中读取:
​​
 
b. d_decoded
 
把每一个编解码通道读取的的数据使用编码算法code进行解码。
 
c. d_decoded_out:解码结果:修正后的数据;
d. d_decoded_raw:未解码前的数据,码文中的原始数据;
e. d_decoded_corrected:是否进行过纠错;
f. d_decoded_uncorrectable:是否存在无法纠正的错误;
 
g. d_need_fix:如果进行过纠错,则需要修正数据;
h. d_error:如果存在无法纠正的错误,则出现错误;
 
F. 通知纠正和不可纠正错误的信息:
 
​​
 
G. 生成回写的数据
 
​​
 
回写是指读取数据,发现错误,进行纠正,然后写回正确数据。
如果eccBytes==1,那么upd=0;回写的是fix也就是ecc纠正之后的数据。
 
H. 生成每个ECC通道是否回写的掩码
 
​​
a. d_wb_lanes_mask:如果发生过纠错,该通道就需要回写;
b. d_wb_poison:存在不可纠正的错误,或者输入的数据有错误;意义是要回写的数据有毒(有错误);
 
I. 是否回写:
 
如果从ram中读取了数据,并且进行了纠错,就要回写:
​​
 
J. 保持解码结果和错误信息:
 
​​
 
K. 组装响应消息到in.d:
 
​​
a. in.d.bits.data
 
如果d_ram_valid为真,那么使用d_decoded_raw。
注释中说,因为d_pause的原因,使用未修正的数据也是安全的。因为如果发生了纠错,那么d_pause就为真,此时in.a/in.d都是被关闭的:
​​
 
考虑到minLatency=1,也就是说in.d在至少一个时钟周期后才能返回,那时候d_ram_valid=0,返回的是d_held_data,这是纠错之后的数据。
整理一下,即:
fire() => d_ram_valid = 1 => in.d.bits.data := d_decoded_raw
=> 至少1个时钟周期 => d_ram_valid = 0 => in.d.bits.data = d_held_data
 
b. in.d.bits.corrupt
 
这里使用的是d_error,也就是存在不可纠正的错误时才会回复数据出错。
也就是可以纠正的错误不会回复数据出错。
 
L. d_pause
 
如果刚读取到的数据需要修正,那么就先暂停接收请求和回复响应:
​​
其中:
如果d_pause为真,表明接收了一个读请求,d_full应当为真;
 
M. 解析接收到的请求:
 
​​
 
N. a_sublane
 
​​
意思是:某些通道没有足够的数据供编解码使用。
 
这里假设eccBytes == 1,先忽略a_sublane。
 
O. 读使能,以及所需ECC通道的掩码:
 
​​
 
P. d.fire()则d_full为假:
 
​​
 
Q. 默认值
 
​​
这里的默认值,实际上是作为最后一个else语句使用。也就是说别处的判断赋值未触发的情况下,就触发这个默认赋值。
 
R. a.fire()
 
解析并存储请求的各项信息:
​​
 
这里跟上面的结合在一起,对a_ram_valid的赋值语句为:
when (in.a.fire()) {
d_ram_valid := a_ren
} otherwise {
d_ram_valid := Bool(false)
}
 
S. 读写使能
 
​​
a. wen:如果需要回写纠正后的数据,或者不是一个读请求,那么需要向SRAM中写数据;
b. ren:如果不是写使能,那么就在a.fire的那个时钟周期打开读使能。这有两个效果:首先,写使能优先;其次,读使能只打开一个时钟周期。
 
T. 生成写逻辑:
 
​​
其中:
a. addr:如果回写,则使用d_address,即有问题数据的地址;否则使用a_address,即要写的数据的地址;
b. sel:如果回写,则使用d_wb_lanes_mask,即发生了修正的ECC通道组成的掩码;否则使用a_lanes_mask,即从in.a.bits.mask中获取到要写哪些数据字节的掩码;
c. dat:如果回写,则使用ECC纠正后的数据作为写入内存的数据;否则使用in.a.bits.data作为写入内存的数据;
d. poison:如果回写,则根据是否有不能纠正的错误来确定要写入的数据是否有毒;否则使用in.a.bits.corrupt来确定;
e. coded:对数据进行编码;如果不能检错,那么就认为没有错;
f. write:写入的是编码后的数据;
 
U. 不支持channel b/c/e:
 
​​
 
3. 流程分析:回写情景
 
这里对读取数据有误而后成功修复后进行回写的流程,进行简单分析。
 
1) 读取数据
 
A. a.fire()
 
​​
 
B. ren打开
 
​​
 
C. read
 
​​
 
D. decode
 
​​
 
E. d_pause
 
因为d_need_fix为真,所以这里暂停channel a/d:
​​
 
2) 回写数据
 
A. d_wb:需要回写
 
​​
 
B. 回写的数据
 
​​
 
C. 回写的掩码
 
​​
 
3) 写数据
 
A. wen
 
​​
 
B. write
 
​​
 
4) 何时回复Get请求?
 
ren打开读取内存数据的下一个时钟周期,d_ram_valid == 0,使得d_pause = 0,进而in.d.valid == 1,可以回复AccessAckData消息:
​​
 
4. sublane
 
sublane的意义为:某些通道没有足够的数据供编解码使用。
​​
 
如果eccBytes == 1,ECC通道要么使用,要么不使用,不存在数据不够用的情况。
 
数据不够ECC通道使用,包含如下几种情况:
a. PutPartial请求中的mask可以为任意值,如果eccBytes == 2,而mask = 0x1011,那么其中一个通道就只有一个字节可以使用,此时就无法进行编码;
b. PutFull请求的大小小于eccBytes,这样数据也不够;如eccBytes == 2,而size==0要写一个字节;
c. Get请求的大小小于eccBytes,虽然也能使a_sublane为真,但是处理与普通的读并无区别;因为每次总是读取beatBytes个字节,足够ECC通道使用;
 
针对Put请求的情况,如何处理呢?
a. 先从RAM中读取缺少的字节;
b. 然后与现有的数据合在一起进行编码;
c. 最后再把合在一起的编码数据写入内存中;
 
5. 附录
 
1) ECC重命名表
 
​​
 
 
 

Rocket - tilelink - SRAM的更多相关文章

  1. Rocket - tilelink - RegisterRouter

    https://mp.weixin.qq.com/s/DaJhf7hEoWsEi_AjwSrOfA   简单介绍RegisterRouter的实现.   ​​   1. 基本介绍   实现挂在Tile ...

  2. Rocket - tilelink - Nodes

    https://mp.weixin.qq.com/s/KJ8pVH76rdxPOZ1vE3QlKA   简单介绍tilelink对Diplomacy Nodes的实现.   ​​   1. TLImp ...

  3. Rocket - tilelink - AsyncCrossing

    https://mp.weixin.qq.com/s/v8plWCBD8vZkxykjJe4TCg   介绍AsyncCrossing的实现,主要介绍如何实现diplomacy Node和LazyMo ...

  4. Rocket - tilelink - mask

    https://mp.weixin.qq.com/s/Gqv09RIgSSg5VKe-wb4aGg   讨论tilelink中使用MaskGen生成mask的用法.   1. tilelink中的ma ...

  5. Rocket - tilelink - Parameters

    https://mp.weixin.qq.com/s/1I6DcONr0Mg7xiX8F1C7SQ   简单介绍TileLink相关的参数实现(具体问题暂时不展开,后续用到时再做分析).   ​​   ...

  6. Rocket - tilelink - Bundles

    https://mp.weixin.qq.com/s/jrqBg2AIpQogBrpwNXjmwg   简单介绍Bundles文件中对TileLink规范(1.7.1)的定义. 参考链接:https: ...

  7. Rocket - tilelink - TLBusWrapper.to

    https://mp.weixin.qq.com/s/jSnhBzU5_ayQCg5fWAcx-g 简单介绍TLBusWrapper.to()的实现.主要介绍确定this{...}对应代码的过程. 1 ...

  8. Rocket - tilelink - BusWrapper

    https://mp.weixin.qq.com/s/03BvgTNQtD75Guco6gUGQg   简单介绍BusWrapper的实现.   1. HasTLBusParams   定义SoC的挂 ...

  9. Rocket - tilelink - Xbar

    https://mp.weixin.qq.com/s/UXFHYEQaYotWNEhshro68Q   简单介绍Xbar的实现.   ​​   1. 基本介绍   用于为Xbar的输入和输出连接生成内 ...

随机推荐

  1. qt creator源码全方面分析(4-4)

    目录 统计接口实现 统计接口实现 我们知道,插件架构必不可少的是定义接口类,即抽象基类,描述用户需要自定义实现的内容.此外,一般还有一个管理器类,对接口类的所有实现类进行管理,并调用其中的接口进行.源 ...

  2. Coursera课程笔记----计算导论与C语言基础----Week 9

    C语言中的控制成分(Week 9) 计算机程序的基本结构 任何具有单入口单出口的程序,都可以用顺序结构.分支结构.循环结构来表达 分支语句 在执行if语句前,先对表达式求解 if()内可以是任意的数值 ...

  3. 第三家面试过程,及导出elcel的进一步小结。(8月11号 周五)

    今天收到第三家公司的面试通知,面试地址也在民治附近,面试时间是上午十点.今早又失眠了,感觉到这边这么几天,总是天天失眠,晚上睡不好白天瞌睡睡不着,估计还需要些许时间的适应,早上七点多我整理好面试需要准 ...

  4. STM32 外部中断详解(原理+配置代码)

    本文介绍了STM32基于标准外设库的外部中断配置,以及基于参考手册如何更加寄存器配置外部中断 文章目录 1 前言 2 STM32的外部中断 3 中断服务函数的映射关系 4 外部中断的配置 5 寄存器的 ...

  5. C:单链表的简单实现

    前言 今天整理资料的时候翻出来的文件,发现是以前学习数据结构的时候写的代码,当初是看郝凯老师的视频学习的C语言的数据结构,下面是对于一个单链表的简单的实现. /** ***************** ...

  6. 房价预测Task1

    pandas:简单的房价预测实例 我们使用pandas等工具,对于给出的.csv文件进行处理,完成要求的几个Task. 利用sklearn的线性回归,对于房价进行简单的预测. 所有的要求,数据集等文件 ...

  7. CF#135 D. Choosing Capital for Treeland 树形DP

    D. Choosing Capital for Treeland 题意 给出一颗有方向的n个节点的树,现在要选择一个点作为首都. 问最少需要翻转多少条边,使得首都可以到所有其他的城市去,以及相应的首都 ...

  8. python中minepy包的下载

    minepy包的下载 今天在做机器学习的时候,需要使用到互信息的有关内容,而python包下正好有处理互信息的包,想直接下一个,没想到遇到了不少问题: 基本指令很简单了: pip install mi ...

  9. JS异步之宏队列与微队列

    1. 原理图 2. 说明 JS 中用来存储待执行回调函数的队列包含 2 个不同特定的列队 宏列队:用来保存待执行的宏任务(回调),比如:定时器回调.DOM 事件回调.ajax 回调 微列队:用来保存待 ...

  10. Unity3D中UGUI不使用DOTween制作渐隐渐现效果

    在做UI后期设计时,我们可能要对UI做一些特效,这篇文章我们来学习下如何在Unity3d中对实现渐隐渐现的效果, 首先我们看下Unity New UI即UGUI中渐隐渐现的做法. 观察我们会发现Uni ...