circt/test/firtool/lower-layers.fir

180 lines
5.3 KiB
Plaintext

; RUN: firtool %s -disable-all-randomization -split-input-file | 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{{[/\]}}layers-Foo-Verification.sv"
; CHECK: `ifndef layers_Foo_Verification
; CHECK: `define layers_Foo_Verification
; CHECK: bind Bar Bar_Verification verification ();
; CHECK: `endif // layers_Foo_Verification
; 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: endmodule
; 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
; // -----
; 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: input clock,
; CHECK: input [31:0] a
; CHECK: );
; CHECK: reg [31:0] pc_d;
; CHECK: wire [31:0] pc_d_probe = pc_d;
; CHECK: always @(posedge clock)
; CHECK: pc_d <= 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: input [31:0] dut_trace,
; CHECK: input clock,
; CHECK: reset
; CHECK: );
; CHECK: `ifndef SYNTHESIS
; CHECK: always @(posedge clock) begin
; CHECK: if ((`PRINTF_COND_) & reset)
; CHECK: $fwrite(`PRINTF_FD_, "The last PC was: %x", dut_trace);
; 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-TestHarness-Verification.sv"
; CHECK: `ifndef layers_TestHarness_Verification
; CHECK: `define layers_TestHarness_Verification
; CHECK: bind DUT DUT_Verification verification (
; CHECK: .clock (clock),
; CHECK: .a (a)
; CHECK: );
; CHECK: bind TestHarness TestHarness_Verification verification (
; CHECK: .dut_trace (TestHarness.dut.verification.pc_d_probe),
; CHECK: .clock (clock),
; CHECK: .reset (reset)
; CHECK: );
; CHECK: `endif // layers_TestHarness_Verification