Rocket - regmapper - RegMapper
https://mp.weixin.qq.com/s/aXxgzWwh6unuztjgyVX0iQ
简单介绍RegMapper的实现。
1. 简单介绍
RegMapper使用指定的输入接口,为一组寄存器生成读写访问逻辑。
2. RegMapperParams
定义RegMapper需要的参数:
a. indexBits:索引号占用的位数;
b. maskBits:数据掩码的位数;
c. extraBits:额外参数的位数;
3. RegMapperInput
访问逻辑使用的输入接口:
a. read:是否读请求;
b. index:访问的目的寄存器的索引号;
c. data:写请求时输入的数据;
d. mask:数据的掩码,每个字节一位掩码;
e. extra:额外的参数;
4. RegMapperOutput
访问逻辑的输出接口,用于返回请求的响应:
a. read:是否读请求的响应;
b. data:读请求的响应数据;
c. extra:返回的额外的数据;
5. RegMapper
1) 可以提取出来的方法
a. toBits/ofBits
Convert to and from Bits:
实例:
b. litOR
用于判断第一个参与OR的参数是否为值为真的字面量,如果是则直接截断返回判断结果,即Bool(true):
c. mux
a) MuxSeq使用index从cases中选择,如果没有则使用default值:
b) f的类型为Seq[(Bool, Bool)];
c) 每一组s/g/f返回一个out || !g;
d) f所有元组中第二个元素相与(and)的结果输出到out;
2) RegMapper.apply
下面使用重构之后的代码介绍。
A. 参数
a. beatBytes:总线宽度(字节数);
b. concurrency:支持多少个并发访问;
c. in:访问请求输入接口;
d. mapping:要访问的所有寄存器域:
根据注释,Map的第一个元素为字节地址,第二个元素为这个字节地址对应的寄存器包含的寄存器域;
B. 过滤掉长度为0的寄存器域
其中,offset为字节地址偏移量;
C. 寄存器的字节地址不能为负值
D. 把字节地址分组的寄存器域,展开成使用位偏移量的寄存器域
其中,元组的第一个元素为寄存器域的位偏移量。
E. 检查寄存器域是否重叠
因为bitmap中的寄存器域已经排序了,所以只需要比较相邻的两个寄存器域是否重叠即可:
F. 把bitmap转换为wordmap:
每个word包含beatBytes个字节。wordmap中的key为字偏移量。对比之下,bytemap中二元组的第一个元素为字节地址偏移量,bitmap中二元组的第一个元素为位偏移量。
G. 确保所有寄存器域都可以按照字偏移量进行索引:
从中可以看出:寄存器索引(index)以字为单位,每个字包含beatBytes个字节。
H. 使用out返回响应结果
I. 使用front接收请求信息
J. 处理并发请求
a. 若寄存器域的读写有一个是时序逻辑,则需要使用pipeline;
b. depth为可以缓存的请求数量,即可以同时处理的请求数量;
c. back为Queue的输出端,或者就是front本身;
K. 找到区分字偏移量所需要的最少的位
其中:
a. mask:使用AddressDecoder获取到的包含最少掩码位的掩码;
b. maskMatch:undefZero相关,这里不关注;
c. maskFilter:把mask中各个位的值转换为Boolean列表;
d. maskBits:统计mask中为1的位的个数;
L. 计算有效寄存器字的数量
M. 计算有效寄存器字索引号
a. 软件计算:regIndexI;
b. 硬件计算:regIndexU;
这里为什么不用重载呢?两个方法都可以叫做regIndex,参数类型不同,编译器可以区分。
N. 使用有效字偏移量,摊平寄存器域
返回值是三元组序列:
a. 第一个元素是使用regIndexI计算出来的有效字偏移量;
b. 第二个元素是寄存器域的字内位偏移量;
c. 第三个元素是寄存器域;
O. 为每个寄存器域和有效寄存器字声明控制信号
其中:
a. frontMask和backMask是把位掩码拓宽为字节掩码的结果;
b. xxvalid/xxready每个寄存器域一个;
c. xxfire每个有效寄存器字一个;
d. dataOut每个有效寄存器字一个,用于处理读取请求时返回寄存器字的数据;
P. 逐个处理每个寄存器域
Q. 提取寄存器域信息
a. reg为有效字索引号;
b. low为字内位起始偏移量;
c. high为字内位终止偏移量;high不能超过字的范围;
d. field为寄存器域;
R. 提取寄存器域对应的掩码
a. rimask:前端掩码相应位相或的结果,r指read,i指input,即读请求的输入掩码;orR()的意义为只要涉及寄存器域的一个位,该寄存器域就参与操作;
b. romask:后端掩码相应位相或的结果,r指read,o指output,即读请求的输出掩码;
c. wimask:前端掩码相应位相与的结果,w指write,i指input,即写请求的输入掩码;andR()的意义为需要涉及寄存器域的全部位,该寄存器域才参与操作;
d. womask:后端掩码相应位相与的结果,w指write,o指output,即写请求的输出掩码;
e. front和back分别是Queue的前端和后端,亦即输入端和输出端,所以这里i和o也有输入端和输出端的意涵(implication),接下来在使用中还要具体辨析其含义;
S. 生成寄存器域的读写逻辑
这里以读请求为例,寄存器域读请求相关信号如下图:
先看f_rivalid:
a. rimask表明请求涉及到当前寄存器域;
b. rivalid(i)标识该寄存器域所在寄存器字中的其他寄存器域是否都准备好接收读请求;
c. 可以想见,其他寄存器域是否准备好接收读请求,也依赖于当前这个寄存器域是否准备好接收(f_riready);也就是说当rivalid(i)为真时,f_riready为真;
d. f_rivalid的意义为读请求输入有效;
再看f_roready:
a. romask表示请求涉及到当前寄存器域;
b. roready(i)表示是否准备好接收,所属寄存器字中的其他寄存器域的响应;
c. 是否准备好接收其他寄存器域的响应,也依赖于是否准备好接收当前寄存器域的响应(f_rovalid),也就是说当roready(i)为真时,f_rovalid为真;
d. f_roready的意义为准备好接收该寄存器域的响应;
然后看i/o:
a. f_rivalid是rimask掩码后的结果,rimask是请求队列(Queue)输入端的掩码,也就是说,只有涉及到该寄存器域时,其输入才有效;
b. f_roready是romask掩码后的结果,romask是请求队列(Queue)输出端的掩码,也就是说只有涉及到该寄存器域的请求出队时,才打开接收响应的开关。Queue是请求队列,没有涉及到该寄存器域的请求出队,则没有对该寄存器域的请求,自然也不需要接收响应;
最后:
a. f_riready由寄存器域输出;
b. f_rovalid由寄存器域输出;
c. 由寄存器域输出的信号,由寄存器域的读函数(RegReadFn)决定,而RegMapper这里不涉及如何产生这些信号的问题;
T. 收集寄存器字的控制信号
a. reg为有效寄存器字索引号,随着对所有寄存器域的遍历,该寄存器字包含的所有寄存器域的控制信号二元组都会被归集到该序列中;
b. litOR(f_riready, !rimask)等效于f_riready || !rimask,即寄存器域准备好接收请求或者不涉及该寄存器域;如果不涉及该寄存器域,那么接收请求又何妨呢?
c. rivalid(i)的值使用所在寄存器字的其他寄存器域的litOR(f_riready, !rimask)决定,这在后续代码中实现;
根据mux的实现:
a) f中包含寄存器字包含的全部寄存器域;
b) ReduceOthers的第一个效果是把f中所有元组的第二个元素相与之后赋值给out;第二个作用就是给rivalid(i)赋值,使用的就是f中除i之外的所有元组的第二个元素相与,然后再与valid && s && g相与;
U. 使用寄存器域读出的数据,组合寄存器字读请求应该返回的数据
a. 如果寄存器域偏移量为0,则直接使用相与的f_data即可;
b. 如果不是0,则需要把已经搜集的寄存器域数据,与f_data组合;需要注意的是flat中的寄存器域都是排过序的,所以f_data应该被置在高位,而dataOut(reg)与UInt(0, width=low)相或,则把现有的dataOut(reg)的位数拓展为low位;
c. 然后再与f_data组合之后的prepend,位数为high位;
d. 更新dataOut(reg)的值为组合之后的新值;需要注意的是,这个更新是在循环中进行。也就是在软件构建过程中进行。当该寄存器字包含的所有寄存器域都遍历完之后,dataOut(reg)中就组合了所有寄存器域读取数据,最后硬件逻辑中使用的是这个构建结果;
V. 入队请求索引号/出队请求索引号
W. 是否可以入队/是否可以出队
a. rifireMux表示读请求是否可以入队;wifireMux表示写请求是否可以入队;
b. rofireMux表示读请求是否可以出队;wofireMux表示写请求是否可以出队;
c. 这里忽略iRightReg/oRightReg,假设其中所有值都为true;
d. 以rifireMux为例:
a) in.valid && front.ready && front.bits.read表示读请求合法,且队列允许输入;
b) 接下来就看各个寄存器域是否允许读请求;
c) f为寄存器字中包含的所有寄存器域对应的二元组:
d) ReduceOthers把f中所有二元组的第二个元素相与之后,输出给out;也就是所有寄存器域的litOR(f_riready, !rimask),即所有寄存器域都准备好接收输入了;
e) 忽略!g,mux方法的输出为out;
f) out只取决于所有寄存器域是否准备好接收输入(f_riready);
g) 每个寄存器域是否有合法输入(f_rivalid),除了取决于其他寄存器域是否准备好接收输入外,则同时取决于valid && s && g。也就是说,即便所有寄存器域都准备好接收请求了,也未必有合法请求输入,取决于valid && s && g:
h) 所有寄存器域的rivalid(i)都依赖于valid && s && g,也就是说,当valid && s && g为假时,所有寄存器域都没有合法请求输入;
i) valid = in.valid && front.ready && front.bits.read,参考a);g忽略;s的意义为请求是否针对当前寄存器字;
j) 可见out在意义上,只相当于ready;在ready为真的情况下,valid && s && g在意义上相当于valid;
X. 根据是否读请求,确定请求队列输入端和输出端的ready信号
Y. 把输入接口与队列输入端相连,把输出接口与队列输出端相连
Z. 输出响应
a. 输出是否读请求的响应;
b. 输出读请求响应的数据;
c. extra原封不动的返回;
从中可以看出,输出接口中包含的响应,是针对队列输出端输出的请求的响应。
当然,如果队列为空,输入其中的请求,可以即时输出。队列是先入先出的。
3) 遗留问题
A. undefZero及其相关的iRightReg/oRightReg:
B. field.write.combinational选择数据的差异:
Rocket - regmapper - RegMapper的更多相关文章
- Rocket - regmapper - RegisterCrossing
		https://mp.weixin.qq.com/s/82iLT-fmDg9Comp2p9bxKg 简单介绍RegisterCrossing的实现. 1. BusyRegisterCrossing 简 ... 
