chisel3:想使用Vec,但需要使用IndexedSeq
chisel3: Want to use Vec, but need to use IndexedSeq
在使用 "scanLeft" 生成抽头移位寄存器时,我需要使用寄存器的 IndexedSeq 并将 scanLeft 的结果显式复制到输出线。这里有四个例子(带测试台)。只有第一个有效。
我最喜欢第二个,不知道为什么不正确。
package tsr
import chisel3._
import chisel3.util._
import chisel3.iotesters._
import org.scalatest.{Matchers, FlatSpec}
object TappedShiftRegister {
def apply[ T <: Data]( d : T, n : Int) : Vec[T] = {
val rs = IndexedSeq.tabulate( n){ (i) => Reg( d.cloneType)}
val rs0 = rs.scanLeft( d){ case (x, r) => r := x; r}
val ys = Wire( Vec( n+1, d.cloneType))
(ys zip rs0).foreach{ case (y,r) => y := r}
ys
}
def apply1[ T <: Data]( d : T, n : Int) : Vec[T] = { // ChiselException
val rs = Vec.tabulate( n){ (i) => Reg( d.cloneType)}
Vec( rs.scanLeft( d){ case (x, r) => r := x; r})
}
def apply2[ T <: Data]( d : T, n : Int) : Vec[T] = { // ChiselException
val rs = IndexedSeq.tabulate( n){ (i) => Reg( d.cloneType)}
Vec( rs.scanLeft( d){ case (x, r) => r := x; r})
}
def apply3[ T <: Data]( d : T, n : Int) : Vec[T] = { // Wrong values
val rs = Vec.tabulate( n){ (i) => Reg( d.cloneType)}
val rs0 = rs.scanLeft( d){ case (x, r) => r := x; r}
val ys = Wire( Vec( n+1, d.cloneType))
(ys zip rs0).foreach{ case (y,r) => y := r}
ys
}
}
class TappedShiftRegisterIfc extends Module {
val io = IO( new Bundle {
val inp = Input( UInt(8.W))
val out = Output( Vec( 5, UInt(8.W)))
})
}
class GenericTSRTest( factory : () => TappedShiftRegisterIfc) extends FlatSpec with Matchers {
it should "meet all PeekPokeTester expectations" in {
chisel3.iotesters.Driver( factory, "firrtl") { c => new PeekPokeTester(c) {
val N = 4
val off = 47
for { i <- 0 until 100} {
poke( c.io.inp, off+i)
expect( c.io.out(0), off+i) // mealy output
step(1)
for { j <- 0 until N if i > j} {
expect( c.io.out(j+1), off+i-j) // moore outputs
}
}
}} should be (true)
}
}
class TSRTest extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister( io.inp, 4) })
class TSRTest1 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply1( io.inp, 4)})
class TSRTest2 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply2( io.inp, 4)})
class TSRTest3 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply3( io.inp, 4)})
首先。以下最接近您喜欢的内容有效。我已添加到您的测试套件中。
def apply4[ T <: Data]( d : T, n : Int) : Vec[T] = { // No ChiselException!
val rs = Seq.fill(n){ Reg(d.cloneType)}
VecInit(rs.scanLeft(d){ case (x, r) => r := x; r})
}
class TSRTest4 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply4( io.inp, 4)})
详情:
- Vec.tabulate 已弃用,请改用 VecInit。
- 使用 VecInit 而不是 Seq 会导致额外的延迟。我仍在尝试解决这个问题,但经验法则应该是不要创建 Vecs 除非你真的需要它们。在这种情况下,你只需要 Vec 这样你就可以将它直接分配给输出 IO.
- 在 Firrtl 文件中很容易看出问题。
在使用 "scanLeft" 生成抽头移位寄存器时,我需要使用寄存器的 IndexedSeq 并将 scanLeft 的结果显式复制到输出线。这里有四个例子(带测试台)。只有第一个有效。 我最喜欢第二个,不知道为什么不正确。
package tsr
import chisel3._
import chisel3.util._
import chisel3.iotesters._
import org.scalatest.{Matchers, FlatSpec}
object TappedShiftRegister {
def apply[ T <: Data]( d : T, n : Int) : Vec[T] = {
val rs = IndexedSeq.tabulate( n){ (i) => Reg( d.cloneType)}
val rs0 = rs.scanLeft( d){ case (x, r) => r := x; r}
val ys = Wire( Vec( n+1, d.cloneType))
(ys zip rs0).foreach{ case (y,r) => y := r}
ys
}
def apply1[ T <: Data]( d : T, n : Int) : Vec[T] = { // ChiselException
val rs = Vec.tabulate( n){ (i) => Reg( d.cloneType)}
Vec( rs.scanLeft( d){ case (x, r) => r := x; r})
}
def apply2[ T <: Data]( d : T, n : Int) : Vec[T] = { // ChiselException
val rs = IndexedSeq.tabulate( n){ (i) => Reg( d.cloneType)}
Vec( rs.scanLeft( d){ case (x, r) => r := x; r})
}
def apply3[ T <: Data]( d : T, n : Int) : Vec[T] = { // Wrong values
val rs = Vec.tabulate( n){ (i) => Reg( d.cloneType)}
val rs0 = rs.scanLeft( d){ case (x, r) => r := x; r}
val ys = Wire( Vec( n+1, d.cloneType))
(ys zip rs0).foreach{ case (y,r) => y := r}
ys
}
}
class TappedShiftRegisterIfc extends Module {
val io = IO( new Bundle {
val inp = Input( UInt(8.W))
val out = Output( Vec( 5, UInt(8.W)))
})
}
class GenericTSRTest( factory : () => TappedShiftRegisterIfc) extends FlatSpec with Matchers {
it should "meet all PeekPokeTester expectations" in {
chisel3.iotesters.Driver( factory, "firrtl") { c => new PeekPokeTester(c) {
val N = 4
val off = 47
for { i <- 0 until 100} {
poke( c.io.inp, off+i)
expect( c.io.out(0), off+i) // mealy output
step(1)
for { j <- 0 until N if i > j} {
expect( c.io.out(j+1), off+i-j) // moore outputs
}
}
}} should be (true)
}
}
class TSRTest extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister( io.inp, 4) })
class TSRTest1 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply1( io.inp, 4)})
class TSRTest2 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply2( io.inp, 4)})
class TSRTest3 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply3( io.inp, 4)})
首先。以下最接近您喜欢的内容有效。我已添加到您的测试套件中。
def apply4[ T <: Data]( d : T, n : Int) : Vec[T] = { // No ChiselException!
val rs = Seq.fill(n){ Reg(d.cloneType)}
VecInit(rs.scanLeft(d){ case (x, r) => r := x; r})
}
class TSRTest4 extends GenericTSRTest( () => new TappedShiftRegisterIfc { io.out := TappedShiftRegister.apply4( io.inp, 4)})
详情:
- Vec.tabulate 已弃用,请改用 VecInit。
- 使用 VecInit 而不是 Seq 会导致额外的延迟。我仍在尝试解决这个问题,但经验法则应该是不要创建 Vecs 除非你真的需要它们。在这种情况下,你只需要 Vec 这样你就可以将它直接分配给输出 IO.
- 在 Firrtl 文件中很容易看出问题。