使用 Cat 运算符维护 FIRRTL 上的连接顺序
Maintain connection order on FIRRTL using Cat operator
我想就以下问题征求意见:
我想将一个名为 dut 的块的输入端口连接到一个字节接口,该块的宽度为 787:0 位。我正在做以下事情:
val io = this.IO(new VerilatorHarnessIO(input_byte_count, output_byte_count*2))
val dut = Module(new DUT(dut_conf))
// inputs
val input_bytes = Cat(io.input_bytes)
val input_width = input_byte_count * 8
dut.io.inputs := input_bytes(input_width-1, input_width - dut_conf.inputBits)
我希望保留连接顺序,即:
Byte_0[7:0] ->输入[7:0]
Byte_1[7:0] ->输入[15:8]
但我得到的是:
Byte_0[7:0] ->输入[787:780]
Byte_1[7:0] ->输入[779:772]
如果端口匹配的话调试起来会容易很多。
有没有办法以正确的顺序建立这种联系?
谢谢
在 Cat
之前使用 reverse
方法应该可以达到您想要的效果。
考虑以下凿子:
import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
import chisel3.util.Cat
class Foo extends RawModule {
val in = IO(Input(Vec(4, UInt(8.W))))
val out = IO(Output(UInt(32.W)))
out := Cat(in.reverse)
}
(new ChiselStage)
.execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new Foo)))
这将生成以下 Verilog,其中的字节按您要查找的顺序排列:
module Foo(
input [7:0] in_0,
input [7:0] in_1,
input [7:0] in_2,
input [7:0] in_3,
output [31:0] out
);
wire [15:0] _T; // @[Cat.scala 29:58]
wire [15:0] _T_1; // @[Cat.scala 29:58]
assign _T = {in_1,in_0}; // @[Cat.scala 29:58]
assign _T_1 = {in_3,in_2}; // @[Cat.scala 29:58]
assign out = {_T_1,_T}; // @[<pastie> 25:7]
endmodule
Cat
之所以出现倒退,是因为它符合Verilog语义,因此从Scala语义的角度来看是倒退的。
考虑:
val xs = List(8, 9, 10)
println(xs(0)) // 8
最左边的元素是 Scala 中的最低阶索引。然而,在 Verilog 中,你会得到相反的结果:
assign x = {4'hde, 4'had};
该串联的最左边部分实际上是结果中的高位半字节。 Chisel Cat
是为了匹配 Verilog 语义,这使得它在 Scala 中有点违反直觉。
正如 Schuyler 提到的,您始终可以 reverse
您的 Vec
或 Seq
论点 Cat
。或者,您可以转换为 UInt
,这将使用更直观的 Scala 顺序:
import chisel3._
class Foo extends RawModule {
val in = IO(Input(Vec(4, UInt(8.W))))
val out = IO(Output(UInt(32.W)))
out := in.asUInt
}
.asUInt
在所有 Chisel Data
上定义,因此您也可以使用它来将 Bundles
和其他类型转换为 UInt
。唯一的问题是 Vec
return Seq
上定义的许多方法,Vec
的 Scala 超类型不是凿子 Data
。这意味着你不能做类似 myVec.map(_ === 0.U).asUInt
的事情。您始终可以通过 VecInit(mySeq)
将 Seq[T <: Data]
(即包含 Chisel Data
元素的 Seq
转换为 Vec
,因此您可以执行 VecInit(myVec.map(_ === 0.U)).asUInt
我想就以下问题征求意见: 我想将一个名为 dut 的块的输入端口连接到一个字节接口,该块的宽度为 787:0 位。我正在做以下事情:
val io = this.IO(new VerilatorHarnessIO(input_byte_count, output_byte_count*2))
val dut = Module(new DUT(dut_conf))
// inputs
val input_bytes = Cat(io.input_bytes)
val input_width = input_byte_count * 8
dut.io.inputs := input_bytes(input_width-1, input_width - dut_conf.inputBits)
我希望保留连接顺序,即:
Byte_0[7:0] ->输入[7:0]
Byte_1[7:0] ->输入[15:8]
但我得到的是:
Byte_0[7:0] ->输入[787:780]
Byte_1[7:0] ->输入[779:772]
如果端口匹配的话调试起来会容易很多。
有没有办法以正确的顺序建立这种联系? 谢谢
在 Cat
之前使用 reverse
方法应该可以达到您想要的效果。
考虑以下凿子:
import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
import chisel3.util.Cat
class Foo extends RawModule {
val in = IO(Input(Vec(4, UInt(8.W))))
val out = IO(Output(UInt(32.W)))
out := Cat(in.reverse)
}
(new ChiselStage)
.execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new Foo)))
这将生成以下 Verilog,其中的字节按您要查找的顺序排列:
module Foo(
input [7:0] in_0,
input [7:0] in_1,
input [7:0] in_2,
input [7:0] in_3,
output [31:0] out
);
wire [15:0] _T; // @[Cat.scala 29:58]
wire [15:0] _T_1; // @[Cat.scala 29:58]
assign _T = {in_1,in_0}; // @[Cat.scala 29:58]
assign _T_1 = {in_3,in_2}; // @[Cat.scala 29:58]
assign out = {_T_1,_T}; // @[<pastie> 25:7]
endmodule
Cat
之所以出现倒退,是因为它符合Verilog语义,因此从Scala语义的角度来看是倒退的。
考虑:
val xs = List(8, 9, 10)
println(xs(0)) // 8
最左边的元素是 Scala 中的最低阶索引。然而,在 Verilog 中,你会得到相反的结果:
assign x = {4'hde, 4'had};
该串联的最左边部分实际上是结果中的高位半字节。 Chisel Cat
是为了匹配 Verilog 语义,这使得它在 Scala 中有点违反直觉。
正如 Schuyler 提到的,您始终可以 reverse
您的 Vec
或 Seq
论点 Cat
。或者,您可以转换为 UInt
,这将使用更直观的 Scala 顺序:
import chisel3._
class Foo extends RawModule {
val in = IO(Input(Vec(4, UInt(8.W))))
val out = IO(Output(UInt(32.W)))
out := in.asUInt
}
.asUInt
在所有 Chisel Data
上定义,因此您也可以使用它来将 Bundles
和其他类型转换为 UInt
。唯一的问题是 Vec
return Seq
上定义的许多方法,Vec
的 Scala 超类型不是凿子 Data
。这意味着你不能做类似 myVec.map(_ === 0.U).asUInt
的事情。您始终可以通过 VecInit(mySeq)
将 Seq[T <: Data]
(即包含 Chisel Data
元素的 Seq
转换为 Vec
,因此您可以执行 VecInit(myVec.map(_ === 0.U)).asUInt