circt/test/Dialect/FIRRTL/annotations-errors.mlir

512 lines
14 KiB
MLIR

// RUN: circt-opt --pass-pipeline='builtin.module(firrtl.circuit(firrtl-lower-annotations))' -split-input-file %s -verify-diagnostics
// An unknown annotation should error.
//
// expected-error @+1 {{Unhandled annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.unknown"
}
]} {
firrtl.module @Foo() {}
}
// -----
// An incorrect circuit target should report an error.
//
// expected-error @+2 {{circuit name doesn't match annotation}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Fooo|Foo>bar"
}
]} {
firrtl.module @Foo() {}
}
// -----
// An incorrect circuit name should report an error.
//
// expected-error @+2 {{circuit name doesn't match annotation}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Fooo"
}
]} {
firrtl.module @Foo() {}
}
// -----
// An empty target string should be illegal.
//
// expected-error @+2 {{Cannot tokenize annotation path}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = ""
}
]} {
firrtl.module @Foo() {}
}
// -----
// A target that does a subindex of an instance should be illegal.
//
// expected-error @+2 {{illegal target '~Foo|Foo>bar[0]' indexes into an instance}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Foo>bar[0]"
}
]} {
firrtl.module @Bar() {}
firrtl.module @Foo() {
firrtl.instance bar @Bar()
}
}
// -----
// A target that uses a string for an index should be illegal.
//
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Foo>bar[a].baz"
}
]} {
firrtl.module @Foo() {
// expected-error @+1 {{Cannot convert 'a' to an integer}}
%bar = firrtl.wire : !firrtl.vector<bundle<baz: uint<1>, qux: uint<1>>, 2>
}
}
// -----
// Invalid subindex or subfield targets are checked.
//
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Foo>bar[1][42]"
},
{
class = "circt.test",
target = "~Foo|Foo>bar[1].qnx"
},
{
class = "circt.test",
target = "~Foo|Foo>bar[1].baz[1337]"
}
]} {
firrtl.module @Foo(in %clock: !firrtl.clock) {
// expected-error @+3 {{index access '42' into non-vector type}}
// expected-error @+2 {{cannot resolve field 'qnx' in subtype}}
// expected-error @+1 {{index access '1337' into non-vector type}}
%bar = firrtl.reg %clock : !firrtl.clock, !firrtl.vector<bundle<baz: uint<1>, qux: uint<1>>, 2>
}
}
// -----
// A target on a non-existent module should error.
//
// expected-error @+2 {{module doesn't exist 'Bar'}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Bar"
}
]} {
firrtl.module @Foo() {}
}
// -----
// A target on a non-existent component should error.
//
// expected-error @+2 {{cannot find name 'x' in Foo}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Foo>x"
}
]} {
firrtl.module @Foo() {}
}
// -----
// A non-local annotation on a non-existent instance should error.
//
// expected-error @+2 {{cannot find instance 'baz' in 'Foo'}}
// expected-error @+1 {{Unable to resolve target of annotation}}
firrtl.circuit "Foo" attributes {rawAnnotations = [
{
class = "circt.test",
target = "~Foo|Foo/baz:Bar"
}
]} {
firrtl.module private @Bar() {}
firrtl.module @Foo() {
firrtl.instance bar interesting_name @Bar()
}
}
// -----
// expected-error @+1 {{Unable to apply annotation}}
firrtl.circuit "LocalOnlyAnnotation" attributes {
rawAnnotations = [
{class = "circt.testLocalOnly",
target = "~LocalOnlyAnnotation|LocalOnlyAnnotation/foo:Foo>w"}
]} {
firrtl.module @Foo() {
// expected-error @+2 {{targeted by a non-local annotation}}
// expected-note @+1 {{see current annotation}}
%w = firrtl.wire : !firrtl.uint<1>
}
firrtl.module @LocalOnlyAnnotation() {
firrtl.instance foo @Foo()
}
}
// -----
// expected-error @+1 {{Unable to apply annotation}}
firrtl.circuit "DontTouchOnNonReferenceTarget" attributes {
rawAnnotations = [
{class = "firrtl.transforms.DontTouchAnnotation",
target = "~DontTouchOnNonReferenceTarget|Submodule"},
{class = "firrtl.transforms.DontTouchAnnotation",
target = "~DontTouchOnNonReferenceTarget|DontTouchOnNonReferenceTarget>submodule"}]} {
firrtl.module @Submodule() {}
firrtl.module @DontTouchOnNonReferenceTarget() {
firrtl.instance submodule @Submodule()
}
}
// -----
// expected-error @+3 {{unknown/unimplemented DataTapKey class 'sifive.enterprise.grandcentral.DeletedDataTapKey'}}
// expected-note @+2 {{full Annotation is reproduced here}}
// expected-error @+1 {{Unable to apply annotation}}
firrtl.circuit "GCTDataTapUnsupportedDeleted" attributes {rawAnnotations = [{
blackBox = "~GCTDataTap|DataTap",
class = "sifive.enterprise.grandcentral.DataTapsAnnotation",
keys = [
{
class = "sifive.enterprise.grandcentral.DeletedDataTapKey",
sink = "~GCTDataTap|GCTDataTap>tap_1"
}
]
}]} {
firrtl.module @GCTDataTapUnsupportedDeleted() {
%tap = firrtl.wire : !firrtl.uint<1>
}
}
// -----
// expected-error @+3 {{unknown/unimplemented DataTapKey class 'sifive.enterprise.grandcentral.LiteralDataTapKey'}}
// expected-note @+2 {{full Annotation is reproduced here}}
// expected-error @+1 {{Unable to apply annotation}}
firrtl.circuit "GCTDataTapUnsupportedLiteral" attributes {rawAnnotations = [{
blackBox = "~GCTDataTap|DataTap",
class = "sifive.enterprise.grandcentral.DataTapsAnnotation",
keys = [
{
class = "sifive.enterprise.grandcentral.LiteralDataTapKey",
literal = "UInt<16>(\22h2a\22)",
sink = "~GCTDataTap|GCTDataTap>tap"
}
]
}]} {
firrtl.module @GCTDataTapUnsupportedLiteral() {
%tap = firrtl.wire : !firrtl.uint<1>
}
}
// -----
// Check instance port target that doesn't exist.
// expected-error @below {{cannot find port 'a' in module Ext}}
// expected-error @below {{Unable to resolve target of annotation}}
firrtl.circuit "InstancePortNotFound" attributes {rawAnnotations = [{
class = "circt.test",
target = "~InstancePortNotFound|InstancePortNotFound>inst.a"
}]} {
firrtl.extmodule @Ext()
firrtl.module @InstancePortNotFound() {
firrtl.instance inst @Ext()
}
}
// -----
// Check ref-type instance port is rejected.
// expected-error @below {{annotation cannot target reference-type port 'ref' in module Ext}}
// expected-error @below {{Unable to resolve target of annotation}}
firrtl.circuit "InstancePortRef" attributes {rawAnnotations = [{
class = "circt.test",
target = "~InstancePortRef|InstancePortRef>inst.ref"
}]} {
firrtl.extmodule @Ext(out ref : !firrtl.ref<uint<1>>)
firrtl.module @InstancePortRef() {
%ref = firrtl.instance inst @Ext(out ref : !firrtl.ref<uint<1>>)
}
}
// -----
// Check indexing into ref-type instance port is rejected.
// expected-error @below {{annotation cannot target reference-type port 'ref' in module Ext}}
// expected-error @below {{Unable to resolve target of annotation}}
firrtl.circuit "InstancePortRefField" attributes {rawAnnotations = [{
class = "circt.test",
target = "~InstancePortRefField|InstancePortRefField>inst.ref.x"
}]} {
firrtl.extmodule @Ext(out ref : !firrtl.ref<bundle<x: uint<1>>>)
firrtl.module @InstancePortRefField() {
%ref = firrtl.instance inst @Ext(out ref : !firrtl.ref<bundle<x: uint<1>>>)
}
}
// -----
// Reject annotations on references.
// expected-error @below {{cannot target reference-type 'out' in RefAnno}}
// expected-error @below {{Unable to resolve target of annotation}}
firrtl.circuit "RefAnno" attributes {rawAnnotations = [{
class = "circt.test",
target = "~RefAnno|RefAnno>out"
}]} {
firrtl.module @RefAnno(in %in : !firrtl.uint<1>, out %out : !firrtl.ref<uint<1>>) {
%ref = firrtl.ref.send %in : !firrtl.uint<1>
firrtl.ref.define %out, %ref : !firrtl.ref<uint<1>>
}
}
// -----
// Reject annotations that index through references.
// expected-error @below {{cannot target reference-type 'out' in RefFieldAnno}}
// expected-error @below {{Unable to resolve target of annotation}}
firrtl.circuit "RefFieldAnno" attributes {rawAnnotations = [{
class = "circt.test",
target = "~RefFieldAnno|RefFieldAnno>out.x"
}]} {
firrtl.module @RefFieldAnno(in %in : !firrtl.bundle<x: uint<1>>, out %out : !firrtl.ref<bundle<x: uint<1>>>) {
%ref = firrtl.ref.send %in : !firrtl.bundle<x: uint<1>>
firrtl.ref.define %out, %ref : !firrtl.ref<bundle<x: uint<1>>>
}
}
// -----
// Reject AttributeAnnotations on ports.
// expected-error @+1 {{Unable to apply annotation:}}
firrtl.circuit "Anno" attributes {rawAnnotations = [{
class = "firrtl.AttributeAnnotation",
target = "~Anno|Anno>in",
description = "attr"
}]} {
// expected-error @+1 {{firrtl.AttributeAnnotation must target an operation. Currently ports are not supported}}
firrtl.module @Anno(in %in : !firrtl.uint<1>) {}
}
// -----
// Reject AttributeAnnotations on external modules.
// expected-error @+1 {{Unable to apply annotation:}}
firrtl.circuit "Anno" attributes {rawAnnotations = [{
class = "firrtl.AttributeAnnotation",
target = "~Anno|Ext",
description = "ext"
}]} {
// expected-error @+1 {{firrtl.AttributeAnnotation unhandled operation. The target must be a module, wire, node or register}}
firrtl.extmodule @Ext()
firrtl.module @Anno(in %in : !firrtl.uint<1>) {}
}
// -----
// Reject annotation on a class.
// expected-error @+1 {{Unable to resolve target of annotation: {class = "circt.test", target = "~Component|Class"}}}
firrtl.circuit "Component"
attributes {
rawAnnotations = [
{
class = "circt.test",
target = "~Component|Class"
}
]
} {
firrtl.module @Component() {}
// expected-error @+1 {{annotations cannot target classes}}
firrtl.class @Class() {}
}
// -----
// Reject annotation on a class's port.
// expected-error @+1 {{Unable to resolve target of annotation: {class = "circt.test", target = "~Component|Class>port"}}}
firrtl.circuit "Component"
attributes {
rawAnnotations = [
{
class = "circt.test",
target = "~Component|Class>port"
}
]
} {
firrtl.module @Component() {}
// expected-error @+1 {{annotations cannot target classes}}
firrtl.class @Class(in %port: !firrtl.string) {}
}
// -----
// Don't crash trying to annotate-subindex through targets that don't name a result.
// expected-error @below {{Unable to resolve target of annotation: {class = "circt.test", target = "~Issue5947|Issue5947>mem[0]"}}}
firrtl.circuit "Issue5947"
attributes {
rawAnnotations = [
{
class = "circt.test",
target = "~Issue5947|Issue5947>mem[0]"
}
]
} {
firrtl.module @Issue5947() {
// expected-error @below {{index access in annotation not supported for this operation}}
%mem = chirrtl.combmem : !chirrtl.cmemory<uint<1>, 2>
}
}
// -----
// Don't crash trying to annotate-subfield through targets that don't name a result.
// expected-error @below {{Unable to resolve target of annotation: {class = "circt.test", target = "~Issue5947|Issue5947>mem.a"}}}
firrtl.circuit "Issue5947"
attributes {
rawAnnotations = [
{
class = "circt.test",
target = "~Issue5947|Issue5947>mem.a"
}
]
} {
firrtl.module @Issue5947() {
// expected-error @below {{field access in annotation not supported for this operation}}
%mem = chirrtl.combmem : !chirrtl.cmemory<uint<1>, 2>
}
}
// -----
// An empty directory on an OutputDirAnnotation should fail.
// expected-error @below {{Unable to apply annotation: {class = "circt.OutputDirAnnotation", dirname = "", target = "~Top|Top"}}}
firrtl.circuit "Top" attributes {
rawAnnotations = [
{
class = "circt.OutputDirAnnotation",
dirname = "",
target = "~Top|Top"
}
]
} {
// expected-error @below {{circt.OutputDirAnnotation dirname must not be empty}}
firrtl.module @Top() {}
}
// -----
// OutputDirAnnotation targeting a non-public module should fail.
// expected-error @below {{Unable to apply annotation: {class = "circt.OutputDirAnnotation", dirname = "foo", target = "~Top|NotTop"}}}
firrtl.circuit "Top" attributes {
rawAnnotations = [
{
class = "circt.OutputDirAnnotation",
dirname = "foo",
target = "~Top|NotTop"
}
]
} {
firrtl.module @Top() {}
// expected-error @below {{circt.OutputDirAnnotation must target a public module}}
firrtl.module private @NotTop() {}
}
// -----
// An OutputDirAnnotation targeting an ExtModule should fail.
// expected-error @below {{Unable to apply annotation: {class = "circt.OutputDirAnnotation", dirname = "foo", target = "~Top|Target"}}}
firrtl.circuit "Top" attributes {
rawAnnotations = [
{
class = "circt.OutputDirAnnotation",
dirname = "foo",
target = "~Top|Target"
}
]
} {
firrtl.module @Top() {}
// expected-error @below {{circt.OutputDirAnnotation must target a module}}
firrtl.extmodule @Target()
}
// -----
// An OutputDirAnnotation targeting a module which already has an output directory, should fail.
// expected-error @below {{Unable to apply annotation: {class = "circt.OutputDirAnnotation", dirname = "bar", target = "~Top|Top"}}}
firrtl.circuit "Top" attributes {
rawAnnotations = [
{
class = "circt.OutputDirAnnotation",
dirname = "bar",
target = "~Top|Top"
}
]
} {
// expected-error @below {{circt.OutputDirAnnotation target already has an output file}}
firrtl.module @Top() attributes {output_file = #hw.output_file<"foo">} {}
}
// -----
// Multiple OutputDirAnnotation targeting the same module should fail.
// expected-error @below {{Unable to apply annotation: {class = "circt.OutputDirAnnotation", dirname = "foo", target = "~Top|Top"}}}
firrtl.circuit "Top" attributes {
rawAnnotations = [
{
class = "circt.OutputDirAnnotation",
dirname = "foo",
target = "~Top|Top"
},
{
class = "circt.OutputDirAnnotation",
dirname = "foo",
target = "~Top|Top"
}
]
} {
// expected-error @below {{circt.OutputDirAnnotation target already has an output file}}
firrtl.module @Top() {}
}