4

我正在学习 chisel 和 scala 语言,并尝试分析一些火箭芯片代码。有人能解释一下吗?https://github.com/chipsalliance/rocket-chip/blob/54237b5602a273378e3b35307bb47eb1e58cb9fb/src/main/scala/rocket/RocketCore.scala#L957

我了解 log2Up 函数在做什么,但不明白为什么 log2Up(n)-1 和 0 像“参数”一样传递给 addr,它是 UInt 类型的 val!?

4

2 回答 2

3

我找不到在哪里UInt定义,但如果我不得不猜测,UInt是一个classapply方法的。这是一种特殊方法,允许我们在类的实例上使用括号运算符。

例如,假设我们有一个Multiply定义了apply方法的类。

class Multiply {
  def apply(a: Int, b: Int): Int = a * b
}

()这允许您在该类的任何实例上调用运算符。例如:

val mul = new Multiply()
println(mul(5, 6)) // prints 30
于 2019-11-11T18:14:26.527 回答
1

我得出的结论是,我们使用 addr(log2Up(n)-1, 0) 来获取从零开始到 log2Up(n)-1 位的地址位。让我们举个例子。

如果我们以这种方式创建类 RegFile 的对象

val reg = RegFile(31, 10)

首先,创建内存 rf。该内存的大小是 31 个 UInt 宽度为 10 的数据,从 0 到 30。当我们计算 log2Up(n)-1 时,我们得到 4,我们有这样的东西:addr(4,0)。这给了我们最后五位 addr。就像@Jack Koenig 在上面的评论中所说的那样:“Rocket 的寄存器文件使用了一个小技巧,与 RISC-V 相比,它在物理上颠倒了寄存器的顺序”,这就是我们使用 ~addr 的原因。并且至少 rf(~addr) 让我们返回了那个内存位置的内容。

这是以这种方式实现的,以提供足够的内存访问。看看如果我们尝试从我们的内存中没有的内存位置获取数据会发生什么。如果以这种方式调用方法访问

access(42)

我们尝试访问第 41 个位置的内存位置,但我们只有 31 个内存位置(30 是顶部)。42二进制是101010。使用我上面所说的

~addr(log2Up(n)-1,0)

将以十进制返回 10101 或 21。因为寄存器的顺序是颠倒的,所以这是第 10 个内存位置(我们尝试访问第 41 个但只有 31 个,41 减去 31 是 10)。

于 2019-11-15T00:12:19.923 回答