circt/test/firtool/lower-layers.fir

315 lines
9.0 KiB
Plaintext

; RUN: firtool %s -disable-all-randomization -split-input-file -advanced-layer-sink -lowering-options=emittedLineLength=1024 | FileCheck %s
; This is an end-to-end example of a test-bench (Foo) enabling verification,
; probing into a device-under-test (Bar), and reading from hardware which is
; only present if the verification layer is enabled.
FIRRTL version 4.0.0
circuit Foo: %[[
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~Foo|Bar>c"},
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~Foo|Foo>d"},
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~Foo|VerificationHelper>w"},
{"class": "circt.OutputDirAnnotation", "target": "~Foo|Foo", "dirname": "testbench"}
]]
; Collateral for the Verification layer should be output into the testbench directory.
layer Verification, bind, "testbench":
; Since VerificationHelper is only used under the Verification layer, it
; should be output in the testbench directory too.
module VerificationHelper:
wire w : UInt<1>
invalidate w
; Although the Component Bar is only instantiated by testbench Foo, since Bar
; is public, it remains in the default build directory.
public module Bar:
input a: UInt<1>
output b: Probe<UInt<1>, Verification>
; The extracted Bar_Verification module should be placed into the
; testbench output directory.
layerblock Verification:
node c = UInt<1>(0)
define b = probe(c)
inst helper of VerificationHelper
; The TestBench module is explicitly annotated to be placed in the testbench
; output directory.
public module Foo enablelayer Verification:
inst bar of Bar
node d = read(bar.b)
connect bar.a, d
; CHECK: module Bar(
; CHECK: input a
; CHECK: );
; CHECK: endmodule
; CHECK: FILE "testbench{{[/\]}}VerificationHelper.sv"
; CHECK: module VerificationHelper();
; CHECK: wire w = 1'h0;
; CHECK: endmodule
; CHECK: FILE "testbench{{[/\]}}Bar_Verification.sv"
; CHECK: module Bar_Verification();
; CHECK: wire c = 1'h0;
; CHECK: wire c_probe = c;
; CHECK: VerificationHelper helper ();
; CHECK: endmodule
; CHECK FILE "testbench{{[/\]}}layers-Bar-Verification.sv"
; CHECK: `ifndef layers_Bar_Verification
; CHECK: `define layers_Bar_Verification
; CHECK: bind Bar Bar_Verification verification ();
; CHECK: `endif // not def layers_Bar_Verification
; CHECK: FILE "testbench{{[/\]}}Foo.sv"
; CHECK: module Foo();
; CHECK: wire d = Foo.bar.verification.c_probe;
; CHECK: Bar bar (
; CHECK: .a (d)
; CHECK: );
; CHECK: endmodule
; CHECK: FILE "testbench{{[/\]}}layers-Foo-Verification.sv"
; CHECK: `ifndef layers_Foo_Verification
; CHECK: `define layers_Foo_Verification
; CHECK: `include "layers-Bar-Verification.sv"
; CHECK: `endif // not def layers_Foo_Verification
; // -----
; This is an end-to-end example of a test-harness enabling verification, probing
; into a device-under-test, and reading from hardware which is only present if
; the verification layer is enabled.
FIRRTL version 4.0.0
circuit TestHarness:
layer Verification, bind:
; CHECK: module DUT_Verification();
; CHECK: reg [31:0] pc_d;
; CHECK: wire [31:0] pc_d_probe = pc_d;
; CHECK: always @(posedge DUT.clock)
; CHECK: pc_d <= DUT.a;
; CHECK: endmodule
; CHECK: module DUT(
; CHECK: input clock,
; CHECK: input [31:0] a,
; CHECK: output [31:0] b
; CHECK: );
; CHECK: reg [31:0] pc;
; CHECK: always @(posedge clock)
; CHECK: pc <= a;
; CHECK: assign b = pc;
; CHECK: endmodule
module DUT:
input clock: Clock
input reset: UInt<1>
input a: UInt<32>
output b: UInt<32>
output trace: Probe<UInt<32>, Verification>
reg pc: UInt<32>, clock
connect pc, a
connect b, pc
wire x : Probe<UInt<32>, Verification>
layerblock Verification:
reg pc_d: UInt<32>, clock
connect pc_d, a
define x = probe(pc_d)
layerblock Verification:
define trace = x
; CHECK: module TestHarness_Verification()
; CHECK: `ifndef SYNTHESIS
; CHECK: always @(posedge TestHarness.clock) begin
; CHECK: if ((`PRINTF_COND_) & TestHarness.reset)
; CHECK: $fwrite(32'h80000002, "The last PC was: %x", TestHarness.dut.verification.pc_d_probe);
; CHECK: end // always @(posedge)
; CHECK: `endif // not def SYNTHESIS
; CHECK: endmodule
; CHECK: module TestHarness(
; CHECK: input clock,
; CHECK: reset,
; CHECK: input [31:0] a,
; CHECK: output [31:0] b
; CHECK: );
; CHECK: DUT dut (
; CHECK: .clock (clock),
; CHECK: .a (a),
; CHECK: .b (b)
; CHECK: );
; CHECK: endmodule
public module TestHarness:
input clock: Clock
input reset: UInt<1>
input a: UInt<32>
output b: UInt<32>
inst dut of DUT
connect dut.clock, clock
connect dut.reset, reset
connect dut.a, a
connect b, dut.b
layerblock Verification:
printf(clock, reset, "The last PC was: %x", read(dut.trace))
; CHECK: FILE "layers-DUT-Verification.sv
; CHECK: `ifndef layers_DUT_Verification
; CHECK: `define layers_DUT_Verification
; CHECK: bind DUT DUT_Verification verification ();
; CHECK: `endif // not def layers_DUT_Verification
; CHECK: FILE "layers-TestHarness-Verification.sv"
; CHECK: `ifndef layers_TestHarness_Verification
; CHECK: `define layers_TestHarness_Verification
; CHECK: `include "layers-DUT-Verification.sv"
; CHECK: bind TestHarness TestHarness_Verification verification ();
; CHECK: `endif // not def layers_TestHarness_Verification
; // -----
; This example demonstrates forcing _out_ of a layer into the outer module, a
; parent layer, or into another module.
FIRRTL version 5.1.0
circuit Foo: %[[
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~|ForceOutOfLayer>a"},
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~|Submodule>root"},
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~|Submodule>a"},
{"class": "firrtl.transforms.DontTouchAnnotation", "target": "~|Submodule>b"}
]]
layer A, bind:
layer B, inline:
; Test that forcing out of a layer into the root module works.
;
; CHECK: module ForceOutOfLayer_A();
; CHECK: initial
; CHECK-NEXT: force ForceOutOfLayer.a = 2'h1;
; CHECK: endmodule
;
; CHECK: module ForceOutOfLayer();
; CHECK: initial
; CHECK-NEXT: force ForceOutOfLayer.a = 2'h2;
; CHECK: endmodule
module ForceOutOfLayer:
wire a: UInt<2>
connect a, UInt<2>(0)
wire a_probe: RWProbe<UInt<2>>
define a_probe = rwprobe(a)
layerblock A:
force_initial(a_probe, UInt<2>(1))
layerblock B:
force_initial(a_probe, UInt<2>(2))
; Test that forcing out of a layer into another works. Test both forcing into
; the other module and forcing into a layer in the other module.
;
; CHECK: module ForceIntoSubmodule_A();
; CHECK: initial
; CHECK-NEXT: force ForceIntoSubmodule.submodule.root = 2'h1;
; CHECK-NEXT: force ForceIntoSubmodule.submodule.a.a = 2'h1;
; CHECK: endmodule
;
; CHECK: module ForceIntoSubmodule();
; CHECK: initial
; CHECK-NEXT: force ForceIntoSubmodule.submodule.root = 2'h2;
; CHECK-NEXT: force ForceIntoSubmodule.submodule.b = 2'h2;
; CHECK: endmodule
module Submodule:
output root_probe: RWProbe<UInt<2>>
output a_probe: RWProbe<UInt<2>, A>
output b_probe: RWProbe<UInt<2>, B>
wire root: UInt<2>
connect root, UInt<2>(0)
define root_probe = rwprobe(root)
layerblock A:
wire a: UInt<2>
connect a, UInt<2>(0)
define a_probe = rwprobe(a)
layerblock B:
wire b: UInt<2>
connect b, UInt<2>(0)
define b_probe = rwprobe(b)
module ForceIntoSubmodule:
inst submodule of Submodule
layerblock A:
force_initial(submodule.root_probe, UInt<2>(1))
force_initial(submodule.a_probe, UInt<2>(1))
layerblock B:
force_initial(submodule.root_probe, UInt<2>(2))
force_initial(submodule.b_probe, UInt<2>(2))
public module Foo:
inst forceOutOfLayer of ForceOutOfLayer
inst forceIntoSubmodule of ForceIntoSubmodule
; // -----
; LowerXMR and LowerLayers should work with nested enablelayers. Just test that
; this doesn't error.
FIRRTL version 5.1.0
circuit Foo:
layer A, bind:
module Bar enablelayer A:
input a: UInt<1>
output b: UInt<1>
connect b, a
; CHECK: module Foo(
public module Foo enablelayer A:
input a: UInt<1>
output b: UInt<1>
inst bar of Bar
connect bar.a, a
connect b, bar.b
; // -----
; Check that when bindfiles include eachother, the include directive uses a path
; relative to the output directory (or absolute).
FIRRTL version 5.1.0
circuit Foo:
layer A, bind, "A":
layer B, bind, "B":
public module Bar:
public module Foo:
inst bar of Bar
; CHECK: FILE "A{{[/\]}}layers-Foo-A.sv"
; CHECK: `include "layers-Bar-A.sv"
; CHECK: FILE "B{{[/\]}}layers-Foo-B.sv"
; CHECK: `include "layers-Bar-B.sv"