- Rocket - regmapper - RegField
		https://mp.weixin.qq.com/s/7WKB1QxcVzqm2Q7bWcKHzA 简单介绍RegField的实现. 1. 简单介绍 定义寄存器域相关的参数类型. 2. RegFiel ... 
- Rocket - tilelink - RegisterRouter
		https://mp.weixin.qq.com/s/DaJhf7hEoWsEi_AjwSrOfA 简单介绍RegisterRouter的实现.  1. 基本介绍 实现挂在Tile ... 
- 64位开源处理器Rocket该人士介绍
		最近大概读一点UCB发布时间Rocket处理器的源代码,的每个文件的源代码的功能有一定的一般理解,Mark一点点. Rocket是一家64bit标量处理器,5第一阶段管道,用途risc-v指令集.综合 ... 
- Slack 开源替代品 Rocket.Chat(聊天,文件上传等等)
		Rocket.Chat 是特性最丰富的 Slack 开源替代品之一. 主要功能:群组聊天,直接通信,私聊群,桌面通知,媒体嵌入,链接预览,文件上传,语音/视频 聊天,截图等等. Rocket.Chat ... 
- web.py 学习(-)Rocket web框架
		Rocket是一个轻量级,多线程,符合WSGI规范的web框架. Rocket使用一个线程监听连接,接收到连接之后放到Queue中,有worker线程进行处理. Rocket含有以下属性: metho ... 
