mirror of https://github.com/llvm/circt.git
305 lines
15 KiB
MLIR
305 lines
15 KiB
MLIR
// RUN: circt-opt -lower-firrtl-to-hw %s -verify-diagnostics | FileCheck %s
|
|
|
|
// The firrtl.circuit should be removed.
|
|
// CHECK-NOT: firrtl.circuit
|
|
|
|
// We should get a large header boilerplate.
|
|
// CHECK: sv.ifdef @PRINTF_COND {
|
|
// CHECK-NEXT: sv.macro.def @PRINTF_COND_ "(`PRINTF_COND)"
|
|
// CHECK-NEXT: } else {
|
|
firrtl.circuit "Simple" {
|
|
|
|
// CHECK-LABEL: hw.module.extern private @MyParameterizedExtModule
|
|
// CHECK-SAME: <DEFAULT: i64, DEPTH: f64, FORMAT: none, WIDTH: i8>
|
|
// CHECK-SAME: (in %in : i1, out out : i8)
|
|
// CHECK: attributes {verilogName = "name_thing"}
|
|
firrtl.extmodule private @MyParameterizedExtModule
|
|
<DEFAULT: i64 = 0,
|
|
DEPTH: f64 = 3.242000e+01,
|
|
FORMAT: none = "xyz_timeout=%d\0A",
|
|
WIDTH: i8 = 32>
|
|
(in in: !firrtl.uint<1>, out out: !firrtl.uint<8>)
|
|
attributes {defname = "name_thing"}
|
|
|
|
// CHECK-LABEL: hw.module @Simple(in %in1 : i4, in %in2 : i2, in %in3 : i8, out out4 : i4)
|
|
firrtl.module @Simple(in %in1: !firrtl.uint<4>,
|
|
in %in2: !firrtl.uint<2>,
|
|
in %in3: !firrtl.sint<8>,
|
|
out %out4: !firrtl.uint<4>) {
|
|
|
|
%1 = firrtl.asUInt %in1 : (!firrtl.uint<4>) -> !firrtl.uint<4>
|
|
|
|
// CHECK: comb.concat %false, %in1
|
|
// CHECK: comb.concat %false, %in1
|
|
|
|
// CHECK: comb.sub
|
|
%2 = firrtl.sub %1, %1 : (!firrtl.uint<4>, !firrtl.uint<4>) -> !firrtl.uint<5>
|
|
|
|
// CHECK: %3 = comb.concat %false, %in2 : i1, i2
|
|
%3 = firrtl.pad %in2, 3 : (!firrtl.uint<2>) -> !firrtl.uint<3>
|
|
// CHECK: comb.concat %false, %3 : i1, i3
|
|
%4 = firrtl.pad %3, 4 : (!firrtl.uint<3>) -> !firrtl.uint<4>
|
|
// CHECK: [[RESULT:%.+]] = comb.xor
|
|
%5 = firrtl.xor %in2, %4 : (!firrtl.uint<2>, !firrtl.uint<4>) -> !firrtl.uint<4>
|
|
|
|
firrtl.connect %out4, %5 : !firrtl.uint<4>, !firrtl.uint<4>
|
|
// CHECK-NEXT: hw.output [[RESULT]] : i4
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @TestInstance(
|
|
firrtl.module private @TestInstance(in %u2: !firrtl.uint<2>, in %s8: !firrtl.sint<8>,
|
|
in %clock: !firrtl.clock,
|
|
in %reset: !firrtl.uint<1>) {
|
|
// CHECK-NEXT: [[CLK:%.+]] = seq.from_clock %clock
|
|
// CHECK-NEXT: %c0_i2 = hw.constant
|
|
// CHECK-NEXT: %xyz.out4 = hw.instance "xyz" @Simple(in1: [[ARG1:%.+]]: i4, in2: %u2: i2, in3: %s8: i8) -> (out4: i4)
|
|
%xyz:4 = firrtl.instance xyz @Simple(in in1: !firrtl.uint<4>, in in2: !firrtl.uint<2>, in in3: !firrtl.sint<8>, out out4: !firrtl.uint<4>)
|
|
|
|
// CHECK: [[ARG1]] = comb.concat %c0_i2, %u2 : i2, i2
|
|
firrtl.connect %xyz#0, %u2 : !firrtl.uint<4>, !firrtl.uint<2>
|
|
|
|
// CHECK-NOT: hw.connect
|
|
firrtl.connect %xyz#1, %u2 : !firrtl.uint<2>, !firrtl.uint<2>
|
|
|
|
firrtl.connect %xyz#2, %s8 : !firrtl.sint<8>, !firrtl.sint<8>
|
|
|
|
firrtl.printf %clock, %reset, "%x"(%xyz#3) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<4>
|
|
|
|
// Parameterized module reference.
|
|
// hw.instance carries the parameters, unlike at the FIRRTL layer.
|
|
|
|
// CHECK: %myext.out = hw.instance "myext" @MyParameterizedExtModule<DEFAULT: i64 = 0, DEPTH: f64 = 3.242000e+01, FORMAT: none = "xyz_timeout=%d\0A", WIDTH: i8 = 32>(in: %reset: i1) -> (out: i8)
|
|
%myext:2 = firrtl.instance myext @MyParameterizedExtModule(in in: !firrtl.uint<1>, out out: !firrtl.uint<8>)
|
|
|
|
// CHECK: %PRINTF_FD_ = sv.macro.ref.expr @PRINTF_FD_() : () -> i32
|
|
// CHECK: sv.fwrite %PRINTF_FD_, "%x"(%xyz.out4) : i4
|
|
// CHECK: sv.fwrite %PRINTF_FD_, "Something interesting! %x"(%myext.out) : i8
|
|
|
|
firrtl.connect %myext#0, %reset : !firrtl.uint<1>, !firrtl.uint<1>
|
|
|
|
firrtl.printf %clock, %reset, "Something interesting! %x"(%myext#1) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<8>
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @OutputFirst(out out4 : i4, in %in1 : i1, in %in4 : i4) {
|
|
firrtl.module private @OutputFirst(out %out4: !firrtl.uint<4>,
|
|
in %in1: !firrtl.uint<1>,
|
|
in %in4: !firrtl.uint<4>) {
|
|
firrtl.connect %out4, %in4 : !firrtl.uint<4>, !firrtl.uint<4>
|
|
|
|
// CHECK-NEXT: hw.output %in4 : i4
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @PortMadness(
|
|
// CHECK: in %inA : i4, in %inB : i4, in %inC : i4,
|
|
// CHECK: out outA : i4, out outB : i4, out outC : i4, out outD : i4, in %inE : i3, out outE : i4) {
|
|
firrtl.module private @PortMadness(in %inA: !firrtl.uint<4>,
|
|
in %inB: !firrtl.uint<4>,
|
|
in %inC: !firrtl.uint<4>,
|
|
out %outA: !firrtl.uint<4>,
|
|
out %outB: !firrtl.uint<4>,
|
|
out %outC: !firrtl.uint<4>,
|
|
out %outD: !firrtl.uint<4>,
|
|
in %inE: !firrtl.uint<3>,
|
|
out %outE: !firrtl.uint<4>) {
|
|
// Normal
|
|
firrtl.connect %outA, %inA : !firrtl.uint<4>, !firrtl.uint<4>
|
|
|
|
// Multi connect
|
|
firrtl.connect %outB, %inA : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %outB, %inB : !firrtl.uint<4>, !firrtl.uint<4>
|
|
|
|
// Unconnected port outC reads as sv.constantZ.
|
|
// CHECK: [[OUTB:%.+]] = hw.wire %inB
|
|
// CHECK-NEXT: [[OUTC:%.+]] = hw.wire %z_i4
|
|
// CHECK-NEXT: [[OUTD:%.+]] = hw.wire %z_i4
|
|
// CHECK-NEXT: [[T0:%.+]] = comb.concat %false, %inA
|
|
// CHECK-NEXT: [[T1:%.+]] = comb.concat %false, [[OUTC]]
|
|
// CHECK-NEXT: comb.sub bin [[T0]], [[T1]]
|
|
%0 = firrtl.sub %inA, %outC : (!firrtl.uint<4>, !firrtl.uint<4>) -> !firrtl.uint<5>
|
|
|
|
// No connections to outD.
|
|
|
|
firrtl.connect %outE, %inE : !firrtl.uint<4>, !firrtl.uint<3>
|
|
|
|
// Extension for outE
|
|
// CHECK: [[OUTE:%.+]] = comb.concat %false, %inE : i1, i3
|
|
// CHECK: hw.output %inA, [[OUTB]], [[OUTC]], [[OUTD]], [[OUTE]]
|
|
}
|
|
|
|
firrtl.module private @InputPorts(in %in : !firrtl.uint<1>) { }
|
|
firrtl.module private @InputPortsParent(in %in : !firrtl.uint<1>) {
|
|
// Double connected.
|
|
// CHECK: hw.instance "ip1" @InputPorts(in: %in: i1) -> ()
|
|
%ip1_in = firrtl.instance ip1 @InputPorts(in in : !firrtl.uint<1>)
|
|
firrtl.connect %ip1_in, %in : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.connect %ip1_in, %in : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @Analog(inout %a1 : i1, out outClock : !seq.clock) {
|
|
// CHECK-NEXT: [[READ:%.+]] = sv.read_inout %a1 : !hw.inout<i1>
|
|
// CHECK-NEXT: [[CLK:%.+]] = seq.to_clock [[READ]]
|
|
// CHECK-NEXT: hw.output [[CLK]] : !seq.clock
|
|
firrtl.module private @Analog(in %a1: !firrtl.analog<1>,
|
|
out %outClock: !firrtl.clock) {
|
|
|
|
%clock = firrtl.asClock %a1 : (!firrtl.analog<1>) -> !firrtl.clock
|
|
firrtl.connect %outClock, %clock : !firrtl.clock, !firrtl.clock
|
|
}
|
|
|
|
// Issue #373: https://github.com/llvm/circt/issues/373
|
|
// CHECK-LABEL: hw.module private @instance_ooo
|
|
firrtl.module private @instance_ooo(in %arg0: !firrtl.uint<2>, in %arg1: !firrtl.uint<2>,
|
|
in %arg2: !firrtl.uint<3>,
|
|
out %out0: !firrtl.uint<8>) {
|
|
// CHECK: %false = hw.constant false
|
|
|
|
// CHECK-NEXT: hw.instance "myext" @MyParameterizedExtModule<DEFAULT: i64 = 0, DEPTH: f64 = 3.242000e+01, FORMAT: none = "xyz_timeout=%d\0A", WIDTH: i8 = 32>(in: [[ARG:%.+]]: i1) -> (out: i8)
|
|
%myext:2 = firrtl.instance myext @MyParameterizedExtModule(in in: !firrtl.uint<1>, out out: !firrtl.uint<8>)
|
|
|
|
// CHECK: [[ADD:%.+]] = comb.add bin %0, %1
|
|
|
|
// Calculation of input (the firrtl.add + firrtl.eq) happens after the
|
|
// instance.
|
|
%0 = firrtl.add %arg0, %arg0 : (!firrtl.uint<2>, !firrtl.uint<2>) -> !firrtl.uint<3>
|
|
|
|
// Multiple uses of the add.
|
|
%a = firrtl.eq %0, %arg2 : (!firrtl.uint<3>, !firrtl.uint<3>) -> !firrtl.uint<1>
|
|
// CHECK-NEXT: [[ARG]] = comb.icmp bin eq [[ADD]], %arg2 : i3
|
|
firrtl.connect %myext#0, %a : !firrtl.uint<1>, !firrtl.uint<1>
|
|
|
|
firrtl.connect %out0, %myext#1 : !firrtl.uint<8>, !firrtl.uint<8>
|
|
|
|
// CHECK-NEXT: hw.output %myext.out
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @instance_cyclic
|
|
firrtl.module private @instance_cyclic(in %arg0: !firrtl.uint<2>, in %arg1: !firrtl.uint<2>) {
|
|
// CHECK: %myext.out = hw.instance "myext" @MyParameterizedExtModule<DEFAULT: i64 = 0, DEPTH: f64 = 3.242000e+01, FORMAT: none = "xyz_timeout=%d\0A", WIDTH: i8 = 32>(in: %0: i1)
|
|
%myext:2 = firrtl.instance myext @MyParameterizedExtModule(in in: !firrtl.uint<1>, out out: !firrtl.uint<8>)
|
|
|
|
// Output of the instance is fed into the input!
|
|
%11 = firrtl.bits %myext#1 2 to 2 : (!firrtl.uint<8>) -> !firrtl.uint<1>
|
|
// CHECK: %0 = comb.extract %myext.out from 2 : (i8) -> i1
|
|
|
|
firrtl.connect %myext#0, %11 : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @ZeroWidthPorts(in %inA : i4, out outa : i4) {
|
|
firrtl.module private @ZeroWidthPorts(in %inA: !firrtl.uint<4>,
|
|
in %inB: !firrtl.uint<0>,
|
|
in %inC: !firrtl.analog<0>,
|
|
out %outa: !firrtl.uint<4>,
|
|
out %outb: !firrtl.uint<0>) {
|
|
%0 = firrtl.mul %inA, %inB : (!firrtl.uint<4>, !firrtl.uint<0>) -> !firrtl.uint<4>
|
|
firrtl.connect %outa, %0 : !firrtl.uint<4>, !firrtl.uint<4>
|
|
|
|
%1 = firrtl.mul %inB, %inB : (!firrtl.uint<0>, !firrtl.uint<0>) -> !firrtl.uint<0>
|
|
firrtl.connect %outb, %1 : !firrtl.uint<0>, !firrtl.uint<0>
|
|
|
|
firrtl.attach %inC, %inC : !firrtl.analog<0>, !firrtl.analog<0>
|
|
|
|
// CHECK: [[OUTAC:%.+]] = hw.constant 0 : i4
|
|
// CHECK-NEXT: hw.output [[OUTAC]] : i4
|
|
}
|
|
firrtl.extmodule private @SameNamePorts(in inA: !firrtl.uint<4>,
|
|
in inA: !firrtl.uint<1>,
|
|
in inA: !firrtl.analog<1>,
|
|
out outa: !firrtl.uint<4>,
|
|
out outa: !firrtl.uint<1>)
|
|
// CHECK-LABEL: hw.module private @ZeroWidthInstance
|
|
firrtl.module private @ZeroWidthInstance(in %iA: !firrtl.uint<4>,
|
|
in %iB: !firrtl.uint<0>,
|
|
in %iC: !firrtl.analog<0>,
|
|
in %iD: !firrtl.uint<1>,
|
|
in %iE: !firrtl.analog<1>,
|
|
out %oA: !firrtl.uint<4>,
|
|
out %oB: !firrtl.uint<0>) {
|
|
|
|
// CHECK: %myinst.outa = hw.instance "myinst" @ZeroWidthPorts(inA: %iA: i4) -> (outa: i4)
|
|
%myinst:5 = firrtl.instance myinst @ZeroWidthPorts(
|
|
in inA: !firrtl.uint<4>, in inB: !firrtl.uint<0>, in inC: !firrtl.analog<0>, out outa: !firrtl.uint<4>, out outb: !firrtl.uint<0>)
|
|
|
|
// Output of the instance is fed into the input!
|
|
firrtl.connect %myinst#0, %iA : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %myinst#1, %iB : !firrtl.uint<0>, !firrtl.uint<0>
|
|
firrtl.attach %myinst#2, %iC : !firrtl.analog<0>, !firrtl.analog<0>
|
|
firrtl.connect %oA, %myinst#3 : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %oB, %myinst#4 : !firrtl.uint<0>, !firrtl.uint<0>
|
|
|
|
// CHECK: = hw.instance "myinst" @SameNamePorts(inA: {{.+}}, inA: {{.+}}, inA: {{.+}}) -> (outa: i4, outa: i1)
|
|
%myinst_sameName:5 = firrtl.instance myinst @SameNamePorts(
|
|
in inA: !firrtl.uint<4>, in inA: !firrtl.uint<1>, in inA: !firrtl.analog<1>, out outa: !firrtl.uint<4>, out outa: !firrtl.uint<1>)
|
|
firrtl.connect %myinst_sameName#0, %iA : !firrtl.uint<4>, !firrtl.uint<4>
|
|
firrtl.connect %myinst_sameName#1, %iD : !firrtl.uint<1>, !firrtl.uint<1>
|
|
firrtl.attach %myinst_sameName#2, %iE : !firrtl.analog<1>, !firrtl.analog<1>
|
|
|
|
// CHECK: hw.output %myinst.outa
|
|
}
|
|
|
|
// CHECK-LABEL: hw.module private @SimpleStruct(in %source : !hw.struct<valid: i1, ready: i1, data: i64>, out sink : !hw.struct<valid: i1, ready: i1, data: i64>) {
|
|
// CHECK-NEXT: hw.output %source : !hw.struct<valid: i1, ready: i1, data: i64>
|
|
firrtl.module private @SimpleStruct(in %source: !firrtl.bundle<valid: uint<1>, ready: uint<1>, data: uint<64>>,
|
|
out %sink: !firrtl.bundle<valid: uint<1>, ready: uint<1>, data: uint<64>>) {
|
|
firrtl.connect %sink, %source : !firrtl.bundle<valid: uint<1>, ready: uint<1>, data: uint<64>>, !firrtl.bundle<valid: uint<1>, ready: uint<1>, data: uint<64>>
|
|
}
|
|
|
|
// https://github.com/llvm/circt/issues/690
|
|
// CHECK-LABEL: hw.module private @bar690(inout %led_0 : i1) {
|
|
firrtl.module private @bar690(in %led_0: !firrtl.analog<1>) {
|
|
}
|
|
// CHECK-LABEL: hw.module private @foo690()
|
|
firrtl.module private @foo690() {
|
|
// CHECK: %.led_0.wire = sv.wire
|
|
// CHECK: hw.instance "fpga" @bar690(led_0: %.led_0.wire: !hw.inout<i1>) -> ()
|
|
%result = firrtl.instance fpga @bar690(in led_0: !firrtl.analog<1>)
|
|
}
|
|
// CHECK-LABEL: hw.module private @foo690a(inout %a : i1) {
|
|
firrtl.module private @foo690a(in %a: !firrtl.analog<1>) {
|
|
%result = firrtl.instance fpga @bar690(in led_0: !firrtl.analog<1>)
|
|
firrtl.attach %result, %a: !firrtl.analog<1>, !firrtl.analog<1>
|
|
}
|
|
|
|
// https://github.com/llvm/circt/issues/740
|
|
// CHECK-LABEL: hw.module private @foo740(inout %led_0 : i1) {
|
|
// CHECK-NEXT: hw.instance "fpga" @bar740(led_0: %led_0: !hw.inout<i1>) -> ()
|
|
firrtl.extmodule private @bar740(in led_0: !firrtl.analog<1>)
|
|
firrtl.module private @foo740(in %led_0: !firrtl.analog<1>) {
|
|
%result = firrtl.instance fpga @bar740(in led_0: !firrtl.analog<1>)
|
|
firrtl.attach %result, %led_0 : !firrtl.analog<1>, !firrtl.analog<1>
|
|
}
|
|
|
|
firrtl.extmodule private @UIntToAnalog_8(out a: !firrtl.analog<8>, out b: !firrtl.analog<8>)
|
|
firrtl.module @Example(out %port: !firrtl.analog<8>) {
|
|
// CHECK-LABEL: hw.module @Example(inout %port : i8)
|
|
// CHECK-NEXT: hw.instance "a2b" @UIntToAnalog_8(a: %port: !hw.inout<i8>, b: %port: !hw.inout<i8>)
|
|
%a2b_a, %a2b_b = firrtl.instance a2b @UIntToAnalog_8(out a: !firrtl.analog<8>, out b: !firrtl.analog<8>)
|
|
firrtl.attach %port, %a2b_b, %a2b_a : !firrtl.analog<8>, !firrtl.analog<8>, !firrtl.analog<8>
|
|
}
|
|
|
|
// Memory modules are lowered to plain external modules.
|
|
// CHECK: hw.module.extern @MRead_ext(in %R0_addr : i4, in %R0_en : i1, in %R0_clk : i1, out R0_data : i42) attributes {verilogName = "MRead_ext"}
|
|
firrtl.memmodule @MRead_ext(in R0_addr: !firrtl.uint<4>, in R0_en: !firrtl.uint<1>, in R0_clk: !firrtl.uint<1>, out R0_data: !firrtl.uint<42>) attributes {dataWidth = 42 : ui32, depth = 12 : ui64, extraPorts = [], maskBits = 0 : ui32, numReadPorts = 1 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 0 : ui32, readLatency = 0 : ui32, writeLatency = 1 : ui32}
|
|
|
|
// The following operations should be passed through without an error.
|
|
// CHECK: sv.interface @SVInterface
|
|
sv.interface @SVInterface { }
|
|
|
|
// DontTouch on ports becomes symbol.
|
|
// CHECK-LABEL: hw.module.extern private @PortDT
|
|
// CHECK-SAME: (in %a : i1 {hw.exportPort = #hw<innerSym@__PortDT__DONTTOUCH__0__a>}, in %hassym : i1 {hw.exportPort = #hw<innerSym@hassym>},
|
|
// CHECK-SAME: out b : i2 {hw.exportPort = #hw<innerSym@__PortDT__DONTTOUCH__2__b>})
|
|
firrtl.extmodule private @PortDT(
|
|
in a: !firrtl.uint<1> [{class = "firrtl.transforms.DontTouchAnnotation"}],
|
|
in hassym: !firrtl.uint<1> sym @hassym [{class = "firrtl.transforms.DontTouchAnnotation"}],
|
|
out b: !firrtl.uint<2> [{class = "firrtl.transforms.DontTouchAnnotation"}]
|
|
)
|
|
|
|
// CHECK-LABEL: @PortDT2
|
|
// CHECK-SAME: {hw.exportPort = #hw<innerSym@__PortDT2__DONTTOUCH__0__>}
|
|
// CHECK-SAME: {hw.exportPort = #hw<innerSym@__PortDT2__DONTTOUCH__1__>}
|
|
firrtl.module private @PortDT2(
|
|
in %0: !firrtl.uint<1> [{class = "firrtl.transforms.DontTouchAnnotation"}],
|
|
in %1: !firrtl.uint<1> [{class = "firrtl.transforms.DontTouchAnnotation"}]
|
|
) {}
|
|
}
|