其他分享
首页 > 其他分享> > RISC-V学习笔记【存储器与总线】

RISC-V学习笔记【存储器与总线】

作者:互联网

存储器架构

存储器架构简介

虽然这部分的内容是存储器,但是因为蜂鸟的原书将BIU总线放到了存储器架构部分的后面,考虑到两者关系还是比较密切的,这里就把存储器架构和总线协议放在一起,个人认为这样更便于理解

蜂鸟E203的处理器中没有配备缓存,处理器外则分别配备了ITCM和DTCM用于存储指令和数据

虽然在常见的PC的CPU大都配备了缓存,甚至有一二三级不同缓存用来提高内核执行效率,但实际上大部分的低功耗中低性能处理器并没有配备缓存,主要原因在于以下几点:

正因如此,即使是ARM的高端Cortex-M7内核也只是配备了一个16KB的I-Cache(指令缓存)和一个16KB的D-Cache(数据缓存),整体的缓存只有一级——补充一下,这玩意是六级流水线、双发射、乱序执行的大号处理器,全力开跑甚至需要散热片

蜂鸟E203采用的是哈佛架构,主要特点如下:

搞嵌入式的不可能没见过哈佛架构,想必各位已经品鉴的足够多了。然而现在的哈佛架构正在逐渐和冯诺依曼架构合体,具体表现如下:

所以说现代处理器中,低功耗处理器正在通过上层封装向冯氏架构靠拢;而高性能处理器则正在通过硬件设计向佛氏架构靠拢

蜂鸟E203的存储器架构

RISC-V架构对于存储器也进行了一定简化

蜂鸟E203的实现则基于RISC-V的规定设计了四个模块:

以上DTCM和ITCM并联到LSU的地址判断和数据对齐控制器之间,AGU则旁挂在LSU上,LSU通过BIU与ICB总线相连

AGU(Address Generation Unit)

因为AGU需要将第一个寄存器索引的源操作数和符号位扩展的立即数相加来得到读写指令最终的方寸地址,所以需要用到加法器

因此蜂鸟E203中将AGU和ALU放在一起,共用ALU的加法器来节省面积

其代码保存在/rtl/e203/core/e203_exu_alu.v、e203_exu_dpath.v、e203_exu_lsuagu.v文件中,很明显和ALU放在了一起

其中e203_exu_alu.v文件中实现了AGU所用的加法器和多路选择器的硬件结构

e203_exu_dpath.v文件则实现了AGU的数据处理代码,其中主模块就是ALU的共享数据通路,复用了ALU处例化的加法器

RISC-V架构对于地址非对齐的读写指令可以使用硬件支持也可以使用软件通过异常服务程序的方式采用软件支持,而蜂鸟E203采用软件支持的解决方案,ALU对生成出的访存地址进行判断,如果地址非对齐,则产生异常标志,通过ALU传送给交付模块,交付模块则据此产生异常,相关代码在e203_exu_lsuagu.v文件中

此外,e203_exu_lsuagu.v文件中还实现了AGU的控制和选择代码,但是不包括加法器部分;生成地址部分的HDL代码也在这个文件中。文件最后还例化了ICB接口用于挂载到BIU

详细内容可以参考源代码,这里不再赘述

LSU(Load Store Unit)

这是蜂鸟E203处理器核存储器子系统的主要控制单元,源代码保存在/rtl/e203/core/e203_lsu.v和e203_lsu_ctrl.v中,它们的架构和代码实现与BIU模块很相似,具体情况可以参考下面的总线协议部分

LSU有2组输入ICB总线接口,分别接入AGU和EAI协处理器的接口;3组输出ICB接口,分别分发给BIU、DTCM和ITCM;LSU还配备了一个写回接口。2组输入总线通过一个ICB汇合模块合成一组ICB总线,采用优先级仲裁的逻辑,EAI总线具有更高的优先级,经过汇合之后的ICB总线通过命令通道的地址进行判断,通过其访问的地址区间产生分发信息,随后接入的ICB分发模块会将其分发给不同存储器组件的ICB接口

如果EAI需要访问存储器,就需要在LSU这里进行配置

特别地,LSU使用的ICB汇合和ICB分发模块的FIFO深度均为1,也就是LSU默认只支持1个滞外传输

最终的返回数据需要经过尺寸对齐后经过LSU写回接口写回。对于可能出现的存储器访问错误,LSU预留了一条反馈通道信号线用于返回标志信号,异常标志会通过LSU的写回接口传送给内核的交付模块,交付模块会据此产生异常

ITCM和DTCM

蜂鸟E200系列处理器使用专用总线分别访问ITCM和DTCM,ITCM位宽为64位,DTCM位宽为32位

ITCM也有一组输入ICB总线接口来自LSU的访问,所以ITCM所在的地址区间同样能够通过LSU被读写指令访问到用于存储数据;另外有一组64位宽ICB总线接入到IFU,有一组32位宽的外部直接访问接口用于SoC中的外设能够直接访问ITCM。三组输入的ICB总线会经过一个ICB汇合模块汇成一组ICB总线,模块依旧采用优先级仲裁,IFU总线优先级>LSU优先级>外部直接访问接口。操作的来源信息会被寄存,SRAM返回的数据会根据寄存结果分发回三个总线之一

对于硬件实现,ITCM采用一块数据宽度为64位的单口SRAM组成,可以通过config.v中的宏定义配置ITCM大小和基地址

DTCM则拥有2组输入ICB总线接口,分别来自LSU和外部直接访问接口,具体实现和ITCM大同小异

ITCM的实现代码为e203_itcm_ctrl.v,DTCM的实现代码为e203_dtcm_ctrl.v

