在 for 循环 chisel3 中使用 yield 时如何访问前一个元素
How to access previous element when using yield in for loop chisel3
这是混合 Chisel / Scala 的问题。
背景,我需要总结很多数字(可配置的输入信号数量)。由于时间限制,我不得不将它分成 4 组并通过管道(注册),然后将其送入下一阶段(它将小 4 倍,直到我到达)
这是我的代码:
// log4 Aux function //
def log4(n : Int): Int = math.ceil(math.log10(n.toDouble) / math.log10(4.0)).toInt
// stage //
def Adder4PipeStage(len: Int,in: Vec[SInt]) : Vec[SInt] = {
require(in.length % 4 == 0) // will not work if not a muliplication of 4
val pipe = RegInit(VecInit(Seq.fill(len/4)(0.S(in(0).getWidth.W))))
pipe.zipWithIndex.foreach {case(p,j) => p := in.slice(j*4,(j+1)*4).reduce(_ +& _)}
pipe
}
// the pipeline
val adderPiped = for(j <- 1 to log4(len)) yield Adder4PipeStage(len/j,if(j==1) io.in else <what here ?>)
如何访问前一阶段,我也愿意听听其他实现上述内容的方法
您可以在这里做几件事:
- 您可以只使用
var
作为“先前”值:
var prev: Vec[SInt] = io.in
val adderPiped = for(j <- 1 to log4(len)) yield {
prev = Adder4PipeStage(len/j, prev)
prev
}
使用 var
和 for yield
有点奇怪(因为前者基本上是可变的,而后者倾向于与不可变样式代码一起使用)。
- 您也可以使用折叠构建
List
// Build up backwards and reverse (typical in functional programming)
val adderPiped = (1 to log4(len)).foldLeft(io.in :: Nil) {
case (pipes, j) => Adder4PipeStage(len/j, pipes.head) :: pipes
}.reverse
.tail // Tail drops "io.in" which was 1st element in the result List
如果你不喜欢前面折叠的反向构造,
- 您可以使用带
Vector
的折叠(比 List
更适合附加):
val adderPiped = (1 to log4(len)).foldLeft(Vector(io.in)) {
case (pipes, j) => pipes :+ Adder4PipeStage(len/j, pipes.last)
}.tail // Tail drops "io.in" which was 1st element in the result Vector
最后,如果您不喜欢这些不可变的方式,您总是可以接受可变性并编写类似于 Java 或 Python:
- For 循环和可变集合
val pipes = new mutable.ArrayBuffer[Vec[SInt]]
for (j <- 1 to log4(len)) {
pipes += Adder4PipeStage(len/j, if (j == 1) io.in else pipes.last)
}
这是混合 Chisel / Scala 的问题。 背景,我需要总结很多数字(可配置的输入信号数量)。由于时间限制,我不得不将它分成 4 组并通过管道(注册),然后将其送入下一阶段(它将小 4 倍,直到我到达) 这是我的代码:
// log4 Aux function //
def log4(n : Int): Int = math.ceil(math.log10(n.toDouble) / math.log10(4.0)).toInt
// stage //
def Adder4PipeStage(len: Int,in: Vec[SInt]) : Vec[SInt] = {
require(in.length % 4 == 0) // will not work if not a muliplication of 4
val pipe = RegInit(VecInit(Seq.fill(len/4)(0.S(in(0).getWidth.W))))
pipe.zipWithIndex.foreach {case(p,j) => p := in.slice(j*4,(j+1)*4).reduce(_ +& _)}
pipe
}
// the pipeline
val adderPiped = for(j <- 1 to log4(len)) yield Adder4PipeStage(len/j,if(j==1) io.in else <what here ?>)
如何访问前一阶段,我也愿意听听其他实现上述内容的方法
您可以在这里做几件事:
- 您可以只使用
var
作为“先前”值:
var prev: Vec[SInt] = io.in
val adderPiped = for(j <- 1 to log4(len)) yield {
prev = Adder4PipeStage(len/j, prev)
prev
}
使用 var
和 for yield
有点奇怪(因为前者基本上是可变的,而后者倾向于与不可变样式代码一起使用)。
- 您也可以使用折叠构建
List
// Build up backwards and reverse (typical in functional programming)
val adderPiped = (1 to log4(len)).foldLeft(io.in :: Nil) {
case (pipes, j) => Adder4PipeStage(len/j, pipes.head) :: pipes
}.reverse
.tail // Tail drops "io.in" which was 1st element in the result List
如果你不喜欢前面折叠的反向构造,
- 您可以使用带
Vector
的折叠(比List
更适合附加):
val adderPiped = (1 to log4(len)).foldLeft(Vector(io.in)) {
case (pipes, j) => pipes :+ Adder4PipeStage(len/j, pipes.last)
}.tail // Tail drops "io.in" which was 1st element in the result Vector
最后,如果您不喜欢这些不可变的方式,您总是可以接受可变性并编写类似于 Java 或 Python:
- For 循环和可变集合
val pipes = new mutable.ArrayBuffer[Vec[SInt]]
for (j <- 1 to log4(len)) {
pipes += Adder4PipeStage(len/j, if (j == 1) io.in else pipes.last)
}