- 参加完Rocket MQ Meetup深圳站,回顾和想法
		最近一段时间才开始关注云栖社区的公众号,在两周前看到要在深圳科兴科学园办一场Rocket MQ的Meetup.因为从来没有参加过这种线下活动,而且对Rocket MQ比较感兴趣,所以就立即报名参加. ... 
- gitlab勾住rocket chat
		出于协作的要求, 需要在把gitlab的push event勾到rocket chat上面, 通知协作的其他人. BUT rocket chat提供的脚本没有具体的文件diff, so, 只好修改一下 ... 
- Mac 下安装运行Rocket.chat
		最近花了一周的时间,复习了HTML.CSS.原生JS,并学习了Node.js.CoffeeScript.js.MongoDB,入了下门. 因为准备在Rocket.chat 上做二次开发,所以先下载和安 ... 
随机推荐
- P1364 医院设置(树型结构)
			传送门闷闷闷闷闷闷 ~~放一个可爱的输入框.~~ 考虑在O(n)的时间内求数以每个节点为医院的距离和. \(设想一下,如果我们已知以1为根节点的距离和f[1],如何求出子节点呢?\) 当医院从1转换到 ... 
- B - Planning 早训 贪心
			B - Planning 这个题目我知道要贪心,也知道怎么贪,但是写不出来,感觉自己好菜. 这个题目要用优先队列维护. 题目大意是飞机延误,不同的飞机每次延误一分钟,它的代价不同,然后问,怎么安排才能 ... 
