[Ibis] Add directions to portrefs

This commit is contained in:
Morten Borup Petersen 2023-08-14 09:18:20 +00:00
parent 5340055233
commit ea9ac11ead
8 changed files with 44 additions and 23 deletions

View File

@ -11,3 +11,9 @@ mlir_tablegen(IbisInterfaces.h.inc -gen-op-interface-decls)
mlir_tablegen(IbisInterfaces.cpp.inc -gen-op-interface-defs)
add_public_tablegen_target(MLIRIbisInterfacIbisncGen)
add_dependencies(circt-headers MLIRIbisInterfacIbisncGen)
set(LLVM_TARGET_DEFINITIONS Ibis.td)
mlir_tablegen(IbisEnums.h.inc -gen-enum-decls)
mlir_tablegen(IbisEnums.cpp.inc -gen-enum-defs)
add_public_tablegen_target(MLIRIbisEnumsIncGen)
add_dependencies(circt-headers MLIRIbisEnumsIncGen)

View File

@ -14,4 +14,7 @@
// Pull in the dialect definition.
#include "circt/Dialect/Ibis/IbisDialect.h.inc"
// Pull in all enum type definitions and utility function declarations.
#include "circt/Dialect/Ibis/IbisEnums.h.inc"
#endif // CIRCT_DIALECT_IBIS_IBISDIALECT_H

View File

