mirror of https://github.com/llvm/circt.git
753 lines
27 KiB
MLIR
753 lines
27 KiB
MLIR
|
|
// RUN: circt-opt %s -split-input-file -verify-diagnostics
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.uint<1>) {
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a" has source flow, expected sink or duplex flow}}
|
|
firrtl.connect %a, %b : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
/// Analog types cannot be connected and must be attached.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.analog, out %b : !firrtl.analog) {
|
|
// expected-error @+1 {{analog types may not be connected}}
|
|
firrtl.connect %b, %a : !firrtl.analog, !firrtl.analog
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.bundle<a: analog>, out %b : !firrtl.bundle<a: analog>) {
|
|
// expected-error @+1 {{analog types may not be connected}}
|
|
firrtl.connect %b, %a : !firrtl.bundle<a: analog>, !firrtl.bundle<a: analog>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.analog, out %b : !firrtl.uint<1>) {
|
|
// expected-error @+1 {{analog types may not be connected}}
|
|
firrtl.connect %b, %a : !firrtl.uint<1>, !firrtl.analog
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.analog) {
|
|
// expected-error @+1 {{analog types may not be connected}}
|
|
firrtl.connect %b, %a : !firrtl.analog, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
/// Reset types can be connected to Reset, UInt<1>, or AsyncReset types.
|
|
|
|
// Reset source.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.reset, out %b : !firrtl.uint<2>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.uint<2>' and source '!firrtl.reset'}}
|
|
firrtl.connect %b, %a : !firrtl.uint<2>, !firrtl.reset
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.reset, out %b : !firrtl.sint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.sint<1>' and source '!firrtl.reset'}}
|
|
firrtl.connect %b, %a : !firrtl.sint<1>, !firrtl.reset
|
|
}
|
|
}
|
|
|
|
// Reset destination.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<2>, out %b : !firrtl.reset) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.reset' and source '!firrtl.uint<2>'}}
|
|
firrtl.connect %b, %a : !firrtl.reset, !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.sint<1>, out %b : !firrtl.reset) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.reset' and source '!firrtl.sint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.reset, !firrtl.sint<1>
|
|
}
|
|
}
|
|
|
|
/// Ground types can be connected if they are the same ground type.
|
|
|
|
// UInt<> source.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.sint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.sint<1>' and source '!firrtl.uint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.sint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.clock) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.clock' and source '!firrtl.uint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.clock, !firrtl.uint<1>
|
|
}
|
|
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.asyncreset) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.asyncreset' and source '!firrtl.uint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.asyncreset, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// SInt<> source.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.sint<1>, out %b : !firrtl.uint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.uint<1>' and source '!firrtl.sint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.uint<1>, !firrtl.sint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.sint<1>, out %b : !firrtl.clock) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.clock' and source '!firrtl.sint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.clock, !firrtl.sint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.sint<1>, out %b : !firrtl.asyncreset) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.asyncreset' and source '!firrtl.sint<1>'}}
|
|
firrtl.connect %b, %a : !firrtl.asyncreset, !firrtl.sint<1>
|
|
}
|
|
}
|
|
|
|
// Clock source.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.clock, out %b : !firrtl.uint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.uint<1>' and source '!firrtl.clock'}}
|
|
firrtl.connect %b, %a : !firrtl.uint<1>, !firrtl.clock
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.clock, out %b : !firrtl.sint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.sint<1>' and source '!firrtl.clock'}}
|
|
firrtl.connect %b, %a : !firrtl.sint<1>, !firrtl.clock
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.clock, out %b : !firrtl.asyncreset) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.asyncreset' and source '!firrtl.clock'}}
|
|
firrtl.connect %b, %a : !firrtl.asyncreset, !firrtl.clock
|
|
}
|
|
}
|
|
|
|
// AsyncReset source.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.asyncreset, out %b : !firrtl.uint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.uint<1>' and source '!firrtl.asyncreset'}}
|
|
firrtl.connect %b, %a : !firrtl.uint<1>, !firrtl.asyncreset
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.asyncreset, out %b : !firrtl.sint<1>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.sint<1>' and source '!firrtl.asyncreset'}}
|
|
firrtl.connect %b, %a : !firrtl.sint<1>, !firrtl.asyncreset
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.asyncreset, out %b : !firrtl.clock) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.clock' and source '!firrtl.asyncreset'}}
|
|
firrtl.connect %b, %a : !firrtl.clock, !firrtl.asyncreset
|
|
}
|
|
}
|
|
|
|
/// Vector types can be connected if they have the same size and element type.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.vector<uint<1>, 3>, out %b : !firrtl.vector<uint<1>, 2>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.vector<uint<1>, 2>' and source '!firrtl.vector<uint<1>, 3>'}}
|
|
firrtl.connect %b, %a : !firrtl.vector<uint<1>, 2>, !firrtl.vector<uint<1>, 3>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.vector<uint<1>, 3>, out %b : !firrtl.vector<sint<1>, 3>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.vector<sint<1>, 3>' and source '!firrtl.vector<uint<1>, 3>'}}
|
|
firrtl.connect %b, %a : !firrtl.vector<sint<1>, 3>, !firrtl.vector<uint<1>, 3>
|
|
}
|
|
}
|
|
|
|
/// Bundle types can be connected if they have the same size, element names, and
|
|
/// element types.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.bundle<f1: uint<1>>, in %b : !firrtl.bundle<f1 flip: uint<1>, f2: sint<1>>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.bundle<f1 flip: uint<1>, f2: sint<1>>' and source '!firrtl.bundle<f1: uint<1>>'}}
|
|
firrtl.connect %b, %a : !firrtl.bundle<f1 flip: uint<1>, f2: sint<1>>, !firrtl.bundle<f1: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.bundle<f1: uint<1>>, in %b : !firrtl.bundle<f2 flip: uint<1>>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.bundle<f2 flip: uint<1>>' and source '!firrtl.bundle<f1: uint<1>>'}}
|
|
firrtl.connect %b, %a : !firrtl.bundle<f2 flip: uint<1>>, !firrtl.bundle<f1: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.bundle<f1: uint<1>>, in %b : !firrtl.bundle<f1 flip: sint<1>>) {
|
|
// expected-error @+1 {{type mismatch between destination '!firrtl.bundle<f1 flip: sint<1>>' and source '!firrtl.bundle<f1: uint<1>>'}}
|
|
firrtl.connect %b, %a : !firrtl.bundle<f1 flip: sint<1>>, !firrtl.bundle<f1: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(in %a : !firrtl.bundle<f1: uint<1>>, out %b : !firrtl.bundle<f1: uint<1>>) {
|
|
%0 = firrtl.subfield %a[f1] : !firrtl.bundle<f1: uint<1>>
|
|
%1 = firrtl.subfield %b[f1] : !firrtl.bundle<f1: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.f1" has source flow, expected sink or duplex flow}}
|
|
firrtl.connect %0, %1 : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.uint<1>) {
|
|
// expected-note @below {{the destination was defined here}}
|
|
%0 = firrtl.and %a, %a: (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
// expected-error @below {{connect has invalid flow: the destination expression has source flow, expected sink or duplex flow}}
|
|
firrtl.connect %0, %b : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
/// Destination bitwidth must be greater than or equal to source bitwidth.
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<2>, out %b : !firrtl.uint<1>) {
|
|
// expected-error @+1 {{destination '!firrtl.uint<1>' is not as wide as the source '!firrtl.uint<2>'}}
|
|
firrtl.connect %b, %a : !firrtl.uint<1>, !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {a: {flip a: UInt<1>}}
|
|
/// wire ax: {a: {flip a: UInt<1>}}
|
|
/// a.a.a <= ax.a.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a: bundle<a flip: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%a_a_a = firrtl.subfield %a_a[a] : !firrtl.bundle<a flip: uint<1>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%ax_a_a = firrtl.subfield %ax_a[a] : !firrtl.bundle<a flip: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.a.a" has source flow}}
|
|
firrtl.connect %a_a_a, %ax_a_a : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {a: UInt<1>}}
|
|
/// wire ax: {flip a: {a: UInt<1>}}
|
|
/// a.a <= ax.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
// expected-error @+1 {{the destination expression "a.a" has source flow}}
|
|
firrtl.connect %a_a, %ax_a : !firrtl.bundle<a: uint<1>>, !firrtl.bundle<a: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {a: UInt<1>}}
|
|
/// wire ax: {flip a: {a: UInt<1>}}
|
|
/// a.a.a <= ax.a.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a_a = firrtl.subfield %a_a[a] : !firrtl.bundle<a: uint<1>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%ax_a_a = firrtl.subfield %ax_a[a] : !firrtl.bundle<a: uint<1>>
|
|
// expected-error @+1 {{connect has invalid flow: the destination expression "a.a.a" has source flow}}
|
|
firrtl.connect %a_a_a, %ax_a_a : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {flip a: UInt<1>}}
|
|
/// wire ax: {flip a: {flip a: UInt<1>}}
|
|
/// a.a <= ax.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a flip: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.a" has source flow}}
|
|
firrtl.connect %a_a, %ax_a : !firrtl.bundle<a flip: uint<1>>, !firrtl.bundle<a flip: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that different labels cause the enumeration to not match.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a: !firrtl.enum<a: uint<1>>, out %b: !firrtl.enum<a: uint<2>>) {
|
|
// expected-error @below {{type mismatch between destination '!firrtl.enum<a: uint<2>>' and source '!firrtl.enum<a: uint<1>>'}}
|
|
firrtl.connect %b, %a : !firrtl.enum<a: uint<2>>, !firrtl.enum<a: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that different data types causes the enumeration to not match.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a: !firrtl.enum<a: uint<0>>, out %b: !firrtl.enum<b: uint<0>>) {
|
|
// expected-error @below {{type mismatch between destination '!firrtl.enum<b: uint<0>>' and source '!firrtl.enum<a: uint<0>>'}}
|
|
firrtl.connect %b, %a : !firrtl.enum<b: uint<0>>, !firrtl.enum<a: uint<0>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid sink flow source. This has to use a
|
|
/// memory because all other sinks (module outputs or instance inputs) can
|
|
/// legally be used as sources.
|
|
///
|
|
/// output a: UInt<1>
|
|
///
|
|
/// mem memory:
|
|
/// data-type => UInt<1>
|
|
/// depth => 2
|
|
/// reader => r
|
|
/// read-latency => 0
|
|
/// write-latency => 1
|
|
/// read-under-write => undefined
|
|
///
|
|
/// a <= memory.r.en
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(out %a: !firrtl.uint<1>) {
|
|
// expected-note @below {{the source was defined here}}
|
|
%memory_r = firrtl.mem Undefined {depth = 2 : i64, name = "memory", portNames = ["r"], readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<1>>
|
|
%memory_r_en = firrtl.subfield %memory_r[en] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the source expression "memory.r.en" has sink flow}}
|
|
firrtl.connect %a, %memory_r_en : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {a: {flip a: UInt<1>}}
|
|
/// wire ax: {a: {flip a: UInt<1>}}
|
|
/// a.a.a <- ax.a.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a: bundle<a flip: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%a_a_a = firrtl.subfield %a_a[a] : !firrtl.bundle<a flip: uint<1>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a: bundle<a flip: uint<1>>>
|
|
%ax_a_a = firrtl.subfield %ax_a[a] : !firrtl.bundle<a flip: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.a.a" has source flow}}
|
|
firrtl.connect %a_a_a, %ax_a_a : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {a: UInt<1>}}
|
|
/// wire ax: {flip a: {a: UInt<1>}}
|
|
/// a.a <- ax.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
// expected-error @+1 {{connect has invalid flow: the destination expression "a.a" has source flow}}
|
|
firrtl.connect %a_a, %ax_a : !firrtl.bundle<a: uint<1>>, !firrtl.bundle<a: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {a: UInt<1>}}
|
|
/// wire ax: {flip a: {a: UInt<1>}}
|
|
/// a.a.a <- ax.a.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%a_a_a = firrtl.subfield %a_a[a] : !firrtl.bundle<a: uint<1>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a: uint<1>>>
|
|
%ax_a_a = firrtl.subfield %ax_a[a] : !firrtl.bundle<a: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.a.a" has source flow}}
|
|
firrtl.connect %a_a_a, %ax_a_a : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid source flow destination:
|
|
///
|
|
/// output a: {flip a: {flip a: UInt<1>}}
|
|
/// wire ax: {flip a: {flip a: UInt<1>}}
|
|
/// a.a <- ax.a
|
|
|
|
firrtl.circuit "test" {
|
|
// expected-note @below {{the destination was defined here}}
|
|
firrtl.module @test(out %a: !firrtl.bundle<a flip: bundle<a flip: uint<1>>>) {
|
|
%ax = firrtl.wire : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
%a_a = firrtl.subfield %a[a] : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
%ax_a = firrtl.subfield %ax[a] : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
// expected-error @below {{connect has invalid flow: the destination expression "a.a" has source flow}}
|
|
firrtl.connect %a_a, %ax_a : !firrtl.bundle<a flip: uint<1>>, !firrtl.bundle<a flip: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Check that the following is an invalid sink flow source. This has to use a
|
|
/// memory because all other sinks (module outputs or instance inputs) can
|
|
/// legally be used as sources.
|
|
///
|
|
/// output a: UInt<1>
|
|
///
|
|
/// mem memory:
|
|
/// data-type => UInt<1>
|
|
/// depth => 2
|
|
/// reader => r
|
|
/// read-latency => 0
|
|
/// write-latency => 1
|
|
/// read-under-write => undefined
|
|
///
|
|
/// a <- memory.r.en
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(out %a: !firrtl.uint<1>) {
|
|
// expected-note @below {{the source was defined here}}
|
|
%memory_r = firrtl.mem Undefined {depth = 2 : i64, name = "memory", portNames = ["r"], readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<1>>
|
|
%memory_r_en = firrtl.subfield %memory_r[en] : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<1>>
|
|
// expected-error @below {{connect has invalid flow: the source expression "memory.r.en" has sink flow}}
|
|
firrtl.connect %a, %memory_r_en : !firrtl.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.bundle<a: uint<1>>, out %b : !firrtl.bundle<a flip: uint<1>>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %b, %a : !firrtl.bundle<a flip: uint<1>>, !firrtl.bundle<a: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.sint<1>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %b, %a : !firrtl.sint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Non-const types cannot be connected to const types.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %a : !firrtl.uint<1>, out %b : !firrtl.const.uint<1>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %b, %a : !firrtl.const.uint<1>, !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Non-const aggregates cannot be connected to const types.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %in : !firrtl.bundle<a: uint<1>>,
|
|
out %out : !firrtl.const.bundle<a: uint<1>>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %out, %in : !firrtl.const.bundle<a: uint<1>>, !firrtl.bundle<a: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Const flip types cannot be connected to non-const flip types.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %in : !firrtl.const.bundle<a flip: uint<1>>,
|
|
out %out : !firrtl.bundle<a flip: uint<1>>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %out, %in : !firrtl.bundle<a flip: uint<1>>, !firrtl.const.bundle<a flip: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Nested const flip types cannot be connected to non-const flip types.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %in : !firrtl.bundle<a flip: const.uint<1>>,
|
|
out %out : !firrtl.bundle<a flip: uint<1>>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %out, %in : !firrtl.bundle<a flip: uint<1>>, !firrtl.bundle<a flip: const.uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
/// Non-const double flip types cannot be connected to const.
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %in : !firrtl.bundle<a flip: bundle<a flip: uint<1>>>,
|
|
out %out : !firrtl.const.bundle<a flip: bundle<a flip: uint<1>>>) {
|
|
// expected-error @+1 {{type mismatch}}
|
|
firrtl.connect %out, %in : !firrtl.const.bundle<a flip: bundle<a flip: uint<1>>>,
|
|
!firrtl.bundle<a flip: bundle<a flip: uint<1>>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that non-const subaccess of a const vector disallows assignment.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %index: !firrtl.uint<1>, out %out: !firrtl.const.vector<uint<1>, 1>) {
|
|
%c = firrtl.constant 0 : !firrtl.uint<1>
|
|
%d = firrtl.subaccess %out[%index] : !firrtl.const.vector<uint<1>, 1>, !firrtl.uint<1>
|
|
// expected-error @+1 {{assignment to non-'const' subaccess of 'const' type is disallowed}}
|
|
firrtl.matchingconnect %d, %c : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that non-const subaccess of a const vector disallows assignment, even if the source is const.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %index: !firrtl.uint<1>, out %out: !firrtl.const.vector<uint<1>, 1>) {
|
|
%c = firrtl.constant 0 : !firrtl.const.uint<1>
|
|
%d = firrtl.subaccess %out[%index] : !firrtl.const.vector<uint<1>, 1>, !firrtl.uint<1>
|
|
// expected-error @+1 {{assignment to non-'const' subaccess of 'const' type is disallowed}}
|
|
firrtl.connect %d, %c : !firrtl.uint<1>, !firrtl.const.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that non-const subaccess of a flipped const vector disallows assignment.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %index: !firrtl.uint<1>, in %in: !firrtl.const.vector<bundle<a flip: uint<1>>, 1>, out %out: !firrtl.bundle<a flip: uint<1>>) {
|
|
%element = firrtl.subaccess %in[%index] : !firrtl.const.vector<bundle<a flip: uint<1>>, 1>, !firrtl.uint<1>
|
|
// expected-error @+1 {{assignment to non-'const' subaccess of 'const' type is disallowed}}
|
|
firrtl.connect %out, %element : !firrtl.bundle<a flip: uint<1>>, !firrtl.bundle<a flip: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that non-const subaccess of a flipped const vector disallows assignment, even if the source is const.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %index: !firrtl.uint<1>, in %in: !firrtl.const.vector<bundle<a flip: uint<1>>, 1>, out %out: !firrtl.bundle<a flip: const.uint<1>>) {
|
|
%element = firrtl.subaccess %in[%index] : !firrtl.const.vector<bundle<a flip: uint<1>>, 1>, !firrtl.uint<1>
|
|
// expected-error @+1 {{assignment to non-'const' subaccess of 'const' type is disallowed}}
|
|
firrtl.connect %out, %element : !firrtl.bundle<a flip: const.uint<1>>, !firrtl.bundle<a flip: uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, in %in: !firrtl.const.uint<2>, out %out: !firrtl.const.uint<2>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.uint<2>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.const.uint<2>, !firrtl.const.uint<2>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, in %in: !firrtl.const.uint<2>, out %out: !firrtl.const.uint<2>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
} else {
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.uint<2>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.const.uint<2>, !firrtl.const.uint<2>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %constP: !firrtl.const.uint<1>, in %p: !firrtl.uint<1>, in %in: !firrtl.const.uint<2>, out %out: !firrtl.const.uint<2>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
firrtl.when %constP : !firrtl.const.uint<1> {
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.uint<2>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.const.uint<2>, !firrtl.const.uint<2>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, in %in: !firrtl.bundle<a: const.uint<2>>, out %out: !firrtl.bundle<a: const.uint<2>>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
// expected-error @+1 {{assignment to nested 'const' member of type '!firrtl.bundle<a: const.uint<2>>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.bundle<a: const.uint<2>>, !firrtl.bundle<a: const.uint<2>>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, in %in: !firrtl.const.bundle<a flip: uint<2>>, out %out: !firrtl.const.bundle<a flip: uint<2>>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.bundle<a flip: uint<2>>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.const.bundle<a flip: uint<2>>, !firrtl.const.bundle<a flip: uint<2>>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, in %in: !firrtl.bundle<a flip: const.uint<2>>, out %out: !firrtl.bundle<a flip: const.uint<2>>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
// expected-error @+1 {{assignment to nested 'const' member of type '!firrtl.bundle<a flip: const.uint<2>>' is dependent on a non-'const' condition}}
|
|
firrtl.connect %out, %in : !firrtl.bundle<a flip: const.uint<2>>, !firrtl.bundle<a flip: const.uint<2>>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that the declaration location of the bundle containing the field is checked.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, out %out: !firrtl.const.bundle<a: uint<1>>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
%f = firrtl.subfield %out[a] : !firrtl.const.bundle<a: uint<1>>
|
|
%c = firrtl.constant 0 : !firrtl.const.uint<1>
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.uint<1>' is dependent on a non-'const' condition}}
|
|
firrtl.matchingconnect %f, %c : !firrtl.const.uint<1>
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test that the declaration location of the vector containing the field is checked.
|
|
firrtl.circuit "test" {
|
|
firrtl.module @test(in %p: !firrtl.uint<1>, out %out: !firrtl.const.vector<uint<1>, 1>) {
|
|
firrtl.when %p : !firrtl.uint<1> {
|
|
%e = firrtl.subindex %out[0] : !firrtl.const.vector<uint<1>, 1>
|
|
%c = firrtl.constant 0 : !firrtl.const.uint<1>
|
|
// expected-error @+1 {{assignment to 'const' type '!firrtl.const.uint<1>' is dependent on a non-'const' condition}}
|
|
firrtl.matchingconnect %e, %c : !firrtl.const.uint<1>
|
|
}
|
|
}
|
|
}
|