如何破译从凿子生成的 Verilog 中的注释?
How to decipher comments in generated Verilog from chisel?
这是从 PassTrough 模块中找到的一些生成的 Verilog:
https://github.com/freechipsproject/chisel-bootcamp/blob/master/2.1_first_module.ipynb
module PassTrough( // @[:@3.2]
input clock, // @[:@4.4]
input reset, // @[:@5.4]
input [9:0] io_in, // @[:@6.4]
output [9:0] io_out // @[:@6.4]
);
assign io_out = io_in; // @[buffer.scala 10:10:@8.4]
endmodule
是否有任何资源可以帮助您理解评论中的内容。我可以看到它们与原始 scala 文件中的代码位置相关,但想了解更多详细信息。
// @[buffer.scala 10:10:@8.4]
对该行进行更详细的解释会很有用。
这些是源定位器,将显示在生成的 FIRRTL 或 Verilog 中。这些告诉您源文件(Chisel 或 FIRRTL)中的哪一行用于在下游 FIRRTL 或 Verilog 中生成特定行。
格式一般为:@[<file> <line>:<column> ...]
可能存在不止一个源定位器。
例子
考虑从 BoringUtilsSpec
中提取的以下示例。行号(不从零开始,因为这是从一个较大的文件中提取的)与列号一起显示。您可以看到它们之间的关系。例如,notA
的声明发生在第 27 行第 20 列,赋值 notA := ~a
发生在第 30 行第 10 列。您会看到 27:20
和 30:10
出现在FIRRTL。在 Verilog 中,这些在某种程度上得到了合并,您最终得到了指示 27:20
和 30:10
:
的源定位器
// -------------------------------------------+----+
// File: BoringUtilsSpec.scala | |
// -------------------------------------------+----+
// Column Number | |
// -------------------------------------------+----+
// 1 2 3 4 | |
// 01234567890123456789012345678901234567890 | |
// -------------------------------------------+----|
class BoringInverter extends Module { // | 24 | Line Number
val io = IO(new Bundle{}) // | 5 |
val a = Wire(UInt(1.W)) // | 6 |
val notA = Wire(UInt(1.W)) // | 7 |
val b = Wire(UInt(1.W)) // | 8 |
a := 0.U // | 9 |
notA := ~a // | 30 |
b := a // | 1 |
chisel3.assert(b === 1.U) // | 2 |
BoringUtils.addSource(notA, "x") // | 3 |
BoringUtils.addSink(b, "x") // | 4 |
} // | 5 |
// -------------------------------------------+----+
这会产生以下 FIRRTL:
module BoringUtilsSpecBoringInverter :
input clock : Clock
input reset : UInt<1>
output io : {}
wire a : UInt<1> @[BoringUtilsSpec.scala 26:17]
wire notA : UInt<1> @[BoringUtilsSpec.scala 27:20]
wire b : UInt<1> @[BoringUtilsSpec.scala 28:17]
a <= UInt<1>("h00") @[BoringUtilsSpec.scala 29:7]
node _T = not(a) @[BoringUtilsSpec.scala 30:13]
notA <= _T @[BoringUtilsSpec.scala 30:10]
b <= a @[BoringUtilsSpec.scala 31:7]
node _T_1 = eq(b, UInt<1>("h01")) @[BoringUtilsSpec.scala 32:22]
node _T_2 = bits(reset, 0, 0) @[BoringUtilsSpec.scala 32:19]
node _T_3 = or(_T_1, _T_2) @[BoringUtilsSpec.scala 32:19]
node _T_4 = eq(_T_3, UInt<1>("h00")) @[BoringUtilsSpec.scala 32:19]
// assert not shown
以及以下 Verilog:
module BoringUtilsSpecBoringInverter(
input clock,
input reset
);
wire _T; // @[BoringUtilsSpec.scala 30:13]
wire notA; // @[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
wire _T_3; // @[BoringUtilsSpec.scala 32:19]
wire _T_4; // @[BoringUtilsSpec.scala 32:19]
assign _T = 1'h1; // @[BoringUtilsSpec.scala 30:13]
assign notA = 1'h1; // @[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
assign _T_3 = _T | reset; // @[BoringUtilsSpec.scala 32:19]
assign _T_4 = _T_3 == 1'h0; // @[BoringUtilsSpec.scala 32:19]
// assert not shown
endmodule
注意事项
发电机训练营
如果您在 Chisel Bootcamp Jupyter Notebook 或通过 sbt console/REPL 运行,源定位器可能没有多大意义,因为这里确实没有带行的文件.
与 Annotation
的区别
这些源定位器 不是 Annotation
,以防有人遇到那个名字。
Annotation
s 是与 circuit 组件关联的元数据。源定位符(映射到 FIRRTL IR 中的 Info
)与某些源文件中的特定语句相关联。在引擎盖下,它们只是生成然后复制的字符串。不能保证源定位器会被保留——它们可能会被任意更改或删除。相反,Annotation
s 在转换过程中被保留和重命名,并且对它们的行为方式有强有力的保证。
因此,如果您需要调试 Chisel 或 FIRRTL 编译器阶段,除了辅助之外,不要依赖源定位器。
这是从 PassTrough 模块中找到的一些生成的 Verilog: https://github.com/freechipsproject/chisel-bootcamp/blob/master/2.1_first_module.ipynb
module PassTrough( // @[:@3.2]
input clock, // @[:@4.4]
input reset, // @[:@5.4]
input [9:0] io_in, // @[:@6.4]
output [9:0] io_out // @[:@6.4]
);
assign io_out = io_in; // @[buffer.scala 10:10:@8.4]
endmodule
是否有任何资源可以帮助您理解评论中的内容。我可以看到它们与原始 scala 文件中的代码位置相关,但想了解更多详细信息。
// @[buffer.scala 10:10:@8.4]
对该行进行更详细的解释会很有用。
这些是源定位器,将显示在生成的 FIRRTL 或 Verilog 中。这些告诉您源文件(Chisel 或 FIRRTL)中的哪一行用于在下游 FIRRTL 或 Verilog 中生成特定行。
格式一般为:@[<file> <line>:<column> ...]
可能存在不止一个源定位器。
例子
考虑从 BoringUtilsSpec
中提取的以下示例。行号(不从零开始,因为这是从一个较大的文件中提取的)与列号一起显示。您可以看到它们之间的关系。例如,notA
的声明发生在第 27 行第 20 列,赋值 notA := ~a
发生在第 30 行第 10 列。您会看到 27:20
和 30:10
出现在FIRRTL。在 Verilog 中,这些在某种程度上得到了合并,您最终得到了指示 27:20
和 30:10
:
// -------------------------------------------+----+
// File: BoringUtilsSpec.scala | |
// -------------------------------------------+----+
// Column Number | |
// -------------------------------------------+----+
// 1 2 3 4 | |
// 01234567890123456789012345678901234567890 | |
// -------------------------------------------+----|
class BoringInverter extends Module { // | 24 | Line Number
val io = IO(new Bundle{}) // | 5 |
val a = Wire(UInt(1.W)) // | 6 |
val notA = Wire(UInt(1.W)) // | 7 |
val b = Wire(UInt(1.W)) // | 8 |
a := 0.U // | 9 |
notA := ~a // | 30 |
b := a // | 1 |
chisel3.assert(b === 1.U) // | 2 |
BoringUtils.addSource(notA, "x") // | 3 |
BoringUtils.addSink(b, "x") // | 4 |
} // | 5 |
// -------------------------------------------+----+
这会产生以下 FIRRTL:
module BoringUtilsSpecBoringInverter :
input clock : Clock
input reset : UInt<1>
output io : {}
wire a : UInt<1> @[BoringUtilsSpec.scala 26:17]
wire notA : UInt<1> @[BoringUtilsSpec.scala 27:20]
wire b : UInt<1> @[BoringUtilsSpec.scala 28:17]
a <= UInt<1>("h00") @[BoringUtilsSpec.scala 29:7]
node _T = not(a) @[BoringUtilsSpec.scala 30:13]
notA <= _T @[BoringUtilsSpec.scala 30:10]
b <= a @[BoringUtilsSpec.scala 31:7]
node _T_1 = eq(b, UInt<1>("h01")) @[BoringUtilsSpec.scala 32:22]
node _T_2 = bits(reset, 0, 0) @[BoringUtilsSpec.scala 32:19]
node _T_3 = or(_T_1, _T_2) @[BoringUtilsSpec.scala 32:19]
node _T_4 = eq(_T_3, UInt<1>("h00")) @[BoringUtilsSpec.scala 32:19]
// assert not shown
以及以下 Verilog:
module BoringUtilsSpecBoringInverter(
input clock,
input reset
);
wire _T; // @[BoringUtilsSpec.scala 30:13]
wire notA; // @[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
wire _T_3; // @[BoringUtilsSpec.scala 32:19]
wire _T_4; // @[BoringUtilsSpec.scala 32:19]
assign _T = 1'h1; // @[BoringUtilsSpec.scala 30:13]
assign notA = 1'h1; // @[BoringUtilsSpec.scala 27:20 BoringUtilsSpec.scala 30:10]
assign _T_3 = _T | reset; // @[BoringUtilsSpec.scala 32:19]
assign _T_4 = _T_3 == 1'h0; // @[BoringUtilsSpec.scala 32:19]
// assert not shown
endmodule
注意事项
发电机训练营
如果您在 Chisel Bootcamp Jupyter Notebook 或通过 sbt console/REPL 运行,源定位器可能没有多大意义,因为这里确实没有带行的文件.
与 Annotation
的区别
这些源定位器 不是 Annotation
,以防有人遇到那个名字。
Annotation
s 是与 circuit 组件关联的元数据。源定位符(映射到 FIRRTL IR 中的 Info
)与某些源文件中的特定语句相关联。在引擎盖下,它们只是生成然后复制的字符串。不能保证源定位器会被保留——它们可能会被任意更改或删除。相反,Annotation
s 在转换过程中被保留和重命名,并且对它们的行为方式有强有力的保证。
因此,如果您需要调试 Chisel 或 FIRRTL 编译器阶段,除了辅助之外,不要依赖源定位器。