@ -346,7 +346,7 @@ def PortReadOp : IbisOp<"port.read", [
class InnerTypeToPortRefTypeConstraint<string lhs, string rhs>
: TypesMatchWith<"the type of the lhs value dictates the rhs portref type",
lhs, rhs, "PortRefType::get($_ctxt, $_self)">;
lhs, rhs, "PortRefType::get($_ctxt, $_self, ibis::Direction::Input)">;
def PortWriteOp : IbisOp<"port.write", [
InnerTypeToPortRefTypeConstraint<"value", "port">

View File

@ -9,6 +9,7 @@
#ifndef CIRCT_DIALECT_IBIS_IBISTYPES_H
#define CIRCT_DIALECT_IBIS_IBISTYPES_H
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Support/LLVM.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"

View File

@ -11,6 +11,7 @@
include "circt/Dialect/Ibis/IbisDialect.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/EnumAttr.td"
class IbisTypeDef<string name> : TypeDef<IbisDialect, name> { }
@ -52,10 +53,17 @@ def OpaqueScopeRefType : Type<
BuildableType<"$_builder.getType<ibis::ScopeRefType>()"> {
}
def Input : I32EnumAttrCase<"Input", 0, "in">;
def Output : I32EnumAttrCase<"Output", 1, "out">;
def Direction : I32EnumAttr<"Direction", "Ibis port direction",
[Input, Output]> {
let cppNamespace = "::circt::ibis";
}
def PortRefType : IbisTypeDef<"PortRef"> {
let mnemonic = "portref";
let parameters = (ins "TypeAttr":$portTypeAttr);
let assemblyFormat = "`<` $portTypeAttr `>`";
let parameters = (ins "TypeAttr":$portTypeAttr, "ibis::Direction":$direction);
let assemblyFormat = "`<` $direction $portTypeAttr `>`";
let description = [{
A reference to an Ibis port.
}];
@ -67,8 +75,8 @@ def PortRefType : IbisTypeDef<"PortRef"> {
}];
let builders = [
TypeBuilder<(ins "Type":$t), [{
return $_get($_ctxt, TypeAttr::get(t));
TypeBuilder<(ins "Type":$t, "ibis::Direction":$d), [{
return $_get($_ctxt, TypeAttr::get(t), d);
}]>
];
}

View File

@ -24,3 +24,6 @@ void IbisDialect::initialize() {
#include "circt/Dialect/Ibis/Ibis.cpp.inc"
>();
}
// Provide implementations for the enums we use.
#include "circt/Dialect/Ibis/IbisEnums.cpp.inc"

View File

@ -34,7 +34,7 @@ ibis.class @C {
ibis.class @MissingPort {
%this = ibis.this @MissingPort
// expected-error @+1 {{'ibis.get_port' op port '@C_in' does not exist in MissingPort}}
%c_in = ibis.get_port %this, @C_in : !ibis.scoperef<@MissingPort> -> !ibis.portref<i1>
%c_in = ibis.get_port %this, @C_in : !ibis.scoperef<@MissingPort> -> !ibis.portref<in i1>
}
// -----
@ -43,7 +43,7 @@ ibis.class @PortTypeMismatch {
%this = ibis.this @PortTypeMismatch
ibis.port.input @in : i1
// expected-error @+1 {{'ibis.get_port' op symbol '@in' refers to a port of type 'i1', but this op has type 'i2'}}
%c_in = ibis.get_port %this, @in : !ibis.scoperef<@PortTypeMismatch> -> !ibis.portref<i2>
%c_in = ibis.get_port %this, @in : !ibis.scoperef<@PortTypeMismatch> -> !ibis.portref<in i2>
}
// -----

View File

@ -13,21 +13,21 @@
// CHECK-NEXT: %1 = ibis.instance @a, @A
// CHECK-NEXT: %2 = ibis.get_parent_of_ref %1 : !ibis.scoperef<@A> -> !ibis.scoperef
// CHECK-NEXT: %3 = ibis.get_instance_in_ref @a : @A in %0 : !ibis.scoperef<@C>
// CHECK-NEXT: %4 = ibis.get_port %1, @A_in : !ibis.scoperef<@A> -> !ibis.portref<i1>
// CHECK-NEXT: %4 = ibis.get_port %1, @A_in : !ibis.scoperef<@A> -> !ibis.portref<in i1>
// CHECK-NEXT: %5 = ibis.get_instance_in_ref @a : @A in %2 : !ibis.scoperef
// CHECK-NEXT: ibis.container @D {
// CHECK-NEXT: %6 = ibis.this @D
// CHECK-NEXT: %7 = ibis.get_parent_of_ref %6 : !ibis.scoperef<@D> -> !ibis.scoperef<@C>
// CHECK-NEXT: %8 = ibis.get_port %7, @C_in : !ibis.scoperef<@C> -> !ibis.portref<i1>
// CHECK-NEXT: %9 = ibis.get_port %7, @C_out : !ibis.scoperef<@C> -> !ibis.portref<i1>
// CHECK-NEXT: %8 = ibis.get_port %7, @C_in : !ibis.scoperef<@C> -> !ibis.portref<in i1>
// CHECK-NEXT: %9 = ibis.get_port %7, @C_out : !ibis.scoperef<@C> -> !ibis.portref<out i1>
// CHECK-NEXT: %true = hw.constant true
// CHECK-NEXT: ibis.port.write %9, %true : i1
// CHECK-NEXT: %10 = ibis.port.read %8 : !ibis.portref<i1>
// CHECK-NEXT: ibis.port.write %8, %true : i1
// CHECK-NEXT: %10 = ibis.port.read %9 : !ibis.portref<out i1>
// CHECK-NEXT: %11 = ibis.get_instance_in_ref @a : @A in %7 : !ibis.scoperef<@C>
// CHECK-NEXT: %12 = ibis.get_port %11, @A_in : !ibis.scoperef<@A> -> !ibis.portref<i1>
// CHECK-NEXT: %13 = ibis.get_port %11, @A_out : !ibis.scoperef<@A> -> !ibis.portref<i1>
// CHECK-NEXT: %12 = ibis.get_port %11, @A_in : !ibis.scoperef<@A> -> !ibis.portref<in i1>
// CHECK-NEXT: %13 = ibis.get_port %11, @A_out : !ibis.scoperef<@A> -> !ibis.portref<out i1>
// CHECK-NEXT: ibis.port.write %12, %10 : i1
// CHECK-NEXT: %14 = ibis.port.read %13 : !ibis.portref<i1>
// CHECK-NEXT: %14 = ibis.port.read %13 : !ibis.portref<out i1>
// CHECK-NEXT: }
// CHECK-NEXT: }
@ -48,7 +48,7 @@ ibis.class @C {
// Test get parent/child
%parent = ibis.get_parent_of_ref %a : !ibis.scoperef<@A> -> !ibis.scoperef
%child = ibis.get_instance_in_ref @a : @A in %this : !ibis.scoperef<@C>
%a_in_cp = ibis.get_port %a, @A_in : !ibis.scoperef<@A> -> !ibis.portref<i1>
%a_in_cp = ibis.get_port %a, @A_in : !ibis.scoperef<@A> -> !ibis.portref<in i1>
// Test siblings
%sibling = ibis.get_instance_in_ref @a : @A in %parent : !ibis.scoperef
@ -57,17 +57,17 @@ ibis.class @C {
%this_d = ibis.this @D
%parent_C = ibis.get_parent_of_ref %this_d : !ibis.scoperef<@D> -> !ibis.scoperef<@C>
// Test local read/writes
%c_in_p = ibis.get_port %parent_C, @C_in : !ibis.scoperef<@C> -> !ibis.portref<i1>
%c_out_p = ibis.get_port %parent_C, @C_out : !ibis.scoperef<@C> -> !ibis.portref<i1>
%c_in_p = ibis.get_port %parent_C, @C_in : !ibis.scoperef<@C> -> !ibis.portref<in i1>
%c_out_p = ibis.get_port %parent_C, @C_out : !ibis.scoperef<@C> -> !ibis.portref<out i1>
%true = hw.constant true
ibis.port.write %c_out_p, %true : i1
%c_out = ibis.port.read %c_in_p : !ibis.portref<i1>
ibis.port.write %c_in_p, %true : i1
%c_out = ibis.port.read %c_out_p : !ibis.portref<out i1>
// Test cross-container read/writes
%a_in_parent = ibis.get_instance_in_ref @a : @A in %parent_C : !ibis.scoperef<@C>
%a_in_p = ibis.get_port %a_in_parent, @A_in : !ibis.scoperef<@A> -> !ibis.portref<i1>
%a_out_p = ibis.get_port %a_in_parent, @A_out : !ibis.scoperef<@A> -> !ibis.portref<i1>
%a_in_p = ibis.get_port %a_in_parent, @A_in : !ibis.scoperef<@A> -> !ibis.portref<in i1>
%a_out_p = ibis.get_port %a_in_parent, @A_out : !ibis.scoperef<@A> -> !ibis.portref<out i1>
ibis.port.write %a_in_p, %c_out : i1
%a_out = ibis.port.read %a_out_p : !ibis.portref<i1>
%a_out = ibis.port.read %a_out_p : !ibis.portref<out i1>
}
}