本文记录了 SpinalHDL 中 RegIf 模块的源码阅读笔记,基于 SpinalHDL 1.11.0。


# 实现细节

该模块的代码生成主要分为两个部分:用户调用 RegInst.field* 时,创建数据写入逻辑,并在 component.addPrePopTask 中调用 readGenerator 生成数据、错误的读取逻辑及写入错误逻辑。

component.addPrePopTask(() => {
  this.readGenerator()  // 生成所有读取逻辑
  if(withSecFireWall) this.writeErrorGenerator()  // 如果启用了安全防火墙,则生成写入错误逻辑
})

# 写入数据

写入数据在用户调用 RegInst.field* 时按需生成。

TODO

# 读取数据及错误

读取逻辑最终生成的变量为 bus_rdatareg_rderr 两个变量。其中, reg_rderr 仅会在未开启 withStrb ,且 readAddress 未对齐时,置为 True

readGenerator 定义在第 296 行,定义如下。该函数会优先生成寄存器及 fifo 的读取逻辑,将 reg_rdata 赋值为寄存器读取结果,然后生成 RAM 及寄存器读取逻辑,并使用 bus_rdata 输出最终的读取结果。

private def readGenerator(): Unit = {
  this.regReadGenerator()  // 生成寄存器及 fifo 的读取逻辑,将 reg_rdata 赋值为寄存器读取结果
  // 接下来枚举所有的 RAM,如果 RAM 被选中读取,则生成 RAM 读取逻辑,将 bus_rdata 赋值为 RAM 读取结果
  val mux = WhenBuilder()
  RamInsts.foreach{ ram =>
    mux.when(ram.ram_rdvalid) {  //ram_rdvalid 定义为 readAddress 在所定义的范围内,askRead 有效,且通过安全校验
      bus_rdata := ram.readBits
    }
  }
  // 如果没有 RAM 被选中读取,则将 bus_rdata 赋值为寄存器读取结果
  mux.otherwise {
    bus_rdata := reg_rdata
  }
}

regReadGenerator 定义在 296 行,定义如下。该函数会在 askRead 有效时,处理寄存器及 fifo 的读取逻辑,将 reg_rdata 赋值为寄存器读取结果。否则,会将 red_rdata 赋值为 readDefaultValuereg_rderr 赋值为 False

private def regReadGenerator() = {
  when(askRead){
    regReadPart()
  }.otherwise{
    // 为了避免数据泄露,在读取后,将 reg_rdata 置为默认值,reg_rderr 置为 False
    //do not keep readData after read for the reason of security risk
    reg_rdata := readDefaultValue
    reg_rderr := False
  }
}

其中, regReadPart 定义在第 278 行,该函数及内部使用的相关函数的源码如下。该函数会枚举所有的寄存器和 Fifo,在 readAddress 等于该实例时,将 reg_rdata 赋值为寄存器读取结果,并在该寄存器包含 WO 属性的域时将 reg_rderr 赋值为 True 。如果没有寄存器或 Fifo 被选中读取,则将 reg_rdata 赋值为 readDefaultValue ,并在启用 withStrb 时将 reg_rderr 赋值为 False ,未启用时则将 reg_rderr 赋值为 True

private def regReadPart() = {
    switch(readAddress()) {
      RegAndFifos.foreach{ (x: RegSlice) =>
        if(!x.allIsNA) x.readGenerator()
      }
      default {
        reg_rdata := readDefaultValue
        //Reserved Address Set False, True is too much strict for software
        if (withStrb) {
          reg_rderr := False
        } else {
          val alignreadhit = readAddress.take(log2Up(wordAddressInc)).orR
          reg_rderr := Mux(alignreadhit, True, False)
        }
      }
    }
  }
  // RegInst.scala:392, 生成寄存器读取逻辑
  override def readGenerator() = {
    is(addr) {
      bi.reg_rdata := rdSecurePassage(this.rdata())
      bi.reg_rderr := rdSecureError(Bool(this.haveWO))
    }
  }

# 写入错误逻辑生成

TODO