- C++关闭同步流 ios::sync_with_stdio(false)
			说明:ios::sync_with_stdio(false) 1.这句语句是用来取消cin的同步,什么叫同步呢?就是iostream的缓冲跟stdio的同步.这就是为什么cin和cout比scanf和 ... 
- 【FPGA篇章七】FPGA系统任务:详述常用的一些系统函数以及使用方法
			欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 系统任务和系统函数是Verilog标准的一部分,都以字符"$"为开头.系统任务可划分为六类,下面分别给出一些常用任务的用 ... 
- Cassandra 简介
			Cassandra是云原生和微服务化场景中最好的NoSQL数据库.我信了~ 1. Cassandra是什么 高可用性和可扩展的分布式数据库 Apache Cassandra™是一个开源分布式数据,可提 ... 
- SAP HTTP调用其他系统接口
			1业务说明 ABAP系统通过HTTP方式调用其他系统发布的接口 2代码实现 2.1认证接口 根据访问的URL创建HTTP客户端 设置访问方式,并调用SEND和接收函数 有时需要专门验证用户名密码 获取 ... 
- u-boot 移植(一)编译环境搭建
			u-boot 移植(一)编译环境搭建 soc:s3c2440 board:jz2440 uboot:u-boot-2016.11 toolchain:gcc-linaro-7.4.1-2019.02- ... 
- Java中Error和Exception的异同以及运行时异常(Runtime exception)与检查型异常(checked exception)的区别
			一:Error和Exception的基本概念: 首先Exception和Error都是继承于Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕 ... 
- CentOS7 Installing Python3
			最近开始学习python. python火了这么久,我终于还是跪舔它了,我是一个跟风的人,学过C.C#.JAVA.PHP,无一例外的浅尝即止,不知道我这双已经近视的眼,确认过的眼神还对不对,希望pyt ... 
- 简述SpringCloud框架
			1.什么是SpringCloud? SpringCloud是一系列框架的有序集合,它利用SpringBoot的开发便利性简化了分布式系统的开发,比如服务发现.服务网关.服务路由.链路追踪等.Sprin ... 