特别地,可以根据片上资源情况选择使用ITCM和DTCM,控制例化的代码位于e203_itcm_ram.v和e203_dtcm_ram.v,如下所示

  `ifdef E203_HAS_DTCM //{

module e203_dtcm_ram(

  input                              sd,
  input                              ds,
  input                              ls,

  input                              cs,  
  input                              we,  
  input  [`E203_DTCM_RAM_AW-1:0] addr, 
  input  [`E203_DTCM_RAM_MW-1:0] wem,
  input  [`E203_DTCM_RAM_DW-1:0] din,          
  output [`E203_DTCM_RAM_DW-1:0] dout,
  input                              rst_n,
  input                              clk

);

  sirv_gnrl_ram #(
    .FORCE_X2ZERO(1),//Always force X to zeros
    .DP(`E203_DTCM_RAM_DP),
    .DW(`E203_DTCM_RAM_DW),
    .MW(`E203_DTCM_RAM_MW),
    .AW(`E203_DTCM_RAM_AW) 
  ) u_e203_dtcm_gnrl_ram(
  .sd  (sd  ),
  .ds  (ds  ),
  .ls  (ls  ),

  .rst_n (rst_n ),
  .clk (clk ),
  .cs  (cs  ),
  .we  (we  ),
  .addr(addr),
  .din (din ),
  .wem (wem ),
  .dout(dout)
  );
                                                      
endmodule
  `endif//}

  `ifdef E203_HAS_ITCM //{
module e203_itcm_ram(

  input                              sd,
  input                              ds,
  input                              ls,

  input                              cs,  
  input                              we,  
  input  [`E203_ITCM_RAM_AW-1:0] addr, 
  input  [`E203_ITCM_RAM_MW-1:0] wem,
  input  [`E203_ITCM_RAM_DW-1:0] din,          
  output [`E203_ITCM_RAM_DW-1:0] dout,
  input                              rst_n,
  input                              clk

);

 
  sirv_gnrl_ram #(
      `ifndef E203_HAS_ECC//{
    .FORCE_X2ZERO(0),
      `endif//}
    .DP(`E203_ITCM_RAM_DP),
    .DW(`E203_ITCM_RAM_DW),
    .MW(`E203_ITCM_RAM_MW),
    .AW(`E203_ITCM_RAM_AW) 
  ) u_e203_itcm_gnrl_ram(
  .sd  (sd  ),
  .ds  (ds  ),
  .ls  (ls  ),

  .rst_n (rst_n ),
  .clk (clk ),
  .cs  (cs  ),
  .we  (we  ),
  .addr(addr),
  .din (din ),
  .wem (wem ),
  .dout(dout)
  );
                                                      
endmodule
  `endif//}

其他指令处理

蜂鸟203默认支持“A”扩展指令子集

详细内容可以查看LSU部分代码

蜂鸟E203通过在派遣控制模块、交付模块、分支处理模块等部分加入Fence指令处理的代码实现了对Fence和Fence.I指令的处理

这些内容大都在源码部分用注释写明,不再赘述

蜂鸟E200系列部分内核配备了ECC算法来对SRAM进行保护,但蜂鸟E203并没有配备

总线协议

蜂鸟E203并没有使用AMBA协议中规定的任何一种总线

这就导致它的总线部署和修改相当恶心

但是好在这玩意的时序和AHB总线比较相似,虽然不能在vivado中一键生成,但是封装一个IP并不是要人命的问题

虽然原书和相关教程中总结比较了各个总线的优缺点,但个人认为采用自定义的总线协议对于一个以应用为目的的处理器而言实属逆天。最重要的是这个破总线给笔者的比赛和队员们的心理造成了极大损伤!

不管怎么吐槽,以学习为目的看待这个自定义总线协议还是可取的(况且这玩意好歹能算是国产总线协议,战狼狂喜)

ICB总线协议

该总线协议和AHB和AXI协议比较类似,最主要的特性如下(括号内注明和哪个协议类似):

总线时序不能说和AXI时序一模一样,只能说差不多得了,所以在这里不多介绍,想了解详细信息可以查看官方书籍和官网的时序图

BIU

位于rtl/e203/core/e203_biu.v

BIU主要负责接收来自IFU和LSU的存储器访问请求,使用标准的ICB接口向内核、外设分发,通过判断指令访问的地址区间来访问以下五种外设接口:快速IO接口、私有外设几口、系统存储接口、CLIENT接口、PLIC接口

BIU有2组输入接口,分别来自IFU和LSU单元,通过一个ICB汇合模块合成一组ICB总线,采用优先级仲裁,LSU具有更高的优先级

为了截断外界和处理器内核之间的时序路径,在汇合的ICB总线处额外插入了一组乒乓缓存

ICB汇合、分发两个模块的FIFO深度默认配置为1,它默认只支持一个滞外交易,用于减少面积开销

此外,如果IFU访问到设备区间,会直接通过反馈通道返回错误标志

特别地,LSU和BIU的结构很相似,除了接口方向、数目不同外,本质上都是用于转发总线数据的“交换机”

详细内容参考代码即可

片上SoC总线

E200系列处理器配套SoC中,总线分为两组:附属于BIU的系统存储总线和通过BIU与内核耦合的私有外设总线

系统存储总线用于访问SoC中的ROM、OTP、FLASH只读区间等外设存储器

私有外设总线则用于外设寄存器映射和访问

其中所有存在时序兼容的重要路径都会插入乒乓缓存来砍断前后的时序路径;任何需要跨越异步时钟域或整数倍分频时钟域都会插入异步FIFO或流水线级数

标签:E203,ITCM,ICB,存储器,总线,RISC,LSU
来源: https://blog.csdn.net/qq_40500005/article/details/117880249