mirror of https://github.com/llvm/circt.git
291 lines
12 KiB
Plaintext
291 lines
12 KiB
Plaintext
; RUN: firtool %s --format=fir --ir-fir | circt-opt | FileCheck %s --check-prefix=MLIR
|
|
; RUN: firtool %s --format=fir --parse-only --annotation-file %s.anno.json,%s.anno.1.json | circt-opt | FileCheck %s --check-prefix=ANNOTATIONS
|
|
; RUN: firtool %s --format=fir --parse-only --annotation-file %s.anno.json --annotation-file %s.anno.1.json | circt-opt | FileCheck %s --check-prefix=ANNOTATIONS
|
|
; RUN: firtool %s --format=fir --ir-hw | circt-opt | FileCheck %s --check-prefix=MLIRLOWER
|
|
; RUN: firtool %s --format=fir -verilog | FileCheck %s --check-prefix=VERILOG
|
|
; RUN: firtool %s --format=fir --ir-verilog | circt-opt | FileCheck %s --check-prefix=VERILOG-IR
|
|
FIRRTL version 4.0.0
|
|
|
|
circuit test_mod : %[[{"class": "circt.testNT", "data": "a"}]]
|
|
|
|
; MLIR: firrtl.circuit "test_mod"
|
|
|
|
; ANNOTATIONS-LABEL: firrtl.circuit "test_mod"
|
|
; ANNOTATIONS-SAME: {class = "circt.testNT", data = "a"}
|
|
; ANNOTATIONS-SAME: {class = "circt.testNT", info = "a NoTargetAnnotation"}
|
|
; ANNOTATIONS-SAME: {class = "circt.test", info = "a CircuitTarget Annotation"}
|
|
; ANNOTATIONS-SAME: {class = "circt.test", info = "a CircuitName Annotation"}
|
|
|
|
; VERILOG-IR: sv.verbatim{{.*}}Standard header to adapt well known macros for register randomization
|
|
; VERILOG-IR: sv.macro.decl @ENABLE_INITIAL_REG_
|
|
; VERILOG-IR: sv.macro.decl @ENABLE_INITIAL_MEM_
|
|
; VERILOG-IR: sv.macro.decl @RANDOMIZE
|
|
; VERILOG-IR: sv.macro.decl @RANDOMIZE_DELAY
|
|
; VERILOG-IR: sv.macro.decl @RANDOM
|
|
; VERILOG-IR: sv.macro.decl @INIT_RANDOM
|
|
; VERILOG-IR: sv.macro.decl @INIT_RANDOM_PROLOG_
|
|
|
|
type V3 = UInt<1>[3]
|
|
type V2 = UInt<1>[2]
|
|
|
|
public module test_mod :
|
|
input clock : Clock
|
|
input a: UInt<1>
|
|
input b: UInt<2>
|
|
output c: UInt<1>
|
|
input vec: V3
|
|
output out_implicitTrunc: UInt<1>
|
|
output out_prettifyExample: UInt<1>
|
|
output out_multibitMux: UInt<1>
|
|
output out_mux2cell: V2
|
|
|
|
inst cat of Cat
|
|
connect cat.a, b
|
|
connect cat.b, b
|
|
connect cat.c, b
|
|
|
|
inst implicitTrunc of ImplicitTrunc
|
|
connect implicitTrunc.inp_1, a
|
|
connect implicitTrunc.inp_2, asSInt(cat.d)
|
|
|
|
inst prettifyExample of PrettifyExample
|
|
connect prettifyExample.inp_1, cat.d
|
|
connect prettifyExample.inp_2, cat.d
|
|
connect prettifyExample.inp_3, cat.d
|
|
|
|
inst flipFlop of FlipFlop
|
|
connect flipFlop.clock, clock
|
|
connect flipFlop.a_d, a
|
|
|
|
connect c, flipFlop.a_q
|
|
|
|
inst multibitMux of MultibitMux
|
|
connect multibitMux.a, vec
|
|
connect multibitMux.sel, b
|
|
|
|
inst unusedPortsMod of UnusedPortsMod
|
|
connect unusedPortsMod.in, a
|
|
|
|
inst mux2cell of Mux2Cell
|
|
connect mux2cell.cond, a
|
|
connect mux2cell.low, a
|
|
connect out_mux2cell, mux2cell.out
|
|
|
|
; These outputs exist to work around the aggressive removal of unused module
|
|
; ports.
|
|
;
|
|
; TODO: This test should be rewritten to not be so brittle around module
|
|
; port removal.
|
|
connect out_implicitTrunc, or(orr(implicitTrunc.out1), orr(implicitTrunc.out2))
|
|
connect out_prettifyExample, or(orr(prettifyExample.out1), orr(prettifyExample.out2))
|
|
connect out_multibitMux, multibitMux.b
|
|
|
|
|
|
; MLIR-LABEL: firrtl.module @test_mod(in %clock: !firrtl.clock, in %a: !firrtl.uint<1>, in %b: !firrtl.uint<2>, out %c: !firrtl.uint<1>, in %vec_0: !firrtl.uint<1>, in %vec_1: !firrtl.uint<1>, in %vec_2: !firrtl.uint<1>, out %out_implicitTrunc: !firrtl.uint<1>, out %out_prettifyExample: !firrtl.uint<1>, out %out_multibitMux: !firrtl.uint<1>, out %out_mux2cell_0: !firrtl.uint<1>, out %out_mux2cell_1: !firrtl.uint<1>) {{.*}}{
|
|
; MLIR: %cat_a, %cat_b, %cat_c, %cat_d = firrtl.instance cat @Cat(in a: !firrtl.uint<2>, in b: !firrtl.uint<2>, in c: !firrtl.uint<2>, out d: !firrtl.uint<6>)
|
|
; MLIR-NEXT: firrtl.matchingconnect %cat_a, %b : !firrtl.uint<2>
|
|
; MLIR-NEXT: firrtl.matchingconnect %cat_b, %b : !firrtl.uint<2>
|
|
; MLIR-NEXT: firrtl.matchingconnect %cat_c, %b : !firrtl.uint<2>
|
|
; MLIR-NEXT: %implicitTrunc_inp_1, %implicitTrunc_inp_2, %implicitTrunc_out1, %implicitTrunc_out2 = firrtl.instance implicitTrunc @ImplicitTrunc(in inp_1: !firrtl.uint<1>, in inp_2: !firrtl.sint<5>, out out1: !firrtl.sint<3>, out out2: !firrtl.sint<3>)
|
|
; MLIR-NEXT: firrtl.matchingconnect %implicitTrunc_inp_1, %a : !firrtl.uint<1>
|
|
; MLIR-NEXT: %0 = firrtl.asSInt %cat_d : (!firrtl.uint<6>) -> !firrtl.sint<6>
|
|
; MLIR-NEXT: %1 = firrtl.bits %0 4 to 0 : (!firrtl.sint<6>) -> !firrtl.uint<5>
|
|
; MLIR-NEXT: %2 = firrtl.asSInt %1 : (!firrtl.uint<5>) -> !firrtl.sint<5>
|
|
; MLIR-NEXT: firrtl.matchingconnect %implicitTrunc_inp_2, %2 : !firrtl.sint<5>
|
|
; MLIR: %prettifyExample_inp_1, %prettifyExample_inp_2, %prettifyExample_inp_3, %prettifyExample_out1, %prettifyExample_out2 = firrtl.instance prettifyExample @PrettifyExample(in inp_1: !firrtl.uint<5>, in inp_2: !firrtl.uint<5>, in inp_3: !firrtl.uint<5>, out out1: !firrtl.uint<10>, out out2: !firrtl.uint<10>)
|
|
; MLIR-NEXT: %3 = firrtl.bits %cat_d 4 to 0 : (!firrtl.uint<6>) -> !firrtl.uint<5>
|
|
; MLIR-NEXT: firrtl.matchingconnect %prettifyExample_inp_1, %3 : !firrtl.uint<5>
|
|
; MLIR-NEXT: firrtl.matchingconnect %prettifyExample_inp_2, %3 : !firrtl.uint<5>
|
|
; MLIR-NEXT: firrtl.matchingconnect %prettifyExample_inp_3, %3 : !firrtl.uint<5>
|
|
; MLIR-NEXT: %flipFlop_clock, %flipFlop_a_d, %flipFlop_a_q = firrtl.instance flipFlop @FlipFlop(in clock: !firrtl.clock, in a_d: !firrtl.uint<1>, out a_q: !firrtl.uint<1>)
|
|
; MLIR-NEXT: firrtl.matchingconnect %flipFlop_clock, %clock : !firrtl.clock
|
|
; MLIR-NEXT: firrtl.matchingconnect %flipFlop_a_d, %a : !firrtl.uint<1>
|
|
; MLIR-NEXT: firrtl.matchingconnect %c, %flipFlop_a_q : !firrtl.uint<1>
|
|
; MLIR-NEXT: %multibitMux_a_0, %multibitMux_a_1, %multibitMux_a_2, %multibitMux_sel, %multibitMux_b = firrtl.instance multibitMux @MultibitMux(in a_0: !firrtl.uint<1>, in a_1: !firrtl.uint<1>, in a_2: !firrtl.uint<1>, in sel: !firrtl.uint<2>, out b: !firrtl.uint<1>)
|
|
; MLIR-NEXT: firrtl.matchingconnect %multibitMux_a_0, %vec_0 : !firrtl.uint<1>
|
|
; MLIR-NEXT: firrtl.matchingconnect %multibitMux_a_1, %vec_1 : !firrtl.uint<1>
|
|
; MLIR-NEXT: firrtl.matchingconnect %multibitMux_a_2, %vec_2 : !firrtl.uint<1>
|
|
; MLIR-NEXT: firrtl.matchingconnect %multibitMux_sel, %b : !firrtl.uint<2>
|
|
|
|
; ANNOTATIONS-LABEL: firrtl.module @test_mod
|
|
; ANNOTATIONS-SAME: {class = "circt.test", info = "a ModuleTarget Annotation"}
|
|
; ANNOTATIONS-SAME: {class = "circt.test", info = "a ModuleName Annotation"}
|
|
|
|
; VERILOG-LABEL: module test_mod(
|
|
; Check that a fir location is stripped.
|
|
; VERILOG-NOT: .fir
|
|
; VERILOG-NEXT: input clock,
|
|
; VERILOG-NEXT: a,
|
|
; VERILOG-NEXT: input [1:0] b,
|
|
; VERILOG-NEXT: output c,
|
|
; VERILOG-NEXT: input vec_0,
|
|
; VERILOG-NEXT: vec_1,
|
|
; VERILOG-NEXT: vec_2,
|
|
; VERILOG-NEXT: output out_implicitTrunc,
|
|
; VERILOG-NEXT: out_prettifyExample,
|
|
; VERILOG-NEXT: out_multibitMux,
|
|
; VERILOG-NEXT: out_mux2cell_0,
|
|
; VERILOG-NEXT: out_mux2cell_1
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-EMPTY:
|
|
; VERILOG-NEXT: wire [9:0] _prettifyExample_out1;
|
|
; VERILOG-NEXT: wire [9:0] _prettifyExample_out2;
|
|
; VERILOG-NEXT: wire [2:0] _implicitTrunc_out1;
|
|
; VERILOG-NEXT: wire [2:0] _implicitTrunc_out2;
|
|
; VERILOG-NEXT: wire [5:0] _cat_d;
|
|
; VERILOG-NEXT: Cat cat (
|
|
; VERILOG-NEXT: .a (b),
|
|
; VERILOG-NEXT: .b (b),
|
|
; VERILOG-NEXT: .c (b),
|
|
; VERILOG-NEXT: .d (_cat_d)
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-NEXT: ImplicitTrunc implicitTrunc (
|
|
; VERILOG-NEXT: .inp_1 (a),
|
|
; VERILOG-NEXT: .inp_2 (_cat_d[4:0]),
|
|
; VERILOG-NEXT: .out1 (_implicitTrunc_out1),
|
|
; VERILOG-NEXT: .out2 (_implicitTrunc_out2)
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-NEXT: PrettifyExample prettifyExample (
|
|
; VERILOG-NEXT: .inp_1 (_cat_d[4:0]),
|
|
; VERILOG-NEXT: .inp_2 (_cat_d[4:0]),
|
|
; VERILOG-NEXT: .inp_3 (_cat_d[4:0]),
|
|
; VERILOG-NEXT: .out1 (_prettifyExample_out1),
|
|
; VERILOG-NEXT: .out2 (_prettifyExample_out2)
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-NEXT: FlipFlop flipFlop (
|
|
; VERILOG-NEXT: .clock (clock),
|
|
; VERILOG-NEXT: .a_d (a),
|
|
; VERILOG-NEXT: .a_q (c)
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-NEXT: MultibitMux multibitMux (
|
|
; VERILOG-NEXT: .a_0 (vec_0),
|
|
; VERILOG-NEXT: .a_1 (vec_1),
|
|
; VERILOG-NEXT: .a_2 (vec_2),
|
|
; VERILOG-NEXT: .sel (b),
|
|
; VERILOG-NEXT: .b (out_multibitMux)
|
|
; VERILOG-NEXT: );
|
|
; VERILOG: endmodule
|
|
|
|
; Check that we canonicalize the HW output of lowering.
|
|
|
|
module Cat :
|
|
input a: UInt<2>
|
|
input b: UInt<2>
|
|
input c: UInt<2>
|
|
output d: UInt<6>
|
|
connect d, cat(cat(a, b), c)
|
|
|
|
; MLIRLOWER-LABEL: hw.module private @Cat(in %a : i2, in %b : i2, in %c : i2, out d : i6) {
|
|
; MLIRLOWER-NEXT: %0 = comb.concat %a, %b, %c : i2, i2, i2
|
|
; MLIRLOWER-NEXT: hw.output %0 : i6
|
|
; MLIRLOWER-NEXT: }
|
|
|
|
|
|
; Check that implicit truncation is working.
|
|
|
|
module ImplicitTrunc :
|
|
input inp_1: UInt<1>
|
|
input inp_2: SInt<5>
|
|
output out1: SInt<3>
|
|
output out2: SInt<3>
|
|
connect out1, dshl(inp_2, inp_1)
|
|
connect out2, inp_2
|
|
|
|
; MLIRLOWER-LABEL: hw.module private @ImplicitTrunc(in %inp_1 : i1, in %inp_2 : i5, out out1 : i3, out out2 : i3) {
|
|
; MLIRLOWER-NEXT: %c0_i5 = hw.constant 0 : i5
|
|
; MLIRLOWER-NEXT: %0 = comb.extract %inp_2 from 4 : (i5) -> i1
|
|
; MLIRLOWER-NEXT: %1 = comb.concat %0, %inp_2 : i1, i5
|
|
; MLIRLOWER-NEXT: %2 = comb.concat %c0_i5, %inp_1 : i5, i1
|
|
; MLIRLOWER-NEXT: %3 = comb.shl bin %1, %2 : i6
|
|
; MLIRLOWER-NEXT: %4 = comb.extract %3 from 0 : (i6) -> i3
|
|
; MLIRLOWER-NEXT: %5 = comb.extract %inp_2 from 0 : (i5) -> i3
|
|
; MLIRLOWER-NEXT: hw.output %4, %5 : i3, i3
|
|
; MLIRLOWER-NEXT: }
|
|
|
|
; VERILOG-LABEL: module ImplicitTrunc(
|
|
; VERILOG-NEXT: input inp_1,
|
|
; VERILOG-NEXT: input [4:0] inp_2,
|
|
; VERILOG-NEXT: output [2:0] out1,
|
|
; VERILOG-NEXT: out2
|
|
; VERILOG-NEXT: );
|
|
; VERILOG-EMPTY:
|
|
; VERILOG-NEXT: wire [5:0] _GEN = {inp_2[4], inp_2} << inp_1;
|
|
; VERILOG-NEXT: assign out1 = _GEN[2:0];
|
|
; VERILOG-NEXT: assign out2 = inp_2[2:0];
|
|
; VERILOG-NEXT: endmodule
|
|
|
|
|
|
; Check that we prettify the IR before Verilog emission.
|
|
|
|
module PrettifyExample :
|
|
input inp_1: UInt<5>
|
|
input inp_2: UInt<5>
|
|
input inp_3: UInt<5>
|
|
output out1: UInt<10>
|
|
output out2: UInt<10>
|
|
connect out1, cat(not(inp_1), inp_2)
|
|
connect out2, cat(not(inp_1), inp_3)
|
|
|
|
; VERILOG-LABEL: module PrettifyExample(
|
|
; VERILOG: assign out1 = {~inp_1, inp_2};
|
|
; VERILOG: assign out2 = {~inp_1, inp_3};
|
|
|
|
|
|
; Check output of a simple flip-flop.
|
|
|
|
module FlipFlop:
|
|
input clock: Clock
|
|
input a_d: UInt<1>
|
|
output a_q: UInt<1>
|
|
|
|
reg r: UInt<1>, clock
|
|
|
|
connect r, a_d
|
|
connect a_q, r
|
|
|
|
; VERILOG-LABEL: module FlipFlop(
|
|
; VERILOG-NEXT: input clock,
|
|
; VERILOG-NEXT: a_d,
|
|
; VERILOG-NEXT: output a_q
|
|
; VERILOG-NEXT: );
|
|
; VERILOG: always @(posedge clock)
|
|
; VERILOG-NEXT: r <= a_d;
|
|
; VERILOG: assign a_q = r;
|
|
|
|
module MultibitMux :
|
|
input a : UInt<1>[3]
|
|
input sel : UInt<2>
|
|
output b : UInt<1>
|
|
connect b, a[sel]
|
|
; VERILOG-LABEL: module MultibitMux(
|
|
; VERILOG: wire [3:0] [[T2:.*]] =
|
|
; VERILOG-SAME{LITERAL}: {{a_0}, {a_2}, {a_1}, {a_0}};
|
|
; VERILOG-NEXT: assign b = [[T2]][sel];
|
|
|
|
module UnusedPortsMod :
|
|
input in : UInt<1>
|
|
output out : UInt<1>
|
|
invalidate out
|
|
|
|
extmodule Val:
|
|
output v: UInt<1>
|
|
; VERILOG-LABEL: Mux2Cell
|
|
; Make sure that mux annotations are emitted properly.
|
|
; VERILOG: /* synopsys infer_mux_override */
|
|
; VERILOG-NEXT: assign [[OUT1:.+]] = mux2cell_in0 ? /* cadence map_to_mux */ mux2cell_in1 : mux2cell_in2;
|
|
; VERILOG: /* synopsys infer_mux_override */
|
|
; VERILOG-NEXT: assign [[OUT2:.+]] =
|
|
; VERILOG-NEXT: mux2cell_in0_0 ? /* cadence map_to_mux */ mux2cell_in1_0 : mux2cell_in2_0;
|
|
; VERILOG: assign out_0 = [[OUT1]];
|
|
; VERILOG: assign out_1 = [[OUT2]];
|
|
|
|
module Mux2Cell:
|
|
input cond: UInt<1>
|
|
input low: UInt<1>
|
|
output out: UInt<1>[2]
|
|
wire w: UInt<1>
|
|
inst ext of Val
|
|
connect w, ext.v
|
|
connect out[0], intrinsic(circt_mux2cell : UInt, xor(cond, UInt<1>(1)), w, low)
|
|
connect out[1], intrinsic(circt_mux2cell : UInt, xor(cond, UInt<1>(1)), ext.v, low)
|